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 bool wxMenu::HandleCommandProcess( wxMenuItem
* item
, wxWindow
* senderWindow
)
417 int id
= item
? item
->GetId() : 0;
418 bool processed
= false;
419 if (item
->IsCheckable())
420 item
->Check( !item
->IsChecked() ) ;
422 if ( SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) )
426 if ( senderWindow
!= NULL
)
428 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, id
);
429 event
.SetEventObject(senderWindow
);
430 event
.SetInt(item
->IsCheckable() ? item
->IsChecked() : -1);
432 if ( senderWindow
->HandleWindowEvent(event
) )
439 void wxMenu::HandleMenuItemHighlighted( wxMenuItem
* item
)
441 int id
= item
? item
->GetId() : 0;
442 wxMenuEvent
wxevent(wxEVT_MENU_HIGHLIGHT
, id
, this);
443 DoHandleMenuEvent( wxevent
);
446 void wxMenu::HandleMenuOpened()
448 wxMenuEvent
wxevent(wxEVT_MENU_OPEN
, 0, this);
449 DoHandleMenuEvent( wxevent
);
452 void wxMenu::HandleMenuClosed()
454 wxMenuEvent
wxevent(wxEVT_MENU_CLOSE
, 0, this);
455 DoHandleMenuEvent( wxevent
);
458 bool wxMenu::DoHandleMenuEvent(wxEvent
& wxevent
)
460 wxevent
.SetEventObject(this);
461 wxEvtHandler
* handler
= GetEventHandler();
462 if (handler
&& handler
->ProcessEvent(wxevent
))
468 wxWindow
*win
= GetInvokingWindow();
471 if ( win
->HandleWindowEvent(wxevent
) )
482 Mac Implementation note :
484 The Mac has only one global menubar, so we attempt to install the currently
485 active menubar from a frame, we currently don't take into account mdi-frames
486 which would ask for menu-merging
488 Secondly there is no mac api for changing a menubar that is not the current
489 menubar, so we have to wait for preparing the actual menubar until the
490 wxMenubar is to be used
492 We can in subsequent versions use MacInstallMenuBar to provide some sort of
493 auto-merge for MDI in case this will be necessary
497 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
498 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
499 bool wxMenuBar::s_macAutoWindowMenu
= true ;
500 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
502 void wxMenuBar::Init()
504 m_eventHandler
= this;
505 m_menuBarFrame
= NULL
;
506 m_invokingWindow
= NULL
;
507 m_rootMenu
= new wxMenu();
508 m_appleMenu
= new wxMenu();
509 m_appleMenu
->SetAllowRearrange(false);
510 m_appleMenu
->Append( wxApp::s_macAboutMenuItemId
, "About..." );
511 m_appleMenu
->AppendSeparator();
512 #if !wxOSX_USE_CARBON
513 m_appleMenu
->Append( wxApp::s_macPreferencesMenuItemId
, "Preferences..." );
514 m_appleMenu
->AppendSeparator();
515 m_appleMenu
->Append( wxApp::s_macExitMenuItemId
, "Quit\tCtrl+Q" );
518 m_rootMenu
->AppendSubMenu(m_appleMenu
, "\x14") ;
521 wxMenuBar::wxMenuBar()
526 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
531 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
535 m_titles
.Alloc(count
);
537 for ( size_t i
= 0; i
< count
; i
++ )
539 m_menus
.Append(menus
[i
]);
540 m_titles
.Add(titles
[i
]);
542 menus
[i
]->Attach(this);
543 Append( menus
[i
], titles
[i
] );
547 wxMenuBar::~wxMenuBar()
549 if (s_macCommonMenuBar
== this)
550 s_macCommonMenuBar
= NULL
;
552 if (s_macInstalledMenuBar
== this)
554 s_macInstalledMenuBar
= NULL
;
558 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
560 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
563 void wxMenuBar::MacInstallMenuBar()
565 if ( s_macInstalledMenuBar
== this )
568 m_rootMenu
->GetPeer()->MakeRoot();
569 // DisableMenuCommand( NULL , kHICommandPreferences ) ;
572 MenuBarHandle menubar
= NULL
;
574 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
576 ::SetMenuBar( menubar
) ;
577 DisposeMenuBar( menubar
) ;
578 MenuHandle appleMenu
= NULL
;
580 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
581 verify_noerr( SetMenuTitleWithCFString( appleMenu
, CFSTR( "\x14" ) ) );
583 // Add About/Preferences separator only on OS X
584 // KH/RN: Separator is always present on 10.3 but not on 10.2
585 // However, the change from 10.2 to 10.3 suggests it is preferred
586 InsertMenuItemTextWithCFString( appleMenu
,
587 CFSTR(""), 0, kMenuItemAttrSeparator
, 0);
588 InsertMenuItemTextWithCFString( appleMenu
,
589 CFSTR("About..."), 0, 0, 0);
590 MacInsertMenu( appleMenu
, 0 ) ;
592 // if we have a mac help menu, clean it up before adding new items
593 MenuHandle helpMenuHandle
;
594 MenuItemIndex firstUserHelpMenuItem
;
596 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
598 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
599 DeleteMenuItem( helpMenuHandle
, i
) ;
603 helpMenuHandle
= NULL
;
606 if ( wxApp::s_macPreferencesMenuItemId
)
608 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
609 if ( item
== NULL
|| !(item
->IsEnabled()) )
610 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
612 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
615 // Unlike preferences which may or may not exist, the Quit item should be always
616 // enabled unless it is added by the application and then disabled, otherwise
617 // a program would be required to add an item with wxID_EXIT in order to get the
618 // Quit menu item to be enabled, which seems a bit burdensome.
619 if ( wxApp::s_macExitMenuItemId
)
621 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
622 if ( item
!= NULL
&& !(item
->IsEnabled()) )
623 DisableMenuCommand( NULL
, kHICommandQuit
) ;
625 EnableMenuCommand( NULL
, kHICommandQuit
) ;
628 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
629 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
630 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
631 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
633 wxMenuItemList::compatibility_iterator node
;
635 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
636 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
638 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
640 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
642 item
= (wxMenuItem
*)node
->GetData();
643 subMenu
= item
->GetSubMenu() ;
646 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding() );
647 MenuItemIndex position
= CountMenuItems(mh
);
648 ::SetMenuItemHierarchicalMenu(mh
, position
, MAC_WXHMENU(subMenu
->GetHMenu()));
652 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
654 // we have found a user help menu and an item other than the about item,
655 // so we can create the mac help menu now, if we haven't created it yet
656 if ( helpMenuHandle
== NULL
)
658 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
660 helpMenuHandle
= NULL
;
666 if ( item
->IsSeparator() )
668 if ( helpMenuHandle
)
669 AppendMenuItemTextWithCFString( helpMenuHandle
,
670 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
675 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
677 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
679 // this will be taken care of below
683 if ( helpMenuHandle
)
685 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
686 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
687 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
697 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
698 && GetAutoWindowMenu() )
700 if ( MacGetWindowMenuHMenu() == NULL
)
702 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
705 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
709 // get the insertion point in the standard menu
710 MenuItemIndex winListStart
;
711 GetIndMenuItemWithCommandID(wm
,
712 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
714 // add a separator so that the standard items and the custom items
715 // aren't mixed together, but only if this is the first run
716 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
717 'WXWM', 1, NULL
, NULL
);
719 if ( err
== menuItemNotFoundErr
)
721 InsertMenuItemTextWithCFString( wm
,
722 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
725 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
729 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
730 menu
->MacBeforeDisplay(false) ;
732 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
736 // take care of the about menu item wherever it is
739 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
743 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
744 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
745 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
746 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
747 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
748 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
753 if ( GetAutoWindowMenu() )
755 if ( MacGetWindowMenuHMenu() == NULL
)
756 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
758 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
764 s_macInstalledMenuBar
= this;
767 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
769 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
771 m_rootMenu
->FindItemByPosition( pos
)->Enable(enable
);
776 bool wxMenuBar::Enable(bool enable
)
778 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
781 for (i
= 0; i
< GetMenuCount(); i
++)
782 EnableTop(i
, enable
);
787 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
789 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
791 m_titles
[pos
] = label
;
796 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
799 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
801 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
802 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
804 return m_titles
[pos
];
807 int wxMenuBar::FindMenu(const wxString
& title
)
809 wxString menuTitle
= wxStripMenuCodes(title
);
811 size_t count
= GetMenuCount();
812 for ( size_t i
= 0; i
< count
; i
++ )
814 wxString title
= wxStripMenuCodes(m_titles
[i
]);
815 if ( menuTitle
== title
)
822 // ---------------------------------------------------------------------------
823 // wxMenuBar construction
824 // ---------------------------------------------------------------------------
826 const int firstMenuPos
= 1; // to account for the 0th application menu on mac
828 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
830 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
834 m_titles
[pos
] = title
;
836 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
837 m_rootMenu
->Remove(item
);
838 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
840 if (m_invokingWindow
)
841 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
846 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
848 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
851 m_titles
.Insert(title
, pos
);
853 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
855 if (m_invokingWindow
)
856 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
861 wxMenu
*wxMenuBar::Remove(size_t pos
)
863 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
867 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
868 m_rootMenu
->Remove(item
);
870 m_titles
.RemoveAt(pos
);
875 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
877 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
878 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
880 if ( !wxMenuBarBase::Append(menu
, title
) )
885 m_rootMenu
->AppendSubMenu(menu
, title
);
887 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
888 // adding menu later on.
889 if (m_invokingWindow
)
890 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
895 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
897 menu
->SetInvokingWindow( NULL
);
898 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
902 wxMenuItem
*menuitem
= node
->GetData();
903 if (menuitem
->IsSubMenu())
904 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
906 node
= node
->GetNext();
910 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
912 menu
->SetInvokingWindow( win
);
913 wxMenuItem
*menuitem
;
914 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
918 menuitem
= node
->GetData();
919 if (menuitem
->IsSubMenu())
920 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
922 node
= node
->GetNext();
926 void wxMenuBar::UnsetInvokingWindow()
928 m_invokingWindow
= NULL
;
929 wxMenubarUnsetInvokingWindow(m_appleMenu
);
932 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
936 menu
= node
->GetData();
937 wxMenubarUnsetInvokingWindow( menu
);
939 node
= node
->GetNext();
943 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
945 m_invokingWindow
= frame
;
946 wxMenubarSetInvokingWindow(m_appleMenu
, frame
);
949 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
953 menu
= node
->GetData();
954 wxMenubarSetInvokingWindow( menu
, frame
);
956 node
= node
->GetNext();
960 void wxMenuBar::Detach()
962 wxMenuBarBase::Detach() ;
965 void wxMenuBar::Attach(wxFrame
*frame
)
967 wxMenuBarBase::Attach( frame
) ;
970 // ---------------------------------------------------------------------------
971 // wxMenuBar searching for menu items
972 // ---------------------------------------------------------------------------
974 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
975 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
976 const wxString
& itemString
) const
978 wxString menuLabel
= wxStripMenuCodes(menuString
);
979 size_t count
= GetMenuCount();
980 for ( size_t i
= 0; i
< count
; i
++ )
982 wxString title
= wxStripMenuCodes(m_titles
[i
]);
983 if ( menuLabel
== title
)
984 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
990 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
995 wxMenuItem
*item
= NULL
;
996 size_t count
= GetMenuCount();
997 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
998 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);