1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/menu_osx.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
19 #include "wx/wxprec.h"
30 #include "wx/dialog.h"
31 #include "wx/menuitem.h"
34 #include "wx/osx/private.h"
36 // other standard headers
37 // ----------------------
40 IMPLEMENT_ABSTRACT_CLASS( wxMenuImpl
, wxObject
)
42 wxMenuImpl::~wxMenuImpl()
46 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
47 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
49 // the (popup) menu title has this special id
50 static const int idMenuTitle
= -3;
52 // ============================================================================
54 // ============================================================================
58 // Construct a menu with optional title (then use append)
62 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
64 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
67 menuIter
= menuIter
->GetNext();
69 return menuIter
->GetData() ;
75 m_startRadioGroup
= -1;
76 m_allowRearrange
= true;
77 m_noEventsMode
= false;
79 m_peer
= wxMenuImpl::Create( this, wxStripMenuCodes(m_title
) );
82 // if we have a title, insert it in the beginning of the menu
83 if ( !m_title
.empty() )
85 Append(idMenuTitle
, m_title
) ;
95 WXHMENU
wxMenu::GetHMenu() const
98 return m_peer
->GetHMenu();
104 // not available on the mac platform
107 void wxMenu::Attach(wxMenuBarBase
*menubar
)
109 wxMenuBase::Attach(menubar
);
114 void wxMenu::SetAllowRearrange( bool allow
)
116 m_allowRearrange
= allow
;
119 void wxMenu::SetNoEventsMode( bool noEvents
)
121 m_noEventsMode
= noEvents
;
124 // function appends a new item or submenu to the menu
125 // append a new item or submenu to the menu
126 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
128 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
129 m_peer
->InsertOrAppend( pItem
, pos
);
131 if ( pItem
->IsSeparator() )
133 // nothing to do here
137 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
138 if ( pSubMenu
!= NULL
)
140 wxASSERT_MSG( pSubMenu
->GetHMenu() != NULL
, wxT("invalid submenu added"));
141 pSubMenu
->m_menuParent
= this ;
143 pSubMenu
->DoRearrange();
147 if ( pItem
->GetId() == idMenuTitle
)
148 pItem
->GetMenu()->Enable( idMenuTitle
, false );
152 // if we're already attached to the menubar, we must update it
153 if ( IsAttached() && GetMenuBar()->IsAttached() )
154 GetMenuBar()->Refresh();
159 void wxMenu::EndRadioGroup()
161 // we're not inside a radio group any longer
162 m_startRadioGroup
= -1;
165 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
167 wxCHECK_MSG( item
, NULL
, wxT("NULL item in wxMenu::DoAppend") );
171 if ( item
->GetKind() == wxITEM_RADIO
)
173 int count
= GetMenuItemCount();
175 if ( m_startRadioGroup
== -1 )
177 // start a new radio group
178 m_startRadioGroup
= count
;
180 // for now it has just one element
181 item
->SetAsRadioGroupStart();
182 item
->SetRadioGroupEnd(m_startRadioGroup
);
184 // ensure that we have a checked item in the radio group
187 else // extend the current radio group
189 // we need to update its end item
190 item
->SetRadioGroupStart(m_startRadioGroup
);
191 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
195 node
->GetData()->SetRadioGroupEnd(count
);
199 wxFAIL_MSG( wxT("where is the radio group start item?") );
203 else // not a radio item
208 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
212 // check the item initially
218 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
220 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
226 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
229 // we need to find the items position in the child list
231 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
233 for ( pos = 0; node; pos++ )
235 if ( node->GetData() == item )
238 node = node->GetNext();
241 // DoRemove() (unlike Remove) can only be called for existing item!
242 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
244 wxOSXMenuRemoveItem(m_hMenu , pos );
246 m_peer
->Remove( item
);
247 // and from internal data structures
248 return wxMenuBase::DoRemove(item
);
251 void wxMenu::SetTitle(const wxString
& label
)
254 m_peer
->SetTitle( wxStripMenuCodes( label
) );
257 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
259 bool processed
= false;
261 // Try the menu's event handler
262 if ( /* !processed && */ GetEventHandler())
263 processed
= GetEventHandler()->SafelyProcessEvent(event
);
265 // Try the window the menu was popped up from
266 // (and up through the hierarchy)
267 wxWindow
*win
= GetWindow();
268 if ( !processed
&& win
)
269 processed
= win
->HandleWindowEvent(event
);
274 // ---------------------------------------------------------------------------
276 // ---------------------------------------------------------------------------
278 // MacOS needs to know about submenus somewhere within this menu
279 // before it can be displayed, also hide special menu items
280 // like preferences that are handled by the OS
281 void wxMenu::DoRearrange()
283 if ( !AllowRearrange() )
286 wxMenuItem
* previousItem
= NULL
;
288 wxMenuItemList::compatibility_iterator node
;
291 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
293 item
= (wxMenuItem
*)node
->GetData();
294 wxMenu
* subMenu
= item
->GetSubMenu() ;
301 // what we do here is to hide the special items which are
302 // shown in the application menu anyhow -- it doesn't make
303 // sense to show them in their normal place as well
304 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
305 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
306 item
->GetId() == wxApp::s_macExitMenuItemId
)
309 item
->GetPeer()->Hide( true );
311 // also check for a separator which was used just to
312 // separate this item from the others, so don't leave
313 // separator at the menu start or end nor 2 consecutive
315 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
316 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
318 wxMenuItem
*sepToHide
= 0;
319 if ( !previousItem
&& next
&& next
->IsSeparator() )
321 // next (i.e. second as we must be first) item is
322 // the separator to hide
323 wxASSERT_MSG( pos
== 0, wxT("should be the menu start") );
326 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
327 previousItem
!= NULL
&&
328 previousItem
->IsSeparator() )
330 // prev item is a trailing separator we want to hide
331 sepToHide
= previousItem
;
333 else if ( previousItem
&& previousItem
->IsSeparator() &&
334 next
&& next
->IsSeparator() )
336 // two consecutive separators, this is one too many
342 // hide the separator as well
343 sepToHide
->GetPeer()->Hide( true );
348 previousItem
= item
;
353 bool wxMenu::HandleCommandUpdateStatus( wxMenuItem
* item
, wxWindow
* senderWindow
)
355 int id
= item
? item
->GetId() : 0;
356 wxUpdateUIEvent
event(id
);
357 event
.SetEventObject( this );
359 bool processed
= false;
361 // Try the menu's event handler
363 wxEvtHandler
*handler
= GetEventHandler();
365 processed
= handler
->ProcessEvent(event
);
368 // Try the window the menu was popped up from
369 // (and up through the hierarchy)
372 wxWindow
*win
= GetWindow();
374 processed
= win
->HandleWindowEvent(event
);
377 if ( !processed
&& senderWindow
!= NULL
)
379 processed
= senderWindow
->HandleWindowEvent(event
);
384 // if anything changed, update the changed attribute
385 if (event
.GetSetText())
386 SetLabel(id
, event
.GetText());
387 if (event
.GetSetChecked())
388 Check(id
, event
.GetChecked());
389 if (event
.GetSetEnabled())
390 Enable(id
, event
.GetEnabled());
395 // these two items are also managed by the Carbon Menu Manager, therefore we must
396 // always reset them ourselves
399 if ( id
== wxApp::s_macExitMenuItemId
)
401 cmd
= kHICommandQuit
;
403 else if (id
== wxApp::s_macPreferencesMenuItemId
)
405 cmd
= kHICommandPreferences
;
410 if ( !item
->IsEnabled() || wxDialog::OSXHasModalDialogsOpen() )
411 DisableMenuCommand( NULL
, cmd
) ;
413 EnableMenuCommand( NULL
, cmd
) ;
422 bool wxMenu::HandleCommandProcess( wxMenuItem
* item
, wxWindow
* senderWindow
)
424 int id
= item
? item
->GetId() : 0;
425 bool processed
= false;
426 if (item
->IsCheckable())
427 item
->Check( !item
->IsChecked() ) ;
429 if ( SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) )
433 if ( senderWindow
!= NULL
)
435 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, id
);
436 event
.SetEventObject(senderWindow
);
437 event
.SetInt(item
->IsCheckable() ? item
->IsChecked() : -1);
439 if ( senderWindow
->HandleWindowEvent(event
) )
444 if(!processed
&& item
)
446 processed
= item
->GetPeer()->DoDefault();
452 void wxMenu::HandleMenuItemHighlighted( wxMenuItem
* item
)
454 int id
= item
? item
->GetId() : 0;
455 wxMenuEvent
wxevent(wxEVT_MENU_HIGHLIGHT
, id
, this);
456 DoHandleMenuEvent( wxevent
);
459 void wxMenu::HandleMenuOpened()
461 wxMenuEvent
wxevent(wxEVT_MENU_OPEN
, 0, this);
462 DoHandleMenuEvent( wxevent
);
465 void wxMenu::HandleMenuClosed()
467 wxMenuEvent
wxevent(wxEVT_MENU_CLOSE
, 0, this);
468 DoHandleMenuEvent( wxevent
);
471 bool wxMenu::DoHandleMenuEvent(wxEvent
& wxevent
)
473 wxevent
.SetEventObject(this);
474 wxEvtHandler
* handler
= GetEventHandler();
475 if (handler
&& handler
->ProcessEvent(wxevent
))
481 wxWindow
*win
= GetWindow();
484 if ( win
->HandleWindowEvent(wxevent
) )
495 Mac Implementation note :
497 The Mac has only one global menubar, so we attempt to install the currently
498 active menubar from a frame, we currently don't take into account mdi-frames
499 which would ask for menu-merging
501 Secondly there is no mac api for changing a menubar that is not the current
502 menubar, so we have to wait for preparing the actual menubar until the
503 wxMenubar is to be used
505 We can in subsequent versions use MacInstallMenuBar to provide some sort of
506 auto-merge for MDI in case this will be necessary
510 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
511 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
512 bool wxMenuBar::s_macAutoWindowMenu
= true ;
513 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
515 void wxMenuBar::Init()
517 m_eventHandler
= this;
518 m_menuBarFrame
= NULL
;
519 m_rootMenu
= new wxMenu();
520 m_rootMenu
->Attach(this);
522 m_appleMenu
= new wxMenu();
523 m_appleMenu
->SetAllowRearrange(false);
525 // Create standard items unless the application explicitly disabled this by
526 // setting the corresponding ids to wxID_NONE: although this is not
527 // recommended, sometimes these items really don't make sense.
528 if ( wxApp::s_macAboutMenuItemId
!= wxID_NONE
)
530 wxString
aboutLabel(_("About"));
532 aboutLabel
<< ' ' << wxTheApp
->GetAppDisplayName();
535 m_appleMenu
->Append( wxApp::s_macAboutMenuItemId
, aboutLabel
);
536 m_appleMenu
->AppendSeparator();
539 #if !wxOSX_USE_CARBON
540 if ( wxApp::s_macPreferencesMenuItemId
!= wxID_NONE
)
542 m_appleMenu
->Append( wxApp::s_macPreferencesMenuItemId
,
543 _("Preferences...") + "\tCtrl+," );
544 m_appleMenu
->AppendSeparator();
547 // standard menu items, handled in wxMenu::HandleCommandProcess(), see above:
548 wxString
hideLabel(_("Hide"));
550 hideLabel
<< ' ' << wxTheApp
->GetAppDisplayName();
551 hideLabel
<< "\tCtrl+H";
552 m_appleMenu
->Append( wxID_OSX_HIDE
, hideLabel
);
553 m_appleMenu
->Append( wxID_OSX_HIDEOTHERS
, _("Hide Others")+"\tAlt+Ctrl+H" );
554 m_appleMenu
->Append( wxID_OSX_SHOWALL
, _("Show All") );
555 m_appleMenu
->AppendSeparator();
557 // Do always add "Quit" item unconditionally however, it can't be disabled.
558 wxString
quitLabel(_("Quit"));
560 quitLabel
<< ' ' << wxTheApp
->GetAppDisplayName();
561 quitLabel
<< "\tCtrl+Q";
562 m_appleMenu
->Append( wxApp::s_macExitMenuItemId
, quitLabel
);
563 #endif // !wxOSX_USE_CARBON
565 m_rootMenu
->AppendSubMenu(m_appleMenu
, "\x14") ;
568 wxMenuBar::wxMenuBar()
573 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
578 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
582 m_titles
.Alloc(count
);
584 for ( size_t i
= 0; i
< count
; i
++ )
586 m_menus
.Append(menus
[i
]);
587 m_titles
.Add(titles
[i
]);
589 menus
[i
]->Attach(this);
590 Append( menus
[i
], titles
[i
] );
594 wxMenuBar::~wxMenuBar()
596 if (s_macCommonMenuBar
== this)
597 s_macCommonMenuBar
= NULL
;
599 if (s_macInstalledMenuBar
== this)
601 s_macInstalledMenuBar
= NULL
;
605 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
607 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
610 void wxMenuBar::MacInstallMenuBar()
612 if ( s_macInstalledMenuBar
== this )
615 m_rootMenu
->GetPeer()->MakeRoot();
619 MenuBarHandle menubar
= NULL
;
621 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
623 ::SetMenuBar( menubar
) ;
624 DisposeMenuBar( menubar
) ;
625 MenuHandle appleMenu
= NULL
;
627 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
628 verify_noerr( SetMenuTitleWithCFString( appleMenu
, CFSTR( "\x14" ) ) );
630 // Add About/Preferences separator only on OS X
631 // KH/RN: Separator is always present on 10.3 but not on 10.2
632 // However, the change from 10.2 to 10.3 suggests it is preferred
633 InsertMenuItemTextWithCFString( appleMenu
,
634 CFSTR(""), 0, kMenuItemAttrSeparator
, 0);
635 InsertMenuItemTextWithCFString( appleMenu
,
636 CFSTR("About..."), 0, 0, 0);
637 MacInsertMenu( appleMenu
, 0 ) ;
639 // if we have a mac help menu, clean it up before adding new items
640 MenuHandle helpMenuHandle
;
641 MenuItemIndex firstUserHelpMenuItem
;
643 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
645 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
646 DeleteMenuItem( helpMenuHandle
, i
) ;
650 helpMenuHandle
= NULL
;
653 if ( wxApp::s_macPreferencesMenuItemId
)
655 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
656 if ( item
== NULL
|| !(item
->IsEnabled()) )
657 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
659 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
662 // Unlike preferences which may or may not exist, the Quit item should be always
663 // enabled unless it is added by the application and then disabled, otherwise
664 // a program would be required to add an item with wxID_EXIT in order to get the
665 // Quit menu item to be enabled, which seems a bit burdensome.
666 if ( wxApp::s_macExitMenuItemId
)
668 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
669 if ( item
!= NULL
&& !(item
->IsEnabled()) )
670 DisableMenuCommand( NULL
, kHICommandQuit
) ;
672 EnableMenuCommand( NULL
, kHICommandQuit
) ;
675 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
676 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
677 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
678 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
680 wxMenuItemList::compatibility_iterator node
;
682 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
683 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
685 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
687 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
689 item
= (wxMenuItem
*)node
->GetData();
690 subMenu
= item
->GetSubMenu() ;
693 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding() );
694 MenuItemIndex position
= CountMenuItems(mh
);
695 ::SetMenuItemHierarchicalMenu(mh
, position
, MAC_WXHMENU(subMenu
->GetHMenu()));
699 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
701 // we have found a user help menu and an item other than the about item,
702 // so we can create the mac help menu now, if we haven't created it yet
703 if ( helpMenuHandle
== NULL
)
705 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
707 helpMenuHandle
= NULL
;
713 if ( item
->IsSeparator() )
715 if ( helpMenuHandle
)
716 AppendMenuItemTextWithCFString( helpMenuHandle
,
717 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
722 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
724 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
726 // this will be taken care of below
730 if ( helpMenuHandle
)
732 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
733 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
734 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
744 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
745 && GetAutoWindowMenu() )
747 if ( MacGetWindowMenuHMenu() == NULL
)
749 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
752 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
756 // get the insertion point in the standard menu
757 MenuItemIndex winListStart
;
758 GetIndMenuItemWithCommandID(wm
,
759 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
761 // add a separator so that the standard items and the custom items
762 // aren't mixed together, but only if this is the first run
763 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
764 'WXWM', 1, NULL
, NULL
);
766 if ( err
== menuItemNotFoundErr
)
768 InsertMenuItemTextWithCFString( wm
,
769 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
772 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
776 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
777 menu
->MacBeforeDisplay(false) ;
779 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
783 // take care of the about menu item wherever it is
786 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
790 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
791 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
792 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
793 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
794 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
795 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
800 if ( GetAutoWindowMenu() )
802 if ( MacGetWindowMenuHMenu() == NULL
)
803 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
805 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
811 s_macInstalledMenuBar
= this;
814 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
816 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
818 m_rootMenu
->FindItemByPosition( pos
)->Enable(enable
);
823 bool wxMenuBar::Enable(bool enable
)
825 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
828 for (i
= 0; i
< GetMenuCount(); i
++)
829 EnableTop(i
, enable
);
834 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
836 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
838 m_titles
[pos
] = label
;
843 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
846 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
848 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
849 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
851 return m_titles
[pos
];
854 int wxMenuBar::FindMenu(const wxString
& title
)
856 wxString menuTitle
= wxStripMenuCodes(title
);
858 size_t count
= GetMenuCount();
859 for ( size_t i
= 0; i
< count
; i
++ )
861 wxString title
= wxStripMenuCodes(m_titles
[i
]);
862 if ( menuTitle
== title
)
869 // ---------------------------------------------------------------------------
870 // wxMenuBar construction
871 // ---------------------------------------------------------------------------
873 const int firstMenuPos
= 1; // to account for the 0th application menu on mac
875 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
877 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
881 m_titles
[pos
] = title
;
883 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
884 m_rootMenu
->Remove(item
);
885 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
890 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
892 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
895 m_titles
.Insert(title
, pos
);
897 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
902 wxMenu
*wxMenuBar::Remove(size_t pos
)
904 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
908 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
909 m_rootMenu
->Remove(item
);
911 m_titles
.RemoveAt(pos
);
916 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
918 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
919 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
921 if ( !wxMenuBarBase::Append(menu
, title
) )
926 m_rootMenu
->AppendSubMenu(menu
, title
);
931 void wxMenuBar::Detach()
933 wxMenuBarBase::Detach() ;
936 void wxMenuBar::Attach(wxFrame
*frame
)
938 wxMenuBarBase::Attach( frame
) ;
941 // ---------------------------------------------------------------------------
942 // wxMenuBar searching for menu items
943 // ---------------------------------------------------------------------------
945 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
946 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
947 const wxString
& itemString
) const
949 wxString menuLabel
= wxStripMenuCodes(menuString
);
950 size_t count
= GetMenuCount();
951 for ( size_t i
= 0; i
< count
; i
++ )
953 wxString title
= wxStripMenuCodes(m_titles
[i
]);
954 if ( menuLabel
== title
)
955 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
961 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
966 wxMenuItem
*item
= NULL
;
967 size_t count
= GetMenuCount();
968 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
969 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);