1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxMenu, wxMenuBar, wxMenuItem 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 // ============================================================================ 
  14 // headers & declarations 
  15 // ============================================================================ 
  21 #pragma implementation "menu.h" 
  22 #pragma implementation "menuitem.h" 
  26 #include "wx/menuitem.h" 
  31 #include "wx/settings.h" 
  34 #include <Xm/LabelG.h> 
  35 #include <Xm/CascadeBG.h> 
  36 #include <Xm/CascadeB.h> 
  37 #include <Xm/SeparatoG.h> 
  38 #include <Xm/PushBG.h> 
  39 #include <Xm/ToggleB.h> 
  40 #include <Xm/ToggleBG.h> 
  41 #include <Xm/RowColumn.h> 
  43 #include "wx/motif/private.h" 
  45 // other standard headers 
  46 // ---------------------- 
  49 #if !USE_SHARED_LIBRARY 
  50 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
) 
  51 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
) 
  54 // ============================================================================ 
  56 // ============================================================================ 
  60 // Construct a menu with optional title (then use append) 
  61 wxMenu::wxMenu(const wxString
& title
, const wxFunction func
) 
  64     m_parent 
= (wxEvtHandler
*) NULL
; 
  65     m_eventHandler 
= this; 
  68     m_pInvokingWindow 
= NULL
; 
  70     //// Motif-specific members 
  72     m_menuWidget 
= (WXWidget
) NULL
; 
  73     m_popupShell 
= (WXWidget
) NULL
; 
  74     m_buttonWidget 
= (WXWidget
) NULL
; 
  76     m_topLevelMenu  
= (wxMenu
*) NULL
; 
  77     m_ownedByMenuBar 
= FALSE
; 
  78     m_menuParent 
= (wxMenu
*) NULL
; 
  79     m_clientData 
= (void*) NULL
; 
  83         Append(ID_SEPARATOR
, m_title
) ; 
  86     m_backgroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENU
); 
  87     m_foregroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENUTEXT
); 
  88     m_font 
= wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
); 
  93 // The wxWindow destructor will take care of deleting the submenus. 
 104     // Not sure if this is right 
 105     if (m_menuParent 
&& m_menuBar
) 
 111     wxNode 
*node 
= m_menuItems
.First(); 
 114         wxMenuItem 
*item 
= (wxMenuItem 
*)node
->Data(); 
 117         if (item->GetSubMenu()) 
 118         item->DeleteSubMenu(); 
 121         wxNode 
*next 
= node
->Next(); 
 133 // function appends a new item or submenu to the menu 
 134 void wxMenu::Append(wxMenuItem 
*pItem
) 
 136     wxCHECK_RET( pItem 
!= NULL
, "can't append NULL item to the menu" ); 
 138     m_menuItems
.Append(pItem
); 
 141         pItem
->CreateItem (m_menuWidget
, m_menuBar
, m_topLevelMenu
);    // this is a dynamic Append 
 146 void wxMenu::AppendSeparator() 
 148     Append(new wxMenuItem(this, ID_SEPARATOR
)); 
 152 // N.B.: difference between old and new code. 
 153 // Old code stores subMenu in 'children' for later deletion, 
 154 // as well as in m_menuItems, whereas we only store it in 
 155 // m_menuItems here. What implications does this have? 
 157 void wxMenu::Append(int id
, const wxString
& label
, wxMenu 
*subMenu
,  
 158                     const wxString
& helpString
) 
 160     Append(new wxMenuItem(this, id
, label
, helpString
, FALSE
, subMenu
)); 
 162     subMenu
->m_topLevelMenu 
= m_topLevelMenu
; 
 165 // Ordinary menu item 
 166 void wxMenu::Append(int id
, const wxString
& label
,  
 167                     const wxString
& helpString
, bool checkable
) 
 169     // 'checkable' parameter is useless for Windows. 
 170     Append(new wxMenuItem(this, id
, label
, helpString
, checkable
)); 
 173 void wxMenu::Delete(int id
) 
 179     for (pos 
= 0, node 
= m_menuItems
.First(); node
; node 
= node
->Next(), pos
++)  
 181         item 
= (wxMenuItem 
*)node
->Data(); 
 182         if (item
->GetId() == id
) 
 189     item
->DestroyItem(TRUE
); 
 191     // See also old code - don't know if this is needed (seems redundant). 
 193     if (item->GetSubMenu()) { 
 194     item->subMenu->top_level_menu = item->GetSubMenu(); 
 195     item->subMenu->window_parent = NULL; 
 196     children->DeleteObject(item->GetSubMenu()); 
 200     m_menuItems
.DeleteNode(node
); 
 204 void wxMenu::Enable(int id
, bool flag
) 
 206     wxMenuItem 
*item 
= FindItemForId(id
); 
 207     wxCHECK_RET( item 
!= NULL
, "can't enable non-existing menu item" ); 
 212 bool wxMenu::Enabled(int Id
) const 
 214     wxMenuItem 
*item 
= FindItemForId(Id
); 
 215     wxCHECK( item 
!= NULL
, FALSE 
); 
 217     return item
->IsEnabled(); 
 220 void wxMenu::Check(int Id
, bool Flag
) 
 222     wxMenuItem 
*item 
= FindItemForId(Id
); 
 223     wxCHECK_RET( item 
!= NULL
, "can't get status of non-existing menu item" ); 
 228 bool wxMenu::Checked(int id
) const 
 230     wxMenuItem 
*item 
= FindItemForId(id
); 
 231     wxCHECK( item 
!= NULL
, FALSE 
); 
 233     return item
->IsChecked(); 
 236 void wxMenu::SetTitle(const wxString
& label
) 
 240     wxNode 
*node 
= m_menuItems
.First (); 
 244     wxMenuItem 
*item 
= (wxMenuItem 
*) node
->Data (); 
 245     Widget widget 
= (Widget
) item
->GetButtonWidget(); 
 249     XmString title_str 
= XmStringCreateSimple ((char*) (const char*) label
); 
 250     XtVaSetValues (widget
, 
 251         XmNlabelString
, title_str
, 
 253     // TODO: should we delete title_str now? 
 256 const wxString 
wxMenu::GetTitle() const 
 261 void wxMenu::SetLabel(int id
, const wxString
& label
) 
 263     wxMenuItem 
*item 
= FindItemForId(id
); 
 264     if (item 
== (wxMenuItem
*) NULL
) 
 267     item
->SetLabel(label
); 
 270 wxString 
wxMenu::GetLabel(int id
) const 
 272     wxMenuItem 
*it 
= NULL
; 
 273     WXWidget w 
= FindMenuItem (id
, &it
); 
 278         XtVaGetValues ((Widget
) w
, 
 279             XmNlabelString
, &text
, 
 282         if (XmStringGetLtoR (text
, XmSTRING_DEFAULT_CHARSET
, &s
)) 
 291             return wxEmptyString
; 
 295         return wxEmptyString
; 
 298 // Finds the item id matching the given string, -1 if not found. 
 299 int wxMenu::FindItem (const wxString
& itemString
) const 
 303     wxStripMenuCodes ((char *)(const char *)itemString
, buf1
); 
 305     for (wxNode 
* node 
= m_menuItems
.First (); node
; node 
= node
->Next ()) 
 307         wxMenuItem 
*item 
= (wxMenuItem 
*) node
->Data (); 
 308         if (item
->GetSubMenu()) 
 310             int ans 
= item
->GetSubMenu()->FindItem(itemString
); 
 314         if ( !item
->IsSeparator() ) 
 316             wxStripMenuCodes((char *)item
->GetName().c_str(), buf2
); 
 317             if (strcmp(buf1
, buf2
) == 0) 
 318                 return item
->GetId(); 
 325 wxMenuItem 
*wxMenu::FindItemForId(int itemId
, wxMenu 
** itemMenu
) const 
 329     for (wxNode 
* node 
= m_menuItems
.First (); node
; node 
= node
->Next ()) 
 331         wxMenuItem 
*item 
= (wxMenuItem 
*) node
->Data (); 
 333         if (item
->GetId() == itemId
) 
 336                 *itemMenu 
= (wxMenu 
*) this; 
 340         if (item
->GetSubMenu()) 
 342             wxMenuItem 
*ans 
= item
->GetSubMenu()->FindItemForId (itemId
, itemMenu
); 
 353 void wxMenu::SetHelpString(int itemId
, const wxString
& helpString
) 
 355     wxMenuItem 
*item 
= FindItemForId (itemId
); 
 357         item
->SetHelp(helpString
); 
 360 wxString 
wxMenu::GetHelpString (int itemId
) const 
 362     wxMenuItem 
*item 
= FindItemForId (itemId
); 
 364     return (item 
== NULL
) ? str 
: item
->GetHelp(); 
 367 void wxMenu::ProcessCommand(wxCommandEvent 
& event
) 
 369     bool processed 
= FALSE
; 
 374         (void) (*(m_callback
)) (*this, event
); 
 378     // Try the menu's event handler 
 379     if ( !processed 
&& GetEventHandler()) 
 381         processed 
= GetEventHandler()->ProcessEvent(event
); 
 383     // Try the window the menu was popped up from (and up 
 384     // through the hierarchy) 
 385     if ( !processed 
&& GetInvokingWindow()) 
 386     processed 
= GetInvokingWindow()->ProcessEvent(event
); 
 389 // Update a menu and all submenus recursively. 
 390 // source is the object that has the update event handlers 
 391 // defined for it. If NULL, the menu or associated window 
 393 void wxMenu::UpdateUI(wxEvtHandler
* source
) 
 395   if (!source 
&& GetInvokingWindow()) 
 396     source 
= GetInvokingWindow()->GetEventHandler(); 
 398     source 
= GetEventHandler(); 
 402   wxNode
* node 
= GetItems().First(); 
 405     wxMenuItem
* item 
= (wxMenuItem
*) node
->Data(); 
 406     if ( !item
->IsSeparator() ) 
 408       wxWindowID id 
= item
->GetId(); 
 409       wxUpdateUIEvent 
event(id
); 
 410       event
.SetEventObject( source 
); 
 412       if (source
->ProcessEvent(event
)) 
 414         if (event
.GetSetText()) 
 415           SetLabel(id
, event
.GetText()); 
 416         if (event
.GetSetChecked()) 
 417           Check(id
, event
.GetChecked()); 
 418         if (event
.GetSetEnabled()) 
 419           Enable(id
, event
.GetEnabled()); 
 422       if (item
->GetSubMenu()) 
 423         item
->GetSubMenu()->UpdateUI(source
); 
 429 bool wxWindow::PopupMenu(wxMenu 
*menu
, int x
, int y
) 
 431     Widget widget 
= (Widget
) GetMainWidget(); 
 433     /* The menuId field seems to be usused, so we'll use it to 
 434     indicate whether a menu is popped up or not: 
 435     0: Not currently created as a popup 
 436     -1: Created as a popup, but not active 
 440     if (menu
->GetParent() && (menu
->GetId() != -1)) 
 443     if (menu
->GetMainWidget()) { 
 444         menu
->DestroyMenu(TRUE
); 
 447     wxWindow 
*parent 
= this; 
 449     menu
->SetId(1); /* Mark as popped-up */ 
 450     menu
->CreateMenu(NULL
, widget
, menu
); 
 451     menu
->SetInvokingWindow(this); 
 455     //  menu->SetParent(parent); 
 456     //  parent->children->Append(menu);  // Store menu for later deletion 
 458     Widget menuWidget 
= (Widget
) menu
->GetMainWidget(); 
 466     if (this->IsKindOf(CLASSINFO(wxCanvas))) 
 468     wxCanvas *canvas = (wxCanvas *) this; 
 469     deviceX = canvas->GetDC ()->LogicalToDeviceX (x); 
 470     deviceY = canvas->GetDC ()->LogicalToDeviceY (y); 
 474     Display 
*display 
= XtDisplay (widget
); 
 475     Window rootWindow 
= RootWindowOfScreen (XtScreen((Widget
)widget
)); 
 476     Window thisWindow 
= XtWindow (widget
); 
 478     XTranslateCoordinates (display
, thisWindow
, rootWindow
, (int) deviceX
, (int) deviceY
, 
 479         &rootX
, &rootY
, &childWindow
); 
 481     XButtonPressedEvent event
; 
 482     event
.type 
= ButtonPress
; 
 488     event
.x_root 
= rootX
; 
 489     event
.y_root 
= rootY
; 
 491     XmMenuPosition (menuWidget
, &event
); 
 492     XtManageChild (menuWidget
); 
 498 wxMenuBar::wxMenuBar() 
 500     m_eventHandler 
= this; 
 504     m_menuBarFrame 
= NULL
; 
 505     m_mainWidget 
= (WXWidget
) NULL
; 
 506     m_backgroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENU
); 
 507     m_foregroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENUTEXT
); 
 508     m_font 
= wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
); 
 511 wxMenuBar::wxMenuBar(long WXUNUSED(style
)) 
 513     m_eventHandler 
= this; 
 517     m_menuBarFrame 
= NULL
; 
 518     m_mainWidget 
= (WXWidget
) NULL
; 
 519     m_backgroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENU
); 
 520     m_foregroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENUTEXT
); 
 521     m_font 
= wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
); 
 524 wxMenuBar::wxMenuBar(int n
, wxMenu 
*menus
[], const wxString titles
[]) 
 526     m_eventHandler 
= this; 
 529     m_titles 
= new wxString
[n
]; 
 531     for ( i 
= 0; i 
< n
; i
++ ) 
 532         m_titles
[i
] = titles
[i
]; 
 533     m_menuBarFrame 
= NULL
; 
 534     m_backgroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENU
); 
 535     m_foregroundColour 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENUTEXT
); 
 536     m_font 
= wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
); 
 539 wxMenuBar::~wxMenuBar() 
 542     for (i 
= 0; i 
< m_menuCount
; i
++) 
 550 // Must only be used AFTER menu has been attached to frame, 
 551 // otherwise use individual menus to enable/disable items 
 552 void wxMenuBar::Enable(int id
, bool flag
) 
 554     wxMenu 
*itemMenu 
= NULL
; 
 555     wxMenuItem 
*item 
= FindItemForId(id
, &itemMenu
) ; 
 561 void wxMenuBar::EnableTop(int pos
, bool flag
) 
 566 // Must only be used AFTER menu has been attached to frame, 
 567 // otherwise use individual menus 
 568 void wxMenuBar::Check(int id
, bool flag
) 
 570     wxMenu 
*itemMenu 
= NULL
; 
 571     wxMenuItem 
*item 
= FindItemForId(id
, &itemMenu
) ; 
 575     if (!item
->IsCheckable()) 
 581 bool wxMenuBar::Checked(int id
) const 
 583     wxMenu 
*itemMenu 
= NULL
; 
 584     wxMenuItem 
*item 
= FindItemForId(id
, &itemMenu
) ; 
 588     return item
->IsChecked(); 
 591 bool wxMenuBar::Enabled(int id
) const 
 593     wxMenu 
*itemMenu 
= NULL
; 
 594     wxMenuItem 
*item 
= FindItemForId(id
, &itemMenu
) ; 
 598     return item
->IsEnabled(); 
 601 void wxMenuBar::SetLabel(int id
, const wxString
& label
) 
 603     wxMenu 
*itemMenu 
= NULL
; 
 604     wxMenuItem 
*item 
= FindItemForId(id
, &itemMenu
) ; 
 609     item
->SetLabel(label
); 
 612 wxString 
wxMenuBar::GetLabel(int id
) const 
 614     wxMenu 
*itemMenu 
= NULL
; 
 615     wxMenuItem 
*item 
= FindItemForId(id
, &itemMenu
) ; 
 620     return item
->GetLabel(); 
 623 void wxMenuBar::SetLabelTop(int pos
, const wxString
& label
) 
 625     wxASSERT( (pos 
< m_menuCount
) ); 
 627     Widget w 
= (Widget
) m_menus
[pos
]->GetButtonWidget(); 
 630         XmString label_str 
= XmStringCreateSimple ((char*) (const char*) label
); 
 632             XmNlabelString
, label_str
, 
 634         XmStringFree (label_str
); 
 638 wxString 
wxMenuBar::GetLabelTop(int pos
) const 
 640     wxASSERT( (pos 
< m_menuCount
) ); 
 642     Widget w 
= (Widget
) m_menus
[pos
]->GetButtonWidget(); 
 648             XmNlabelString
, &text
, 
 651         if (XmStringGetLtoR (text
, XmSTRING_DEFAULT_CHARSET
, &s
)) 
 659             return wxEmptyString
; 
 663         return wxEmptyString
; 
 667 bool wxMenuBar::OnDelete(wxMenu 
*menu
, int pos
) 
 669     // Only applies to dynamic deletion (when set in frame) 
 673     menu
->DestroyMenu(TRUE
); 
 677 bool wxMenuBar::OnAppend(wxMenu 
*menu
, const char *title
) 
 679     // Only applies to dynamic append (when set in frame) 
 683     // Probably should be an assert here 
 684     if (menu
->GetParent()) 
 687     // Has already been appended 
 688     if (menu
->GetButtonWidget()) 
 691     WXWidget w 
= menu
->CreateMenu(this, GetMainWidget(), menu
, title
, TRUE
); 
 692     menu
->SetButtonWidget(w
); 
 697 void wxMenuBar::Append (wxMenu 
* menu
, const wxString
& title
) 
 699     if (!OnAppend(menu
, title
)) 
 703     wxMenu 
**new_menus 
= new wxMenu 
*[m_menuCount
]; 
 704     wxString 
*new_titles 
= new wxString
[m_menuCount
]; 
 707     for (i 
= 0; i 
< m_menuCount 
- 1; i
++) 
 709         new_menus
[i
] = m_menus
[i
]; 
 711         new_titles
[i
] = m_titles
[i
]; 
 720     m_titles 
= new_titles
; 
 722     m_menus
[m_menuCount 
- 1] = (wxMenu 
*)menu
; 
 723     m_titles
[m_menuCount 
- 1] = title
; 
 725     menu
->SetMenuBar(this); 
 726     menu
->SetParent(this); 
 729 void wxMenuBar::Delete(wxMenu 
* menu
, int i
) 
 736         for (ii 
= 0; ii 
< m_menuCount
; ii
++) 
 738             if (m_menus
[ii
] == menu
) 
 741         if (ii 
>= m_menuCount
) 
 745         if (ii 
< 0 || ii 
>= m_menuCount
) 
 750     if (!OnDelete(menu
, ii
)) 
 753     menu
->SetParent((wxEvtHandler
*) NULL
); 
 756     for (j 
= ii
; j 
< m_menuCount
; j
++) 
 758         m_menus
[j
] = m_menus
[j 
+ 1]; 
 759         m_titles
[j
] = m_titles
[j 
+ 1]; 
 763 // Find the menu menuString, item itemString, and return the item id. 
 764 // Returns -1 if none found. 
 765 int wxMenuBar::FindMenuItem (const wxString
& menuString
, const wxString
& itemString
) const 
 769     wxStripMenuCodes ((char *)(const char *)menuString
, buf1
); 
 771     for (i 
= 0; i 
< m_menuCount
; i
++) 
 773         wxStripMenuCodes ((char *)(const char *)m_titles
[i
], buf2
); 
 774         if (strcmp (buf1
, buf2
) == 0) 
 775             return m_menus
[i
]->FindItem (itemString
); 
 780 wxMenuItem 
*wxMenuBar::FindItemForId (int id
, wxMenu 
** itemMenu
) const 
 785     wxMenuItem 
*item 
= NULL
; 
 787     for (i 
= 0; i 
< m_menuCount
; i
++) 
 788         if ((item 
= m_menus
[i
]->FindItemForId (id
, itemMenu
))) 
 793 void wxMenuBar::SetHelpString (int id
, const wxString
& helpString
) 
 796     for (i 
= 0; i 
< m_menuCount
; i
++) 
 798         if (m_menus
[i
]->FindItemForId (id
)) 
 800             m_menus
[i
]->SetHelpString (id
, helpString
); 
 806 wxString 
wxMenuBar::GetHelpString (int id
) const 
 809     for (i 
= 0; i 
< m_menuCount
; i
++) 
 811         if (m_menus
[i
]->FindItemForId (id
)) 
 812             return wxString(m_menus
[i
]->GetHelpString (id
)); 
 818 bool wxMenuBar::CreateMenuBar(wxFrame
* parent
) 
 822         XtVaSetValues((Widget
) parent
->GetMainWindowWidget(), XmNmenuBar
, (Widget
) m_mainWidget
, NULL
); 
 824         if (!XtIsManaged((Widget) m_mainWidget)) 
 825         XtManageChild((Widget) m_mainWidget); 
 827         XtMapWidget((Widget
) m_mainWidget
); 
 831     Widget menuBarW 
= XmCreateMenuBar ((Widget
) parent
->GetMainWindowWidget(), "MenuBar", NULL
, 0); 
 832     m_mainWidget 
= (WXWidget
) menuBarW
; 
 835     for (i 
= 0; i 
< GetMenuCount(); i
++) 
 837         wxMenu 
*menu 
= GetMenu(i
); 
 838         wxString 
title(m_titles
[i
]); 
 839         menu
->SetButtonWidget(menu
->CreateMenu (this, menuBarW
, menu
, title
, TRUE
)); 
 842         * COMMENT THIS OUT IF YOU DON'T LIKE A RIGHT-JUSTIFIED HELP MENU 
 844         wxStripMenuCodes ((char*) (const char*) title
, wxBuffer
); 
 846         if (strcmp (wxBuffer
, "Help") == 0) 
 847             XtVaSetValues ((Widget
) menuBarW
, XmNmenuHelpWidget
, (Widget
) menu
->GetButtonWidget(), NULL
); 
 850     SetBackgroundColour(m_backgroundColour
); 
 851     SetForegroundColour(m_foregroundColour
); 
 854     XtVaSetValues((Widget
) parent
->GetMainWindowWidget(), XmNmenuBar
, (Widget
) m_mainWidget
, NULL
); 
 855     XtRealizeWidget ((Widget
) menuBarW
); 
 856     XtManageChild ((Widget
) menuBarW
); 
 857     SetMenuBarFrame(parent
); 
 862 // Destroy menubar, but keep data structures intact so we can recreate it. 
 863 bool wxMenuBar::DestroyMenuBar() 
 867         SetMenuBarFrame((wxFrame
*) NULL
); 
 871     XtUnmanageChild ((Widget
) m_mainWidget
); 
 872     XtUnrealizeWidget ((Widget
) m_mainWidget
); 
 875     for (i 
= 0; i 
< GetMenuCount(); i
++) 
 877         wxMenu 
*menu 
= GetMenu(i
); 
 878         menu
->DestroyMenu(TRUE
); 
 881     XtDestroyWidget((Widget
) m_mainWidget
); 
 882     m_mainWidget 
= (WXWidget
) 0; 
 884     SetMenuBarFrame((wxFrame
*) NULL
); 
 891 extern wxApp 
*wxTheApp
; 
 892 static XtWorkProcId WorkProcMenuId
; 
 894 /* Since PopupMenu under Motif stills grab right mouse button events 
 895 * after it was closed, we need to delete the associated widgets to 
 896 * allow next PopUpMenu to appear... 
 899 int PostDeletionOfMenu( XtPointer
* clientData 
) 
 901     XtRemoveWorkProc(WorkProcMenuId
); 
 902     wxMenu 
*menu 
= (wxMenu 
*)clientData
; 
 904     if (menu
->GetMainWidget()) { 
 905         if (menu
->GetParent()) 
 907             wxList
& list 
= menu
->GetParent()->GetItems(); 
 908             list
.DeleteObject(menu
); 
 910         menu
->DestroyMenu(TRUE
); 
 912     /* Mark as no longer popped up */ 
 918 wxMenuPopdownCallback(Widget w
, XtPointer clientData
, 
 921     wxMenu 
*menu 
= (wxMenu 
*)clientData
; 
 923     // Added by JOREL Jean-Charles <jjorel@silr.ireste.fr> 
 924     /* Since Callbacks of MenuItems are not yet processed, we put a 
 925     * background job which will be done when system will be idle. 
 926     * What awful hack!! :( 
 929     WorkProcMenuId 
= XtAppAddWorkProc(  
 930         (XtAppContext
) wxTheApp
->GetAppContext(),  
 931         (XtWorkProc
) PostDeletionOfMenu
, 
 933     // Apparently not found in Motif headers 
 934     //  XtVaSetValues( w, XmNpopupEnabled, XmPOPUP_DISABLED, NULL ); 
 938 * Create a popup or pulldown menu. 
 939 * Submenus of a popup will be pulldown. 
 943 WXWidget 
wxMenu::CreateMenu (wxMenuBar 
* menuBar
, WXWidget parent
, wxMenu 
* topMenu
, const wxString
& title
, bool pullDown
) 
 945     Widget menu 
= (Widget
) 0; 
 946     Widget buttonWidget 
= (Widget
) 0; 
 948     XtSetArg (args
[0], XmNnumColumns
, m_numColumns
); 
 949     XtSetArg (args
[1], XmNpacking
, XmPACK_COLUMN
); 
 953         menu 
= XmCreatePopupMenu ((Widget
) parent
, "popup", args
, 2); 
 956             (XtCallbackProc
)wxMenuPopdownCallback
, 
 961         char mnem 
= wxFindMnemonic (title
); 
 962         wxStripMenuCodes ((char*) (const char*) title
, wxBuffer
); 
 964         menu 
= XmCreatePulldownMenu ((Widget
) parent
, "pulldown", args
, 2); 
 966         XmString label_str 
= XmStringCreateSimple (wxBuffer
); 
 967         buttonWidget 
= XtVaCreateManagedWidget (wxBuffer
, 
 969             xmCascadeButtonGadgetClass
, (Widget
) parent
, 
 971             xmCascadeButtonWidgetClass
, (Widget
) parent
, 
 973             XmNlabelString
, label_str
, 
 978             XtVaSetValues (buttonWidget
, XmNmnemonic
, mnem
, NULL
); 
 980         XmStringFree (label_str
); 
 983     m_menuWidget 
= (WXWidget
) menu
; 
 986     m_topLevelMenu 
= topMenu
; 
 988     for (wxNode 
* node 
= m_menuItems
.First (); node
; node 
= node
->Next ()) 
 990         wxMenuItem 
*item 
= (wxMenuItem 
*) node
->Data (); 
 991         item
->CreateItem (menu
, menuBar
, topMenu
); 
 994     SetBackgroundColour(m_backgroundColour
); 
 995     SetForegroundColour(m_foregroundColour
); 
1001 // Destroys the Motif implementation of the menu, 
1002 // but maintains the wxWindows data structures so we can 
1003 // do a CreateMenu again.  
1004 void wxMenu::DestroyMenu (bool full
) 
1006     for (wxNode 
* node 
= m_menuItems
.First (); node
; node 
= node
->Next ()) 
1008         wxMenuItem 
*item 
= (wxMenuItem 
*) node
->Data (); 
1009         item
->SetMenuBar((wxMenuBar
*) NULL
); 
1011         item
->DestroyItem(full
); 
1018             XtVaSetValues((Widget
) m_buttonWidget
, XmNsubMenuId
, NULL
, NULL
); 
1019             XtDestroyWidget ((Widget
) m_buttonWidget
); 
1020             m_buttonWidget 
= (WXWidget
) 0; 
1023     if (m_menuWidget 
&& full
) 
1025         XtDestroyWidget((Widget
) m_menuWidget
); 
1026         m_menuWidget 
= (WXWidget
) NULL
; 
1030 WXWidget 
wxMenu::FindMenuItem (int id
, wxMenuItem 
** it
) const 
1035             *it 
= (wxMenuItem
*) NULL
; 
1036         return m_buttonWidget
; 
1039     for (wxNode 
* node 
= m_menuItems
.First (); node
; node 
= node
->Next ()) 
1041         wxMenuItem 
*item 
= (wxMenuItem 
*) node
->Data (); 
1042         if (item
->GetId() == id
) 
1046             return item
->GetButtonWidget(); 
1049         if (item
->GetSubMenu()) 
1051             WXWidget w 
= item
->GetSubMenu()->FindMenuItem (id
, it
); 
1060         *it 
= (wxMenuItem
*) NULL
; 
1061     return (WXWidget
) NULL
; 
1064 void wxMenu::SetBackgroundColour(const wxColour
& col
) 
1066     m_backgroundColour 
= col
; 
1068         wxDoChangeBackgroundColour(m_menuWidget
, (wxColour
&) col
); 
1070         wxDoChangeBackgroundColour(m_buttonWidget
, (wxColour
&) col
, TRUE
); 
1072     wxNode
* node 
= m_menuItems
.First(); 
1075         wxMenuItem
* item 
= (wxMenuItem
*) node
->Data(); 
1076         if (item
->GetButtonWidget()) 
1078             // This crashes because it uses gadgets 
1079             //            wxDoChangeBackgroundColour(item->GetButtonWidget(), (wxColour&) col, TRUE); 
1081         if (item
->GetSubMenu()) 
1082             item
->GetSubMenu()->SetBackgroundColour((wxColour
&) col
); 
1083         node 
= node
->Next(); 
1087 void wxMenu::SetForegroundColour(const wxColour
& col
) 
1089     m_foregroundColour 
= col
; 
1091         wxDoChangeForegroundColour(m_menuWidget
, (wxColour
&) col
); 
1093         wxDoChangeForegroundColour(m_buttonWidget
, (wxColour
&) col
); 
1095     wxNode
* node 
= m_menuItems
.First(); 
1098         wxMenuItem
* item 
= (wxMenuItem
*) node
->Data(); 
1099         if (item
->GetButtonWidget()) 
1101             // This crashes because it uses gadgets 
1102             //            wxDoChangeForegroundColour(item->GetButtonWidget(), (wxColour&) col); 
1104         if (item
->GetSubMenu()) 
1105             item
->GetSubMenu()->SetForegroundColour((wxColour
&) col
); 
1106         node 
= node
->Next(); 
1110 void wxMenu::ChangeFont(bool keepOriginalSize
) 
1112     // lesstif 0.87 hangs when setting XmNfontList 
1113 #ifndef LESSTIF_VERSION  
1114     if (!m_font
.Ok() || !m_menuWidget
) 
1117     XmFontList fontList 
= (XmFontList
) m_font
.GetFontList(1.0, XtDisplay((Widget
) m_menuWidget
)); 
1119     XtVaSetValues ((Widget
) m_menuWidget
, 
1120         XmNfontList
, fontList
, 
1124         XtVaSetValues ((Widget
) m_buttonWidget
, 
1125             XmNfontList
, fontList
, 
1128     wxNode
* node 
= m_menuItems
.First(); 
1131         wxMenuItem
* item 
= (wxMenuItem
*) node
->Data(); 
1132         if (m_menuWidget 
&& item
->GetButtonWidget() && m_font
.Ok()) 
1134             XtVaSetValues ((Widget
) item
->GetButtonWidget(), 
1135                 XmNfontList
, fontList
, 
1138         if (item
->GetSubMenu()) 
1139             item
->GetSubMenu()->ChangeFont(keepOriginalSize
); 
1140         node 
= node
->Next(); 
1145 void wxMenu::SetFont(const wxFont
& font
) 
1151 void wxMenuBar::SetBackgroundColour(const wxColour
& col
) 
1154     m_backgroundColour 
= col
; 
1156         wxDoChangeBackgroundColour(m_mainWidget
, (wxColour
&) col
); 
1158     for (i 
= 0; i 
< m_menuCount
; i
++) 
1159         m_menus
[i
]->SetBackgroundColour((wxColour
&) col
); 
1162 void wxMenuBar::SetForegroundColour(const wxColour
& col
) 
1164     m_foregroundColour 
= col
; 
1166         wxDoChangeForegroundColour(m_mainWidget
, (wxColour
&) col
); 
1169     for (i 
= 0; i 
< m_menuCount
; i
++) 
1170         m_menus
[i
]->SetForegroundColour((wxColour
&) col
); 
1173 void wxMenuBar::ChangeFont(bool keepOriginalSize
) 
1175     // Nothing to do for menubar, fonts are kept in wxMenus 
1178 void wxMenuBar::SetFont(const wxFont
& font
) 
1184     for (i 
= 0; i 
< m_menuCount
; i
++) 
1185         m_menus
[i
]->SetFont(font
);