/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	ModalDialog.cpp
 *
 *****************************************************************************/

// SOL++2000
// 2001/03/11 Modified a create method.

#include <sol\ModalDialog.h>
#include <sol\Application.h>


ModalDialog* ModalDialog::self = NULL;


ModalDialog::ModalDialog(View* owner, const char* name, Args& args)
	:PopupView(owner)
{
	centering = (int) args.get(XmNcentering);

	templateName = (char*) args.get(XmNtemplateName);
	addEventHandler(WM_INITDIALOG, this,
		(Handler)&ModalDialog::initDialog, NULL);

	int focusId = IDOK;
	ulong val;
	if (args.get(XmNfocusId, &val)) {
		focusId = (int)val;
	}
	setFocusId(focusId);

// Use a virtual effect!
	addCallback(XmNactivateCallback, IDCANCEL, this,
		(Callback)&ModalDialog::popdown, NULL);
}



Boolean ModalDialog::create(View* owner, const char* name, Args& args)
{
	// 2001/03/11
	Boolean rc = PopupView::create(owner);

	setOwner(owner);

	centering = (int) args.get(XmNcentering);

	templateName = (char*) args.get(XmNtemplateName);
	addEventHandler(WM_INITDIALOG, this,
		(Handler)&ModalDialog::initDialog, NULL);

	int focusId = IDOK;
	ulong val;
	if (args.get(XmNfocusId, &val)) {
		focusId = (int)val;
	}
	setFocusId(focusId);

// Use a virtual effect!
	addCallback(XmNactivateCallback, IDCANCEL, this,
		(Callback)&ModalDialog::popdown, NULL);
	return rc;
}


void ModalDialog::popup(Action& action)
{
	View* owner    = getParent();
	HWND howner    = NULL;
	HINSTANCE hins = NULL;

	if(owner) {
		howner = owner -> getWindow();
		hins   = owner -> getInstanceHandle();
	}
	
	setSelf(this);
	::DialogBox(hins, templateName, howner, 
				(DLGPROC)ModalDialog::procedure);
}


BOOL CALLBACK ModalDialog::procedure(HWND hwnd, 
		UINT message, WPARAM wParam, LPARAM lParam)
{
	if(self) {
		Application::add(hwnd, self);
		self -> setWindow(hwnd);
		self = NULL;
	}
	ModalDialog* dlg = (ModalDialog*)Application::lookup(hwnd);
	if(dlg == NULL) { 
		return FALSE;
	}

	Event event(message, wParam, lParam);
	if(message == WM_DESTROY) {
		Application::remove(hwnd);
		return FALSE;
	}
	else {
		return (BOOL)dlg -> dispatch(event);
	}
}


long ModalDialog::command(Event& event) 
{
	HWND child  = event.getChild();
	const char* name = findCallbackName(event, child);

	WPARAM wParam = event.getWParam();
	if(name == XmNactivateCallback && wParam == IDOK) {
		child = ::GetFocus();
	}

	if(child) {
		callCallback(name, (Key)child, NULL, event);
	}
	// ESC key
	if(child == NULL && wParam == IDCANCEL) {
		end(0);
	}
	return TRUE;
}


long ModalDialog::initDialog(Event& event)
{
	setPopupFocus();
	if(centering) {
		centerOn();	
	}
	return NULL;
}
