/*	XGPopWindow.cpp
 *
 *		This is a very simplified class which handles a short-term
 *	popup window. Generally this is used for tracking popup menus
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  This library is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Library
 *  General Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or any
 *  later version.
 *  
 *  This library is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU Library General Public License for
 *  more details.
 *  
 *  You should have received a copy of the GNU Library General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <XDraw.h>
#include <XView.h>
#include <XWindow.h>

#if OPT_MACOS
#include "MacFloater.h"
#endif

/************************************************************************/
/*																		*/
/*	Globals																*/
/*																		*/
/************************************************************************/

long XGPopWindow::gPopCount = 0;

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

// @G"Construction/Destruction"

/*	@F"XGPopWindow::XGPopWindow" @I
 *
 *		Create a popup window
 */

XGPopWindow::XGPopWindow(XGView *base, Rect r, XGView *view)
{
	/*
	 *	Initialize
	 */
	
	fBase = base;
	fLocation = r;
	fView = view;
	gPopCount++;
	
	/*
	 *	Now figure the global location (in the OS, where to build
	 *	the window)
	 */
	
#if OPT_MACOS == 1
	{
		/* This works by creating a local coordinate system in the */
		/* base object which then gets converted by the OS to the */
		/* correct global coordinate system */
		Point pt;
		XGDraw draw(base);			// set up graphics port for here
		
		pt.h = 0;
		pt.v = 0;
		::LocalToGlobal(&pt);
		::OffsetRect(&r,pt.h,pt.v);
	}
#endif

#if OPT_WINOS == 1
	{
		POINT pt;
		
		base->ViewToGlobal(&r);		// go from view to global coordinates
		pt.x = 0;
		pt.y = 0;
		::ClientToScreen(base->GetRootWindow(),&pt);
		::OffsetRect(&r,pt.x,pt.y);
	}
#endif

#if OPT_XWIN == 1
	{
		int newx,newy;
		Window tmpw;
		
		base->ViewToGlobal(&r);

		::XTranslateCoordinates(_GDisplay,
								base->GetRootWindow(),
								DefaultRootWindow(_GDisplay),
								0,0,
								&newx,&newy,
								&tmpw);
		::OffsetRect(&r,newx,newy);
	}
#endif

	/*
	 *	Now that I know where my popup window goes, create it.
	 */
	
	CreateOSWindow(r);
	
	/*
	 *	And set the window parameter of this view
	 */
	
#if OPT_MACOS == 1
	fView->SetRootWindow(&fWindow.port);
#endif

#if OPT_WINOS == 1
	fView->SetRootWindow(fWindow);
#endif

#if OPT_XWIN == 1
	fView->SetRootWindow(fWindow);
#endif
	
	::OffsetRect(&r,-r.left,-r.top);
	fView->SetLocation(r);
	fView->ProcessDraw(r);
}

/*	@F"XGPopWindow::~XGPopWindow" @I
 *
 *		Delete me
 */

XGPopWindow::~XGPopWindow()
{
	gPopCount--;
	fView->SetRootWindow(0);
	delete fView;
	DestroyOSWindow();
}

/*	XGPopWindow::FixToScreen
 *
 *		Fix the location of the rectangle to the screen boundaries
 */

void XGPopWindow::FixToScreen(Rect *r)
{
	Rect s;
	short tmp;
	
#if OPT_WINOS
	/* Windows: GetScreenSize doesn't quite return the right thing. */
	s.left   = 0;
	s.top    = 0;
	s.right  = ::GetSystemMetrics(SM_CXFULLSCREEN);
	s.bottom = ::GetSystemMetrics(SM_CYFULLSCREEN);
#else
	XGWindow::GetScreenSize(&s);
#endif
	if (r->left < s.left + 5) {
		tmp = s.left + 5 - r->left;
		::OffsetRect(r,tmp,0);
		::OffsetRect(&fLocation,tmp,0);
	}
	if (r->right > s.right - 5) {
		tmp = r->right - s.right + 5;
		::OffsetRect(r,-tmp,0);
		::OffsetRect(&fLocation,-tmp,0);
	}
	if (r->top < s.top + 5) {
		tmp = s.top + 5 - r->top;
		::OffsetRect(r,0,tmp);
		::OffsetRect(&fLocation,0,tmp);
	}
	if (r->bottom > s.bottom - 5) {
		tmp = r->bottom - s.bottom + 5;
		::OffsetRect(r,0,-tmp);
		::OffsetRect(&fLocation,0,-tmp);
	}
}

/************************************************************************/
/*																		*/
/*	OS Window Construction (Macintosh)									*/
/*																		*/
/************************************************************************/

#if OPT_MACOS == 1

/*	XGPopWindow::CreateOSWindow
 *
 *		Actually build the OS window that will contain this popup. In
 *	order to prevent window activation, this is kludged to create the
 *	window and then show it. The 'ShowWindow()' call bypasses the
 *	activation stuff...
 */

void XGPopWindow::CreateOSWindow(Rect r)
{
	FixToScreen(&r);
	::NewCWindow((Ptr)&fWindow,
			     &r,
			     "\p",
			     false,
			     plainDBox,
			     (WindowPtr)-1L,
			     false,
			     0L);
	fWindow.windowKind = userKind;				// not an XGWindow object...

	::ShowHide(&fWindow.port,true);
}

/*	XGPopWindow::DestroyOSWindow
 *
 *		Destroy the OS window that will contain this popup
 */

void XGPopWindow::DestroyOSWindow()
{
	::CloseWindow(&fWindow.port);
}

#endif


/************************************************************************/
/*																		*/
/*	OS Window Construction (Microsoft Windows)							*/
/*																		*/
/************************************************************************/

#if OPT_WINOS == 1

/*	PopWindowProc
 *
 *		This is a very brain dead callback routine
 */

static LRESULT CALLBACK PopWindowProc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
{
	PAINTSTRUCT ps;
	
	switch (msg) {
		case WM_NCACTIVATE:
			if (!wp) {
				return TRUE;
			}
			break;
		case WM_PAINT:
			::BeginPaint(w,&ps);
			::EndPaint(w,&ps);
			break;
		default:
			return ::DefWindowProc(w,msg,wp,lp);
	}
	return 0;
}

/*	RegisterPopWindow
 *
 *		Register the popup window if it isn't already
 */

static void RegisterPopWindow(void)
{
	WNDCLASS wc;
	static bool gRegFlag;
	
	if (gRegFlag) return;
	gRegFlag = true;
	
	wc.style = 0;
	wc.lpfnWndProc = PopWindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = _GInstance;
	wc.hIcon = NULL;
	wc.hCursor = NULL;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = _GPopClass;
	RegisterClass(&wc);
}

/*	XGPopWindow::CreateOSWindow
 *
 *		Actually build the OS window that will contain this popup
 */

void XGPopWindow::CreateOSWindow(Rect r)
{
	RegisterPopWindow();
	
	FixToScreen(&r);
	fWindow = ::CreateWindowEx(WS_EX_TOPMOST,
						     	_GPopClass,
						     	"Copyright",
						     	WS_POPUP | WS_VISIBLE,
						     	r.left,r.top,
						     	r.right-r.left,r.bottom-r.top,
						     	fBase->GetRootWindow(),
						     	NULL,
						     	_GInstance,
						     	NULL);
	if (fWindow) {
		::ShowWindow(fWindow,SW_SHOW);
	}
}

/*	XGPopWindow::DestroyOSWindow
 *
 *		Destroy the OS window that will contain this popup
 */

void XGPopWindow::DestroyOSWindow()
{
	::DestroyWindow(fWindow);
	fWindow = NULL;
}

#endif


/************************************************************************/
/*																		*/
/*	OS Window Construction (X)											*/
/*																		*/
/************************************************************************/

#if OPT_XWIN == 1

/*	XGPopWindow::CreateOSWindow
 *
 *		Actually build the OS window that will contain this popup
 */

void XGPopWindow::CreateOSWindow(Rect r)
{
	XSetWindowAttributes attrib;

	FixToScreen(&r);
	attrib.event_mask = KeyPressMask |
						ButtonPressMask |
						ButtonReleaseMask |
						EnterWindowMask |
						LeaveWindowMask |
						PointerMotionMask |
						ExposureMask |
						StructureNotifyMask |
						ColormapChangeMask;
	attrib.override_redirect = true;
	fWindow = ::XCreateWindow(_GDisplay,
							  DefaultRootWindow(_GDisplay),
							  r.left,
							  r.top,
							  r.right-r.left,
							  r.bottom-r.top,
							  0,
							  CopyFromParent,
							  InputOutput,
							  CopyFromParent,
							  CWEventMask | CWOverrideRedirect,
							  &attrib);
	::XMapRaised(_GDisplay,fWindow);
}

/*	XGPopWindow::DestroyOSWindow
 *
 *		Destroy the OS window that will contain this popup
 */

void XGPopWindow::DestroyOSWindow()
{
	::XDestroyWindow(_GDisplay,fWindow);
}

#endif
