/*	XGAppSingleWindow.cpp
 *
 *		This creates a single-window application.
 */

/**********************************************************************

  YAAF is Copyright 1997-1999 by William Woody.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions 
  are met:

  Redistributions of source code must retain the above copyright notice, 
  this list of conditions and the following disclaimer.

  Neither the name of the copyright holder or other contributors may
  be used to promote products derived from this software without
  specific written prior permission.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
  SOFTWARE.
  
  Contact:   woody@alumni.caltech.edu
  Web page:  http://www.pandawave.com/yaaf/

**********************************************************************/

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <XWindow.h>
#include <XMenu.h>
#include <XError.h>
#include <XApplication.h>
#include <XMessages.h>
#include <XAppMenu.h>

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

/*$	XGAppSingleWindow::XGAppSingleWindow
 *
 *		Create me. This performs the initialization steps for bringing
 *	up a single window application.
 */

XGAppSingleWindow::XGAppSingleWindow()
{
	fMyWindow = NULL;
	fMyMenuBar = NULL;

#if OPT_WINOS == 1
	_GMainWindow = NULL;
	_GMDIWindow = NULL;				/* Make sure this is clear */
	if (_GPrevInstance == NULL) InitApplication();
	InitInstance();					/* Start up instance */
#endif

	XGBroadcast::AddBroadcast(this);
}

/*$	XGAppSingleWindow:::~XGAppSingleWindow
 *
 *		Delete me. This is normally called internally by YAAF.
 */

XGAppSingleWindow::~XGAppSingleWindow()
{
	if (fMyWindow) delete fMyWindow;
	if (fMyMenuBar) delete fMyMenuBar;
}

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

/*$	XGAppSingleWindow::Run
 *
 *		This verifies that a window was in fact created. If not, this
 *	complains and quits. You *must* create a window before returning
 *	from the StartApplication() method, or else when YAAF calls this
 *	routine, it will fail.
 */

void XGAppSingleWindow::Run(void)
{
	if (fMyWindow == NULL) throw XGPostError(KXGSingleAppError);
	XGAppCore::Run();
}

/************************************************************************/
/*																		*/
/*	Event Dispatch														*/
/*																		*/
/************************************************************************/

/*
 *	Dispatch table
 */

BEGINDISPATCH(XGAppSingleWindow,XGAppCore)
	DISPATCHTABLE(KXGEventWindowCreate,XGAppSingleWindow::DoWindowCreate)
	DISPATCHTABLE(KXGEventWindowDestroy,XGAppSingleWindow::DoWindowDestroy)
	DISPATCHTABLE(KXGAppPostEvent,XGAppSingleWindow::DoPostPeriodic)
ENDDISPATCH

/*	XGAppSingleWindow::DoWindowCreate
 *
 *		Handle the window create event
 */

long XGAppSingleWindow::DoWindowCreate(long, void *parg)
{
	XGWindow *w;
	int menuID;
	
	w = ((XGSWindowEvent *)parg)->window;
	if (w->GetWindowKind() != KWinDocument) return -1;

	/*
	 *	Record the creation of this window. We only allow one
	 */
	
	if (fMyWindow) throw XGPostError(KXGSingleAppDupError);
	fMyWindow = w;
	
	/*
	 *	Now that we have a window, initialize the menu bar
	 *	that is associated with this menu
	 */
	
#if OPT_MACOS == 1
	fMyMenuBar = new XGMenuBar();
#endif

#if OPT_WINOS == 1
	_GMainWindow = w->GetHWND();
	fMyMenuBar = new XGMenuBar(_GMainWindow,false);
#endif

#if OPT_XWIN == 1
	fMyMenuBar = new XGMenuBar(w->GetWindow());
	w->SetMenuBar(fMyMenuBar);
#endif
			
	menuID = w->GetMenuBarID();
	Assert(menuID != -1);
	if (menuID == 0) menuID = KXGDefaultMenu;
	fMyMenuBar->LoadFromResource(menuID);
	return -1;
}

/*	XGAppSingleWindow::DoWindowDestroy
 *
 *		Handle the window destruction event
 */

long XGAppSingleWindow::DoWindowDestroy(long, void *parg)
{
	XGWindow *w;
	
	w = ((XGSWindowEvent *)parg)->window;
	if (w->GetWindowKind() != KWinDocument) return -1;

	/* 
	 *  Record destruction of this window. Quit if it's mine 
	 */
	
	if (fMyWindow == w) {
		fMyWindow = NULL;

#if OPT_WINOS == 1
		_GMainWindow = NULL;
#endif
		XGDispatch::SendDispatch(KXGQuitApplication,0,NULL);
	}
	return -1;
}

/*	XGAppSingleWindow::DoPostPeriodic
 *
 *		Process postperiodic event to update menu bar
 */

long XGAppSingleWindow::DoPostPeriodic(long, void *)
{
	int menuID;
	bool f;
	
	/*
	 *	Update the menu bar
	 */
	
	if ((fMyMenuBar != NULL) && (fMyWindow != NULL)) {
		menuID = fMyWindow->GetMenuBarID();
		if (menuID == -1) return 0;
		if (menuID == 0) menuID = KXGDefaultMenu;

		f = fMyMenuBar->LoadFromResource(menuID);
		fEventOwner = fMyWindow;
		fMyMenuBar->UpdateMenuBar(GetFocus());
		fEventOwner = NULL;
		
#if OPT_XWIN
		if (f) fMyWindow->RedrawMenuBar();
#endif
	}
	return 0;
}

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

/*$	XGAppSingleWindow::GetCurMenu
 *
 *		The current menu for this single window application. This can
 *	be used by your XGApplication override to handle menu processing.
 */

XGMenuBar *XGAppSingleWindow::GetCurMenu()
{
	return fMyMenuBar;
}

/************************************************************************/
/*																		*/
/*	Windows initialization support										*/
/*																		*/
/************************************************************************/

#if OPT_WINOS == 1

/*	XGAppSingleWinodw::InitApplication
 *
 *		Register the classes which are in me
 */

void XGAppSingleWindow::InitApplication(void)
{
	static bool gInit = false;
	WNDCLASSEX wc;
	
	if (gInit) return;					// run this only once.
	gInit = true;
	
	/*
	 *	Initialize three instances: a class of class name "_XGWindow"
	 *	and a class of class name "_XGView", and "_XGDialog"
	 */
	
	wc.cbSize = sizeof(wc);
	wc.style = CS_DBLCLKS;
	wc.lpfnWndProc = _GSingleWindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = _GInstance;
	wc.hIcon = (HICON)LoadImage(_GInstance,"AppIcon",IMAGE_ICON,32,32,LR_SHARED);;
	wc.hCursor = NULL;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = _GWindowClass;
	wc.hIconSm = (HICON)LoadImage(_GInstance,"AppIconSmall",IMAGE_ICON,16,16,LR_SHARED);
	Assert(RegisterClassEx(&wc));
	
	wc.cbSize = sizeof(wc);
	wc.style = CS_DBLCLKS;
	wc.lpfnWndProc = _GSingleWindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = _GInstance;
	wc.hIcon = (HICON)LoadImage(_GInstance,"AppIcon",IMAGE_ICON,32,32,LR_SHARED);;
	wc.hCursor = NULL;
	wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = _GDlogClass;
	wc.hIconSm = (HICON)LoadImage(_GInstance,"AppIconSmall",IMAGE_ICON,16,16,LR_SHARED);
	Assert(RegisterClassEx(&wc));
}

/*	XGAppSingleWindow::InitInstance
 *
 *		Initialize the instance of this thing. This does nothing; we assume
 *	the window that is initialized elsewhere will provide me the UI.
 */

void XGAppSingleWindow::InitInstance(void)
{
}


#endif
