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/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 // ============================================================================
55 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
56 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
60 // Construct a menu with optional title (then use append)
64 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
66 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
69 menuIter
= menuIter
->GetNext();
71 return menuIter
->GetData() ;
77 m_startRadioGroup
= -1;
78 m_allowRearrange
= true;
79 m_noEventsMode
= false;
81 m_peer
= wxMenuImpl::Create( this, wxStripMenuCodes(m_title
) );
84 // if we have a title, insert it in the beginning of the menu
85 if ( !m_title
.empty() )
87 Append(idMenuTitle
, m_title
) ;
97 WXHMENU
wxMenu::GetHMenu() const
100 return m_peer
->GetHMenu();
106 // not available on the mac platform
109 void wxMenu::Attach(wxMenuBarBase
*menubar
)
111 wxMenuBase::Attach(menubar
);
116 void wxMenu::SetAllowRearrange( bool allow
)
118 m_allowRearrange
= allow
;
121 void wxMenu::SetNoEventsMode( bool noEvents
)
123 m_noEventsMode
= noEvents
;
126 // function appends a new item or submenu to the menu
127 // append a new item or submenu to the menu
128 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
130 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
131 m_peer
->InsertOrAppend( pItem
, pos
);
133 if ( pItem
->IsSeparator() )
135 // nothing to do here
139 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
140 if ( pSubMenu
!= NULL
)
142 wxASSERT_MSG( pSubMenu
->GetHMenu() != NULL
, wxT("invalid submenu added"));
143 pSubMenu
->m_menuParent
= this ;
145 pSubMenu
->DoRearrange();
149 if ( pItem
->GetId() == idMenuTitle
)
150 pItem
->GetMenu()->Enable( idMenuTitle
, false );
154 // if we're already attached to the menubar, we must update it
155 if ( IsAttached() && GetMenuBar()->IsAttached() )
156 GetMenuBar()->Refresh();
161 void wxMenu::EndRadioGroup()
163 // we're not inside a radio group any longer
164 m_startRadioGroup
= -1;
167 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
169 wxCHECK_MSG( item
, NULL
, wxT("NULL item in wxMenu::DoAppend") );
173 if ( item
->GetKind() == wxITEM_RADIO
)
175 int count
= GetMenuItemCount();
177 if ( m_startRadioGroup
== -1 )
179 // start a new radio group
180 m_startRadioGroup
= count
;
182 // for now it has just one element
183 item
->SetAsRadioGroupStart();
184 item
->SetRadioGroupEnd(m_startRadioGroup
);
186 // ensure that we have a checked item in the radio group
189 else // extend the current radio group
191 // we need to update its end item
192 item
->SetRadioGroupStart(m_startRadioGroup
);
193 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
197 node
->GetData()->SetRadioGroupEnd(count
);
201 wxFAIL_MSG( wxT("where is the radio group start item?") );
205 else // not a radio item
210 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
214 // check the item initially
220 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
222 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
228 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
231 // we need to find the items position in the child list
233 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
235 for ( pos = 0; node; pos++ )
237 if ( node->GetData() == item )
240 node = node->GetNext();
243 // DoRemove() (unlike Remove) can only be called for existing item!
244 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
246 wxOSXMenuRemoveItem(m_hMenu , pos );
248 m_peer
->Remove( item
);
249 // and from internal data structures
250 return wxMenuBase::DoRemove(item
);
253 void wxMenu::SetTitle(const wxString
& label
)
256 m_peer
->SetTitle( wxStripMenuCodes( label
) );
259 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
261 bool processed
= false;
263 // Try the menu's event handler
264 if ( /* !processed && */ GetEventHandler())
265 processed
= GetEventHandler()->SafelyProcessEvent(event
);
267 // Try the window the menu was popped up from
268 // (and up through the hierarchy)
269 wxWindow
*win
= GetInvokingWindow();
270 if ( !processed
&& win
)
271 processed
= win
->HandleWindowEvent(event
);
276 // ---------------------------------------------------------------------------
278 // ---------------------------------------------------------------------------
280 wxWindow
*wxMenu::GetWindow() const
282 if ( m_invokingWindow
!= NULL
)
283 return m_invokingWindow
;
284 else if ( GetMenuBar() != NULL
)
285 return (wxWindow
*) GetMenuBar()->GetFrame();
290 // MacOS needs to know about submenus somewhere within this menu
291 // before it can be displayed, also hide special menu items
292 // like preferences that are handled by the OS
293 void wxMenu::DoRearrange()
295 if ( !AllowRearrange() )
298 wxMenuItem
* previousItem
= NULL
;
300 wxMenuItemList::compatibility_iterator node
;
303 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
305 item
= (wxMenuItem
*)node
->GetData();
306 wxMenu
* subMenu
= item
->GetSubMenu() ;
313 // what we do here is to hide the special items which are
314 // shown in the application menu anyhow -- it doesn't make
315 // sense to show them in their normal place as well
316 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
317 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
318 item
->GetId() == wxApp::s_macExitMenuItemId
)
321 item
->GetPeer()->Hide( true );
323 // also check for a separator which was used just to
324 // separate this item from the others, so don't leave
325 // separator at the menu start or end nor 2 consecutive
327 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
328 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
330 wxMenuItem
*sepToHide
= 0;
331 if ( !previousItem
&& next
&& next
->IsSeparator() )
333 // next (i.e. second as we must be first) item is
334 // the separator to hide
335 wxASSERT_MSG( pos
== 0, wxT("should be the menu start") );
338 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
339 previousItem
!= NULL
&&
340 previousItem
->IsSeparator() )
342 // prev item is a trailing separator we want to hide
343 sepToHide
= previousItem
;
345 else if ( previousItem
&& previousItem
->IsSeparator() &&
346 next
&& next
->IsSeparator() )
348 // two consecutive separators, this is one too many
354 // hide the separator as well
355 sepToHide
->GetPeer()->Hide( true );
360 previousItem
= item
;
365 bool wxMenu::HandleCommandUpdateStatus( wxMenuItem
* item
, wxWindow
* senderWindow
)
367 int id
= item
? item
->GetId() : 0;
368 wxUpdateUIEvent
event(id
);
369 event
.SetEventObject( this );
371 bool processed
= false;
373 // Try the menu's event handler
375 wxEvtHandler
*handler
= GetEventHandler();
377 processed
= handler
->ProcessEvent(event
);
380 // Try the window the menu was popped up from
381 // (and up through the hierarchy)
384 const wxMenuBase
*menu
= this;
387 wxWindow
*win
= menu
->GetInvokingWindow();
390 processed
= win
->HandleWindowEvent(event
);
394 menu
= menu
->GetParent();
398 if ( !processed
&& senderWindow
!= NULL
)
400 processed
= senderWindow
->HandleWindowEvent(event
);
405 // if anything changed, update the changed attribute
406 if (event
.GetSetText())
407 SetLabel(id
, event
.GetText());
408 if (event
.GetSetChecked())
409 Check(id
, event
.GetChecked());
410 if (event
.GetSetEnabled())
411 Enable(id
, event
.GetEnabled());
416 // these two items are also managed by the Carbon Menu Manager, therefore we must
417 // always reset them ourselves
420 if ( id
== wxApp::s_macExitMenuItemId
)
422 cmd
= kHICommandQuit
;
424 else if (id
== wxApp::s_macPreferencesMenuItemId
)
426 cmd
= kHICommandPreferences
;
431 if ( !item
->IsEnabled() || wxDialog::OSXHasModalDialogsOpen() )
432 DisableMenuCommand( NULL
, cmd
) ;
434 EnableMenuCommand( NULL
, cmd
) ;
443 bool wxMenu::HandleCommandProcess( wxMenuItem
* item
, wxWindow
* senderWindow
)
445 int id
= item
? item
->GetId() : 0;
446 bool processed
= false;
447 if (item
->IsCheckable())
448 item
->Check( !item
->IsChecked() ) ;
450 if ( SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) )
454 if ( senderWindow
!= NULL
)
456 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, id
);
457 event
.SetEventObject(senderWindow
);
458 event
.SetInt(item
->IsCheckable() ? item
->IsChecked() : -1);
460 if ( senderWindow
->HandleWindowEvent(event
) )
467 void wxMenu::HandleMenuItemHighlighted( wxMenuItem
* item
)
469 int id
= item
? item
->GetId() : 0;
470 wxMenuEvent
wxevent(wxEVT_MENU_HIGHLIGHT
, id
, this);
471 DoHandleMenuEvent( wxevent
);
474 void wxMenu::HandleMenuOpened()
476 wxMenuEvent
wxevent(wxEVT_MENU_OPEN
, 0, this);
477 DoHandleMenuEvent( wxevent
);
480 void wxMenu::HandleMenuClosed()
482 wxMenuEvent
wxevent(wxEVT_MENU_CLOSE
, 0, this);
483 DoHandleMenuEvent( wxevent
);
486 bool wxMenu::DoHandleMenuEvent(wxEvent
& wxevent
)
488 wxevent
.SetEventObject(this);
489 wxEvtHandler
* handler
= GetEventHandler();
490 if (handler
&& handler
->ProcessEvent(wxevent
))
496 wxWindow
*win
= GetInvokingWindow();
499 if ( win
->HandleWindowEvent(wxevent
) )
510 Mac Implementation note :
512 The Mac has only one global menubar, so we attempt to install the currently
513 active menubar from a frame, we currently don't take into account mdi-frames
514 which would ask for menu-merging
516 Secondly there is no mac api for changing a menubar that is not the current
517 menubar, so we have to wait for preparing the actual menubar until the
518 wxMenubar is to be used
520 We can in subsequent versions use MacInstallMenuBar to provide some sort of
521 auto-merge for MDI in case this will be necessary
525 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
526 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
527 bool wxMenuBar::s_macAutoWindowMenu
= true ;
528 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
530 void wxMenuBar::Init()
532 m_eventHandler
= this;
533 m_menuBarFrame
= NULL
;
534 m_invokingWindow
= NULL
;
535 m_rootMenu
= new wxMenu();
536 m_appleMenu
= new wxMenu();
537 m_appleMenu
->SetAllowRearrange(false);
538 m_appleMenu
->Append( wxApp::s_macAboutMenuItemId
, "About..." );
539 m_appleMenu
->AppendSeparator();
540 #if !wxOSX_USE_CARBON
541 m_appleMenu
->Append( wxApp::s_macPreferencesMenuItemId
, "Preferences..." );
542 m_appleMenu
->AppendSeparator();
543 m_appleMenu
->Append( wxApp::s_macExitMenuItemId
, "Quit\tCtrl+Q" );
546 m_rootMenu
->AppendSubMenu(m_appleMenu
, "\x14") ;
549 wxMenuBar::wxMenuBar()
554 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
559 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
563 m_titles
.Alloc(count
);
565 for ( size_t i
= 0; i
< count
; i
++ )
567 m_menus
.Append(menus
[i
]);
568 m_titles
.Add(titles
[i
]);
570 menus
[i
]->Attach(this);
571 Append( menus
[i
], titles
[i
] );
575 wxMenuBar::~wxMenuBar()
577 if (s_macCommonMenuBar
== this)
578 s_macCommonMenuBar
= NULL
;
580 if (s_macInstalledMenuBar
== this)
582 s_macInstalledMenuBar
= NULL
;
586 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
588 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
591 void wxMenuBar::MacInstallMenuBar()
593 if ( s_macInstalledMenuBar
== this )
596 m_rootMenu
->GetPeer()->MakeRoot();
600 MenuBarHandle menubar
= NULL
;
602 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
604 ::SetMenuBar( menubar
) ;
605 DisposeMenuBar( menubar
) ;
606 MenuHandle appleMenu
= NULL
;
608 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
609 verify_noerr( SetMenuTitleWithCFString( appleMenu
, CFSTR( "\x14" ) ) );
611 // Add About/Preferences separator only on OS X
612 // KH/RN: Separator is always present on 10.3 but not on 10.2
613 // However, the change from 10.2 to 10.3 suggests it is preferred
614 InsertMenuItemTextWithCFString( appleMenu
,
615 CFSTR(""), 0, kMenuItemAttrSeparator
, 0);
616 InsertMenuItemTextWithCFString( appleMenu
,
617 CFSTR("About..."), 0, 0, 0);
618 MacInsertMenu( appleMenu
, 0 ) ;
620 // if we have a mac help menu, clean it up before adding new items
621 MenuHandle helpMenuHandle
;
622 MenuItemIndex firstUserHelpMenuItem
;
624 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
626 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
627 DeleteMenuItem( helpMenuHandle
, i
) ;
631 helpMenuHandle
= NULL
;
634 if ( wxApp::s_macPreferencesMenuItemId
)
636 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
637 if ( item
== NULL
|| !(item
->IsEnabled()) )
638 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
640 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
643 // Unlike preferences which may or may not exist, the Quit item should be always
644 // enabled unless it is added by the application and then disabled, otherwise
645 // a program would be required to add an item with wxID_EXIT in order to get the
646 // Quit menu item to be enabled, which seems a bit burdensome.
647 if ( wxApp::s_macExitMenuItemId
)
649 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
650 if ( item
!= NULL
&& !(item
->IsEnabled()) )
651 DisableMenuCommand( NULL
, kHICommandQuit
) ;
653 EnableMenuCommand( NULL
, kHICommandQuit
) ;
656 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
657 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
658 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
659 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
661 wxMenuItemList::compatibility_iterator node
;
663 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
664 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
666 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
668 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
670 item
= (wxMenuItem
*)node
->GetData();
671 subMenu
= item
->GetSubMenu() ;
674 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding() );
675 MenuItemIndex position
= CountMenuItems(mh
);
676 ::SetMenuItemHierarchicalMenu(mh
, position
, MAC_WXHMENU(subMenu
->GetHMenu()));
680 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
682 // we have found a user help menu and an item other than the about item,
683 // so we can create the mac help menu now, if we haven't created it yet
684 if ( helpMenuHandle
== NULL
)
686 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
688 helpMenuHandle
= NULL
;
694 if ( item
->IsSeparator() )
696 if ( helpMenuHandle
)
697 AppendMenuItemTextWithCFString( helpMenuHandle
,
698 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
703 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
705 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
707 // this will be taken care of below
711 if ( helpMenuHandle
)
713 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
714 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
715 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
725 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
726 && GetAutoWindowMenu() )
728 if ( MacGetWindowMenuHMenu() == NULL
)
730 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
733 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
737 // get the insertion point in the standard menu
738 MenuItemIndex winListStart
;
739 GetIndMenuItemWithCommandID(wm
,
740 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
742 // add a separator so that the standard items and the custom items
743 // aren't mixed together, but only if this is the first run
744 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
745 'WXWM', 1, NULL
, NULL
);
747 if ( err
== menuItemNotFoundErr
)
749 InsertMenuItemTextWithCFString( wm
,
750 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
753 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
757 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
758 menu
->MacBeforeDisplay(false) ;
760 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
764 // take care of the about menu item wherever it is
767 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
771 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
772 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
773 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
774 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
775 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
776 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
781 if ( GetAutoWindowMenu() )
783 if ( MacGetWindowMenuHMenu() == NULL
)
784 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
786 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
792 s_macInstalledMenuBar
= this;
795 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
797 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
799 m_rootMenu
->FindItemByPosition( pos
)->Enable(enable
);
804 bool wxMenuBar::Enable(bool enable
)
806 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
809 for (i
= 0; i
< GetMenuCount(); i
++)
810 EnableTop(i
, enable
);
815 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
817 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
819 m_titles
[pos
] = label
;
824 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
827 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
829 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
830 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
832 return m_titles
[pos
];
835 int wxMenuBar::FindMenu(const wxString
& title
)
837 wxString menuTitle
= wxStripMenuCodes(title
);
839 size_t count
= GetMenuCount();
840 for ( size_t i
= 0; i
< count
; i
++ )
842 wxString title
= wxStripMenuCodes(m_titles
[i
]);
843 if ( menuTitle
== title
)
850 // ---------------------------------------------------------------------------
851 // wxMenuBar construction
852 // ---------------------------------------------------------------------------
854 const int firstMenuPos
= 1; // to account for the 0th application menu on mac
856 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
858 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
862 m_titles
[pos
] = title
;
864 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
865 m_rootMenu
->Remove(item
);
866 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
868 if (m_invokingWindow
)
869 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
874 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
876 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
879 m_titles
.Insert(title
, pos
);
881 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
883 if (m_invokingWindow
)
884 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
889 wxMenu
*wxMenuBar::Remove(size_t pos
)
891 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
895 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
896 m_rootMenu
->Remove(item
);
898 m_titles
.RemoveAt(pos
);
903 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
905 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
906 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
908 if ( !wxMenuBarBase::Append(menu
, title
) )
913 m_rootMenu
->AppendSubMenu(menu
, title
);
915 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
916 // adding menu later on.
917 if (m_invokingWindow
)
918 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
923 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
925 menu
->SetInvokingWindow( NULL
);
926 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
930 wxMenuItem
*menuitem
= node
->GetData();
931 if (menuitem
->IsSubMenu())
932 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
934 node
= node
->GetNext();
938 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
940 menu
->SetInvokingWindow( win
);
941 wxMenuItem
*menuitem
;
942 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
946 menuitem
= node
->GetData();
947 if (menuitem
->IsSubMenu())
948 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
950 node
= node
->GetNext();
954 void wxMenuBar::UnsetInvokingWindow()
956 m_invokingWindow
= NULL
;
957 wxMenubarUnsetInvokingWindow(m_appleMenu
);
960 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
964 menu
= node
->GetData();
965 wxMenubarUnsetInvokingWindow( menu
);
967 node
= node
->GetNext();
971 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
973 m_invokingWindow
= frame
;
974 wxMenubarSetInvokingWindow(m_appleMenu
, frame
);
977 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
981 menu
= node
->GetData();
982 wxMenubarSetInvokingWindow( menu
, frame
);
984 node
= node
->GetNext();
988 void wxMenuBar::Detach()
990 wxMenuBarBase::Detach() ;
993 void wxMenuBar::Attach(wxFrame
*frame
)
995 wxMenuBarBase::Attach( frame
) ;
998 // ---------------------------------------------------------------------------
999 // wxMenuBar searching for menu items
1000 // ---------------------------------------------------------------------------
1002 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1003 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1004 const wxString
& itemString
) const
1006 wxString menuLabel
= wxStripMenuCodes(menuString
);
1007 size_t count
= GetMenuCount();
1008 for ( size_t i
= 0; i
< count
; i
++ )
1010 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1011 if ( menuLabel
== title
)
1012 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1018 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1023 wxMenuItem
*item
= NULL
;
1024 size_t count
= GetMenuCount();
1025 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1026 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);