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

#include <z_popup.hpp>
#include <w_app.hpp>

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

ZafEventType ZafPopUpMenu::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;

	if (ccode == E_OSEVENT)
		return ZafPopUpMenu::OSEvent(event);

	switch (ccode)
	{
	case S_INITIALIZE:
	case S_DEINITIALIZE:
	case S_REGISTER_OBJECT:
		ZafWindowObject::Event(event);
		BroadcastEvent(event);
		break;

	// Needed if the popup menu is added directly to the window manager.
	case S_DESTROY:
		if (screenID)
		{
			if (SystemObject())
				DestroyMenu((HMENU)screenID);
			Event(S_DEINITIALIZE);
		}
		break;

	case S_CURRENT:
		ccode = ZafWindowObject::Event(event);
		Event(N_CURRENT);
		break;

	case S_NON_CURRENT:
		// NotifyFocus() is not used by menus... propegate the message.
		if (current && Current()->Focus())
			Current()->Event(event);
		SetCurrent(ZAF_NULLP(ZafWindowObject));
		Event(N_NON_CURRENT);
		ccode = ZafWindowObject::Event(event);
		break;

	case S_CREATE:
		Event(S_INITIALIZE);
		Event(S_REGISTER_OBJECT);
		if (!parent && next)
		{
//??? Pop up menus should have a control loop similar to dialogs.
			// Attach the pop-up menu directly to the screen.

			HWND hwndOwner = Next()->OSScreenID(ZAF_FRAMEID);

			// Process the menu.
			UINT flags = TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
			TrackPopupMenu((HMENU)screenID, flags, zafRegion.left,
				zafRegion.top, 0, hwndOwner, ZAF_NULLP(RECT));

			// Flush the window's queue to force processing of
			// the WM_COMMAND message.
			MSG msg;
			while (PeekMessage(&msg, hwndOwner, WM_COMMAND, WM_COMMAND, PM_REMOVE))
				DispatchMessage(&msg);

			eventManager->Put(S_CLOSE_TEMPORARY, Q_BEGIN);
		}
		break;

	case N_CLOSE:
		// Allow the pop-up to be closed.
		ccode = 0;
		break;

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

	default:
		ccode = ZafWindowObject::Event(event);
		break;
	}

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

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

ZafEventType ZafPopUpMenu::OSEvent(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;

	switch (event.osEvent.message)
	{
	case WM_COMMAND:
		ccode = ZafWindow::OSEvent(event);
		break;

	case WM_MENUSELECT:
		{
#if defined(ZAF_WIN32)
		UINT itemID = (UINT)LOWORD(event.osEvent.wParam);
		UINT flags = (UINT)HIWORD(event.osEvent.wParam);
		HWND hMenu = (HWND)event.osEvent.lParam;
#else
		WORD itemID = event.osEvent.wParam;
		WORD flags = LOWORD(event.osEvent.lParam);
		HWND hMenu = (HWND)HIWORD(event.osEvent.lParam);
#endif
		ZafPopUpItem *currentItem = DynamicPtrCast(Current(), ZafPopUpItem);
		if (hMenu == screenID)
		{
			// Find the selected item.
			ZafWindowObject *selectedItem;
			for (selectedItem = First(); selectedItem; selectedItem = selectedItem->Next())
			{
				ZafPopUpItem *item = DynamicPtrCast(selectedItem, ZafPopUpItem);
				if (item)
				{
					if (flags & MF_POPUP)
					{
#if defined(ZAF_WIN32)
						if (Index(item) == (int)itemID)
							break;
#else
						if ((HMENU)item->menu.screenID == (HMENU)itemID)
							break;
#endif
					}
					else if ((UINT)item->NumberID() == itemID)
						break;
				}
			}

			// Adjust the focus at the menu level.
			if (!focus)
				Event(ZafEventStruct(S_CURRENT));
			else if (currentItem && currentItem->menu.Focus())
				currentItem->menu.Event(ZafEventStruct(S_NON_CURRENT));

			// Adjust the focus at the item level.
			if (selectedItem && !selectedItem->Focus())
			{
				if (currentItem && currentItem->Focus())
					currentItem->Event(ZafEventStruct(S_NON_CURRENT));
				SetCurrent(selectedItem);
				selectedItem->Event(ZafEventStruct(S_CURRENT));
			}
		}
		else if (currentItem)
			currentItem->menu.Event(event);
		}
		break;
	
	default:
		ccode = ZafWindowObject::OSEvent(event);
	}

	return (ccode);
}


void ZafPopUpMenu::OSRegisterObject(void)
{
	if (First())
		screenID = (HWND)CreatePopupMenu();
}

// ----- Stubs --------------------------------------------------------------

OSWindowID ZafPopUpMenu::OSScreenID(ZafScreenIDType) const
{
	return (screenID);
}

void ZafPopUpMenu::OSSize(void)
{
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafPopUpMenu::DrawBorder(ZafRegionStruct &, ZafEventType ccode)
{
	return (ccode);
}
#endif

void ZafPopUpMenu::GetClip(ZafWindowObject *, ZafRegionStruct &, ZafRegionStruct &)
{
}

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