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"
29 #include "wx/window.h"
34 #include "wx/mac/uma.h"
36 // other standard headers
37 // ----------------------
40 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
41 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
43 // the (popup) menu title has this special id
44 static const int idMenuTitle
= -3;
46 const short kwxMacMenuBarResource
= 1 ;
47 const short kwxMacAppleMenuId
= 1 ;
50 // Find an item given the Macintosh Menu Reference
52 WX_DECLARE_HASH_MAP(MenuRef
, wxMenu
*, wxPointerHash
, wxPointerEqual
, MacMenuMap
);
54 static MacMenuMap wxWinMacMenuList
;
56 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
58 MacMenuMap::iterator node
= wxWinMacMenuList
.find(inMenuRef
);
60 return (node
== wxWinMacMenuList
.end()) ? NULL
: node
->second
;
63 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
64 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
66 // adding NULL MenuRef is (first) surely a result of an error and
67 // (secondly) breaks menu command processing
68 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
70 wxWinMacMenuList
[inMenuRef
] = menu
;
73 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
74 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
76 // iterate over all the elements in the class
77 MacMenuMap::iterator it
;
78 for ( it
= wxWinMacMenuList
.begin(); it
!= wxWinMacMenuList
.end(); ++it
)
80 if ( it
->second
== menu
)
82 wxWinMacMenuList
.erase(it
);
88 // ============================================================================
90 // ============================================================================
91 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
92 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
96 // Construct a menu with optional title (then use append)
99 short wxMenu::s_macNextMenuId
= 3 ;
101 short wxMenu::s_macNextMenuId
= 2 ;
106 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
108 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
111 menuIter
= menuIter
->GetNext();
113 return menuIter
->GetData() ;
119 m_startRadioGroup
= -1;
122 m_macMenuId
= s_macNextMenuId
++;
123 m_hMenu
= UMANewMenu(m_macMenuId
, m_title
, wxFont::GetDefaultEncoding() );
127 wxLogLastError(wxT("UMANewMenu failed"));
130 wxAssociateMenuWithMacMenu( (MenuRef
)m_hMenu
, this ) ;
132 // if we have a title, insert it in the beginning of the menu
133 if ( !m_title
.empty() )
135 Append(idMenuTitle
, m_title
) ;
142 wxRemoveMacMenuAssociation( this ) ;
143 if (MAC_WXHMENU(m_hMenu
))
144 ::DisposeMenu(MAC_WXHMENU(m_hMenu
));
149 // not available on the mac platform
152 void wxMenu::Attach(wxMenuBarBase
*menubar
)
154 wxMenuBase::Attach(menubar
);
159 // function appends a new item or submenu to the menu
160 // append a new item or submenu to the menu
161 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
163 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
165 if ( pItem
->IsSeparator() )
167 if ( pos
== (size_t)-1 )
168 MacAppendMenu(MAC_WXHMENU(m_hMenu
), "\p-");
170 MacInsertMenuItem(MAC_WXHMENU(m_hMenu
), "\p-" , pos
);
174 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
175 if ( pSubMenu
!= NULL
)
177 wxASSERT_MSG( pSubMenu
->m_hMenu
!= NULL
, wxT("invalid submenu added"));
178 pSubMenu
->m_menuParent
= this ;
180 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
181 pSubMenu
->MacBeforeDisplay( true ) ;
183 if ( pos
== (size_t)-1 )
184 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pSubMenu
->m_macMenuId
);
186 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu
), wxStripMenuCodes(pItem
->GetText()), wxFont::GetDefaultEncoding(), pos
, pSubMenu
->m_macMenuId
);
188 pItem
->UpdateItemBitmap() ;
189 pItem
->UpdateItemStatus() ;
193 if ( pos
== (size_t)-1 )
195 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a") , wxFont::GetDefaultEncoding() );
196 pos
= CountMenuItems(MAC_WXHMENU(m_hMenu
)) ;
200 // MacOS counts menu items from 1 and inserts after, therefore having the
201 // same effect as wx 0 based and inserting before, we must correct pos
202 // after however for updates to be correct
203 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a"), wxFont::GetDefaultEncoding(), pos
);
207 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu
) , pos
, wxIdToMacCommand ( pItem
->GetId() ) ) ;
208 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu
) , pos
, (UInt32
) pItem
) ;
209 pItem
->UpdateItemText() ;
210 pItem
->UpdateItemBitmap() ;
211 pItem
->UpdateItemStatus() ;
213 if ( pItem
->GetId() == idMenuTitle
)
214 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , pos
, false ) ;
218 // if we're already attached to the menubar, we must update it
219 if ( IsAttached() && GetMenuBar()->IsAttached() )
220 GetMenuBar()->Refresh();
225 void wxMenu::EndRadioGroup()
227 // we're not inside a radio group any longer
228 m_startRadioGroup
= -1;
231 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
233 wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") );
237 if ( item
->GetKind() == wxITEM_RADIO
)
239 int count
= GetMenuItemCount();
241 if ( m_startRadioGroup
== -1 )
243 // start a new radio group
244 m_startRadioGroup
= count
;
246 // for now it has just one element
247 item
->SetAsRadioGroupStart();
248 item
->SetRadioGroupEnd(m_startRadioGroup
);
250 // ensure that we have a checked item in the radio group
253 else // extend the current radio group
255 // we need to update its end item
256 item
->SetRadioGroupStart(m_startRadioGroup
);
257 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
261 node
->GetData()->SetRadioGroupEnd(count
);
265 wxFAIL_MSG( _T("where is the radio group start item?") );
269 else // not a radio item
274 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
278 // check the item initially
284 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
286 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
292 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
294 // we need to find the items position in the child list
296 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
298 for ( pos
= 0; node
; pos
++ )
300 if ( node
->GetData() == item
)
303 node
= node
->GetNext();
306 // DoRemove() (unlike Remove) can only be called for existing item!
307 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
309 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu
) , pos
+ 1);
311 if ( IsAttached() && GetMenuBar()->IsAttached() )
312 // otherwise, the change won't be visible
313 GetMenuBar()->Refresh();
315 // and from internal data structures
316 return wxMenuBase::DoRemove(item
);
319 void wxMenu::SetTitle(const wxString
& label
)
322 UMASetMenuTitle(MAC_WXHMENU(m_hMenu
) , label
, wxFont::GetDefaultEncoding() ) ;
325 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
327 bool processed
= false;
329 // Try the menu's event handler
330 if ( /* !processed && */ GetEventHandler())
331 processed
= GetEventHandler()->ProcessEvent(event
);
333 // Try the window the menu was popped up from
334 // (and up through the hierarchy)
335 wxWindow
*win
= GetInvokingWindow();
336 if ( !processed
&& win
)
337 processed
= win
->GetEventHandler()->ProcessEvent(event
);
342 // ---------------------------------------------------------------------------
344 // ---------------------------------------------------------------------------
346 wxWindow
*wxMenu::GetWindow() const
348 if ( m_invokingWindow
!= NULL
)
349 return m_invokingWindow
;
350 else if ( GetMenuBar() != NULL
)
351 return (wxWindow
*) GetMenuBar()->GetFrame();
356 // helper functions returning the mac menu position for a certain item, note that this is
357 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
359 int wxMenu::MacGetIndexFromId( int id
)
362 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
363 for ( pos
= 0; node
; pos
++ )
365 if ( node
->GetData()->GetId() == id
)
368 node
= node
->GetNext();
377 int wxMenu::MacGetIndexFromItem( wxMenuItem
*pItem
)
380 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
381 for ( pos
= 0; node
; pos
++ )
383 if ( node
->GetData() == pItem
)
386 node
= node
->GetNext();
395 void wxMenu::MacEnableMenu( bool bDoEnable
)
397 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable
) ;
402 // MacOS needs to know about submenus somewhere within this menu
403 // before it can be displayed, also hide special menu items
404 // like preferences that are handled by the OS
405 void wxMenu::MacBeforeDisplay( bool isSubMenu
)
407 wxMenuItem
* previousItem
= NULL
;
409 wxMenuItemList::compatibility_iterator node
;
412 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
414 item
= (wxMenuItem
*)node
->GetData();
415 wxMenu
* subMenu
= item
->GetSubMenu() ;
418 subMenu
->MacBeforeDisplay( true ) ;
423 // what we do here is to hide the special items which are
424 // shown in the application menu anyhow -- it doesn't make
425 // sense to show them in their normal place as well
426 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
427 ( UMAGetSystemVersion() >= 0x1000 && (
428 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
429 item
->GetId() == wxApp::s_macExitMenuItemId
) ) )
432 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
433 pos
+ 1, kMenuItemAttrHidden
, 0 );
435 // also check for a separator which was used just to
436 // separate this item from the others, so don't leave
437 // separator at the menu start or end nor 2 consecutive
439 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
440 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
443 if ( !previousItem
&& next
&& next
->IsSeparator() )
445 // next (i.e. second as we must be first) item is
446 // the separator to hide
447 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
450 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
451 previousItem
!= NULL
&&
452 previousItem
->IsSeparator() )
454 // prev item is a trailing separator we want to hide
457 else if ( previousItem
&& previousItem
->IsSeparator() &&
458 next
&& next
->IsSeparator() )
460 // two consecutive separators, this is one too many
463 else // no separators to hide
470 // hide the separator as well
471 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
477 #endif // TARGET_CARBON
480 previousItem
= item
;
484 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
487 // undo all changes from the MacBeforeDisplay call
488 void wxMenu::MacAfterDisplay( bool isSubMenu
)
491 ::DeleteMenu(MacGetMenuId());
493 wxMenuItem
* previousItem
= NULL
;
494 wxMenuItemList::compatibility_iterator node
;
498 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
500 item
= (wxMenuItem
*)node
->GetData();
501 wxMenu
* subMenu
= item
->GetSubMenu() ;
504 subMenu
->MacAfterDisplay( true ) ;
508 // no need to undo hidings
511 previousItem
= item
;
519 Mac Implementation note :
521 The Mac has only one global menubar, so we attempt to install the currently
522 active menubar from a frame, we currently don't take into account mdi-frames
523 which would ask for menu-merging
525 Secondly there is no mac api for changing a menubar that is not the current
526 menubar, so we have to wait for preparing the actual menubar until the
527 wxMenubar is to be used
529 We can in subsequent versions use MacInstallMenuBar to provide some sort of
530 auto-merge for MDI in case this will be necessary
534 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
535 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
536 bool wxMenuBar::s_macAutoWindowMenu
= true ;
537 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
539 void wxMenuBar::Init()
541 m_eventHandler
= this;
542 m_menuBarFrame
= NULL
;
543 m_invokingWindow
= (wxWindow
*) NULL
;
546 wxMenuBar::wxMenuBar()
551 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
556 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
560 m_titles
.Alloc(count
);
562 for ( size_t i
= 0; i
< count
; i
++ )
564 m_menus
.Append(menus
[i
]);
565 m_titles
.Add(titles
[i
]);
567 menus
[i
]->Attach(this);
571 wxMenuBar::~wxMenuBar()
573 if (s_macCommonMenuBar
== this)
574 s_macCommonMenuBar
= NULL
;
576 if (s_macInstalledMenuBar
== this)
579 s_macInstalledMenuBar
= NULL
;
583 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
585 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
590 void wxMenuBar::MacInstallMenuBar()
592 if ( s_macInstalledMenuBar
== this )
595 MenuBarHandle menubar
= NULL
;
597 #if TARGET_API_MAC_OSX
598 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
600 menubar
= NewHandleClear( 12 ) ;
601 (*menubar
)[3] = 0x0a ;
604 ::SetMenuBar( menubar
) ;
605 DisposeMenuBar( menubar
) ;
606 MenuHandle appleMenu
= NULL
;
607 char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph
, 0 } ;
609 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
610 verify_noerr( SetMenuTitle( appleMenu
, (ConstStr255Param
) appleMenuTitle
) );
612 // Add About/Preferences separator only on OS X
613 // KH/RN: Separator is always present on 10.3 but not on 10.2
614 // However, the change from 10.2 to 10.3 suggests it is preferred
615 #if TARGET_API_MAC_OSX
616 MacInsertMenuItem( appleMenu
, "\p-" , 0 ) ;
619 MacInsertMenuItem( appleMenu
, "\pAbout..." , 0 ) ;
620 MacInsertMenu( appleMenu
, 0 ) ;
622 // clean-up the help menu before adding new items
623 static MenuHandle mh
= NULL
;
627 MenuItemIndex firstUserHelpMenuItem
;
628 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
630 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
631 DeleteMenuItem( mh
, i
) ;
640 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
)
642 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
643 if ( item
== NULL
|| !(item
->IsEnabled()) )
644 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
646 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
649 // Unlike preferences which may or may not exist, the Quit item should be always
650 // enabled unless it is added by the application and then disabled, otherwise
651 // a program would be required to add an item with wxID_EXIT in order to get the
652 // Quit menu item to be enabled, which seems a bit burdensome.
653 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId
)
655 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
656 if ( item
!= NULL
&& !(item
->IsEnabled()) )
657 DisableMenuCommand( NULL
, kHICommandQuit
) ;
659 EnableMenuCommand( NULL
, kHICommandQuit
) ;
663 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
664 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
666 wxMenuItemList::compatibility_iterator node
;
669 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
671 if ( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
673 for (pos
= 0 , node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
675 item
= (wxMenuItem
*)node
->GetData();
676 subMenu
= item
->GetSubMenu() ;
679 // we don't support hierarchical menus in the help menu yet
683 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
687 MenuItemIndex firstUserHelpMenuItem
;
688 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) != noErr
)
696 if ( item
->IsSeparator() )
699 MacAppendMenu(mh
, "\p-" );
703 wxAcceleratorEntry
* entry
= wxGetAccelFromString( item
->GetText() ) ;
705 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
707 // this will be taken care of below
713 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding(), entry
);
714 SetMenuItemCommandID( mh
, CountMenuItems(mh
) , wxIdToMacCommand ( item
->GetId() ) ) ;
715 SetMenuItemRefCon( mh
, CountMenuItems(mh
) , (UInt32
)item
) ;
726 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding() ) ;
727 menu
->MacBeforeDisplay(false) ;
728 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
732 // take care of the about menu item wherever it is
735 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
738 wxAcceleratorEntry
* entry
= wxGetAccelFromString( aboutMenuItem
->GetText() ) ;
739 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetText() ) , wxFont::GetDefaultEncoding() );
740 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
741 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
742 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (UInt32
)aboutMenuItem
) ;
743 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
747 if ( GetAutoWindowMenu() )
749 if ( MacGetWindowMenuHMenu() == NULL
)
750 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
752 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
756 s_macInstalledMenuBar
= this;
759 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
761 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
763 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
767 bool wxMenuBar::Enable(bool enable
)
769 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
772 for (i
= 0; i
< GetMenuCount(); i
++)
773 EnableTop(i
, enable
);
778 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
780 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
782 m_titles
[pos
] = label
;
787 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
789 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
791 ::SetMenuBar( GetMenuBar() ) ;
796 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
798 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
799 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
801 return m_titles
[pos
];
804 int wxMenuBar::FindMenu(const wxString
& title
)
806 wxString menuTitle
= wxStripMenuCodes(title
);
808 size_t count
= GetMenuCount();
809 for ( size_t i
= 0; i
< count
; i
++ )
811 wxString title
= wxStripMenuCodes(m_titles
[i
]);
812 if ( menuTitle
== title
)
819 // ---------------------------------------------------------------------------
820 // wxMenuBar construction
821 // ---------------------------------------------------------------------------
823 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
825 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
829 m_titles
[pos
] = title
;
833 if (s_macInstalledMenuBar
== this)
835 menuOld
->MacAfterDisplay( false ) ;
836 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
838 menu
->MacBeforeDisplay( false ) ;
839 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
840 if ( pos
== m_menus
.GetCount() - 1)
841 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
843 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+ 1)->MacGetMenuId() ) ;
849 if (m_invokingWindow
)
850 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
855 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
857 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
860 m_titles
.Insert(title
, pos
);
862 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
864 if ( IsAttached() && s_macInstalledMenuBar
== this )
866 if (s_macInstalledMenuBar
== this)
868 menu
->MacBeforeDisplay( false ) ;
870 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
871 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
873 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
879 if (m_invokingWindow
)
880 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
885 wxMenu
*wxMenuBar::Remove(size_t pos
)
887 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
893 if (s_macInstalledMenuBar
== this)
894 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
899 m_titles
.RemoveAt(pos
);
904 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
906 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
907 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
909 if ( !wxMenuBarBase::Append(menu
, title
) )
914 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
918 if (s_macInstalledMenuBar
== this)
920 menu
->MacBeforeDisplay( false ) ;
921 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
927 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
928 // adding menu later on.
929 if (m_invokingWindow
)
930 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
935 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
937 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
938 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
942 wxMenuItem
*menuitem
= node
->GetData();
943 if (menuitem
->IsSubMenu())
944 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
946 node
= node
->GetNext();
950 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
952 menu
->SetInvokingWindow( win
);
953 wxMenuItem
*menuitem
;
954 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
958 menuitem
= node
->GetData();
959 if (menuitem
->IsSubMenu())
960 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
962 node
= node
->GetNext();
966 void wxMenuBar::UnsetInvokingWindow()
968 m_invokingWindow
= (wxWindow
*) NULL
;
970 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
974 menu
= node
->GetData();
975 wxMenubarUnsetInvokingWindow( menu
);
977 node
= node
->GetNext();
981 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
983 m_invokingWindow
= frame
;
985 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
989 menu
= node
->GetData();
990 wxMenubarSetInvokingWindow( menu
, frame
);
992 node
= node
->GetNext();
996 void wxMenuBar::Detach()
998 wxMenuBarBase::Detach() ;
1001 void wxMenuBar::Attach(wxFrame
*frame
)
1003 wxMenuBarBase::Attach( frame
) ;
1006 // ---------------------------------------------------------------------------
1007 // wxMenuBar searching for menu items
1008 // ---------------------------------------------------------------------------
1010 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1011 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1012 const wxString
& itemString
) const
1014 wxString menuLabel
= wxStripMenuCodes(menuString
);
1015 size_t count
= GetMenuCount();
1016 for ( size_t i
= 0; i
< count
; i
++ )
1018 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1019 if ( menuLabel
== title
)
1020 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1026 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1031 wxMenuItem
*item
= NULL
;
1032 size_t count
= GetMenuCount();
1033 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1034 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);