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"
27 #include "wx/window.h"
29 #include "wx/menuitem.h"
32 #include "wx/mac/uma.h"
34 // other standard headers
35 // ----------------------
38 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
39 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
41 // the (popup) menu title has this special id
42 static const int idMenuTitle
= -3;
44 const short kwxMacMenuBarResource
= 1 ;
45 const short kwxMacAppleMenuId
= 1 ;
48 // Find an item given the Macintosh Menu Reference
50 WX_DECLARE_HASH_MAP(MenuRef
, wxMenu
*, wxPointerHash
, wxPointerEqual
, MacMenuMap
);
52 static MacMenuMap wxWinMacMenuList
;
54 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
56 MacMenuMap::iterator node
= wxWinMacMenuList
.find(inMenuRef
);
58 return (node
== wxWinMacMenuList
.end()) ? NULL
: node
->second
;
61 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
62 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
64 // adding NULL MenuRef is (first) surely a result of an error and
65 // (secondly) breaks menu command processing
66 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
68 wxWinMacMenuList
[inMenuRef
] = menu
;
71 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
72 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
74 // iterate over all the elements in the class
75 MacMenuMap::iterator it
;
76 for ( it
= wxWinMacMenuList
.begin(); it
!= wxWinMacMenuList
.end(); ++it
)
78 if ( it
->second
== menu
)
80 wxWinMacMenuList
.erase(it
);
86 // ============================================================================
88 // ============================================================================
89 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
90 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
94 // Construct a menu with optional title (then use append)
97 short wxMenu::s_macNextMenuId
= 3 ;
99 short wxMenu::s_macNextMenuId
= 2 ;
104 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
106 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
109 menuIter
= menuIter
->GetNext();
111 return menuIter
->GetData() ;
117 m_startRadioGroup
= -1;
120 m_macMenuId
= s_macNextMenuId
++;
121 m_hMenu
= UMANewMenu(m_macMenuId
, m_title
, wxFont::GetDefaultEncoding() );
125 wxLogLastError(wxT("UMANewMenu failed"));
128 wxAssociateMenuWithMacMenu( (MenuRef
)m_hMenu
, this ) ;
130 // if we have a title, insert it in the beginning of the menu
131 if ( !m_title
.empty() )
133 Append(idMenuTitle
, m_title
) ;
140 wxRemoveMacMenuAssociation( this ) ;
141 if (MAC_WXHMENU(m_hMenu
))
142 ::DisposeMenu(MAC_WXHMENU(m_hMenu
));
147 // not available on the mac platform
150 void wxMenu::Attach(wxMenuBarBase
*menubar
)
152 wxMenuBase::Attach(menubar
);
157 // function appends a new item or submenu to the menu
158 // append a new item or submenu to the menu
159 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
161 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
163 if ( pItem
->IsSeparator() )
165 if ( pos
== (size_t)-1 )
166 MacAppendMenu(MAC_WXHMENU(m_hMenu
), "\p-");
168 MacInsertMenuItem(MAC_WXHMENU(m_hMenu
), "\p-" , pos
);
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
, (UInt32
) 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 wxMenuItem
* previousItem
= NULL
;
492 wxMenuItemList::compatibility_iterator node
;
496 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
498 item
= (wxMenuItem
*)node
->GetData();
499 wxMenu
* subMenu
= item
->GetSubMenu() ;
502 subMenu
->MacAfterDisplay( true ) ;
506 // no need to undo hidings
509 previousItem
= item
;
517 Mac Implementation note :
519 The Mac has only one global menubar, so we attempt to install the currently
520 active menubar from a frame, we currently don't take into account mdi-frames
521 which would ask for menu-merging
523 Secondly there is no mac api for changing a menubar that is not the current
524 menubar, so we have to wait for preparing the actual menubar until the
525 wxMenubar is to be used
527 We can in subsequent versions use MacInstallMenuBar to provide some sort of
528 auto-merge for MDI in case this will be necessary
532 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
533 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
534 bool wxMenuBar::s_macAutoWindowMenu
= true ;
535 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
537 void wxMenuBar::Init()
539 m_eventHandler
= this;
540 m_menuBarFrame
= NULL
;
541 m_invokingWindow
= (wxWindow
*) NULL
;
544 wxMenuBar::wxMenuBar()
549 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
554 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
558 m_titles
.Alloc(count
);
560 for ( size_t i
= 0; i
< count
; i
++ )
562 m_menus
.Append(menus
[i
]);
563 m_titles
.Add(titles
[i
]);
565 menus
[i
]->Attach(this);
569 wxMenuBar::~wxMenuBar()
571 if (s_macCommonMenuBar
== this)
572 s_macCommonMenuBar
= NULL
;
574 if (s_macInstalledMenuBar
== this)
577 s_macInstalledMenuBar
= NULL
;
581 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
583 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
588 void wxMenuBar::MacInstallMenuBar()
590 if ( s_macInstalledMenuBar
== this )
593 MenuBarHandle menubar
= NULL
;
595 #if TARGET_API_MAC_OSX
596 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
598 menubar
= NewHandleClear( 12 ) ;
599 (*menubar
)[3] = 0x0a ;
602 ::SetMenuBar( menubar
) ;
603 DisposeMenuBar( menubar
) ;
604 MenuHandle appleMenu
= NULL
;
605 char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph
, 0 } ;
607 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
608 verify_noerr( SetMenuTitle( appleMenu
, (ConstStr255Param
) appleMenuTitle
) );
610 // Add About/Preferences separator only on OS X
611 // KH/RN: Separator is always present on 10.3 but not on 10.2
612 // However, the change from 10.2 to 10.3 suggests it is preferred
613 #if TARGET_API_MAC_OSX
614 MacInsertMenuItem( appleMenu
, "\p-" , 0 ) ;
617 MacInsertMenuItem( appleMenu
, "\pAbout..." , 0 ) ;
618 MacInsertMenu( appleMenu
, 0 ) ;
620 // clean-up the help menu before adding new items
621 static MenuHandle mh
= NULL
;
625 MenuItemIndex firstUserHelpMenuItem
;
626 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
628 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
629 DeleteMenuItem( mh
, i
) ;
638 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
)
640 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
641 if ( item
== NULL
|| !(item
->IsEnabled()) )
642 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
644 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
647 // Unlike preferences which may or may not exist, the Quit item should be always
648 // enabled unless it is added by the application and then disabled, otherwise
649 // a program would be required to add an item with wxID_EXIT in order to get the
650 // Quit menu item to be enabled, which seems a bit burdensome.
651 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId
)
653 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
654 if ( item
!= NULL
&& !(item
->IsEnabled()) )
655 DisableMenuCommand( NULL
, kHICommandQuit
) ;
657 EnableMenuCommand( NULL
, kHICommandQuit
) ;
661 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
662 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
664 wxMenuItemList::compatibility_iterator node
;
667 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
669 if ( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
671 for (pos
= 0 , node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
673 item
= (wxMenuItem
*)node
->GetData();
674 subMenu
= item
->GetSubMenu() ;
677 // we don't support hierarchical menus in the help menu yet
681 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
685 MenuItemIndex firstUserHelpMenuItem
;
686 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) != noErr
)
694 if ( item
->IsSeparator() )
697 MacAppendMenu(mh
, "\p-" );
701 wxAcceleratorEntry
* entry
= wxGetAccelFromString( item
->GetText() ) ;
703 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
705 // this will be taken care of below
711 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding(), entry
);
712 SetMenuItemCommandID( mh
, CountMenuItems(mh
) , wxIdToMacCommand ( item
->GetId() ) ) ;
713 SetMenuItemRefCon( mh
, CountMenuItems(mh
) , (UInt32
)item
) ;
724 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding() ) ;
725 menu
->MacBeforeDisplay(false) ;
726 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
730 // take care of the about menu item wherever it is
733 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
736 wxAcceleratorEntry
* entry
= wxGetAccelFromString( aboutMenuItem
->GetText() ) ;
737 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetText() ) , wxFont::GetDefaultEncoding() );
738 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
739 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
740 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (UInt32
)aboutMenuItem
) ;
741 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
745 if ( GetAutoWindowMenu() )
747 if ( MacGetWindowMenuHMenu() == NULL
)
748 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
750 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
754 s_macInstalledMenuBar
= this;
757 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
759 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
761 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
765 bool wxMenuBar::Enable(bool enable
)
767 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
770 for (i
= 0; i
< GetMenuCount(); i
++)
771 EnableTop(i
, enable
);
776 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
778 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
780 m_titles
[pos
] = label
;
785 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
787 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
789 ::SetMenuBar( GetMenuBar() ) ;
794 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
796 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
797 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
799 return m_titles
[pos
];
802 int wxMenuBar::FindMenu(const wxString
& title
)
804 wxString menuTitle
= wxStripMenuCodes(title
);
806 size_t count
= GetMenuCount();
807 for ( size_t i
= 0; i
< count
; i
++ )
809 wxString title
= wxStripMenuCodes(m_titles
[i
]);
810 if ( menuTitle
== title
)
817 // ---------------------------------------------------------------------------
818 // wxMenuBar construction
819 // ---------------------------------------------------------------------------
821 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
823 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
827 m_titles
[pos
] = title
;
831 if (s_macInstalledMenuBar
== this)
833 menuOld
->MacAfterDisplay( false ) ;
834 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
836 menu
->MacBeforeDisplay( false ) ;
837 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
838 if ( pos
== m_menus
.GetCount() - 1)
839 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
841 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+ 1)->MacGetMenuId() ) ;
847 if (m_invokingWindow
)
848 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
853 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
855 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
858 m_titles
.Insert(title
, pos
);
860 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
862 if ( IsAttached() && s_macInstalledMenuBar
== this )
864 if (s_macInstalledMenuBar
== this)
866 menu
->MacBeforeDisplay( false ) ;
868 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
869 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
871 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
877 if (m_invokingWindow
)
878 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
883 wxMenu
*wxMenuBar::Remove(size_t pos
)
885 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
891 if (s_macInstalledMenuBar
== this)
892 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
897 m_titles
.RemoveAt(pos
);
902 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
904 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
905 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
907 if ( !wxMenuBarBase::Append(menu
, title
) )
912 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
916 if (s_macInstalledMenuBar
== this)
918 menu
->MacBeforeDisplay( false ) ;
919 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
925 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
926 // adding menu later on.
927 if (m_invokingWindow
)
928 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
933 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
935 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
936 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
940 wxMenuItem
*menuitem
= node
->GetData();
941 if (menuitem
->IsSubMenu())
942 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
944 node
= node
->GetNext();
948 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
950 menu
->SetInvokingWindow( win
);
951 wxMenuItem
*menuitem
;
952 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
956 menuitem
= node
->GetData();
957 if (menuitem
->IsSubMenu())
958 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
960 node
= node
->GetNext();
964 void wxMenuBar::UnsetInvokingWindow()
966 m_invokingWindow
= (wxWindow
*) NULL
;
968 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
972 menu
= node
->GetData();
973 wxMenubarUnsetInvokingWindow( menu
);
975 node
= node
->GetNext();
979 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
981 m_invokingWindow
= frame
;
983 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
987 menu
= node
->GetData();
988 wxMenubarSetInvokingWindow( menu
, frame
);
990 node
= node
->GetNext();
994 void wxMenuBar::Detach()
996 wxMenuBarBase::Detach() ;
999 void wxMenuBar::Attach(wxFrame
*frame
)
1001 wxMenuBarBase::Attach( frame
) ;
1004 // ---------------------------------------------------------------------------
1005 // wxMenuBar searching for menu items
1006 // ---------------------------------------------------------------------------
1008 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1009 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1010 const wxString
& itemString
) const
1012 wxString menuLabel
= wxStripMenuCodes(menuString
);
1013 size_t count
= GetMenuCount();
1014 for ( size_t i
= 0; i
< count
; i
++ )
1016 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1017 if ( menuLabel
== title
)
1018 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1024 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1029 wxMenuItem
*item
= NULL
;
1030 size_t count
= GetMenuCount();
1031 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1032 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);