1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
19 #include "wx/wxprec.h"
23 #include "wx/menuitem.h"
24 #include "wx/window.h"
29 #include "wx/mac/uma.h"
31 // other standard headers
32 // ----------------------
35 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
36 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
38 // the (popup) menu title has this special id
39 static const int idMenuTitle
= -3;
41 const short kwxMacMenuBarResource
= 1 ;
42 const short kwxMacAppleMenuId
= 1 ;
45 // Find an item given the Macintosh Menu Reference
47 WX_DECLARE_HASH_MAP(MenuRef
, wxMenu
*, wxPointerHash
, wxPointerEqual
, MacMenuMap
);
49 static MacMenuMap wxWinMacMenuList
;
51 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
53 MacMenuMap::iterator node
= wxWinMacMenuList
.find(inMenuRef
);
55 return (node
== wxWinMacMenuList
.end()) ? NULL
: node
->second
;
58 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
59 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
61 // adding NULL MenuRef is (first) surely a result of an error and
62 // (secondly) breaks menu command processing
63 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
65 wxWinMacMenuList
[inMenuRef
] = menu
;
68 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
69 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
71 // iterate over all the elements in the class
72 MacMenuMap::iterator it
;
73 for ( it
= wxWinMacMenuList
.begin(); it
!= wxWinMacMenuList
.end(); ++it
)
75 if ( it
->second
== menu
)
77 wxWinMacMenuList
.erase(it
);
83 // ============================================================================
85 // ============================================================================
86 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
87 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
91 // Construct a menu with optional title (then use append)
94 short wxMenu::s_macNextMenuId
= 3 ;
96 short wxMenu::s_macNextMenuId
= 2 ;
101 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
103 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
106 menuIter
= menuIter
->GetNext();
108 return menuIter
->GetData() ;
114 m_startRadioGroup
= -1;
117 m_macMenuId
= s_macNextMenuId
++;
118 m_hMenu
= UMANewMenu(m_macMenuId
, m_title
, wxFont::GetDefaultEncoding() );
122 wxLogLastError(wxT("UMANewMenu failed"));
125 wxAssociateMenuWithMacMenu( (MenuRef
)m_hMenu
, this ) ;
127 // if we have a title, insert it in the beginning of the menu
128 if ( !m_title
.empty() )
130 Append(idMenuTitle
, m_title
) ;
137 wxRemoveMacMenuAssociation( this ) ;
138 if (MAC_WXHMENU(m_hMenu
))
139 ::DisposeMenu(MAC_WXHMENU(m_hMenu
));
144 // not available on the mac platform
147 void wxMenu::Attach(wxMenuBarBase
*menubar
)
149 wxMenuBase::Attach(menubar
);
154 // function appends a new item or submenu to the menu
155 // append a new item or submenu to the menu
156 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
158 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
160 if ( pItem
->IsSeparator() )
162 if ( pos
== (size_t)-1 )
163 MacAppendMenu(MAC_WXHMENU(m_hMenu
), "\p-");
165 MacInsertMenuItem(MAC_WXHMENU(m_hMenu
), "\p-" , pos
);
169 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
170 if ( pSubMenu
!= NULL
)
172 wxASSERT_MSG( pSubMenu
->m_hMenu
!= NULL
, wxT("invalid submenu added"));
173 pSubMenu
->m_menuParent
= this ;
175 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
176 pSubMenu
->MacBeforeDisplay( true ) ;
178 if ( pos
== (size_t)-1 )
179 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pSubMenu
->m_macMenuId
);
181 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pos
, pSubMenu
->m_macMenuId
);
183 pItem
->UpdateItemBitmap() ;
184 pItem
->UpdateItemStatus() ;
188 if ( pos
== (size_t)-1 )
190 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a") , wxFont::GetDefaultEncoding() );
191 pos
= CountMenuItems(MAC_WXHMENU(m_hMenu
)) ;
195 // MacOS counts menu items from 1 and inserts after, therefore having the
196 // same effect as wx 0 based and inserting before, we must correct pos
197 // after however for updates to be correct
198 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a"), wxFont::GetDefaultEncoding(), pos
);
202 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu
) , pos
, wxIdToMacCommand ( pItem
->GetId() ) ) ;
203 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu
) , pos
, (UInt32
) pItem
) ;
204 pItem
->UpdateItemText() ;
205 pItem
->UpdateItemBitmap() ;
206 pItem
->UpdateItemStatus() ;
208 if ( pItem
->GetId() == idMenuTitle
)
209 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , pos
, false ) ;
213 // if we're already attached to the menubar, we must update it
214 if ( IsAttached() && GetMenuBar()->IsAttached() )
215 GetMenuBar()->Refresh();
220 void wxMenu::EndRadioGroup()
222 // we're not inside a radio group any longer
223 m_startRadioGroup
= -1;
226 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
228 wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") );
232 if ( item
->GetKind() == wxITEM_RADIO
)
234 int count
= GetMenuItemCount();
236 if ( m_startRadioGroup
== -1 )
238 // start a new radio group
239 m_startRadioGroup
= count
;
241 // for now it has just one element
242 item
->SetAsRadioGroupStart();
243 item
->SetRadioGroupEnd(m_startRadioGroup
);
245 // ensure that we have a checked item in the radio group
248 else // extend the current radio group
250 // we need to update its end item
251 item
->SetRadioGroupStart(m_startRadioGroup
);
252 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
256 node
->GetData()->SetRadioGroupEnd(count
);
260 wxFAIL_MSG( _T("where is the radio group start item?") );
264 else // not a radio item
269 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
273 // check the item initially
279 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
281 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
287 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
289 // we need to find the items position in the child list
291 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
293 for ( pos
= 0; node
; pos
++ )
295 if ( node
->GetData() == item
)
298 node
= node
->GetNext();
301 // DoRemove() (unlike Remove) can only be called for existing item!
302 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
304 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu
) , pos
+ 1);
306 if ( IsAttached() && GetMenuBar()->IsAttached() )
307 // otherwise, the change won't be visible
308 GetMenuBar()->Refresh();
310 // and from internal data structures
311 return wxMenuBase::DoRemove(item
);
314 void wxMenu::SetTitle(const wxString
& label
)
317 UMASetMenuTitle(MAC_WXHMENU(m_hMenu
) , label
, wxFont::GetDefaultEncoding() ) ;
320 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
322 bool processed
= false;
324 // Try the menu's event handler
325 if ( /* !processed && */ GetEventHandler())
326 processed
= GetEventHandler()->ProcessEvent(event
);
328 // Try the window the menu was popped up from
329 // (and up through the hierarchy)
330 wxWindow
*win
= GetInvokingWindow();
331 if ( !processed
&& win
)
332 processed
= win
->GetEventHandler()->ProcessEvent(event
);
337 // ---------------------------------------------------------------------------
339 // ---------------------------------------------------------------------------
341 wxWindow
*wxMenu::GetWindow() const
343 if ( m_invokingWindow
!= NULL
)
344 return m_invokingWindow
;
345 else if ( GetMenuBar() != NULL
)
346 return (wxWindow
*) GetMenuBar()->GetFrame();
351 // helper functions returning the mac menu position for a certain item, note that this is
352 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
354 int wxMenu::MacGetIndexFromId( int id
)
357 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
358 for ( pos
= 0; node
; pos
++ )
360 if ( node
->GetData()->GetId() == id
)
363 node
= node
->GetNext();
372 int wxMenu::MacGetIndexFromItem( wxMenuItem
*pItem
)
375 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
376 for ( pos
= 0; node
; pos
++ )
378 if ( node
->GetData() == pItem
)
381 node
= node
->GetNext();
390 void wxMenu::MacEnableMenu( bool bDoEnable
)
392 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable
) ;
397 // MacOS needs to know about submenus somewhere within this menu
398 // before it can be displayed, also hide special menu items
399 // like preferences that are handled by the OS
400 void wxMenu::MacBeforeDisplay( bool isSubMenu
)
402 wxMenuItem
* previousItem
= NULL
;
404 wxMenuItemList::compatibility_iterator node
;
407 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
409 item
= (wxMenuItem
*)node
->GetData();
410 wxMenu
* subMenu
= item
->GetSubMenu() ;
413 subMenu
->MacBeforeDisplay( true ) ;
418 // what we do here is to hide the special items which are
419 // shown in the application menu anyhow -- it doesn't make
420 // sense to show them in their normal place as well
421 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
422 ( UMAGetSystemVersion() >= 0x1000 && (
423 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
424 item
->GetId() == wxApp::s_macExitMenuItemId
) ) )
427 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
428 pos
+ 1, kMenuItemAttrHidden
, 0 );
430 // also check for a separator which was used just to
431 // separate this item from the others, so don't leave
432 // separator at the menu start or end nor 2 consecutive
434 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
435 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
438 if ( !previousItem
&& next
&& next
->IsSeparator() )
440 // next (i.e. second as we must be first) item is
441 // the separator to hide
442 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
445 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
446 previousItem
!= NULL
&&
447 previousItem
->IsSeparator() )
449 // prev item is a trailing separator we want to hide
452 else if ( previousItem
&& previousItem
->IsSeparator() &&
453 next
&& next
->IsSeparator() )
455 // two consecutive separators, this is one too many
458 else // no separators to hide
465 // hide the separator as well
466 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
472 #endif // TARGET_CARBON
475 previousItem
= item
;
479 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
482 // undo all changes from the MacBeforeDisplay call
483 void wxMenu::MacAfterDisplay( bool isSubMenu
)
486 ::DeleteMenu(MacGetMenuId());
488 wxMenuItem
* previousItem
= NULL
;
489 wxMenuItemList::compatibility_iterator node
;
493 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
495 item
= (wxMenuItem
*)node
->GetData();
496 wxMenu
* subMenu
= item
->GetSubMenu() ;
499 subMenu
->MacAfterDisplay( true ) ;
503 // no need to undo hidings
506 previousItem
= item
;
514 Mac Implementation note :
516 The Mac has only one global menubar, so we attempt to install the currently
517 active menubar from a frame, we currently don't take into account mdi-frames
518 which would ask for menu-merging
520 Secondly there is no mac api for changing a menubar that is not the current
521 menubar, so we have to wait for preparing the actual menubar until the
522 wxMenubar is to be used
524 We can in subsequent versions use MacInstallMenuBar to provide some sort of
525 auto-merge for MDI in case this will be necessary
529 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
530 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
531 bool wxMenuBar::s_macAutoWindowMenu
= true ;
532 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
534 void wxMenuBar::Init()
536 m_eventHandler
= this;
537 m_menuBarFrame
= NULL
;
538 m_invokingWindow
= (wxWindow
*) NULL
;
541 wxMenuBar::wxMenuBar()
546 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
551 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
555 m_titles
.Alloc(count
);
557 for ( size_t i
= 0; i
< count
; i
++ )
559 m_menus
.Append(menus
[i
]);
560 m_titles
.Add(titles
[i
]);
562 menus
[i
]->Attach(this);
566 wxMenuBar::~wxMenuBar()
568 if (s_macCommonMenuBar
== this)
569 s_macCommonMenuBar
= NULL
;
571 if (s_macInstalledMenuBar
== this)
574 s_macInstalledMenuBar
= NULL
;
578 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
580 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
585 void wxMenuBar::MacInstallMenuBar()
587 if ( s_macInstalledMenuBar
== this )
590 MenuBarHandle menubar
= NULL
;
592 #if TARGET_API_MAC_OSX
593 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
595 menubar
= NewHandleClear( 12 ) ;
596 (*menubar
)[3] = 0x0a ;
599 ::SetMenuBar( menubar
) ;
600 DisposeMenuBar( menubar
) ;
601 MenuHandle appleMenu
= NULL
;
602 char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph
, 0 } ;
604 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
605 verify_noerr( SetMenuTitle( appleMenu
, (ConstStr255Param
) appleMenuTitle
) );
607 // Add About/Preferences separator only on OS X
608 // KH/RN: Separator is always present on 10.3 but not on 10.2
609 // However, the change from 10.2 to 10.3 suggests it is preferred
610 #if TARGET_API_MAC_OSX
611 MacInsertMenuItem( appleMenu
, "\p-" , 0 ) ;
614 MacInsertMenuItem( appleMenu
, "\pAbout..." , 0 ) ;
615 MacInsertMenu( appleMenu
, 0 ) ;
617 // clean-up the help menu before adding new items
618 static MenuHandle mh
= NULL
;
622 MenuItemIndex firstUserHelpMenuItem
;
623 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
625 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
626 DeleteMenuItem( mh
, i
) ;
635 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
)
637 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
638 if ( item
== NULL
|| !(item
->IsEnabled()) )
639 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
641 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
644 // Unlike preferences which may or may not exist, the Quit item should be always
645 // enabled unless it is added by the application and then disabled, otherwise
646 // a program would be required to add an item with wxID_EXIT in order to get the
647 // Quit menu item to be enabled, which seems a bit burdensome.
648 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId
)
650 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
651 if ( item
!= NULL
&& !(item
->IsEnabled()) )
652 DisableMenuCommand( NULL
, kHICommandQuit
) ;
654 EnableMenuCommand( NULL
, kHICommandQuit
) ;
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
;
664 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
666 if ( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
668 for (pos
= 0 , node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
670 item
= (wxMenuItem
*)node
->GetData();
671 subMenu
= item
->GetSubMenu() ;
674 // we don't support hierarchical menus in the help menu yet
678 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
682 MenuItemIndex firstUserHelpMenuItem
;
683 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) != noErr
)
691 if ( item
->IsSeparator() )
694 MacAppendMenu(mh
, "\p-" );
698 wxAcceleratorEntry
* entry
= wxGetAccelFromString( item
->GetText() ) ;
700 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
702 // this will be taken care of below
708 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding(), entry
);
709 SetMenuItemCommandID( mh
, CountMenuItems(mh
) , wxIdToMacCommand ( item
->GetId() ) ) ;
710 SetMenuItemRefCon( mh
, CountMenuItems(mh
) , (UInt32
)item
) ;
721 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding() ) ;
722 menu
->MacBeforeDisplay(false) ;
723 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
727 // take care of the about menu item wherever it is
730 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
733 wxAcceleratorEntry
* entry
= wxGetAccelFromString( aboutMenuItem
->GetText() ) ;
734 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetText() ) , wxFont::GetDefaultEncoding() );
735 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
736 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
737 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (UInt32
)aboutMenuItem
) ;
738 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
742 if ( GetAutoWindowMenu() )
744 if ( MacGetWindowMenuHMenu() == NULL
)
745 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
747 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
751 s_macInstalledMenuBar
= this;
754 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
756 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
758 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
762 bool wxMenuBar::Enable(bool enable
)
764 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
767 for (i
= 0; i
< GetMenuCount(); i
++)
768 EnableTop(i
, enable
);
773 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
775 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
777 m_titles
[pos
] = label
;
782 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
784 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
786 ::SetMenuBar( GetMenuBar() ) ;
791 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
793 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
794 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
796 return m_titles
[pos
];
799 int wxMenuBar::FindMenu(const wxString
& title
)
801 wxString menuTitle
= wxStripMenuCodes(title
);
803 size_t count
= GetMenuCount();
804 for ( size_t i
= 0; i
< count
; i
++ )
806 wxString title
= wxStripMenuCodes(m_titles
[i
]);
807 if ( menuTitle
== title
)
814 // ---------------------------------------------------------------------------
815 // wxMenuBar construction
816 // ---------------------------------------------------------------------------
818 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
820 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
824 m_titles
[pos
] = title
;
828 if (s_macInstalledMenuBar
== this)
830 menuOld
->MacAfterDisplay( false ) ;
831 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
833 menu
->MacBeforeDisplay( false ) ;
834 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
835 if ( pos
== m_menus
.GetCount() - 1)
836 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
838 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+ 1)->MacGetMenuId() ) ;
844 if (m_invokingWindow
)
845 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
850 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
852 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
855 m_titles
.Insert(title
, pos
);
857 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
859 if ( IsAttached() && s_macInstalledMenuBar
== this )
861 if (s_macInstalledMenuBar
== this)
863 menu
->MacBeforeDisplay( false ) ;
865 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
866 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
868 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
874 if (m_invokingWindow
)
875 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
880 wxMenu
*wxMenuBar::Remove(size_t pos
)
882 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
888 if (s_macInstalledMenuBar
== this)
889 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
894 m_titles
.RemoveAt(pos
);
899 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
901 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
902 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
904 if ( !wxMenuBarBase::Append(menu
, title
) )
909 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
913 if (s_macInstalledMenuBar
== this)
915 menu
->MacBeforeDisplay( false ) ;
916 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
922 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
923 // adding menu later on.
924 if (m_invokingWindow
)
925 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
930 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
932 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
933 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
937 wxMenuItem
*menuitem
= node
->GetData();
938 if (menuitem
->IsSubMenu())
939 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
941 node
= node
->GetNext();
945 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
947 menu
->SetInvokingWindow( win
);
948 wxMenuItem
*menuitem
;
949 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
953 menuitem
= node
->GetData();
954 if (menuitem
->IsSubMenu())
955 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
957 node
= node
->GetNext();
961 void wxMenuBar::UnsetInvokingWindow()
963 m_invokingWindow
= (wxWindow
*) NULL
;
965 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
969 menu
= node
->GetData();
970 wxMenubarUnsetInvokingWindow( menu
);
972 node
= node
->GetNext();
976 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
978 m_invokingWindow
= frame
;
980 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
984 menu
= node
->GetData();
985 wxMenubarSetInvokingWindow( menu
, frame
);
987 node
= node
->GetNext();
991 void wxMenuBar::Detach()
993 wxMenuBarBase::Detach() ;
996 void wxMenuBar::Attach(wxFrame
*frame
)
998 wxMenuBarBase::Attach( frame
) ;
1001 // ---------------------------------------------------------------------------
1002 // wxMenuBar searching for menu items
1003 // ---------------------------------------------------------------------------
1005 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1006 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1007 const wxString
& itemString
) const
1009 wxString menuLabel
= wxStripMenuCodes(menuString
);
1010 size_t count
= GetMenuCount();
1011 for ( size_t i
= 0; i
< count
; i
++ )
1013 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1014 if ( menuLabel
== title
)
1015 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1021 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1026 wxMenuItem
*item
= NULL
;
1027 size_t count
= GetMenuCount();
1028 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1029 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);