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

#include "m_win.hpp"
#include "m_popup.hpp"

static void popdown_callback(Widget *, ZafWindow *window, XEvent *, Boolean *)
{
	// Remove the menu from the window manager.
	ZafWindowManager *windowManager = window->windowManager;
	windowManager->Subtract(window);
}

// ----- ZafPopUpMenu -------------------------------------------------------

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafPopUpMenu::DrawBorder(ZafRegionStruct &region, ZafEventType ccode)
{
	// Defer to the base class.
	return (ZafWindowObject::DrawBorder(region, ccode));
}
#endif

ZafEventType ZafPopUpMenu::Event(const ZafEventStruct &event)
{
	// Check for zinc events.
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	// ----- Create messages -----
	case S_INITIALIZE:
		// This widget will be in the motif frame, not in the client area.
		ccode = ZafWindow::Event(event);
		if (parent)
			zafRegion.left = zafRegion.top = zafRegion.right = zafRegion.bottom = -1;
		break;

	case S_DEINITIALIZE:
	case S_REGISTER_OBJECT:
		ccode = ZafWindow::Event(event);
		break;

	case S_ADD_OBJECT:
	case S_SUBTRACT_OBJECT:
		if (parent)
			ccode = parent->Event(event);
		else
			ccode = ZafWindow::Event(event);
		break;

	// ----- Unknown or error messages -----
	default:
		ccode = parent ? ZafWindowObject::Event(event) : ZafWindow::Event(event);
		break;
	}

	// Return the control code.
	return (ccode);
}

void ZafPopUpMenu::GetClip(ZafWindowObject *object, ZafRegionStruct &clip, ZafRegionStruct &virtualRegion)
{
	// Defer to the base class.
	ZafWindowObject::GetClip(object, clip, virtualRegion);
}

ZafWindowObject *ZafPopUpMenu::Subtract(ZafWindowObject *object)
{
	// Defer to the base class.
	return (ZafWindow::Subtract(object));
}

// ----- OS Specific Functions ----------------------------------------------

ZafEventType ZafPopUpMenu::OSEvent(const ZafEventStruct &)
{
	return (S_ERROR);
}

OSWindowID ZafPopUpMenu::OSScreenID(ZafScreenIDType type) const
{
	// See if there is a menu shell.
	if (type == ZAF_SHELLID && screenID)
		return (XtParent(screenID));
	return (ZafWindowObject::OSScreenID(type));
}

void ZafPopUpMenu::OSRegisterObject(void)
{
	// Make sure there are menu items to register.
	if (!first)
		return;

	// Check for a popup shell.  The popup shell is located at the parent's
	// parent and is a menu shell widget.
	char *name = zafCodeSet->ConvertToOSString(stringID, 0, false);
	if (parent)
	{
		Widget frame = parent->parent->OSScreenID(ZAF_FRAMEID);
		Widget shell = XtVaCreatePopupShell(name,
			xmMenuShellWidgetClass, frame,
			// user information
			XmNuserData, this,
			// miscellaneous
			XmNwidth, 5,
			XmNheight, 5,
			XmNallowShellResize, true,
			XmNoverrideRedirect, true,
			0);

		// Create the popup menu.
		screenID = XtVaCreateWidget(name,
			xmRowColumnWidgetClass, shell,
			// user information
			XmNuserData, this,
			// miscellaneous
			XmNrowColumnType, XmMENU_PULLDOWN,
			XmNtearOffModel, XmTEAR_OFF_DISABLED,
			0);

		// Register the menu with it's parent.
		XtVaSetValues(parent->screenID, XmNsubMenuId, screenID, 0);
	}
	else
	{
		ZafRegionStruct osRegion = windowManager->ConvertToOSRegion(this);
		screenID = XtVaCreatePopupShell(name,
			xmMenuShellWidgetClass, ((ZafScreenDisplay *)display)->topLevelShell,
			// user information
			XmNuserData, this,
			// miscellaneous
			XmNx, osRegion.left,
			XmNy, osRegion.top,
			XmNwidth, 10,
			XmNheight, 10,
			XmNallowShellResize, true,
			XmNoverrideRedirect, true,
			0);

		// Register the callbacks.
		XtAddCallback(screenID, XmNpopdownCallback,
			(XtCallbackProc)popdown_callback, (XtPointer)this);

		// Create the popup menu.
		screenID = XtVaCreateWidget(name,
			xmRowColumnWidgetClass, screenID,
			// user information
			XmNuserData, this,
			// miscellaneous
			XmNrowColumnType, XmMENU_POPUP,
			0);
	}
}

void ZafPopUpMenu::OSSize(void)
{
	// Child menus do not need to be sized.
	if (!parent)
	{
		ZafRegionStruct newRegion = windowManager->ConvertToOSRegion(this, &zafRegion);
		XtMoveWidget(screenID, newRegion.left, newRegion.top);
		if (!XtIsManaged(screenID))
			XtManageChild(screenID);
	}
}

