home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
menu.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-07
|
26KB
|
877 lines
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
#if defined(__GNUC__)
#pragma implementation
#endif
#define MNEMONIC_CHAR '&' // For alt- functions
#if defined(__MS_WINDOWS__)
#include <windows.h>
#elif defined(__X_MOTIF__)
#include <Xm/RowColumn.h>
#include <Xm/CascadeB.h>
#include <Xm/PushB.h>
#include <Xm/CascadeBG.h>
#include <Xm/PushBG.h>
#include <Xm/Separator.h>
#endif
#include "ui/menu.h"
#include "ui/cntroler.h"
#include "ui/composit.h"
#include "base/binding.h"
#include "base/treewalk.h"
#if defined(__GNUC__) && __GNUC_MINOR__ >= 6
template class CL_Binding<UI_Menu>;
#endif
UI_MenuItem::UI_MenuItem (UI_Menu* container, const char*
label, UI_ViewID id)
: UI_SimpleVObject ((UI_CompositeVObject*) container->Parent(),
// --------------^^^^^^^^^^^^^^^^^^^^
// We can safely cast down, because the constructor of UI_Menu insists
// on a Composite for its parent.
UI_Rectangle (), id, -1),
_container (*container)
{
_SetTitle (label);
_ownModel = FALSE;
#if defined(__MS_WINDOWS__)
_handle = 0;
#elif defined(__OS2__)
_handle = 0;
#elif defined(__X_MOTIF__)
_xitemw = NULL;
#endif
}
UI_WindowClass UI_MenuItem::WindowClass () const
{
// This method is not used for widget creation, only for run-time type
// identification
#if defined(__MS_WINDOWS__)
return "";
#elif defined(__OS2__)
return NULL;
#elif defined (__X_MOTIF__)
return NULL;
#endif
}
bool UI_MenuItem::MakeVisualElement ()
{
#if defined(__MS_WINDOWS__)
// The actual visual element for a popup menu is created by the UI_Menu
// object, so if we are a popup, our handle is already set
return FALSE; // We don't register menu items under Windows
#elif defined(__OS2__)
return _handle ? TRUE : FALSE;
// Only non-leaf items have non-zero handles, and those are the ones we
// register.
#elif defined (__X_MOTIF__)
return TRUE; // We register all menu items under X
#endif
}
void UI_MenuItem::_PrivateInitialize ()
{
UI_SimpleVObject::_PrivateInitialize();
#if defined(__MS_WINDOWS__)
// Under Windows, the Controller maintains a map of menu id's
// for each window, and the MenuItemCreated method updates this map.
if (_id > 0 && !_Controller->MenuItemCreated (this))
CL_Error::Warning ("MenuItem constructor: duplicate view id %ld",
_id);
#endif
}
bool UI_MenuItem::DestroyVisualElement ()
{
#if defined (__MS_WINDOWS__)
if (_handle > 0) {
DestroyMenu (_handle);
return TRUE;
}
return FALSE;
#elif defined(__OS2__)
return UI_SimpleVObject::DestroyVisualElement ();
#elif defined (__X_MOTIF__)
if (_xwidget)
XtDestroyWidget (_xwidget);
if (_xitemw)
XtDestroyWidget (_xitemw);
_xitemw = _xwidget = 0; // So that the controller does not attempt
// destruction again
#endif
}
bool UI_MenuItem::Enable ()
{
_enabled = TRUE;
#if defined(__MS_WINDOWS__)
_SetState ();
return TRUE;
#elif defined(__OS2__)
WinSendMsg (_container.ViewHandle(), MM_SETITEMATTR,
MPFROM2SHORT (_id, TRUE), MPFROM2SHORT (MIA_DISABLED, 0));
return TRUE;
#elif defined(__X_MOTIF__)
if (_xitemw)
XtSetSensitive (_xitemw, TRUE);
return TRUE;
#endif
}
bool UI_MenuItem::Disable ()
{
_enabled = FALSE;
#if defined(__MS_WINDOWS__)
_SetState ();
return TRUE;
#elif defined(__OS2__)
WinSendMsg (_parentHandle, MM_SETITEMATTR,
MPFROM2SHORT (_id, TRUE),
MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED));
return TRUE;
#elif defined(__X_MOTIF__)
if (_xitemw)
XtSetSensitive (_xitemw, FALSE);
return TRUE;
#endif
}
#if defined (__MS_WINDOWS__)
void UI_MenuItem::_SetState ()
{
if (!_parentHandle)
return;
short pos = _container.Index(_id);
UINT state = MF_STRING;
if (_handle)
state |= MF_POPUP;
if (IsEnabled())
state |= MF_ENABLED;
else
state |= MF_GRAYED;
if (state & MF_POPUP) {
short count = GetMenuItemCount (_parentHandle);
for (short i = 0; i < count; i++)
if (_handle == GetSubMenu (_parentHandle, i)) {
ModifyMenu (_parentHandle, pos, state | MF_BYPOSITION,
_handle, _title);
break;
}
SetWindowPos (_container.Parent()->ViewHandle(),
NULL, 0, 0, 0, 0, SWP_SHOWWINDOW |
SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER); // Force re-draw
}
else
ModifyMenu (_parentHandle, _id, state, _id, _title);
DrawMenuBar (_container.ViewHandle());
}
#endif
bool UI_MenuItem::_TitleChanged (CL_Object&, long)
{
#if defined (__MS_WINDOWS__)
_SetState ();
return TRUE;
#elif defined(__OS2__)
CL_String title = _title;
title.Replace ("&", "~");
WinSendMsg (_container.ViewHandle(), MM_SETITEMTEXT, MPFROMSHORT (_id),
MPFROMP (title.AsPtr()));
return TRUE;
#elif defined (__X_MOTIF__)
if (!_xitemw)
return TRUE; // Not yet set up
SetLabel ();
XmUpdateDisplay (_xitemw);
return TRUE;
#endif
}
UI_ViewHandle UI_MenuItem::ViewHandle () const
{
#if defined (__MS_WINDOWS__)
return UI_VisualObject::ViewHandle ();
#elif defined(__OS2__)
return _handle;
#elif defined (__X_MOTIF__)
return UI_ViewHandle (_xitemw);
#endif
}
UI_MenuItem::~UI_MenuItem ()
{
#if defined(__MS_WINDOWS__)
_Controller->MenuItemDestroyed (this);
#endif
}
#if defined (__X_MOTIF__)
void UI_MenuItem::SetLabel ()
{
CL_String label = _title;
if (label == UIMenu_Separator)
return;
short mnemonic_pos = label.CharIndex (MNEMONIC_CHAR);
if (mnemonic_pos >= 0 && mnemonic_pos < label.Size()-1) {
label(mnemonic_pos,1) = ""; // Remove the mnemonic char
if (label[mnemonic_pos] == MNEMONIC_CHAR) // Two consecutive?
mnemonic_pos = -1;
}
XmString xmlabel = XmStringCreate ((char*) label.AsPtr(),
XmSTRING_DEFAULT_CHARSET);
Arg arg[2];
short argn = 0;
XtSetArg (arg[0], XmNlabelString, xmlabel); argn++;
if (mnemonic_pos >= 0) {
XtSetArg (arg[1], XmNmnemonic, label[mnemonic_pos]); argn++;
}
XtSetValues (_xitemw, arg, argn);
XmStringFree (xmlabel);
}
void UI_MenuItem::GetFocusCallback (Widget w, void *client, void *call)
{
UI_MenuItem *mi = (UI_MenuItem *) client;
_Controller->AddEvent (new UI_Event (Event_GetFocus, mi, mi));
}
void UI_MenuItem::LoseFocusCallback (Widget w, void *client, void *call)
{
UI_MenuItem *mi = (UI_MenuItem *) client;
_Controller->AddEvent (new UI_Event (Event_LoseFocus, mi, mi));
}
#include <iostream.h> // DEBUG
void UI_MenuItem::SelectionCallback (Widget w, void *client, void *call)
{
UI_MenuItem* mi = (UI_MenuItem *) client;
_Controller->AddEvent (new UI_Event (Event_Select, mi, mi));
}
#endif
// --------------------- UI_Menu methods -----------------------
#if defined(__OS2__)
#define ROOT_ID FID_MENU
#else
#define ROOT_ID 0
#endif
UI_Menu::UI_Menu (UI_CompositeVObject* parent, UI_MenuItemDescriptor* items)
: UI_VisualObject (parent, UI_Rectangle (), -1)
{
UI_MenuItem* root_item = new UI_MenuItem (this, "", ROOT_ID);
if (!root_item)
return;
_menuTree.NewRoot (ROOT_ID);
_menuTree.Root()->Content() = (long) root_item;
if (_BuildMenuSubtree (items, ROOT_ID) <= 0)
CL_Error::Warning ("UI_Menu constructor: no menu items to build!");
_focusItem = NULL;
}
UI_ViewID UI_Menu::RootID () const
{
return ROOT_ID;
}
static long _SeparatorIdCount = -3; // Hack to support separators
short UI_Menu::_BuildMenuSubtree (UI_MenuItemDescriptor* items,
UI_ViewID subtree_root)
{
if (!items)
return 0;
CL_IntegerTreeNode* root = _menuTree.Node (subtree_root);
if (!root)
return 0;
for (short n = 0; items[n].label != NULL; n++) {
UI_ViewID id;
if (CL_String (UIMenu_Separator) == items[n].label)
id = _SeparatorIdCount--;
else
id = items[n].id;
UI_MenuItem* new_itm = new UI_MenuItem
(this, items[n].label, id);
CL_IntegerTreeNode* node = _menuTree.AddChild (id, subtree_root);
if (node) {
node->Content() = (long) new_itm;
_BuildMenuSubtree (items[n].submenu, items[n].id);
}
else
CL_Error::Warning ("YACL: UI_Menu: invalid (duplicate?) "
"menu item id %ld", id);
}
return n;
}
bool UI_Menu::Add (UI_ViewID id, const char* label,
UI_ViewID parent_id, short rank)
{
if (id <= 0)
return FALSE; // Cannot add new root
CL_IntegerTreeNode* subtree_root = _menuTree.Node (parent_id);
if (!subtree_root)
return FALSE;
UI_MenuItem* new_itm = new UI_MenuItem (this, label, id);
CL_IntegerTreeNode* node = _menuTree.AddChild (id, parent_id, rank);
if (node) {
node->Content() = (long) new_itm;
if (ViewHandle())
_CreateMenuItemVisual (*node);
return TRUE;
}
return FALSE;
}
bool UI_Menu::AddSeparator (UI_ViewID parent_id, short rank)
{
CL_IntegerTreeNode* subtree_root = _menuTree.Node (parent_id);
if (!subtree_root)
return FALSE;
UI_ViewID id = _SeparatorIdCount--;
UI_MenuItem* new_itm = new UI_MenuItem (this, UIMenu_Separator, id);
CL_IntegerTreeNode* node = _menuTree.AddChild (id, parent_id, rank);
if (node) {
node->Content() = (long) new_itm;
if (ViewHandle())
_CreateMenuItemVisual (*node);
return TRUE;
}
return FALSE;
}
bool UI_Menu::Remove (UI_ViewID id)
{
CL_IntegerTreeNode* node = _menuTree.Node (id);
if (!node)
return FALSE;
UI_MenuItem* itm = (UI_MenuItem*) node->Content();
#if defined(__MS_WINDOWS__)
if (!node->IsLeaf()) {
short count = GetMenuItemCount (itm->_parentHandle);
for (short i = 0; i < count; i++)
if (itm->_handle == GetSubMenu (itm->_parentHandle, i)) {
RemoveMenu (itm->_parentHandle, i, MF_BYPOSITION);
break;
}
}
else
RemoveMenu (itm->_parentHandle, itm->_id, MF_BYCOMMAND);
DrawMenuBar (Parent()->ViewHandle());
CL_IntegerTreePostWalker walker (_menuTree.Node (id));
while (walker.More()) {
CL_IntegerTreeNode* node = walker.Next();
UI_MenuItem* itm = (UI_MenuItem*) node->Content();
if (itm) {
itm->Finalize ();
itm->DestroyVisualElement();
delete itm;
node->Content() = NULL; // Better safe than sorry
}
}
_menuTree.DestroySubtree (id);
// Don't use Application->Destroy because, under Windows, menu items are
// not registered with the Controller.
#elif defined(__X_MOTIF__)
_Application->Destroy (itm);
_menuTree.DestroySubtree (id);
#elif defined(__OS2__)
WinSendMsg (itm->_parentHandle, MM_DELETEITEM, MPFROM2SHORT (id, TRUE),
0);
CL_IntegerTreePostWalker walker (_menuTree.Node (id));
while (walker.More()) {
CL_IntegerTreeNode* node = walker.Next();
UI_MenuItem* itm = (UI_MenuItem*) node->Content();
if (itm) {
itm->Finalize ();
itm->DestroyVisualElement();
delete itm;
node->Content() = NULL; // Better safe than sorry
}
}
_menuTree.DestroySubtree (id);
#endif
return TRUE;
}
short UI_Menu::ChildCount (UI_ViewID id) const
{
CL_IntegerTreeNode* node = _menuTree.Node (id);
return node ? node->ChildCount() : -1;
}
UI_MenuItem* UI_Menu::Child (UI_ViewID id, short i) const
{
CL_IntegerTreeNode* node = _menuTree.Node (id);
if (!node)
return (UI_MenuItem*) NULL;
node = node->Child(i);
return (node ? (UI_MenuItem*) node->Content () : (UI_MenuItem*) NULL);
}
short UI_Menu::Index (UI_ViewID id) const
{
CL_IntegerTreeNode* node = _menuTree.Node (id);
return node ? node->IndexInParent() : -1;
}
UI_MenuItem* UI_Menu::operator [] (UI_ViewID id)
{
CL_IntegerTreeNode* node = _menuTree.Node (id);
return node ? ((UI_MenuItem*) node->Content()) : (UI_MenuItem*) NULL;
}
UI_WindowClass UI_Menu::WindowClass () const
{
// This method is not used for widget creation, only for run-time type
// identification
#if defined(__MS_WINDOWS__)
return "menu";
#elif defined(__OS2__)
return WC_MENU;
#elif defined (__X_MOTIF__)
return NULL;
#endif
}
#if defined(__MS_WINDOWS__)
bool UI_Menu::_CreateMenuItemVisual (CL_IntegerTreeNode& node)
{
UI_MenuItem* itm = (UI_MenuItem *) node.Content ();
CL_IntegerTreeNode* parent = node.Parent();
UI_MenuItem* parentItem = parent ? (UI_MenuItem*)
parent->Content() : 0;
if (parentItem && !parentItem->_handle) {
UI_MenuItem* gpItem = (UI_MenuItem*) parent->Parent()->Content();
UI_ViewHandle gpHandle = gpItem->_handle;
parentItem->_handle = CreatePopupMenu ();
ModifyMenu (gpHandle, parentItem->ViewID(),
MF_BYCOMMAND | MF_STRING | MF_POPUP,
parentItem->_handle, parentItem->Title());
DrawMenuBar (Parent()->ViewHandle());
}
UI_ViewHandle h = parent ? parentItem->ViewHandle() : 0;
itm->_parentHandle = h;
short position = node.IndexInParent();
if ( !node.IsLeaf () ) {
if (parent) {
// This is not the root. The root's handle is set by the
// MakeVisualElement method that is calling us.
itm->_handle = CreatePopupMenu ();
InsertMenu (h, position, MF_STRING | MF_POPUP | MF_BYPOSITION,
itm->_handle, itm->_title.AsPtr());
}
}
else {
if ( h ) {
if (CL_String (UIMenu_Separator) == itm->_title)
InsertMenu (h, position, MF_SEPARATOR, -1, 0);
else
InsertMenu (h, position, MF_STRING | MF_BYPOSITION,
itm->_id, itm->_title.AsPtr());
}
}
return TRUE;
}
#endif
#if defined(__OS2__)
bool UI_Menu::_CreateMenuItemVisual (CL_IntegerTreeNode& node)
{
UI_MenuItem* itm = (UI_MenuItem *) node.Content ();
CL_IntegerTreeNode* parent = node.Parent();
UI_MenuItem* parentItem = parent ? (UI_MenuItem*)
parent->Content() : 0;
HWND frame = WinQueryWindow (_parent->ViewHandle(), QW_PARENT);
HWND parentHandle = parentItem ? parentItem->ViewHandle() : frame;
if (!parent) {
itm->_handle = _handle;
itm->_parentHandle = 0;
}
short position = node.IndexInParent();
if (parent && position >= parent->ChildCount())
position = MIT_END;
MENUITEM menuItemStruct;
menuItemStruct.iPosition = position;
CL_String title = itm->Title();
if (title == UIMenu_Separator)
menuItemStruct.afStyle = MIS_SEPARATOR;
else {
title.Replace ("&", "~");
menuItemStruct.afStyle = MIS_TEXT;
if (!parentItem) {
menuItemStruct.afStyle |= MIS_SUBMENU;
menuItemStruct.hwndSubMenu = _handle;
}
else if (node.ChildCount()) {
menuItemStruct.afStyle |= MIS_SUBMENU;
menuItemStruct.hwndSubMenu = WinCreateWindow
(parentHandle, WC_MENU, title.AsPtr(),
WS_VISIBLE, 0, 0, 0, 0, parentHandle,
HWND_BOTTOM, _id, NULL, NULL);
}
else
menuItemStruct.hwndSubMenu = 0;
}
menuItemStruct.afAttribute = 0;
menuItemStruct.id = itm->ViewID();
menuItemStruct.hItem = 0;
WinSendMsg (parentHandle, MM_INSERTITEM, (MPARAM) &menuItemStruct,
(MPARAM) title.AsPtr());
itm->_handle = menuItemStruct.hwndSubMenu;
itm->_parentHandle = parentHandle;
WinSendMsg (frame, WM_UPDATEFRAME, (MPARAM) FCF_MENU, 0);
return TRUE;
}
#endif
#if defined(__X_MOTIF__)
bool UI_Menu::_CreateMenuItemVisual (CL_IntegerTreeNode& node)
{
UI_MenuItem* itm = (UI_MenuItem *) node.Content ();
CL_IntegerTreeNode* parent = node.Parent();
UI_MenuItem* parentItem = parent ? (UI_MenuItem*)
parent->Content() : 0;
if (parentItem && !parentItem->_xwidget) {
// This can happen if "node" is a newly-added leaf
Widget gpWidget = ((UI_MenuItem *)
parent->Parent()->Content())->_xwidget;
char *title = "menuitems";
parentItem->_xwidget = XmCreatePulldownMenu (gpWidget, title,
NULL, 0);
XtRealizeWidget (parentItem->_xwidget);
}
if ( !node.IsLeaf () ) {
if (parent) {
// This is not the root. The root's handle is set by the
// MakeVisualElement method that is calling us.
Widget parentw = ((UI_MenuItem *)
parent->Content())->_xwidget;
char *title = "menuitems";
itm->_xwidget = XmCreatePulldownMenu (parentw, title,
NULL, 0);
itm->_xitemw = XtVaCreateManagedWidget
((char*) itm->_title.AsPtr(),
xmCascadeButtonGadgetClass, parentw,
XmNsubMenuId, itm->_xwidget,
NULL);
itm->SetLabel ();
XtAddCallback (itm->_xitemw, XmNactivateCallback,
&(UI_MenuItem::GetFocusCallback), itm);
XtRealizeWidget (itm->_xwidget);
XtRealizeWidget (itm->_xitemw);
}
}
else {
Widget parentw = ((UI_MenuItem *) parent->Content ())->_xwidget;
CL_String instance_name = itm->InstanceName();
char* label = (char *) instance_name.AsPtr ();
UI_MenuItem* root_item = (UI_MenuItem *)
_menuTree.Node (ROOT_ID)->Content();
UI_MenuItem* parent_item = (UI_MenuItem *) parent->Content ();
struct _WidgetClassRec* wclass;
if (CL_String (UIMenu_Separator) != itm->_title)
wclass = (parent_item == root_item ? xmCascadeButtonGadgetClass:
xmPushButtonGadgetClass);
else
wclass = xmSeparatorWidgetClass;
parentw = (parent_item == root_item ? _xwidget : parentw);
if ( parent_item == root_item ) {
itm->_xitemw = XtVaCreateManagedWidget
(label, wclass, parentw, NULL);
if (wclass != xmSeparatorWidgetClass) {
XtAddCallback (itm->_xitemw, XmNactivateCallback,
&(UI_MenuItem::SelectionCallback), itm);
itm->SetLabel ();
}
XtRealizeWidget (itm->_xitemw);
}
else {
itm->_xitemw = XtCreateManagedWidget
(label, wclass, parentw, NULL, 0);
if (wclass != xmSeparatorWidgetClass) {
XtAddCallback (itm->_xitemw, XmNarmCallback,
&(UI_MenuItem::GetFocusCallback), itm);
XtAddCallback (itm->_xitemw, XmNdisarmCallback,
&(UI_MenuItem::LoseFocusCallback), itm);
XtAddCallback (itm->_xitemw, XmNactivateCallback,
&(UI_MenuItem::SelectionCallback), itm);
itm->SetLabel ();
}
XtRealizeWidget (itm->_xitemw);
}
}
return TRUE;
}
#endif
bool UI_Menu::HandleEvent (UI_Event* e)
{
if (e->Type() == Event_LoseFocus)
_focusItem = NULL;
return ProcessEvent (e);
}
bool UI_Menu::MakeVisualElement ()
{
return UI_VisualObject::MakeVisualElement ();
}
bool UI_Menu::DestroyVisualElement ()
{
#if defined(__MS_WINDOWS__)
// We need to walk the tree and destroy the menu items explicitly here;
// Under MS-Windows, this is
// because menu items are not registered with the Controller.
CL_IntegerTreePostWalker walker (_menuTree.Root());
for (walker.Reset(); walker.More(); ) {
UI_MenuItem* m = (UI_MenuItem*) walker.Next()->Content();
m->DestroyVisualElement();
delete m;
}
#elif defined(__OS2__)
// Non-leaf menu items will be destroyed by the Controller, but we do
// need to destroy the menu bar or popup menu.
WinDestroyWindow (_handle);
#endif
return FALSE;
}
UI_Menu::~UI_Menu()
{
}
#if defined(__MS_WINDOWS__) || defined(__OS2__)
void UI_Menu::MoveFocusTo (UI_MenuItem* itm)
{
if (_focusItem != itm)
_focusItem = itm;
}
#endif
// ----------------- UI_MenuBar methods -------------------------
UI_MenuBar::UI_MenuBar (UI_CompositeVObject* parent,
UI_MenuItemDescriptor* item)
: UI_Menu (parent, item)
{
#if defined(__OS2__)
_style = MS_ACTIONBAR | WS_VISIBLE;
#endif
parent->UseMenuBar (this);
}
bool UI_MenuBar::MakeVisualElement ()
{
#if defined (__MS_WINDOWS__)
UI_MenuItem* root_item = (UI_MenuItem*)
_menuTree.Node (ROOT_ID)->Content();
root_item->_handle = CreateMenu ();
_handle = root_item->_handle;
#elif defined(__OS2__)
_id = FID_MENU;
HWND frame = WinQueryWindow (_parent->ViewHandle(), QW_PARENT);
WinSendMsg (frame, WM_UPDATEFRAME, (MPARAM) FCF_MENU, 0);
_handle = WinCreateWindow
(frame, WC_MENU, "", _style,
0, 0, 0, 0, frame, HWND_TOP, _id, NULL, NULL);
#elif defined (__X_MOTIF__)
UI_MenuItem* root_item = (UI_MenuItem*)
_menuTree.Node (ROOT_ID)->Content();
root_item->_xwidget = XmCreateMenuBar ((Widget)_parent->ViewHandle (),
"menubar", NULL, 0);
root_item->_xitemw = 0;
_xwidget = root_item->_xwidget;
XtManageChild (root_item->_xwidget);
XtRealizeWidget (root_item->_xwidget);
#endif
CL_IntegerTreePreWalker walk (_menuTree.Root());
while (walk.More()) {
CL_IntegerTreeNode* node = walk.Next();
_CreateMenuItemVisual (*node);
}
_created = TRUE;
#if defined(__OS2__)
WinSendMsg (frame, WM_UPDATEFRAME, (MPARAM) FCF_MENU, 0);
#endif
return TRUE;
}
UI_PopupMenu::UI_PopupMenu (UI_CompositeVObject* parent,
UI_MenuItemDescriptor* item)
: UI_Menu (parent, item)
{
_visible = FALSE; // Initially invisible
}
UI_PopupMenu::~UI_PopupMenu ()
{
}
bool UI_PopupMenu::MakeVisualElement ()
{
UI_MenuItem* root_item = (UI_MenuItem*)
_menuTree.Node (ROOT_ID)->Content();
#if defined (__MS_WINDOWS__)
root_item->_handle = CreatePopupMenu ();
_handle = root_item->_handle;
#elif defined(__OS2__)
_style = WS_VISIBLE;
UI_ViewHandle parentHandle = _parent->ViewHandle();
_handle = WinCreateWindow
(parentHandle, WC_MENU, "", _style,
0, 0, 0, 0, parentHandle, HWND_TOP, _id, NULL, NULL);
root_item->_handle = _handle;
#elif defined (__X_MOTIF__)
root_item->_visible = FALSE;
root_item->_xwidget = XmCreatePopupMenu ((Widget)_parent->ViewHandle (),
NULL, NULL, 0);
root_item->_xitemw = 0;
_xwidget = root_item->_xwidget;
XtRealizeWidget (root_item->_xwidget);
#endif
CL_IntegerTreePreWalker walk (_menuTree.Root());
while (walk.More()) {
CL_IntegerTreeNode* node = walk.Next();
_CreateMenuItemVisual (*node);
}
_created = TRUE;
return TRUE;
}
bool UI_PopupMenu::ShowAt (const UI_Point& p)
{
UI_ViewHandle parentHandle = _parent->ViewHandle();
#if defined(__MS_WINDOWS__)
UI_Point q = p + _parent->ClientArea().Origin();
return TrackPopupMenu (_handle, TPM_LEFTALIGN, q.XCoord(), q.YCoord(), 0,
parentHandle, NULL);
#elif defined(__OS2__)
UI_Point q = p; // + _parent->ClientArea().Origin();
WinPopupMenu (parentHandle, parentHandle, _handle, q.XCoord(),
_YACLWindowHeight (parentHandle) - q.YCoord() - 1,
0, PU_MOUSEBUTTON2 | PU_KEYBOARD | PU_MOUSEBUTTON1);
return TRUE;
#elif defined(__X_MOTIF__)
Position x, y;
XtTranslateCoords (parentHandle, p.XCoord(), p.YCoord(), &x, &y);
XtVaSetValues (_xwidget, XtNx, x, XtNy, y, NULL);
XtManageChild (_xwidget);
return TRUE;
#endif
}