/******************************************************************************
 *
 * 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.
 *
 *
 *	PropertyPage.cpp
 *
 *****************************************************************************/

// SOL++2000

#include <sol\Application.h>
#include <sol\PropertyPage.h>
#include <sol\stdio.h>
#include <sol\PropertyDialog.h>


PropertyPage* PropertyPage::self = NULL;


PropertyPage::PropertyPage(PropertyDialog* parent, const char* title, Args& args)
	:PopupView(parent)
{
	hpage = NULL;
	self  = NULL;
	// Assuming that parent != NULL
	psp = parent->getCurPage();
	if(psp) {
		memset(psp, 0, sizeof(PROPSHEETPAGE));
		psp -> dwSize = sizeof(PROPSHEETPAGE);
		// set default values
		psp -> dwFlags     = PSP_USETITLE|PSP_USECALLBACK;
		psp -> pfnDlgProc  = (DLGPROC)PropertyPage::procedure;
		psp -> hInstance   = Application::getInstance();
		psp -> pfnCallback = (LPFNPSPCALLBACK)
					PropertyPage::pageCallback;
			
		psp -> pszTitle    = title;
		psp -> pszTemplate = (char*)args.get(XmNtemplateName);
		psp -> lParam      = (LPARAM)this;

		ulong val = NULL;
		val = args.get(XmNflags);
		if(val) {
			psp -> dwFlags |= val;
		}

		val = args.get(XmNicon);
		if(val) {
			psp -> pszIcon = (char*)val;
		}
		// 
		if(parent->isWindow()) {		
			hpage = ::CreatePropertySheetPage(psp);
		}		
		addEventHandler(WM_INITDIALOG, this,
			(Handler)&PropertyPage::initDialog, NULL);
		
		parent -> addPage(this);
	}
}


PropertyPage::~PropertyPage()
{
	delete psp;
	if(hpage) {
		::DestroyPropertySheetPage(hpage);
	}
}



Boolean PropertyPage::create(PropertyDialog* parent, const char* title, Args& args)
{
	Boolean rc = True;
	View::setParent(parent);

	hpage = NULL;
	self  = NULL;
	// Assuming that parent != NULL
	psp = parent->getCurPage();
	if(psp) {
		memset(psp, 0, sizeof(PROPSHEETPAGE));
		psp -> dwSize = sizeof(PROPSHEETPAGE);
		// set default values
		psp -> dwFlags     = PSP_USETITLE|PSP_USECALLBACK;
		psp -> pfnDlgProc  = (DLGPROC)PropertyPage::procedure;
		psp -> hInstance   = Application::getInstance();
		psp -> pfnCallback = (LPFNPSPCALLBACK)
					PropertyPage::pageCallback;
			
		psp -> pszTitle    = title;
		psp -> pszTemplate = (char*)args.get(XmNtemplateName);
		psp -> lParam      = (LPARAM)this;

		ulong val = NULL;
		val = args.get(XmNflags);
		if(val) {
			psp -> dwFlags |= val;
		}

		val = args.get(XmNicon);
		if(val) {
			psp -> pszIcon = (char*)val;
		}
		// 
		if(parent->isWindow()) {		
			hpage = ::CreatePropertySheetPage(psp);
		}		
		addEventHandler(WM_INITDIALOG, this,
			(Handler)&PropertyPage::initDialog, NULL);
		
		parent -> addPage(this);
	}

	return rc;
}


UINT CALLBACK PropertyPage::pageCallback(HWND  hwnd, UINT message,	
						LPPROPSHEETPAGE  ppsp)
{
	//Printf("PageCallback hwnd = %d  message = %d\r\n", 
	//	(int)hwnd, message);
	if(message == PSPCB_CREATE) {
		self = (PropertyPage*)ppsp->lParam;
	}
	return TRUE;
}


BOOL PropertyPage::procedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if(self) {
		self -> setWindow(hwnd);

		Application::add(hwnd, self);
		HWND hparent = ::GetParent(hwnd);
		View* sheet = self -> getParent();
		if(sheet && sheet->getWindow() == NULL) {
		//	Printf("Set PageCallback hparent  %d 3\r\n",(int)hparent);
			sheet -> setWindow(hparent);
			Application::add(hparent, sheet);
		}
		self = NULL;
	}
	
	PropertyPage* page = (PropertyPage*)Application::lookup(hwnd);
	if(page == NULL) { 
		return FALSE;
	}

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

void PropertyPage::addCallback(const char* name, Object* object,
		       Callback proc, void* data)
{
	View::addCallback(name, (Key)this, object, 
							proc, data);
}



Arg* PropertyPage::getCallbackTable(int* num)
{
	static Arg table[] = {
	{XmNsetActiveCallback, PSN_SETACTIVE},
	{XmNkillActiveCallback, PSN_KILLACTIVE},
	{XmNapplyCallback,  PSN_APPLY},
	{XmNresetCallback,   PSN_RESET},
	{XmNhasHelpCallback, PSN_HELP},
	{XmNwizBackCallback, PSN_WIZBACK},
	{XmNwizNextCallback, PSN_WIZNEXT},
	{XmNwizFinishCallback, PSN_WIZFINISH},
	{XmNqueryCancelCallback, PSN_QUERYCANCEL},
	};
	*num = XtNumber(table);
	return table;
}


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

	return TRUE;
}


long PropertyPage::initDialog(Event& event)
{
	return NULL;
}
	

long PropertyPage::notify(Event& event)
{
	NMHDR* hdr = (NMHDR*)event.getLParam();
	HWND  sender  = hdr->hwndFrom;

	HWND self = getWindow();
	HWND hparent = ::GetParent(self);
	const char* name = NULL;
	if(hparent == sender) {
		name = getCallbackName(event);
		if(name) {	
			callCallback(name, (Key)this , NULL, event);
		}
		return event.getResult();
	}

	View* view = (View*)Application::lookup(sender);
	if(view) {
		name = isCommonNotification(event);
		if(name == NULL) {
			name = view->getCallbackName(event);
		}
		if(name) {
			callCallback(name, (Key)sender, NULL, event);
		}
	}
  	return event.getResult();
}


void PropertyPage::setMsgResult(long result)
{
	setWindowLong(DWL_MSGRESULT, result);
}
