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"
30 #include "wx/menuitem.h"
33 #include "wx/osx/private.h"
35 // other standard headers
36 // ----------------------
39 IMPLEMENT_ABSTRACT_CLASS( wxMenuImpl
, wxObject
)
41 wxMenuImpl::~wxMenuImpl()
45 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
46 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
48 // the (popup) menu title has this special id
49 static const int idMenuTitle
= -3;
51 // ============================================================================
53 // ============================================================================
54 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
55 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
59 // Construct a menu with optional title (then use append)
63 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
65 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
68 menuIter
= menuIter
->GetNext();
70 return menuIter
->GetData() ;
76 m_startRadioGroup
= -1;
77 m_allowRearrange
= true;
78 m_noEventsMode
= false;
80 m_peer
= wxMenuImpl::Create( this, wxStripMenuCodes(m_title
) );
83 // if we have a title, insert it in the beginning of the menu
84 if ( !m_title
.empty() )
86 Append(idMenuTitle
, m_title
) ;
96 WXHMENU
wxMenu::GetHMenu() const
99 return m_peer
->GetHMenu();
105 // not available on the mac platform
108 void wxMenu::Attach(wxMenuBarBase
*menubar
)
110 wxMenuBase::Attach(menubar
);
115 void wxMenu::SetAllowRearrange( bool allow
)
117 m_allowRearrange
= allow
;
120 void wxMenu::SetNoEventsMode( bool noEvents
)
122 m_noEventsMode
= noEvents
;
125 // function appends a new item or submenu to the menu
126 // append a new item or submenu to the menu
127 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
129 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
130 m_peer
->InsertOrAppend( pItem
, pos
);
132 if ( pItem
->IsSeparator() )
134 // nothing to do here
138 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
139 if ( pSubMenu
!= NULL
)
141 wxASSERT_MSG( pSubMenu
->GetHMenu() != NULL
, wxT("invalid submenu added"));
142 pSubMenu
->m_menuParent
= this ;
144 pSubMenu
->DoRearrange();
148 if ( pItem
->GetId() == idMenuTitle
)
149 pItem
->GetMenu()->Enable( idMenuTitle
, false );
153 // if we're already attached to the menubar, we must update it
154 if ( IsAttached() && GetMenuBar()->IsAttached() )
155 GetMenuBar()->Refresh();
160 void wxMenu::EndRadioGroup()
162 // we're not inside a radio group any longer
163 m_startRadioGroup
= -1;
166 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
168 wxCHECK_MSG( item
, NULL
, wxT("NULL item in wxMenu::DoAppend") );
172 if ( item
->GetKind() == wxITEM_RADIO
)
174 int count
= GetMenuItemCount();
176 if ( m_startRadioGroup
== -1 )
178 // start a new radio group
179 m_startRadioGroup
= count
;
181 // for now it has just one element
182 item
->SetAsRadioGroupStart();
183 item
->SetRadioGroupEnd(m_startRadioGroup
);
185 // ensure that we have a checked item in the radio group
188 else // extend the current radio group
190 // we need to update its end item
191 item
->SetRadioGroupStart(m_startRadioGroup
);
192 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
196 node
->GetData()->SetRadioGroupEnd(count
);
200 wxFAIL_MSG( wxT("where is the radio group start item?") );
204 else // not a radio item
209 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
213 // check the item initially
219 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
221 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
227 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
230 // we need to find the items position in the child list
232 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
234 for ( pos = 0; node; pos++ )
236 if ( node->GetData() == item )
239 node = node->GetNext();
242 // DoRemove() (unlike Remove) can only be called for existing item!
243 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
245 wxOSXMenuRemoveItem(m_hMenu , pos );
247 m_peer
->Remove( item
);
248 // and from internal data structures
249 return wxMenuBase::DoRemove(item
);
252 void wxMenu::SetTitle(const wxString
& label
)
255 m_peer
->SetTitle( wxStripMenuCodes( label
) );
258 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
260 bool processed
= false;
262 // Try the menu's event handler
263 if ( /* !processed && */ GetEventHandler())
264 processed
= GetEventHandler()->SafelyProcessEvent(event
);
266 // Try the window the menu was popped up from
267 // (and up through the hierarchy)
268 wxWindow
*win
= GetInvokingWindow();
269 if ( !processed
&& win
)
270 processed
= win
->HandleWindowEvent(event
);
275 // ---------------------------------------------------------------------------
277 // ---------------------------------------------------------------------------
279 wxWindow
*wxMenu::GetWindow() const
281 if ( m_invokingWindow
!= NULL
)
282 return m_invokingWindow
;
283 else if ( GetMenuBar() != NULL
)
284 return (wxWindow
*) GetMenuBar()->GetFrame();
289 // MacOS needs to know about submenus somewhere within this menu
290 // before it can be displayed, also hide special menu items
291 // like preferences that are handled by the OS
292 void wxMenu::DoRearrange()
294 if ( !AllowRearrange() )
297 wxMenuItem
* previousItem
= NULL
;
299 wxMenuItemList::compatibility_iterator node
;
302 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
304 item
= (wxMenuItem
*)node
->GetData();
305 wxMenu
* subMenu
= item
->GetSubMenu() ;
312 // what we do here is to hide the special items which are
313 // shown in the application menu anyhow -- it doesn't make
314 // sense to show them in their normal place as well
315 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
316 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
317 item
->GetId() == wxApp::s_macExitMenuItemId
)
320 item
->GetPeer()->Hide( true );
322 // also check for a separator which was used just to
323 // separate this item from the others, so don't leave
324 // separator at the menu start or end nor 2 consecutive
326 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
327 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
329 wxMenuItem
*sepToHide
= 0;
330 if ( !previousItem
&& next
&& next
->IsSeparator() )
332 // next (i.e. second as we must be first) item is
333 // the separator to hide
334 wxASSERT_MSG( pos
== 0, wxT("should be the menu start") );
337 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
338 previousItem
!= NULL
&&
339 previousItem
->IsSeparator() )
341 // prev item is a trailing separator we want to hide
342 sepToHide
= previousItem
;
344 else if ( previousItem
&& previousItem
->IsSeparator() &&
345 next
&& next
->IsSeparator() )
347 // two consecutive separators, this is one too many
353 // hide the separator as well
354 sepToHide
->GetPeer()->Hide( true );
359 previousItem
= item
;
364 bool wxMenu::HandleCommandUpdateStatus( wxMenuItem
* item
, wxWindow
* senderWindow
)
366 int id
= item
? item
->GetId() : 0;
367 wxUpdateUIEvent
event(id
);
368 event
.SetEventObject( this );
370 bool processed
= false;
372 // Try the menu's event handler
374 wxEvtHandler
*handler
= GetEventHandler();
376 processed
= handler
->ProcessEvent(event
);
379 // Try the window the menu was popped up from
380 // (and up through the hierarchy)
383 const wxMenuBase
*menu
= this;
386 wxWindow
*win
= menu
->GetInvokingWindow();
389 processed
= win
->HandleWindowEvent(event
);
393 menu
= menu
->GetParent();
397 if ( !processed
&& senderWindow
!= NULL
)
399 processed
= senderWindow
->HandleWindowEvent(event
);
404 // if anything changed, update the changed attribute
405 if (event
.GetSetText())
406 SetLabel(id
, event
.GetText());
407 if (event
.GetSetChecked())
408 Check(id
, event
.GetChecked());
409 if (event
.GetSetEnabled())
410 Enable(id
, event
.GetEnabled());
415 // these two items are also managed by the Carbon Menu Manager, therefore we must
416 // always reset them ourselves
419 if ( id
== wxApp::s_macExitMenuItemId
)
421 cmd
= kHICommandQuit
;
423 else if (id
== wxApp::s_macPreferencesMenuItemId
)
425 cmd
= kHICommandPreferences
;
430 if ( !item
->IsEnabled() || wxDialog::OSXHasModalDialogsOpen() )
431 DisableMenuCommand( NULL
, cmd
) ;
433 EnableMenuCommand( NULL
, cmd
) ;
442 bool wxMenu::HandleCommandProcess( wxMenuItem
* item
, wxWindow
* senderWindow
)
444 int id
= item
? item
->GetId() : 0;
445 bool processed
= false;
446 if (item
->IsCheckable())
447 item
->Check( !item
->IsChecked() ) ;
449 if ( SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) )
453 if ( senderWindow
!= NULL
)
455 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, id
);
456 event
.SetEventObject(senderWindow
);
457 event
.SetInt(item
->IsCheckable() ? item
->IsChecked() : -1);
459 if ( senderWindow
->HandleWindowEvent(event
) )
466 void wxMenu::HandleMenuItemHighlighted( wxMenuItem
* item
)
468 int id
= item
? item
->GetId() : 0;
469 wxMenuEvent
wxevent(wxEVT_MENU_HIGHLIGHT
, id
, this);
470 DoHandleMenuEvent( wxevent
);
473 void wxMenu::HandleMenuOpened()
475 wxMenuEvent
wxevent(wxEVT_MENU_OPEN
, 0, this);
476 DoHandleMenuEvent( wxevent
);
479 void wxMenu::HandleMenuClosed()
481 wxMenuEvent
wxevent(wxEVT_MENU_CLOSE
, 0, this);
482 DoHandleMenuEvent( wxevent
);
485 bool wxMenu::DoHandleMenuEvent(wxEvent
& wxevent
)
487 wxevent
.SetEventObject(this);
488 wxEvtHandler
* handler
= GetEventHandler();
489 if (handler
&& handler
->ProcessEvent(wxevent
))
495 wxWindow
*win
= GetInvokingWindow();
498 if ( win
->HandleWindowEvent(wxevent
) )
509 Mac Implementation note :
511 The Mac has only one global menubar, so we attempt to install the currently
512 active menubar from a frame, we currently don't take into account mdi-frames
513 which would ask for menu-merging
515 Secondly there is no mac api for changing a menubar that is not the current
516 menubar, so we have to wait for preparing the actual menubar until the
517 wxMenubar is to be used
519 We can in subsequent versions use MacInstallMenuBar to provide some sort of
520 auto-merge for MDI in case this will be necessary
524 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
525 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
526 bool wxMenuBar::s_macAutoWindowMenu
= true ;
527 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
529 void wxMenuBar::Init()
531 m_eventHandler
= this;
532 m_menuBarFrame
= NULL
;
533 m_invokingWindow
= NULL
;
534 m_rootMenu
= new wxMenu();
535 m_appleMenu
= new wxMenu();
536 m_appleMenu
->SetAllowRearrange(false);
537 m_appleMenu
->Append( wxApp::s_macAboutMenuItemId
, "About..." );
538 m_appleMenu
->AppendSeparator();
539 #if !wxOSX_USE_CARBON
540 m_appleMenu
->Append( wxApp::s_macPreferencesMenuItemId
, "Preferences..." );
541 m_appleMenu
->AppendSeparator();
542 m_appleMenu
->Append( wxApp::s_macExitMenuItemId
, "Quit\tCtrl+Q" );
545 m_rootMenu
->AppendSubMenu(m_appleMenu
, "\x14") ;
548 wxMenuBar::wxMenuBar()
553 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
558 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
562 m_titles
.Alloc(count
);
564 for ( size_t i
= 0; i
< count
; i
++ )
566 m_menus
.Append(menus
[i
]);
567 m_titles
.Add(titles
[i
]);
569 menus
[i
]->Attach(this);
570 Append( menus
[i
], titles
[i
] );
574 wxMenuBar::~wxMenuBar()
576 if (s_macCommonMenuBar
== this)
577 s_macCommonMenuBar
= NULL
;
579 if (s_macInstalledMenuBar
== this)
581 s_macInstalledMenuBar
= NULL
;
585 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
587 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
590 void wxMenuBar::MacInstallMenuBar()
592 if ( s_macInstalledMenuBar
== this )
595 m_rootMenu
->GetPeer()->MakeRoot();
599 MenuBarHandle menubar
= NULL
;
601 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
603 ::SetMenuBar( menubar
) ;
604 DisposeMenuBar( menubar
) ;
605 MenuHandle appleMenu
= NULL
;
607 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
608 verify_noerr( SetMenuTitleWithCFString( appleMenu
, CFSTR( "\x14" ) ) );
610 // Add About/Preferences separator only on OS X
611 // KH/RN: Separator is always present on 10.3 but not on 10.2
612 // However, the change from 10.2 to 10.3 suggests it is preferred
613 InsertMenuItemTextWithCFString( appleMenu
,
614 CFSTR(""), 0, kMenuItemAttrSeparator
, 0);
615 InsertMenuItemTextWithCFString( appleMenu
,
616 CFSTR("About..."), 0, 0, 0);
617 MacInsertMenu( appleMenu
, 0 ) ;
619 // if we have a mac help menu, clean it up before adding new items
620 MenuHandle helpMenuHandle
;
621 MenuItemIndex firstUserHelpMenuItem
;
623 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
625 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
626 DeleteMenuItem( helpMenuHandle
, i
) ;
630 helpMenuHandle
= NULL
;
633 if ( wxApp::s_macPreferencesMenuItemId
)
635 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
636 if ( item
== NULL
|| !(item
->IsEnabled()) )
637 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
639 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
642 // Unlike preferences which may or may not exist, the Quit item should be always
643 // enabled unless it is added by the application and then disabled, otherwise
644 // a program would be required to add an item with wxID_EXIT in order to get the
645 // Quit menu item to be enabled, which seems a bit burdensome.
646 if ( wxApp::s_macExitMenuItemId
)
648 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
649 if ( item
!= NULL
&& !(item
->IsEnabled()) )
650 DisableMenuCommand( NULL
, kHICommandQuit
) ;
652 EnableMenuCommand( NULL
, kHICommandQuit
) ;
655 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
656 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
657 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
658 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
660 wxMenuItemList::compatibility_iterator node
;
662 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
663 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
665 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
667 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
669 item
= (wxMenuItem
*)node
->GetData();
670 subMenu
= item
->GetSubMenu() ;
673 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding() );
674 MenuItemIndex position
= CountMenuItems(mh
);
675 ::SetMenuItemHierarchicalMenu(mh
, position
, MAC_WXHMENU(subMenu
->GetHMenu()));
679 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
681 // we have found a user help menu and an item other than the about item,
682 // so we can create the mac help menu now, if we haven't created it yet
683 if ( helpMenuHandle
== NULL
)
685 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
687 helpMenuHandle
= NULL
;
693 if ( item
->IsSeparator() )
695 if ( helpMenuHandle
)
696 AppendMenuItemTextWithCFString( helpMenuHandle
,
697 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
702 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
704 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
706 // this will be taken care of below
710 if ( helpMenuHandle
)
712 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
713 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
714 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
724 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
725 && GetAutoWindowMenu() )
727 if ( MacGetWindowMenuHMenu() == NULL
)
729 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
732 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
736 // get the insertion point in the standard menu
737 MenuItemIndex winListStart
;
738 GetIndMenuItemWithCommandID(wm
,
739 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
741 // add a separator so that the standard items and the custom items
742 // aren't mixed together, but only if this is the first run
743 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
744 'WXWM', 1, NULL
, NULL
);
746 if ( err
== menuItemNotFoundErr
)
748 InsertMenuItemTextWithCFString( wm
,
749 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
752 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
756 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
757 menu
->MacBeforeDisplay(false) ;
759 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
763 // take care of the about menu item wherever it is
766 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
770 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
771 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
772 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
773 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
774 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
775 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
780 if ( GetAutoWindowMenu() )
782 if ( MacGetWindowMenuHMenu() == NULL
)
783 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
785 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
791 s_macInstalledMenuBar
= this;
794 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
796 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
798 m_rootMenu
->FindItemByPosition( pos
)->Enable(enable
);
803 bool wxMenuBar::Enable(bool enable
)
805 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
808 for (i
= 0; i
< GetMenuCount(); i
++)
809 EnableTop(i
, enable
);
814 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
816 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
818 m_titles
[pos
] = label
;
823 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
826 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
828 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
829 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
831 return m_titles
[pos
];
834 int wxMenuBar::FindMenu(const wxString
& title
)
836 wxString menuTitle
= wxStripMenuCodes(title
);
838 size_t count
= GetMenuCount();
839 for ( size_t i
= 0; i
< count
; i
++ )
841 wxString title
= wxStripMenuCodes(m_titles
[i
]);
842 if ( menuTitle
== title
)
849 // ---------------------------------------------------------------------------
850 // wxMenuBar construction
851 // ---------------------------------------------------------------------------
853 const int firstMenuPos
= 1; // to account for the 0th application menu on mac
855 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
857 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
861 m_titles
[pos
] = title
;
863 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
864 m_rootMenu
->Remove(item
);
865 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
867 if (m_invokingWindow
)
868 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
873 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
875 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
878 m_titles
.Insert(title
, pos
);
880 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
882 if (m_invokingWindow
)
883 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
888 wxMenu
*wxMenuBar::Remove(size_t pos
)
890 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
894 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
895 m_rootMenu
->Remove(item
);
897 m_titles
.RemoveAt(pos
);
902 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
904 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
905 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
907 if ( !wxMenuBarBase::Append(menu
, title
) )
912 m_rootMenu
->AppendSubMenu(menu
, title
);
914 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
915 // adding menu later on.
916 if (m_invokingWindow
)
917 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
922 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
924 menu
->SetInvokingWindow( NULL
);
925 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
929 wxMenuItem
*menuitem
= node
->GetData();
930 if (menuitem
->IsSubMenu())
931 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
933 node
= node
->GetNext();
937 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
939 menu
->SetInvokingWindow( win
);
940 wxMenuItem
*menuitem
;
941 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
945 menuitem
= node
->GetData();
946 if (menuitem
->IsSubMenu())
947 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
949 node
= node
->GetNext();
953 void wxMenuBar::UnsetInvokingWindow()
955 m_invokingWindow
= NULL
;
956 wxMenubarUnsetInvokingWindow(m_appleMenu
);
959 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
963 menu
= node
->GetData();
964 wxMenubarUnsetInvokingWindow( menu
);
966 node
= node
->GetNext();
970 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
972 m_invokingWindow
= frame
;
973 wxMenubarSetInvokingWindow(m_appleMenu
, frame
);
976 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
980 menu
= node
->GetData();
981 wxMenubarSetInvokingWindow( menu
, frame
);
983 node
= node
->GetNext();
987 void wxMenuBar::Detach()
989 wxMenuBarBase::Detach() ;
992 void wxMenuBar::Attach(wxFrame
*frame
)
994 wxMenuBarBase::Attach( frame
) ;
997 // ---------------------------------------------------------------------------
998 // wxMenuBar searching for menu items
999 // ---------------------------------------------------------------------------
1001 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1002 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1003 const wxString
& itemString
) const
1005 wxString menuLabel
= wxStripMenuCodes(menuString
);
1006 size_t count
= GetMenuCount();
1007 for ( size_t i
= 0; i
< count
; i
++ )
1009 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1010 if ( menuLabel
== title
)
1011 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1017 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1022 wxMenuItem
*item
= NULL
;
1023 size_t count
= GetMenuCount();
1024 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1025 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);