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 AppendMenuItemTextWithCFString( MAC_WXHMENU(m_hMenu
),
165 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
167 InsertMenuItemTextWithCFString( MAC_WXHMENU(m_hMenu
),
168 CFSTR(""), pos
, kMenuItemAttrSeparator
, 0);
172 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
173 if ( pSubMenu
!= NULL
)
175 wxASSERT_MSG( pSubMenu
->m_hMenu
!= NULL
, wxT("invalid submenu added"));
176 pSubMenu
->m_menuParent
= this ;
178 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
179 pSubMenu
->MacBeforeDisplay( true ) ;
181 if ( pos
== (size_t)-1 )
182 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pSubMenu
->m_macMenuId
);
184 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pos
, pSubMenu
->m_macMenuId
);
186 pItem
->UpdateItemBitmap() ;
187 pItem
->UpdateItemStatus() ;
191 if ( pos
== (size_t)-1 )
193 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a") , wxFont::GetDefaultEncoding() );
194 pos
= CountMenuItems(MAC_WXHMENU(m_hMenu
)) ;
198 // MacOS counts menu items from 1 and inserts after, therefore having the
199 // same effect as wx 0 based and inserting before, we must correct pos
200 // after however for updates to be correct
201 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a"), wxFont::GetDefaultEncoding(), pos
);
205 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu
) , pos
, wxIdToMacCommand ( pItem
->GetId() ) ) ;
206 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu
) , pos
, (URefCon
) pItem
) ;
207 pItem
->UpdateItemText() ;
208 pItem
->UpdateItemBitmap() ;
209 pItem
->UpdateItemStatus() ;
211 if ( pItem
->GetId() == idMenuTitle
)
212 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , pos
, false ) ;
216 // if we're already attached to the menubar, we must update it
217 if ( IsAttached() && GetMenuBar()->IsAttached() )
218 GetMenuBar()->Refresh();
223 void wxMenu::EndRadioGroup()
225 // we're not inside a radio group any longer
226 m_startRadioGroup
= -1;
229 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
231 wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") );
235 if ( item
->GetKind() == wxITEM_RADIO
)
237 int count
= GetMenuItemCount();
239 if ( m_startRadioGroup
== -1 )
241 // start a new radio group
242 m_startRadioGroup
= count
;
244 // for now it has just one element
245 item
->SetAsRadioGroupStart();
246 item
->SetRadioGroupEnd(m_startRadioGroup
);
248 // ensure that we have a checked item in the radio group
251 else // extend the current radio group
253 // we need to update its end item
254 item
->SetRadioGroupStart(m_startRadioGroup
);
255 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
259 node
->GetData()->SetRadioGroupEnd(count
);
263 wxFAIL_MSG( _T("where is the radio group start item?") );
267 else // not a radio item
272 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
276 // check the item initially
282 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
284 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
290 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
292 // we need to find the items position in the child list
294 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
296 for ( pos
= 0; node
; pos
++ )
298 if ( node
->GetData() == item
)
301 node
= node
->GetNext();
304 // DoRemove() (unlike Remove) can only be called for existing item!
305 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
307 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu
) , pos
+ 1);
309 if ( IsAttached() && GetMenuBar()->IsAttached() )
310 // otherwise, the change won't be visible
311 GetMenuBar()->Refresh();
313 // and from internal data structures
314 return wxMenuBase::DoRemove(item
);
317 void wxMenu::SetTitle(const wxString
& label
)
320 UMASetMenuTitle(MAC_WXHMENU(m_hMenu
) , label
, wxFont::GetDefaultEncoding() ) ;
323 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
325 bool processed
= false;
327 // Try the menu's event handler
328 if ( /* !processed && */ GetEventHandler())
329 processed
= GetEventHandler()->ProcessEvent(event
);
331 // Try the window the menu was popped up from
332 // (and up through the hierarchy)
333 wxWindow
*win
= GetInvokingWindow();
334 if ( !processed
&& win
)
335 processed
= win
->GetEventHandler()->ProcessEvent(event
);
340 // ---------------------------------------------------------------------------
342 // ---------------------------------------------------------------------------
344 wxWindow
*wxMenu::GetWindow() const
346 if ( m_invokingWindow
!= NULL
)
347 return m_invokingWindow
;
348 else if ( GetMenuBar() != NULL
)
349 return (wxWindow
*) GetMenuBar()->GetFrame();
354 // helper functions returning the mac menu position for a certain item, note that this is
355 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
357 int wxMenu::MacGetIndexFromId( int id
)
360 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
361 for ( pos
= 0; node
; pos
++ )
363 if ( node
->GetData()->GetId() == id
)
366 node
= node
->GetNext();
375 int wxMenu::MacGetIndexFromItem( wxMenuItem
*pItem
)
378 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
379 for ( pos
= 0; node
; pos
++ )
381 if ( node
->GetData() == pItem
)
384 node
= node
->GetNext();
393 void wxMenu::MacEnableMenu( bool bDoEnable
)
395 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable
) ;
400 // MacOS needs to know about submenus somewhere within this menu
401 // before it can be displayed, also hide special menu items
402 // like preferences that are handled by the OS
403 void wxMenu::MacBeforeDisplay( bool isSubMenu
)
405 wxMenuItem
* previousItem
= NULL
;
407 wxMenuItemList::compatibility_iterator node
;
410 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
412 item
= (wxMenuItem
*)node
->GetData();
413 wxMenu
* subMenu
= item
->GetSubMenu() ;
416 subMenu
->MacBeforeDisplay( true ) ;
421 // what we do here is to hide the special items which are
422 // shown in the application menu anyhow -- it doesn't make
423 // sense to show them in their normal place as well
424 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
425 ( UMAGetSystemVersion() >= 0x1000 && (
426 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
427 item
->GetId() == wxApp::s_macExitMenuItemId
) ) )
430 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
431 pos
+ 1, kMenuItemAttrHidden
, 0 );
433 // also check for a separator which was used just to
434 // separate this item from the others, so don't leave
435 // separator at the menu start or end nor 2 consecutive
437 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
438 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
441 if ( !previousItem
&& next
&& next
->IsSeparator() )
443 // next (i.e. second as we must be first) item is
444 // the separator to hide
445 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
448 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
449 previousItem
!= NULL
&&
450 previousItem
->IsSeparator() )
452 // prev item is a trailing separator we want to hide
455 else if ( previousItem
&& previousItem
->IsSeparator() &&
456 next
&& next
->IsSeparator() )
458 // two consecutive separators, this is one too many
461 else // no separators to hide
468 // hide the separator as well
469 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
475 #endif // TARGET_CARBON
478 previousItem
= item
;
482 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
485 // undo all changes from the MacBeforeDisplay call
486 void wxMenu::MacAfterDisplay( bool isSubMenu
)
489 ::DeleteMenu(MacGetMenuId());
491 wxMenuItemList::compatibility_iterator node
;
494 for (node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
496 item
= (wxMenuItem
*)node
->GetData();
497 wxMenu
* subMenu
= item
->GetSubMenu() ;
500 subMenu
->MacAfterDisplay( true ) ;
504 // no need to undo hidings
513 Mac Implementation note :
515 The Mac has only one global menubar, so we attempt to install the currently
516 active menubar from a frame, we currently don't take into account mdi-frames
517 which would ask for menu-merging
519 Secondly there is no mac api for changing a menubar that is not the current
520 menubar, so we have to wait for preparing the actual menubar until the
521 wxMenubar is to be used
523 We can in subsequent versions use MacInstallMenuBar to provide some sort of
524 auto-merge for MDI in case this will be necessary
528 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
529 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
530 bool wxMenuBar::s_macAutoWindowMenu
= true ;
531 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
533 void wxMenuBar::Init()
535 m_eventHandler
= this;
536 m_menuBarFrame
= NULL
;
537 m_invokingWindow
= (wxWindow
*) NULL
;
540 wxMenuBar::wxMenuBar()
545 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
550 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
554 m_titles
.Alloc(count
);
556 for ( size_t i
= 0; i
< count
; i
++ )
558 m_menus
.Append(menus
[i
]);
559 m_titles
.Add(titles
[i
]);
561 menus
[i
]->Attach(this);
565 wxMenuBar::~wxMenuBar()
567 if (s_macCommonMenuBar
== this)
568 s_macCommonMenuBar
= NULL
;
570 if (s_macInstalledMenuBar
== this)
573 s_macInstalledMenuBar
= NULL
;
577 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
579 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
584 void wxMenuBar::MacInstallMenuBar()
586 if ( s_macInstalledMenuBar
== this )
589 MenuBarHandle menubar
= NULL
;
591 #if TARGET_API_MAC_OSX
592 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
594 menubar
= NewHandleClear( 12 ) ;
595 (*menubar
)[3] = 0x0a ;
598 ::SetMenuBar( menubar
) ;
599 DisposeMenuBar( menubar
) ;
600 MenuHandle appleMenu
= NULL
;
602 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
603 verify_noerr( SetMenuTitleWithCFString( appleMenu
, CFSTR( "\x14" ) ) );
605 // Add About/Preferences separator only on OS X
606 // KH/RN: Separator is always present on 10.3 but not on 10.2
607 // However, the change from 10.2 to 10.3 suggests it is preferred
608 #if TARGET_API_MAC_OSX
609 InsertMenuItemTextWithCFString( appleMenu
,
610 CFSTR(""), 0, kMenuItemAttrSeparator
, 0);
612 InsertMenuItemTextWithCFString( appleMenu
,
613 CFSTR("About..."), 0, kMenuItemAttrSeparator
, 0);
614 MacInsertMenu( appleMenu
, 0 ) ;
616 // clean-up the help menu before adding new items
617 static MenuHandle mh
= NULL
;
621 MenuItemIndex firstUserHelpMenuItem
;
622 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
624 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
625 DeleteMenuItem( mh
, i
) ;
634 if ( UMAGetSystemVersion() >= 0x1000 && 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 ( UMAGetSystemVersion() >= 0x1000 && 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
) ;
657 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
658 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
660 wxMenuItemList::compatibility_iterator node
;
662 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
664 if ( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
666 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
668 item
= (wxMenuItem
*)node
->GetData();
669 subMenu
= item
->GetSubMenu() ;
672 // we don't support hierarchical menus in the help menu yet
676 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
680 MenuItemIndex firstUserHelpMenuItem
;
681 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) != noErr
)
689 if ( item
->IsSeparator() )
692 AppendMenuItemTextWithCFString( mh
,
693 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
698 entry
= wxAcceleratorEntry::Create( 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
) , (URefCon
) 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
) ;
734 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetText() ) ;
735 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetText() ) , wxFont::GetDefaultEncoding() );
736 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
737 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
738 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
739 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
743 if ( GetAutoWindowMenu() )
745 if ( MacGetWindowMenuHMenu() == NULL
)
746 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
748 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
752 s_macInstalledMenuBar
= this;
755 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
757 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
759 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
763 bool wxMenuBar::Enable(bool enable
)
765 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
768 for (i
= 0; i
< GetMenuCount(); i
++)
769 EnableTop(i
, enable
);
774 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
776 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
778 m_titles
[pos
] = label
;
783 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
785 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
787 ::SetMenuBar( GetMenuBar() ) ;
792 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
794 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
795 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
797 return m_titles
[pos
];
800 int wxMenuBar::FindMenu(const wxString
& title
)
802 wxString menuTitle
= wxStripMenuCodes(title
);
804 size_t count
= GetMenuCount();
805 for ( size_t i
= 0; i
< count
; i
++ )
807 wxString title
= wxStripMenuCodes(m_titles
[i
]);
808 if ( menuTitle
== title
)
815 // ---------------------------------------------------------------------------
816 // wxMenuBar construction
817 // ---------------------------------------------------------------------------
819 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
821 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
825 m_titles
[pos
] = title
;
829 if (s_macInstalledMenuBar
== this)
831 menuOld
->MacAfterDisplay( false ) ;
832 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
834 menu
->MacBeforeDisplay( false ) ;
835 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
836 if ( pos
== m_menus
.GetCount() - 1)
837 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
839 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+ 1)->MacGetMenuId() ) ;
845 if (m_invokingWindow
)
846 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
851 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
853 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
856 m_titles
.Insert(title
, pos
);
858 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
860 if ( IsAttached() && s_macInstalledMenuBar
== this )
862 if (s_macInstalledMenuBar
== this)
864 menu
->MacBeforeDisplay( false ) ;
866 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
867 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
869 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
875 if (m_invokingWindow
)
876 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
881 wxMenu
*wxMenuBar::Remove(size_t pos
)
883 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
889 if (s_macInstalledMenuBar
== this)
890 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
895 m_titles
.RemoveAt(pos
);
900 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
902 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
903 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
905 if ( !wxMenuBarBase::Append(menu
, title
) )
910 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
914 if (s_macInstalledMenuBar
== this)
916 menu
->MacBeforeDisplay( false ) ;
917 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
923 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
924 // adding menu later on.
925 if (m_invokingWindow
)
926 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
931 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
933 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
934 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
938 wxMenuItem
*menuitem
= node
->GetData();
939 if (menuitem
->IsSubMenu())
940 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
942 node
= node
->GetNext();
946 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
948 menu
->SetInvokingWindow( win
);
949 wxMenuItem
*menuitem
;
950 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
954 menuitem
= node
->GetData();
955 if (menuitem
->IsSubMenu())
956 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
958 node
= node
->GetNext();
962 void wxMenuBar::UnsetInvokingWindow()
964 m_invokingWindow
= (wxWindow
*) NULL
;
966 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
970 menu
= node
->GetData();
971 wxMenubarUnsetInvokingWindow( menu
);
973 node
= node
->GetNext();
977 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
979 m_invokingWindow
= frame
;
981 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
985 menu
= node
->GetData();
986 wxMenubarSetInvokingWindow( menu
, frame
);
988 node
= node
->GetNext();
992 void wxMenuBar::Detach()
994 wxMenuBarBase::Detach() ;
997 void wxMenuBar::Attach(wxFrame
*frame
)
999 wxMenuBarBase::Attach( frame
) ;
1002 // ---------------------------------------------------------------------------
1003 // wxMenuBar searching for menu items
1004 // ---------------------------------------------------------------------------
1006 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1007 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1008 const wxString
& itemString
) const
1010 wxString menuLabel
= wxStripMenuCodes(menuString
);
1011 size_t count
= GetMenuCount();
1012 for ( size_t i
= 0; i
< count
; i
++ )
1014 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1015 if ( menuLabel
== title
)
1016 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1022 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1027 wxMenuItem
*item
= NULL
;
1028 size_t count
= GetMenuCount();
1029 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1030 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);