1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/menu.cpp
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"
28 #include "wx/menuitem.h"
31 #include "wx/mac/uma.h"
33 // other standard headers
34 // ----------------------
37 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
38 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
40 // the (popup) menu title has this special id
41 static const int idMenuTitle
= -3;
43 static const short kwxMacAppleMenuId
= 1 ;
46 // Find an item given the Macintosh Menu Reference
48 WX_DECLARE_HASH_MAP(MenuRef
, wxMenu
*, wxPointerHash
, wxPointerEqual
, MacMenuMap
);
50 static MacMenuMap wxWinMacMenuList
;
52 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
54 MacMenuMap::iterator node
= wxWinMacMenuList
.find(inMenuRef
);
56 return (node
== wxWinMacMenuList
.end()) ? NULL
: node
->second
;
59 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
60 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
62 // adding NULL MenuRef is (first) surely a result of an error and
63 // (secondly) breaks menu command processing
64 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
66 wxWinMacMenuList
[inMenuRef
] = menu
;
69 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
70 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
72 // iterate over all the elements in the class
73 MacMenuMap::iterator it
;
74 for ( it
= wxWinMacMenuList
.begin(); it
!= wxWinMacMenuList
.end(); ++it
)
76 if ( it
->second
== menu
)
78 wxWinMacMenuList
.erase(it
);
84 // ============================================================================
86 // ============================================================================
87 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
88 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
92 // Construct a menu with optional title (then use append)
95 short wxMenu::s_macNextMenuId
= 3 ;
97 short wxMenu::s_macNextMenuId
= 2 ;
102 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
104 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
107 menuIter
= menuIter
->GetNext();
109 return menuIter
->GetData() ;
115 m_startRadioGroup
= -1;
118 m_macMenuId
= s_macNextMenuId
++;
119 m_hMenu
= UMANewMenu(m_macMenuId
, m_title
, wxFont::GetDefaultEncoding() );
123 wxLogLastError(wxT("UMANewMenu failed"));
126 wxAssociateMenuWithMacMenu( (MenuRef
)m_hMenu
, this ) ;
128 // if we have a title, insert it in the beginning of the menu
129 if ( !m_title
.empty() )
131 Append(idMenuTitle
, m_title
) ;
138 wxRemoveMacMenuAssociation( this ) ;
139 if (MAC_WXHMENU(m_hMenu
))
140 ::DisposeMenu(MAC_WXHMENU(m_hMenu
));
145 // not available on the mac platform
148 void wxMenu::Attach(wxMenuBarBase
*menubar
)
150 wxMenuBase::Attach(menubar
);
155 // function appends a new item or submenu to the menu
156 // append a new item or submenu to the menu
157 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
159 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
161 if ( pItem
->IsSeparator() )
163 if ( pos
== (size_t)-1 )
164 MacAppendMenu(MAC_WXHMENU(m_hMenu
), "\p-");
166 MacInsertMenuItem(MAC_WXHMENU(m_hMenu
), "\p-" , pos
);
170 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
171 if ( pSubMenu
!= NULL
)
173 wxASSERT_MSG( pSubMenu
->m_hMenu
!= NULL
, wxT("invalid submenu added"));
174 pSubMenu
->m_menuParent
= this ;
176 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
177 pSubMenu
->MacBeforeDisplay( true ) ;
179 if ( pos
== (size_t)-1 )
180 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pSubMenu
->m_macMenuId
);
182 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pos
, pSubMenu
->m_macMenuId
);
184 pItem
->UpdateItemBitmap() ;
185 pItem
->UpdateItemStatus() ;
189 if ( pos
== (size_t)-1 )
191 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a") , wxFont::GetDefaultEncoding() );
192 pos
= CountMenuItems(MAC_WXHMENU(m_hMenu
)) ;
196 // MacOS counts menu items from 1 and inserts after, therefore having the
197 // same effect as wx 0 based and inserting before, we must correct pos
198 // after however for updates to be correct
199 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a"), wxFont::GetDefaultEncoding(), pos
);
203 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu
) , pos
, wxIdToMacCommand ( pItem
->GetId() ) ) ;
204 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu
) , pos
, (UInt32
) pItem
) ;
205 pItem
->UpdateItemText() ;
206 pItem
->UpdateItemBitmap() ;
207 pItem
->UpdateItemStatus() ;
209 if ( pItem
->GetId() == idMenuTitle
)
210 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , pos
, false ) ;
214 // if we're already attached to the menubar, we must update it
215 if ( IsAttached() && GetMenuBar()->IsAttached() )
216 GetMenuBar()->Refresh();
221 void wxMenu::EndRadioGroup()
223 // we're not inside a radio group any longer
224 m_startRadioGroup
= -1;
227 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
229 wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") );
233 if ( item
->GetKind() == wxITEM_RADIO
)
235 int count
= GetMenuItemCount();
237 if ( m_startRadioGroup
== -1 )
239 // start a new radio group
240 m_startRadioGroup
= count
;
242 // for now it has just one element
243 item
->SetAsRadioGroupStart();
244 item
->SetRadioGroupEnd(m_startRadioGroup
);
246 // ensure that we have a checked item in the radio group
249 else // extend the current radio group
251 // we need to update its end item
252 item
->SetRadioGroupStart(m_startRadioGroup
);
253 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
257 node
->GetData()->SetRadioGroupEnd(count
);
261 wxFAIL_MSG( _T("where is the radio group start item?") );
265 else // not a radio item
270 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
274 // check the item initially
280 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
282 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
288 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
290 // we need to find the items position in the child list
292 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
294 for ( pos
= 0; node
; pos
++ )
296 if ( node
->GetData() == item
)
299 node
= node
->GetNext();
302 // DoRemove() (unlike Remove) can only be called for existing item!
303 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
305 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu
) , pos
+ 1);
307 if ( IsAttached() && GetMenuBar()->IsAttached() )
308 // otherwise, the change won't be visible
309 GetMenuBar()->Refresh();
311 // and from internal data structures
312 return wxMenuBase::DoRemove(item
);
315 void wxMenu::SetTitle(const wxString
& label
)
318 UMASetMenuTitle(MAC_WXHMENU(m_hMenu
) , label
, wxFont::GetDefaultEncoding() ) ;
321 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
323 bool processed
= false;
325 // Try the menu's event handler
326 if ( /* !processed && */ GetEventHandler())
327 processed
= GetEventHandler()->ProcessEvent(event
);
329 // Try the window the menu was popped up from
330 // (and up through the hierarchy)
331 wxWindow
*win
= GetInvokingWindow();
332 if ( !processed
&& win
)
333 processed
= win
->GetEventHandler()->ProcessEvent(event
);
338 // ---------------------------------------------------------------------------
340 // ---------------------------------------------------------------------------
342 wxWindow
*wxMenu::GetWindow() const
344 if ( m_invokingWindow
!= NULL
)
345 return m_invokingWindow
;
346 else if ( GetMenuBar() != NULL
)
347 return (wxWindow
*) GetMenuBar()->GetFrame();
352 // helper functions returning the mac menu position for a certain item, note that this is
353 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
355 int wxMenu::MacGetIndexFromId( int id
)
358 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
359 for ( pos
= 0; node
; pos
++ )
361 if ( node
->GetData()->GetId() == id
)
364 node
= node
->GetNext();
373 int wxMenu::MacGetIndexFromItem( wxMenuItem
*pItem
)
376 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
377 for ( pos
= 0; node
; pos
++ )
379 if ( node
->GetData() == pItem
)
382 node
= node
->GetNext();
391 void wxMenu::MacEnableMenu( bool bDoEnable
)
393 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable
) ;
398 // MacOS needs to know about submenus somewhere within this menu
399 // before it can be displayed, also hide special menu items
400 // like preferences that are handled by the OS
401 void wxMenu::MacBeforeDisplay( bool isSubMenu
)
403 wxMenuItem
* previousItem
= NULL
;
405 wxMenuItemList::compatibility_iterator node
;
408 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
410 item
= (wxMenuItem
*)node
->GetData();
411 wxMenu
* subMenu
= item
->GetSubMenu() ;
414 subMenu
->MacBeforeDisplay( true ) ;
419 // what we do here is to hide the special items which are
420 // shown in the application menu anyhow -- it doesn't make
421 // sense to show them in their normal place as well
422 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
423 ( UMAGetSystemVersion() >= 0x1000 && (
424 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
425 item
->GetId() == wxApp::s_macExitMenuItemId
) ) )
428 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
429 pos
+ 1, kMenuItemAttrHidden
, 0 );
431 // also check for a separator which was used just to
432 // separate this item from the others, so don't leave
433 // separator at the menu start or end nor 2 consecutive
435 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
436 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
439 if ( !previousItem
&& next
&& next
->IsSeparator() )
441 // next (i.e. second as we must be first) item is
442 // the separator to hide
443 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
446 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
447 previousItem
!= NULL
&&
448 previousItem
->IsSeparator() )
450 // prev item is a trailing separator we want to hide
453 else if ( previousItem
&& previousItem
->IsSeparator() &&
454 next
&& next
->IsSeparator() )
456 // two consecutive separators, this is one too many
459 else // no separators to hide
466 // hide the separator as well
467 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
473 #endif // TARGET_CARBON
476 previousItem
= item
;
480 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
483 // undo all changes from the MacBeforeDisplay call
484 void wxMenu::MacAfterDisplay( bool isSubMenu
)
487 ::DeleteMenu(MacGetMenuId());
489 wxMenuItemList::compatibility_iterator node
;
492 for (node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
494 item
= (wxMenuItem
*)node
->GetData();
495 wxMenu
* subMenu
= item
->GetSubMenu() ;
498 subMenu
->MacAfterDisplay( true ) ;
502 // no need to undo hidings
511 Mac Implementation note :
513 The Mac has only one global menubar, so we attempt to install the currently
514 active menubar from a frame, we currently don't take into account mdi-frames
515 which would ask for menu-merging
517 Secondly there is no mac api for changing a menubar that is not the current
518 menubar, so we have to wait for preparing the actual menubar until the
519 wxMenubar is to be used
521 We can in subsequent versions use MacInstallMenuBar to provide some sort of
522 auto-merge for MDI in case this will be necessary
526 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
527 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
528 bool wxMenuBar::s_macAutoWindowMenu
= true ;
529 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
531 void wxMenuBar::Init()
533 m_eventHandler
= this;
534 m_menuBarFrame
= NULL
;
535 m_invokingWindow
= (wxWindow
*) NULL
;
538 wxMenuBar::wxMenuBar()
543 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
548 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
552 m_titles
.Alloc(count
);
554 for ( size_t i
= 0; i
< count
; i
++ )
556 m_menus
.Append(menus
[i
]);
557 m_titles
.Add(titles
[i
]);
559 menus
[i
]->Attach(this);
563 wxMenuBar::~wxMenuBar()
565 if (s_macCommonMenuBar
== this)
566 s_macCommonMenuBar
= NULL
;
568 if (s_macInstalledMenuBar
== this)
571 s_macInstalledMenuBar
= NULL
;
575 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
577 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
582 void wxMenuBar::MacInstallMenuBar()
584 if ( s_macInstalledMenuBar
== this )
587 MenuBarHandle menubar
= NULL
;
589 #if TARGET_API_MAC_OSX
590 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
592 menubar
= NewHandleClear( 12 ) ;
593 (*menubar
)[3] = 0x0a ;
596 ::SetMenuBar( menubar
) ;
597 DisposeMenuBar( menubar
) ;
598 MenuHandle appleMenu
= NULL
;
599 char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph
, 0 } ;
601 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
602 verify_noerr( SetMenuTitle( appleMenu
, (ConstStr255Param
) appleMenuTitle
) );
604 // Add About/Preferences separator only on OS X
605 // KH/RN: Separator is always present on 10.3 but not on 10.2
606 // However, the change from 10.2 to 10.3 suggests it is preferred
607 #if TARGET_API_MAC_OSX
608 MacInsertMenuItem( appleMenu
, "\p-" , 0 ) ;
611 MacInsertMenuItem( appleMenu
, "\pAbout..." , 0 ) ;
612 MacInsertMenu( appleMenu
, 0 ) ;
614 // clean-up the help menu before adding new items
615 static MenuHandle mh
= NULL
;
619 MenuItemIndex firstUserHelpMenuItem
;
620 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
622 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
623 DeleteMenuItem( mh
, i
) ;
632 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
)
634 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
635 if ( item
== NULL
|| !(item
->IsEnabled()) )
636 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
638 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
641 // Unlike preferences which may or may not exist, the Quit item should be always
642 // enabled unless it is added by the application and then disabled, otherwise
643 // a program would be required to add an item with wxID_EXIT in order to get the
644 // Quit menu item to be enabled, which seems a bit burdensome.
645 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId
)
647 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
648 if ( item
!= NULL
&& !(item
->IsEnabled()) )
649 DisableMenuCommand( NULL
, kHICommandQuit
) ;
651 EnableMenuCommand( NULL
, kHICommandQuit
) ;
655 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
656 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
658 wxMenuItemList::compatibility_iterator node
;
660 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
662 if ( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
664 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
666 item
= (wxMenuItem
*)node
->GetData();
667 subMenu
= item
->GetSubMenu() ;
670 // we don't support hierarchical menus in the help menu yet
674 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
678 MenuItemIndex firstUserHelpMenuItem
;
679 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) != noErr
)
687 if ( item
->IsSeparator() )
690 MacAppendMenu(mh
, "\p-" );
695 entry
= wxAcceleratorEntry::Create( item
->GetText() ) ;
697 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
699 // this will be taken care of below
705 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding(), entry
);
706 SetMenuItemCommandID( mh
, CountMenuItems(mh
) , wxIdToMacCommand ( item
->GetId() ) ) ;
707 SetMenuItemRefCon( mh
, CountMenuItems(mh
) , (UInt32
)item
) ;
718 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding() ) ;
719 menu
->MacBeforeDisplay(false) ;
720 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
724 // take care of the about menu item wherever it is
727 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
731 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetText() ) ;
732 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetText() ) , wxFont::GetDefaultEncoding() );
733 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
734 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
735 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (UInt32
)aboutMenuItem
) ;
736 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
740 if ( GetAutoWindowMenu() )
742 if ( MacGetWindowMenuHMenu() == NULL
)
743 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
745 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
749 s_macInstalledMenuBar
= this;
752 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
754 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
756 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
760 bool wxMenuBar::Enable(bool enable
)
762 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
765 for (i
= 0; i
< GetMenuCount(); i
++)
766 EnableTop(i
, enable
);
771 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
773 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
775 m_titles
[pos
] = label
;
780 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
782 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
784 ::SetMenuBar( GetMenuBar() ) ;
789 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
791 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
792 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
794 return m_titles
[pos
];
797 int wxMenuBar::FindMenu(const wxString
& title
)
799 wxString menuTitle
= wxStripMenuCodes(title
);
801 size_t count
= GetMenuCount();
802 for ( size_t i
= 0; i
< count
; i
++ )
804 wxString title
= wxStripMenuCodes(m_titles
[i
]);
805 if ( menuTitle
== title
)
812 // ---------------------------------------------------------------------------
813 // wxMenuBar construction
814 // ---------------------------------------------------------------------------
816 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
818 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
822 m_titles
[pos
] = title
;
826 if (s_macInstalledMenuBar
== this)
828 menuOld
->MacAfterDisplay( false ) ;
829 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
831 menu
->MacBeforeDisplay( false ) ;
832 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
833 if ( pos
== m_menus
.GetCount() - 1)
834 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
836 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+ 1)->MacGetMenuId() ) ;
842 if (m_invokingWindow
)
843 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
848 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
850 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
853 m_titles
.Insert(title
, pos
);
855 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
857 if ( IsAttached() && s_macInstalledMenuBar
== this )
859 if (s_macInstalledMenuBar
== this)
861 menu
->MacBeforeDisplay( false ) ;
863 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
864 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
866 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
872 if (m_invokingWindow
)
873 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
878 wxMenu
*wxMenuBar::Remove(size_t pos
)
880 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
886 if (s_macInstalledMenuBar
== this)
887 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
892 m_titles
.RemoveAt(pos
);
897 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
899 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
900 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
902 if ( !wxMenuBarBase::Append(menu
, title
) )
907 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
911 if (s_macInstalledMenuBar
== this)
913 menu
->MacBeforeDisplay( false ) ;
914 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
920 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
921 // adding menu later on.
922 if (m_invokingWindow
)
923 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
928 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
930 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
931 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
935 wxMenuItem
*menuitem
= node
->GetData();
936 if (menuitem
->IsSubMenu())
937 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
939 node
= node
->GetNext();
943 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
945 menu
->SetInvokingWindow( win
);
946 wxMenuItem
*menuitem
;
947 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
951 menuitem
= node
->GetData();
952 if (menuitem
->IsSubMenu())
953 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
955 node
= node
->GetNext();
959 void wxMenuBar::UnsetInvokingWindow()
961 m_invokingWindow
= (wxWindow
*) NULL
;
963 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
967 menu
= node
->GetData();
968 wxMenubarUnsetInvokingWindow( menu
);
970 node
= node
->GetNext();
974 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
976 m_invokingWindow
= frame
;
978 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
982 menu
= node
->GetData();
983 wxMenubarSetInvokingWindow( menu
, frame
);
985 node
= node
->GetNext();
989 void wxMenuBar::Detach()
991 wxMenuBarBase::Detach() ;
994 void wxMenuBar::Attach(wxFrame
*frame
)
996 wxMenuBarBase::Attach( frame
) ;
999 // ---------------------------------------------------------------------------
1000 // wxMenuBar searching for menu items
1001 // ---------------------------------------------------------------------------
1003 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1004 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1005 const wxString
& itemString
) const
1007 wxString menuLabel
= wxStripMenuCodes(menuString
);
1008 size_t count
= GetMenuCount();
1009 for ( size_t i
= 0; i
< count
; i
++ )
1011 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1012 if ( menuLabel
== title
)
1013 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1019 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1024 wxMenuItem
*item
= NULL
;
1025 size_t count
= GetMenuCount();
1026 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1027 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);