/*	XGButton::XGButton
 *
 *		This is the base control for all my buttons. On the
 *	Macintosh and on Microsoft Windows, this manages the generic
 *	control object. On X, this really doesn't do very much...
 */

/*  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 <string.h>
#include <XButtons.h>
#include <XDraw.h>
#include <XMessages.h>
#include <XCursorUtil.h>

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

/*	@F"XGButton::XGButton" @I
 *
 *		Construct me.
 */

XGButton::XGButton(XGOwner *v, XGArgStream &s) : XGControl(v,s)
{
	int i;
	
	i = s.ReadInteger();
	fFont = XGFont::LoadFont(i);

#if OPT_MACOS || OPT_WINOS
	fControl = NULL;
#endif

#if OPT_XWIN
	fValue = 0;
	fName[0] = 0;
#endif

#if OPT_MACOS
	ClearTabStop();
#endif
}

/*	@F"XGButton::~XGButton" @I
 *
 *		Destruct me
 */

XGButton::~XGButton()
{
#if OPT_MACOS
	if (fControl) ::DisposeControl(fControl);
#endif

#if OPT_WINOS
	if (fControl) ::DestroyWindow(fControl);
#endif

	if (fFont) fFont->Detach();
}

/************************************************************************/
/*																		*/
/*	Control's value														*/
/*																		*/
/************************************************************************/

/*	@F"XGButton::GetValue" @I
 *
 *		Get the value of this thing
 */

long XGButton::GetValue(void)
{
#if OPT_MACOS
	if (!fControl) return 0;
	return (long)::GetControlValue(fControl);
#endif

#if OPT_WINOS
	long result;
	
	if (!fControl) return 0;
	result = (long)::SendMessage(fControl,BM_GETCHECK,0,0);
	switch (result) {
		case BST_UNCHECKED:
		default:
			return 0;
		case BST_CHECKED:
			return 1;
		case BST_INDETERMINATE:
			return -1;
	}
#endif

#if OPT_XWIN
	return fValue;
#endif
}

/*	@F"XGButton::SetValue" @I
 *
 *		Set the value of this thing
 */

void XGButton::SetValue(long value)
{
#if OPT_MACOS
	if (fControl) {
		/* The MacOS redraws the control, so this makes sure */
		/* the Mac grafport is set up correctly */
		XGDraw draw(this,false);
		if (fFont) {
			fFont->Attach();
			draw.SetFont(fFont);
		}
		::SetControlValue(fControl,value);
	}
#endif

#if OPT_WINOS
	if (fControl) {
		WPARAM w;
		
		switch (value) {
			case 0:
			default:
				w = BST_UNCHECKED;
				break;
			case 1:
				w = BST_CHECKED;
				break;
			case 2:
				w = BST_INDETERMINATE;
				break;
		}
		::SendMessage(fControl,BM_SETCHECK,w,0);
	}
#endif

#if OPT_XWIN
	fValue = value;
	InvalView();
#endif
}


/*	@F"XGButton::PushButton" @I
 *
 *		Temporary push button act, and return message. This does the
 *	appropriate thing on the target platform
 */

void XGButton::PushButton()
{
	if (!IsEnabled() && !IsActive()) return;

#if OPT_MACOS
	unsigned long tmp;
	XGDraw draw(this,false);
	if (fFont) {
		fFont->Attach();
		draw.SetFont(fFont);
	}
	
	::HiliteControl(fControl,kControlButtonPart);
	::Delay(5,&tmp);
	::HiliteControl(fControl,0);
	DoDispatch(KXGControlClick,GetViewID(),NULL);
#endif

#if OPT_WINOS
	::SendMessage(fControl,BM_CLICK,0,0);		// simulate click
#endif

#if OPT_XWIN
	DoDispatch(KXGControlClick,GetViewID(),NULL);
#endif
}

/************************************************************************/
/*																		*/
/*	Events																*/
/*																		*/
/************************************************************************/

/*	@F"XGButton::DoDrawView" @I
 *
 *		Handle the drawing
 */

void XGButton::DoDrawView(Rect)
{
#if OPT_MACOS
	if (fControl) {
		XGDraw draw(this,false);
		if (fFont) {
			fFont->Attach();
			draw.SetFont(fFont);
		}
		
		if (IsEnabled() && IsActive()) {
			/*
			 *	Enabled
			 */
			
			::HiliteControl(fControl,0);
		} else {
			::HiliteControl(fControl,255);
		}
		::ShowControl(fControl);
		::Draw1Control(fControl);
	}
#endif

#if OPT_WINOS
	if (fControl) {
		::ShowWindow(fControl,SW_SHOW);
	}
#endif

#if OPT_XWIN
	DrawControl(false);
#endif
}

/*	@F"XGButton::DoActivate" @I
 *
 *		Activate/deactivate.
 */

void XGButton::DoActivate(bool)
{
#if OPT_MACOS || OPT_XWIN
	if (IsEnabled()) {
		InvalView();
	}
#endif

#if OPT_WINOS
	/* Does nothing; activation/deactivation handled automatically */
#endif
}

/*	@F"XGButton::DoMouseDown" @I
 *
 *		Handle the mouse down event. Only used for the Macintosh
 */

bool XGButton::DoMouseDown(Point pt, short a)
{
#if OPT_MACOS
	if (fControl) {
		XGDraw draw(this,false);
		if (fFont) {
			fFont->Attach();
			draw.SetFont(fFont);
		}
		ViewToGlobal(&pt);
		if (::TrackControl(fControl,pt,NULL)) {
			DoDispatch(KXGControlClick,GetViewID(),NULL);
		}
	} else {
		XGControl::DoMouseDown(pt,a);
	}
	return false;
#endif

#if OPT_WINOS
	return XGControl::DoMouseDown(pt,a);
#endif

#if OPT_XWIN
	fDown = true;
	DrawControl(true);
	return true;
#endif
}

/*	@F"XGButton::DoMouseMove" @I
 *
 *		handle mouse move events
 */

void XGButton::DoMouseMove(Point pt, short a)
{
#if OPT_XWIN
	Rect r;
	
	if (a & KCapturedMouse) {
		r = GetContentRect();

		if (PtInRect(pt,&r)) {
			if (!fDown) {
				fDown = true;
				DrawControl(true);
			}
		} else {
			if (fDown) {
				fDown = false;
				DrawControl(false);
			}
		}
	} else {
		::SetCursorID(KNormalCursor);
	}
#else
	XGControl::DoMouseMove(pt,a);
#endif
}

/*	@F"XGButton::DoMouseUp" @I
 *
 *		handle mouse up
 */

void XGButton::DoMouseUp(Point pt, short a)
{
#if OPT_XWIN
	if (fDown) {
		DrawControl(false);
		DoDispatch(KXGControlClick,GetViewID(),NULL);
	}
#else
	XGControl::DoMouseUp(pt,a);
#endif
}

/*	@F"XGButton::GetTitle" @I
 *
 *		Get the name
 */

void XGButton::GetTitle(char *name) const
{
#if OPT_MACOS
	::GetControlTitle(fControl,(unsigned char *)name);
	p2cstr((unsigned char *)name);
#endif

#if OPT_WINOS
	::SendMessage(fControl,WM_GETTEXT,255,(LPARAM)(LPSTR)name);
#endif

#if OPT_XWIN
	::strcpy(name,fName);
#endif
}

/*	@F"XGButton::SetTitle" @I
 *
 *		Set the name
 */

void XGButton::SetTitle(const char *name)
{
#if OPT_MACOS
	char buffer[256];
	
	strcpy(buffer,name);
	XGDraw draw(this,false);
	if (fFont) {
		fFont->Attach();
		draw.SetFont(fFont);
	}
	::SetControlTitle(fControl,c2pstr(buffer));
#endif

#if OPT_WINOS
	::SendMessage(fControl,WM_SETTEXT,0,(LPARAM)(LPSTR)name);
#endif

#if OPT_XWIN
	::strcpy(fName,name);
	InvalView();
#endif
}

/*	@F"XGButton::DoSizeView" @I
 *
 *		Handle resize event
 */

void XGButton::DoSizeView()
{
#if OPT_MACOS || OPT_WINOS
	DoMoveView();
#endif

	/*
	 *	Pass upwards
	 */
	
	XGControl::DoSizeView();
}

/*	@F"XGButton::DoMoveView" @I
 *
 *		Move the view.
 */

void XGButton::DoMoveView()
{
#if OPT_MACOS || OPT_WINOS
	Rect r;
	
	if (!fControl) return;
	r = GetContentRect();
	ViewToGlobal(&r);
	
#if OPT_MACOS
	XGDraw draw(this,false);
	if (fFont) {
		fFont->Attach();
		draw.SetFont(fFont);
	}
	::HideControl(fControl);
	::MoveControl(fControl,r.left,r.top);
	::SizeControl(fControl,r.right-r.left,r.bottom-r.top);
#endif

#if OPT_WINOS
	::SetWindowPos(fControl,
				   NULL,
				   r.left,
				   r.top,
				   r.right-r.left,
				   r.bottom-r.top,
				   SWP_NOZORDER | SWP_HIDEWINDOW);
#endif
#endif
}

/*	@F"XGButton::DoShowHide" @I
 *
 *		This is called when the control is to be hidden or
 *	shown. This only needs to hide the control; the call to
 *	DoDrawView() will show the control if needed.
 */

void XGButton::DoShowHide()
{
#if OPT_MACOS
	if (!IsVisible() && fControl) {
		XGDraw draw(this,false);
		if (fFont) {
			fFont->Attach();
			draw.SetFont(fFont);
		}
		::HideControl(fControl);
		::MoveControl(fControl,-20,-20);
		::SizeControl(fControl,10,10);
	} else {
		if (fControl) {
			Rect r;
			
			r = GetContentRect();
			ViewToGlobal(&r);
			::MoveControl(fControl,r.left,r.top);
			::SizeControl(fControl,r.right-r.left,r.bottom-r.top);
		}
	}
#endif

#if OPT_WINOS
	if (!IsVisible() && fControl) {
		::ShowWindow(fControl,SW_HIDE);
	}
#endif

	XGView::DoShowHide();
}

/*	@F"XGButton::DoEnable" @I
 *
 *		Handle enable/disable events. Passes the enable/disable
 *	event to the control
 */

void XGButton::DoEnable()
{
#if OPT_WINOS
	if (fControl) ::EnableWindow(fControl,IsEnabled());
#endif
}

#if OPT_WINOS

/*	@F"XGButton::SetFocus" @I
 *
 *		Set the focus. This overrides stuff on Windows by setting the
 *	MS Window focus as well.
 */

bool XGButton::SetFocus(void)
{
	if (XGDispatch::SetFocus()) {
		::SetFocus(fControl);
		return true;
	} else return false;
}

#endif

/************************************************************************/
/*																		*/
/*	Windows Event Implementation										*/
/*																		*/
/************************************************************************/

#if OPT_WINOS

BEGINDISPATCH(XGButton,XGView)
	DISPATCHTABLE(KXGWInternal,XGButton::DoWInternal)
ENDDISPATCH

/*	XGButton::DoWInternal
 *
 *		This is where messages that are received from my
 *	control is sent
 */

long XGButton::DoWInternal(long,void *ptr)
{
	XGSWInternalRecord *r;
	
	r = (XGSWInternalRecord *)ptr;
	
	/*
	 *	How to handle this
	 */
	
	if (r->msg == WM_COMMAND) {
		if (HIWORD(r->wp) == BN_CLICKED) {
			/*
			 *	I've been clicked on
			 */
			
			DoDispatch(KXGControlClick,GetViewID(),NULL);
			return 0;
		}
	}
	return -1;
}

#endif
