1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/menu_osx.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Stefan Csomor
7 // RCS-ID: $Id: menu.cpp 54129 2008-06-11 19:30:52Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
19 #include "wx/wxprec.h"
28 #include "wx/menuitem.h"
31 #include "wx/osx/private.h"
33 // other standard headers
34 // ----------------------
37 IMPLEMENT_ABSTRACT_CLASS( wxMenuImpl
, wxObject
)
39 wxMenuImpl::~wxMenuImpl()
43 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
44 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
46 // the (popup) menu title has this special id
47 static const int idMenuTitle
= -3;
49 // ============================================================================
51 // ============================================================================
52 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
53 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
57 // Construct a menu with optional title (then use append)
61 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
63 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
66 menuIter
= menuIter
->GetNext();
68 return menuIter
->GetData() ;
74 m_startRadioGroup
= -1;
75 m_allowRearrange
= true;
76 m_noEventsMode
= false;
78 m_peer
= wxMenuImpl::Create( this, wxStripMenuCodes(m_title
) );
81 // if we have a title, insert it in the beginning of the menu
82 if ( !m_title
.empty() )
84 Append(idMenuTitle
, m_title
) ;
94 WXHMENU
wxMenu::GetHMenu() const
97 return m_peer
->GetHMenu();
103 // not available on the mac platform
106 void wxMenu::Attach(wxMenuBarBase
*menubar
)
108 wxMenuBase::Attach(menubar
);
113 void wxMenu::SetAllowRearrange( bool allow
)
115 m_allowRearrange
= allow
;
118 void wxMenu::SetNoEventsMode( bool noEvents
)
120 m_noEventsMode
= noEvents
;
123 // function appends a new item or submenu to the menu
124 // append a new item or submenu to the menu
125 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
127 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
128 m_peer
->InsertOrAppend( pItem
, pos
);
130 if ( pItem
->IsSeparator() )
132 // nothing to do here
136 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
137 if ( pSubMenu
!= NULL
)
139 wxASSERT_MSG( pSubMenu
->GetHMenu() != NULL
, wxT("invalid submenu added"));
140 pSubMenu
->m_menuParent
= this ;
142 pSubMenu
->DoRearrange();
146 if ( pItem
->GetId() == idMenuTitle
)
147 pItem
->GetMenu()->Enable( idMenuTitle
, false );
151 // if we're already attached to the menubar, we must update it
152 if ( IsAttached() && GetMenuBar()->IsAttached() )
153 GetMenuBar()->Refresh();
158 void wxMenu::EndRadioGroup()
160 // we're not inside a radio group any longer
161 m_startRadioGroup
= -1;
164 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
166 wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") );
170 if ( item
->GetKind() == wxITEM_RADIO
)
172 int count
= GetMenuItemCount();
174 if ( m_startRadioGroup
== -1 )
176 // start a new radio group
177 m_startRadioGroup
= count
;
179 // for now it has just one element
180 item
->SetAsRadioGroupStart();
181 item
->SetRadioGroupEnd(m_startRadioGroup
);
183 // ensure that we have a checked item in the radio group
186 else // extend the current radio group
188 // we need to update its end item
189 item
->SetRadioGroupStart(m_startRadioGroup
);
190 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
194 node
->GetData()->SetRadioGroupEnd(count
);
198 wxFAIL_MSG( _T("where is the radio group start item?") );
202 else // not a radio item
207 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
211 // check the item initially
217 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
219 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
225 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
228 // we need to find the items position in the child list
230 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
232 for ( pos = 0; node; pos++ )
234 if ( node->GetData() == item )
237 node = node->GetNext();
240 // DoRemove() (unlike Remove) can only be called for existing item!
241 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
243 wxOSXMenuRemoveItem(m_hMenu , pos );
245 m_peer
->Remove( item
);
246 // and from internal data structures
247 return wxMenuBase::DoRemove(item
);
250 void wxMenu::SetTitle(const wxString
& label
)
253 m_peer
->SetTitle( wxStripMenuCodes( label
) );
256 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
258 bool processed
= false;
260 // Try the menu's event handler
261 if ( /* !processed && */ GetEventHandler())
262 processed
= GetEventHandler()->SafelyProcessEvent(event
);
264 // Try the window the menu was popped up from
265 // (and up through the hierarchy)
266 wxWindow
*win
= GetInvokingWindow();
267 if ( !processed
&& win
)
268 processed
= win
->HandleWindowEvent(event
);
273 // ---------------------------------------------------------------------------
275 // ---------------------------------------------------------------------------
277 wxWindow
*wxMenu::GetWindow() const
279 if ( m_invokingWindow
!= NULL
)
280 return m_invokingWindow
;
281 else if ( GetMenuBar() != NULL
)
282 return (wxWindow
*) GetMenuBar()->GetFrame();
287 // MacOS needs to know about submenus somewhere within this menu
288 // before it can be displayed, also hide special menu items
289 // like preferences that are handled by the OS
290 void wxMenu::DoRearrange()
292 if ( !AllowRearrange() )
295 wxMenuItem
* previousItem
= NULL
;
297 wxMenuItemList::compatibility_iterator node
;
300 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
302 item
= (wxMenuItem
*)node
->GetData();
303 wxMenu
* subMenu
= item
->GetSubMenu() ;
310 // what we do here is to hide the special items which are
311 // shown in the application menu anyhow -- it doesn't make
312 // sense to show them in their normal place as well
313 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
314 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
315 item
->GetId() == wxApp::s_macExitMenuItemId
)
318 item
->GetPeer()->Hide( true );
320 // also check for a separator which was used just to
321 // separate this item from the others, so don't leave
322 // separator at the menu start or end nor 2 consecutive
324 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
325 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
327 wxMenuItem
*sepToHide
= 0;
328 if ( !previousItem
&& next
&& next
->IsSeparator() )
330 // next (i.e. second as we must be first) item is
331 // the separator to hide
332 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
335 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
336 previousItem
!= NULL
&&
337 previousItem
->IsSeparator() )
339 // prev item is a trailing separator we want to hide
340 sepToHide
= previousItem
;
342 else if ( previousItem
&& previousItem
->IsSeparator() &&
343 next
&& next
->IsSeparator() )
345 // two consecutive separators, this is one too many
351 // hide the separator as well
352 sepToHide
->GetPeer()->Hide( true );
357 previousItem
= item
;
362 bool wxMenu::HandleCommandUpdateStatus( wxMenuItem
* item
, wxWindow
* senderWindow
)
364 int id
= item
? item
->GetId() : 0;
365 wxUpdateUIEvent
event(id
);
366 event
.SetEventObject( this );
368 bool processed
= false;
370 // Try the menu's event handler
372 wxEvtHandler
*handler
= GetEventHandler();
374 processed
= handler
->ProcessEvent(event
);
377 // Try the window the menu was popped up from
378 // (and up through the hierarchy)
381 const wxMenuBase
*menu
= this;
384 wxWindow
*win
= menu
->GetInvokingWindow();
387 processed
= win
->HandleWindowEvent(event
);
391 menu
= menu
->GetParent();
395 if ( !processed
&& senderWindow
!= NULL
)
397 processed
= senderWindow
->HandleWindowEvent(event
);
402 // if anything changed, update the changed attribute
403 if (event
.GetSetText())
404 SetLabel(id
, event
.GetText());
405 if (event
.GetSetChecked())
406 Check(id
, event
.GetChecked());
407 if (event
.GetSetEnabled())
408 Enable(id
, event
.GetEnabled());
413 bool wxMenu::HandleCommandProcess( wxMenuItem
* item
, wxWindow
* senderWindow
)
415 int id
= item
? item
->GetId() : 0;
416 bool processed
= false;
417 if (item
->IsCheckable())
418 item
->Check( !item
->IsChecked() ) ;
420 if ( SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) )
424 if ( senderWindow
!= NULL
)
426 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, id
);
427 event
.SetEventObject(senderWindow
);
428 event
.SetInt(item
->IsCheckable() ? item
->IsChecked() : -1);
430 if ( senderWindow
->HandleWindowEvent(event
) )
437 void wxMenu::HandleMenuItemHighlighted( wxMenuItem
* item
)
439 int id
= item
? item
->GetId() : 0;
440 wxMenuEvent
wxevent(wxEVT_MENU_HIGHLIGHT
, id
, this);
441 DoHandleMenuEvent( wxevent
);
444 void wxMenu::HandleMenuOpened()
446 wxMenuEvent
wxevent(wxEVT_MENU_OPEN
, 0, this);
447 DoHandleMenuEvent( wxevent
);
450 void wxMenu::HandleMenuClosed()
452 wxMenuEvent
wxevent(wxEVT_MENU_CLOSE
, 0, this);
453 DoHandleMenuEvent( wxevent
);
456 bool wxMenu::DoHandleMenuEvent(wxEvent
& wxevent
)
458 wxevent
.SetEventObject(this);
459 wxEvtHandler
* handler
= GetEventHandler();
460 if (handler
&& handler
->ProcessEvent(wxevent
))
466 wxWindow
*win
= GetInvokingWindow();
469 if ( win
->HandleWindowEvent(wxevent
) )
480 Mac Implementation note :
482 The Mac has only one global menubar, so we attempt to install the currently
483 active menubar from a frame, we currently don't take into account mdi-frames
484 which would ask for menu-merging
486 Secondly there is no mac api for changing a menubar that is not the current
487 menubar, so we have to wait for preparing the actual menubar until the
488 wxMenubar is to be used
490 We can in subsequent versions use MacInstallMenuBar to provide some sort of
491 auto-merge for MDI in case this will be necessary
495 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
496 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
497 bool wxMenuBar::s_macAutoWindowMenu
= true ;
498 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
500 void wxMenuBar::Init()
502 m_eventHandler
= this;
503 m_menuBarFrame
= NULL
;
504 m_invokingWindow
= NULL
;
505 m_rootMenu
= new wxMenu();
506 wxMenu
* applemenu
= new wxMenu();
507 applemenu
->SetAllowRearrange(false);
508 applemenu
->Append( wxApp::s_macAboutMenuItemId
, "About..." );
509 applemenu
->AppendSeparator();
510 applemenu
->Append( wxApp::s_macPreferencesMenuItemId
, "Preferences..." );
511 applemenu
->AppendSeparator();
513 #if ! wxOSX_USE_CARBON
514 applemenu
->Append( wxApp::s_macExitMenuItemId
, "Quit\tCtrl+Q" );
517 m_rootMenu
->AppendSubMenu(applemenu
, "\x14") ;
520 wxMenuBar::wxMenuBar()
525 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
530 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
534 m_titles
.Alloc(count
);
536 for ( size_t i
= 0; i
< count
; i
++ )
538 m_menus
.Append(menus
[i
]);
539 m_titles
.Add(titles
[i
]);
541 menus
[i
]->Attach(this);
542 Append( menus
[i
], titles
[i
] );
546 wxMenuBar::~wxMenuBar()
548 if (s_macCommonMenuBar
== this)
549 s_macCommonMenuBar
= NULL
;
551 if (s_macInstalledMenuBar
== this)
553 s_macInstalledMenuBar
= NULL
;
557 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
559 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
562 void wxMenuBar::MacInstallMenuBar()
564 if ( s_macInstalledMenuBar
== this )
567 m_rootMenu
->GetPeer()->MakeRoot();
570 MenuBarHandle menubar
= NULL
;
572 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
574 ::SetMenuBar( menubar
) ;
575 DisposeMenuBar( menubar
) ;
576 MenuHandle appleMenu
= NULL
;
578 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
579 verify_noerr( SetMenuTitleWithCFString( appleMenu
, CFSTR( "\x14" ) ) );
581 // Add About/Preferences separator only on OS X
582 // KH/RN: Separator is always present on 10.3 but not on 10.2
583 // However, the change from 10.2 to 10.3 suggests it is preferred
584 InsertMenuItemTextWithCFString( appleMenu
,
585 CFSTR(""), 0, kMenuItemAttrSeparator
, 0);
586 InsertMenuItemTextWithCFString( appleMenu
,
587 CFSTR("About..."), 0, 0, 0);
588 MacInsertMenu( appleMenu
, 0 ) ;
590 // if we have a mac help menu, clean it up before adding new items
591 MenuHandle helpMenuHandle
;
592 MenuItemIndex firstUserHelpMenuItem
;
594 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
596 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
597 DeleteMenuItem( helpMenuHandle
, i
) ;
601 helpMenuHandle
= NULL
;
604 if ( wxApp::s_macPreferencesMenuItemId
)
606 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
607 if ( item
== NULL
|| !(item
->IsEnabled()) )
608 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
610 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
613 // Unlike preferences which may or may not exist, the Quit item should be always
614 // enabled unless it is added by the application and then disabled, otherwise
615 // a program would be required to add an item with wxID_EXIT in order to get the
616 // Quit menu item to be enabled, which seems a bit burdensome.
617 if ( wxApp::s_macExitMenuItemId
)
619 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
620 if ( item
!= NULL
&& !(item
->IsEnabled()) )
621 DisableMenuCommand( NULL
, kHICommandQuit
) ;
623 EnableMenuCommand( NULL
, kHICommandQuit
) ;
626 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
627 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
628 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
629 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
631 wxMenuItemList::compatibility_iterator node
;
633 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
634 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
636 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
638 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
640 item
= (wxMenuItem
*)node
->GetData();
641 subMenu
= item
->GetSubMenu() ;
644 // we don't support hierarchical menus in the help menu yet
648 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
650 // we have found a user help menu and an item other than the about item,
651 // so we can create the mac help menu now, if we haven't created it yet
652 if ( helpMenuHandle
== NULL
)
654 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
656 helpMenuHandle
= NULL
;
662 if ( item
->IsSeparator() )
664 if ( helpMenuHandle
)
665 AppendMenuItemTextWithCFString( helpMenuHandle
,
666 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
671 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
673 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
675 // this will be taken care of below
679 if ( helpMenuHandle
)
681 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
682 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
683 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
693 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
694 && GetAutoWindowMenu() )
696 if ( MacGetWindowMenuHMenu() == NULL
)
698 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
701 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
705 // get the insertion point in the standard menu
706 MenuItemIndex winListStart
;
707 GetIndMenuItemWithCommandID(wm
,
708 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
710 // add a separator so that the standard items and the custom items
711 // aren't mixed together, but only if this is the first run
712 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
713 'WXWM', 1, NULL
, NULL
);
715 if ( err
== menuItemNotFoundErr
)
717 InsertMenuItemTextWithCFString( wm
,
718 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
721 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
725 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
726 menu
->MacBeforeDisplay(false) ;
728 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
732 // take care of the about menu item wherever it is
735 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
739 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
740 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
741 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
742 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
743 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
744 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
749 if ( GetAutoWindowMenu() )
751 if ( MacGetWindowMenuHMenu() == NULL
)
752 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
754 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
760 s_macInstalledMenuBar
= this;
763 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
765 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
767 m_rootMenu
->FindItemByPosition( pos
)->Enable(enable
);
772 bool wxMenuBar::Enable(bool enable
)
774 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
777 for (i
= 0; i
< GetMenuCount(); i
++)
778 EnableTop(i
, enable
);
783 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
785 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
787 m_titles
[pos
] = label
;
792 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
795 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
797 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
798 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
800 return m_titles
[pos
];
803 int wxMenuBar::FindMenu(const wxString
& title
)
805 wxString menuTitle
= wxStripMenuCodes(title
);
807 size_t count
= GetMenuCount();
808 for ( size_t i
= 0; i
< count
; i
++ )
810 wxString title
= wxStripMenuCodes(m_titles
[i
]);
811 if ( menuTitle
== title
)
818 // ---------------------------------------------------------------------------
819 // wxMenuBar construction
820 // ---------------------------------------------------------------------------
822 const int firstMenuPos
= 1; // to account for the 0th application menu on mac
824 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
826 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
830 m_titles
[pos
] = title
;
832 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
833 m_rootMenu
->Remove(item
);
834 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
836 if (m_invokingWindow
)
837 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
842 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
844 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
847 m_titles
.Insert(title
, pos
);
849 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
851 if (m_invokingWindow
)
852 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
857 wxMenu
*wxMenuBar::Remove(size_t pos
)
859 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
863 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
864 m_rootMenu
->Remove(item
);
866 m_titles
.RemoveAt(pos
);
871 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
873 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
874 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
876 if ( !wxMenuBarBase::Append(menu
, title
) )
881 m_rootMenu
->AppendSubMenu(menu
, title
);
883 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
884 // adding menu later on.
885 if (m_invokingWindow
)
886 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
891 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
893 menu
->SetInvokingWindow( NULL
);
894 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
898 wxMenuItem
*menuitem
= node
->GetData();
899 if (menuitem
->IsSubMenu())
900 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
902 node
= node
->GetNext();
906 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
908 menu
->SetInvokingWindow( win
);
909 wxMenuItem
*menuitem
;
910 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
914 menuitem
= node
->GetData();
915 if (menuitem
->IsSubMenu())
916 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
918 node
= node
->GetNext();
922 void wxMenuBar::UnsetInvokingWindow()
924 m_invokingWindow
= NULL
;
926 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
930 menu
= node
->GetData();
931 wxMenubarUnsetInvokingWindow( menu
);
933 node
= node
->GetNext();
937 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
939 m_invokingWindow
= frame
;
941 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
945 menu
= node
->GetData();
946 wxMenubarSetInvokingWindow( menu
, frame
);
948 node
= node
->GetNext();
952 void wxMenuBar::Detach()
954 wxMenuBarBase::Detach() ;
957 void wxMenuBar::Attach(wxFrame
*frame
)
959 wxMenuBarBase::Attach( frame
) ;
962 // ---------------------------------------------------------------------------
963 // wxMenuBar searching for menu items
964 // ---------------------------------------------------------------------------
966 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
967 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
968 const wxString
& itemString
) const
970 wxString menuLabel
= wxStripMenuCodes(menuString
);
971 size_t count
= GetMenuCount();
972 for ( size_t i
= 0; i
< count
; i
++ )
974 wxString title
= wxStripMenuCodes(m_titles
[i
]);
975 if ( menuLabel
== title
)
976 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
982 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
987 wxMenuItem
*item
= NULL
;
988 size_t count
= GetMenuCount();
989 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
990 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);