//	Zinc Application Framework - m_client.cpp
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include "m_win.hpp"

// ----- MtfWindowClient widget definition ----------------------------------

XmOffsetPtr MtfWindowClient::offsets;

XtActionsRec MtfWindowClient::action[] =
{
	{ "ManagerGadgetActivate",		(XtActionProc)activate },
	{ "ManagerGadgetArm",			(XtActionProc)arm },
	{ "ManagerGadgetMultiActivate",	(XtActionProc)multi_activate },
	{ "ManagerGadgetMultiArm",		(XtActionProc)multi_arm },
	{ "ZafCallDefault", 			(XtActionProc)call_default },
	{ "ZafDragDrop",				(XtActionProc)drag_drop },
	{ "ZafEnter",					(XtActionProc)enter },
	{ "ZafHelp", 					(XtActionProc)help },
	{ "ZafLeave",					(XtActionProc)leave },
	{ "ZafMouse", 					(XtActionProc)mouse }
};

char MtfWindowClient::translations[] =
	"<Key>osfActivate:		ZafCallDefault()\n\
	 <Key>osfSelect:		ZafCallDefault()\n\
	 ~s ~m ~a <Key>Return:	ZafCallDefault()\n\
	 <Btn2Down>:			ZafDragDrop()\n\
	 <Btn3Down>:			ZafMouse()\n\
	 <Btn3Up>:				ZafMouse()\n\
	 <Btn3Motion>:			ZafMouse()\n\
	 <Enter>:				ZafEnter()\n\
	 <Key>F1:				ZafHelp()\n\
	 <Key>osfHelp:			ZafHelp()\n\
	 <Leave>:				ZafLeave()";

MtfWindowClientClassRec MtfWindowClient::classRecord =
{
	// --- CoreClassPart ---
	{
		(WidgetClass)&xmBulletinBoardClassRec,	// superclass
		"ZafWindow",							// class_name
		sizeof(MtfWindowClientPart),				// widget_size (data part)
		MtfWindowClient::classInitialize,		// class_initialize
		0,										// class_part_initialize
		false,									// class inited
		(XtInitProc)initialize,					// initialize
		0,										// initialize_hook
		XtInheritRealize,						// realize
		action,									// actions
		XtNumber(action),						// num_actions
		0, 										// resources
		0, 										// num_resources
		NULLQUARK,								// xrm
		true,									// compress_motion
		XtExposeCompressMultiple,				// compress_exposure
		true,									// compress_enterleave
		false,									// visible_interest
		0, 										// destroy
		(XtWidgetProc)resize,					// resize
		(XtExposeProc)expose,					// expose
		0,										// set_values
		0, 										// set_values_hook
		XtInheritSetValuesAlmost,				// set_values_almost
		0, 										// get_values_hook
		XtInheritAcceptFocus,					// accept_focus
		XtVersionDontCheck,					// version
		0, 										// callback_private
		XtInheritTranslations,					// tm_table
		XtInheritQueryGeometry, 				// query_geometry
		XtInheritDisplayAccelerator,			// display_accelerator
		0 										// extension
	},
	// --- CompositeClassPart ---
	{
		gmgr,									// geometry_manager
		XtInheritChangeManaged,					// change_managed
		XtInheritInsertChild,					// insert_child
		XtInheritDeleteChild,					// delete_child
		0										// extension
	},
	// --- ConstraintClassPart ---
	{
		0,										// resources
		0,										// num_resources
		0,										// constraint_size
		0,										// initialize
		0,										// destroy
		0,										// set_values
		0										// extension
	},
	// --- XmManagerClassPart ---
	{
		XtInheritTranslations,					// translations
		0,										// syn_resources
		0,										// num_syn_resources
		0,										// syn_constraint_resources
		0,										// num_syn_constraint_resources
		XmInheritParentProcess,					// parent_process
		0										// extension
	},
	// --- XmBulletinBoardClassPart ---
	{
		false,									// always_install_accelerators
		0,										// geo_matrix_create
		XmInheritFocusMovedProc,				// focus_moved_proc
		0										// extension
	},
	// --- MtfWindowClientClassPart ---
	{
		0									// extension
	}
};

void MtfWindowClient::activate(MtfWindowClient *mtfObject, XEvent *xEvent, String *, Cardinal *)
{
	// This action occurs on the first "up-click" portion of a mouse click.

	// Match up zinc.
	ZafWindow *zafObject = GetZincObject(mtfObject);
	ZafEventStruct event(E_MOTIF, xEvent);
	zafObject->ConvertToZafEvent(event);
	event.type = L_END_SELECT;
	zafObject->Event(event);
}

void MtfWindowClient::arm(MtfWindowClient *mtfObject, XEvent *xEvent, String *, Cardinal *)
{
	// This action occurs on the first "down-click" portion of a mouse click.

	// Perform the motif arm.
	XmProcessTraversal((Widget)mtfObject, XmTRAVERSE_CURRENT);

	// Match up zinc.
	ZafWindow *zafObject = GetZincObject(mtfObject);
	ZafEventStruct event(E_MOTIF, xEvent);
	zafObject->ConvertToZafEvent(event);
	event.type = L_BEGIN_SELECT;
	zafObject->Event(event);
}

void MtfWindowClient::classInitialize()
{
	XmResolvePartOffsets((WidgetClass) &(MtfWindowClient::classRecord),
	 &(MtfWindowClient::offsets));
}

void MtfWindowClient::drag_drop(MtfWindowClient *mtfObject, XEvent *xEvent, String *, Cardinal *)
{
	// Begin the drag/drop operation.
	ZafEventStruct event(S_BEGIN_DRAG, xEvent);
	GetZincObject(mtfObject)->Event(event);
}

void MtfWindowClient::enter(MtfWindowClient *mtfObject, XEvent *xEvent, String *param, Cardinal *nparams)
{
	// Chain to the base class.
	XtCallActionProc((Widget)mtfObject, "ManagerEnter", xEvent, param, *nparams);
	if (xEvent->xcrossing.detail != NotifyNonlinearVirtual)
	{
		ZafEventStruct event(N_MOUSE_ENTER, xEvent);
		GetZincObject(mtfObject)->Event(event);
	}
}

void MtfWindowClient::expose(MtfWindowClient *mtfObject, XEvent *xEvent, Region xRegion)
{
	// Draw the object.
	ZafEventStruct event(E_MOTIF, xEvent);
	XRectangle xRect;
	XClipBox(xRegion, &xRect);
  	event.region.Assign(xRect.x, xRect.y, xRect.width, xRect.height, ZAF_PIXEL);
	GetZincObject(mtfObject)->Draw(event, E_MOTIF);
}

XtGeometryResult MtfWindowClient::gmgr(Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
{
	// ZAF automatically handles geometry of children.
	ZafWindowObject *zafObject = ZAF_NULLP(ZafWindowObject);
	XtVaGetValues(widget, XmNuserData, &zafObject, 0);
	if (zafObject)
	{
		request->x = widget->core.x = zafObject->zafRegion.left;
		request->y = widget->core.y = zafObject->zafRegion.top;
		request->width = widget->core.width = zafObject->zafRegion.Width();
		request->height = widget->core.height = zafObject->zafRegion.Height();
		*result = *request;
		if (request->request_mode & CWBorderWidth)
			widget->core.border_width = request->border_width;
	}
    return (XtGeometryYes);
}

void MtfWindowClient::initialize(MtfWindowClient *, MtfWindowClient *init, ArgList , Cardinal *)
{
	// Fix initialization problems.
	init->manager.has_focus = false;
}

void MtfWindowClient::leave(MtfWindowClient *mtfObject, XEvent *xEvent, String *param, Cardinal *nparams)
{
	// Perform the motif enter and match with zinc.
	XtCallActionProc((Widget)mtfObject, "ManagerLeave", xEvent, param, *nparams);
	if (xEvent->xcrossing.detail != NotifyNonlinearVirtual)
	{
		ZafEventStruct event(N_MOUSE_LEAVE, xEvent);
		GetZincObject(mtfObject)->Event(event);
	}
}

void MtfWindowClient::mouse(MtfWindowClient *mtfObject, XEvent *xEvent, String *, Cardinal *)
{
	// This event is received at the callback level.  Thus, the mouse
	// message has already passed through the window manager and must 
	// be interpreted as a logical event to prevent recursion.
	ZafWindowObject *zafObject = GetZincObject(mtfObject);
	ZafEventStruct event(E_MOTIF, xEvent);
	zafObject->ConvertToZafEvent(event);

	// Choose the proper message.
	if (xEvent->type == MotionNotify)
		event.type = L_CONTINUE_ESCAPE;
	else if (xEvent->xbutton.type == ButtonPress)
		event.type = L_BEGIN_ESCAPE;
	else if (xEvent->xbutton.type == ButtonRelease)
		event.type = L_END_ESCAPE;
	else
		event.type = L_CONTINUE_ESCAPE;
	zafObject->Event(event);
}

void MtfWindowClient::multi_activate(MtfWindowClient *, XEvent *, String *, Cardinal *)
{
	// This action occurs on the "up-click" portion of a mouse double-click.
	// Double-click actions are performed on the down-click so no actions
	// are performed.
}

void MtfWindowClient::multi_arm(MtfWindowClient *mtfObject, XEvent *xEvent, String *, Cardinal *)
{
	// This action occurs on the "down-click" portion of a mouse double-click.
	// Perform the motif multi-activate and zinc double-click.
	ZafWindow *zafObject = GetZincObject(mtfObject);
	ZafEventStruct event(E_MOTIF, xEvent);
	zafObject->ConvertToZafEvent(event);
	event.type = L_DOUBLE_CLICK;
	zafObject->Event(event);
}

void MtfWindowClient::resize(MtfWindowClient *mtfObject)
{
	GetZincObject(mtfObject)->Event(N_SIZE);
}

void MtfWindowClient::OverrideTranslations(void)
{
	// Override translations.
	XtTranslations translationTable = XtParseTranslationTable(translations);
	XtOverrideTranslations((Widget)this, translationTable);
}

