1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "menu.h"
14 #pragma implementation "menuitem.h"
17 // ============================================================================
18 // headers & declarations
19 // ============================================================================
24 #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 #if KEY_wxList_DEPRECATED
53 wxList
wxWinMacMenuList(wxKEY_INTEGER
);
54 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
56 wxNode
*node
= wxWinMacMenuList
.Find((long)inMenuRef
);
59 return (wxMenu
*)node
->GetData();
62 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
63 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
65 // adding NULL MenuRef is (first) surely a result of an error and
66 // (secondly) breaks menu command processing
67 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
69 if ( !wxWinMacMenuList
.Find((long)inMenuRef
) )
70 wxWinMacMenuList
.Append((long)inMenuRef
, menu
);
73 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
74 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
76 wxWinMacMenuList
.DeleteObject(menu
);
80 WX_DECLARE_HASH_MAP(MenuRef
, wxMenu
*, wxPointerHash
, wxPointerEqual
, MacMenuMap
);
82 static MacMenuMap wxWinMacMenuList
;
84 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
86 MacMenuMap::iterator node
= wxWinMacMenuList
.find(inMenuRef
);
88 return (node
== wxWinMacMenuList
.end()) ? NULL
: node
->second
;
91 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
92 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
94 // adding NULL MenuRef is (first) surely a result of an error and
95 // (secondly) breaks menu command processing
96 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
98 wxWinMacMenuList
[inMenuRef
] = menu
;
101 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
102 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
104 // iterate over all the elements in the class
105 MacMenuMap::iterator it
;
106 for ( it
= wxWinMacMenuList
.begin(); it
!= wxWinMacMenuList
.end(); ++it
)
108 if ( it
->second
== menu
)
110 wxWinMacMenuList
.erase(it
);
115 #endif // deprecated wxList
117 // ============================================================================
119 // ============================================================================
120 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
121 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
125 // Construct a menu with optional title (then use append)
128 short wxMenu::s_macNextMenuId
= 3 ;
130 short wxMenu::s_macNextMenuId
= 2 ;
135 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
137 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
139 while (pos
-- > 0) menuIter
= menuIter
->GetNext();
141 return menuIter
->GetData() ;
147 m_startRadioGroup
= -1;
150 m_macMenuId
= s_macNextMenuId
++;
151 m_hMenu
= UMANewMenu(m_macMenuId
, m_title
, wxFont::GetDefaultEncoding() );
155 wxLogLastError(wxT("UMANewMenu failed"));
158 wxAssociateMenuWithMacMenu( (MenuRef
)m_hMenu
, this ) ;
160 // if we have a title, insert it in the beginning of the menu
161 if ( !m_title
.empty() )
163 Append(idMenuTitle
, m_title
) ;
170 wxRemoveMacMenuAssociation( this ) ;
171 if (MAC_WXHMENU(m_hMenu
))
172 ::DisposeMenu(MAC_WXHMENU(m_hMenu
));
177 // not available on the mac platform
180 void wxMenu::Attach(wxMenuBarBase
*menubar
)
182 wxMenuBase::Attach(menubar
);
187 // function appends a new item or submenu to the menu
188 // append a new item or submenu to the menu
189 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
191 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
193 if ( pItem
->IsSeparator() )
195 if ( pos
== (size_t)-1 )
196 MacAppendMenu(MAC_WXHMENU(m_hMenu
), "\p-");
198 MacInsertMenuItem(MAC_WXHMENU(m_hMenu
), "\p-" , pos
);
202 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
203 if ( pSubMenu
!= NULL
)
205 wxASSERT_MSG( pSubMenu
->m_hMenu
!= NULL
, wxT("invalid submenu added"));
206 pSubMenu
->m_menuParent
= this ;
208 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
210 pSubMenu
->MacBeforeDisplay( true ) ;
213 if ( pos
== (size_t)-1 )
214 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu
), pItem
->GetText(), wxFont::GetDefaultEncoding() , pSubMenu
->m_macMenuId
);
216 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu
), pItem
->GetText(), wxFont::GetDefaultEncoding() , pos
, pSubMenu
->m_macMenuId
);
217 pItem
->UpdateItemBitmap() ;
218 pItem
->UpdateItemStatus() ;
222 if ( pos
== (size_t)-1 )
224 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a") , wxFont::GetDefaultEncoding() );
225 pos
= CountMenuItems(MAC_WXHMENU(m_hMenu
)) ;
229 // MacOS counts menu items from 1 and inserts after, therefore having the
230 // same effect as wx 0 based and inserting before, we must correct pos
231 // after however for updates to be correct
232 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a"), wxFont::GetDefaultEncoding(), pos
);
236 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu
) , pos
, pItem
->GetId() ) ;
237 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu
) , pos
, (UInt32
) pItem
) ;
238 pItem
->UpdateItemText() ;
239 pItem
->UpdateItemBitmap() ;
240 pItem
->UpdateItemStatus() ;
242 if ( pItem
->GetId() == idMenuTitle
)
244 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , pos
, false ) ;
248 // if we're already attached to the menubar, we must update it
249 if ( IsAttached() && GetMenuBar()->IsAttached() )
251 GetMenuBar()->Refresh();
256 void wxMenu::EndRadioGroup()
258 // we're not inside a radio group any longer
259 m_startRadioGroup
= -1;
262 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
264 wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") );
268 if ( item
->GetKind() == wxITEM_RADIO
)
270 int count
= GetMenuItemCount();
272 if ( m_startRadioGroup
== -1 )
274 // start a new radio group
275 m_startRadioGroup
= count
;
277 // for now it has just one element
278 item
->SetAsRadioGroupStart();
279 item
->SetRadioGroupEnd(m_startRadioGroup
);
281 // ensure that we have a checked item in the radio group
284 else // extend the current radio group
286 // we need to update its end item
287 item
->SetRadioGroupStart(m_startRadioGroup
);
288 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
292 node
->GetData()->SetRadioGroupEnd(count
);
296 wxFAIL_MSG( _T("where is the radio group start item?") );
300 else // not a radio item
305 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
312 // check the item initially
319 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
321 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
327 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
329 // we need to find the items position in the child list
331 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
332 for ( pos
= 0; node
; pos
++ )
334 if ( node
->GetData() == item
)
337 node
= node
->GetNext();
340 // DoRemove() (unlike Remove) can only be called for existing item!
341 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
343 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu
) , pos
+ 1);
345 if ( IsAttached() && GetMenuBar()->IsAttached() )
347 // otherwise, the change won't be visible
348 GetMenuBar()->Refresh();
351 // and from internal data structures
352 return wxMenuBase::DoRemove(item
);
355 void wxMenu::SetTitle(const wxString
& label
)
358 UMASetMenuTitle(MAC_WXHMENU(m_hMenu
) , label
, wxFont::GetDefaultEncoding() ) ;
361 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
363 bool processed
= false;
365 // Try the menu's event handler
366 if ( /* !processed && */ GetEventHandler())
368 processed
= GetEventHandler()->ProcessEvent(event
);
371 // Try the window the menu was popped up from (and up through the
373 wxWindow
*win
= GetInvokingWindow();
374 if ( !processed
&& win
)
375 processed
= win
->GetEventHandler()->ProcessEvent(event
);
381 // ---------------------------------------------------------------------------
383 // ---------------------------------------------------------------------------
385 wxWindow
*wxMenu::GetWindow() const
387 if ( m_invokingWindow
!= NULL
)
388 return m_invokingWindow
;
389 else if ( GetMenuBar() != NULL
)
390 return (wxWindow
*) GetMenuBar()->GetFrame();
395 // helper functions returning the mac menu position for a certain item, note that this is
396 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
398 int wxMenu::MacGetIndexFromId( int id
)
401 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
402 for ( pos
= 0; node
; pos
++ )
404 if ( node
->GetData()->GetId() == id
)
407 node
= node
->GetNext();
416 int wxMenu::MacGetIndexFromItem( wxMenuItem
*pItem
)
419 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
420 for ( pos
= 0; node
; pos
++ )
422 if ( node
->GetData() == pItem
)
425 node
= node
->GetNext();
434 void wxMenu::MacEnableMenu( bool bDoEnable
)
436 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable
) ;
441 // MacOS needs to know about submenus somewhere within this menu
442 // before it can be displayed , also hide special menu items like preferences
443 // that are handled by the OS
444 void wxMenu::MacBeforeDisplay( bool isSubMenu
)
446 wxMenuItem
* previousItem
= NULL
;
448 wxMenuItemList::compatibility_iterator node
;
450 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
452 item
= (wxMenuItem
*)node
->GetData();
453 wxMenu
* subMenu
= item
->GetSubMenu() ;
456 subMenu
->MacBeforeDisplay( true ) ;
461 // what we do here is to hide the special items which are
462 // shown in the application menu anyhow -- it doesn't make
463 // sense to show them in their normal place as well
464 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
465 ( UMAGetSystemVersion() >= 0x1000 && (
466 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
467 item
->GetId() == wxApp::s_macExitMenuItemId
) ) )
470 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
471 pos
+ 1, kMenuItemAttrHidden
, 0 );
473 // also check for a separator which was used just to
474 // separate this item from the others, so don't leave
475 // separator at the menu start or end nor 2 consecutive
477 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
478 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
481 if ( !previousItem
&& next
&& next
->IsSeparator() )
483 // next (i.e. second as we must be first) item is
484 // the separator to hide
485 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
488 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
489 previousItem
!= NULL
&&
490 previousItem
->IsSeparator() )
492 // prev item is a trailing separator we want to hide
495 else if ( previousItem
&& previousItem
->IsSeparator() &&
496 next
&& next
->IsSeparator() )
498 // two consecutive separators, this is one too many
501 else // no separators to hide
508 // hide the separator as well
509 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
515 #endif // TARGET_CARBON
517 previousItem
= item
;
521 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
524 // undo all changes from the MacBeforeDisplay call
525 void wxMenu::MacAfterDisplay( bool isSubMenu
)
528 ::DeleteMenu(MacGetMenuId());
530 wxMenuItem
* previousItem
= NULL
;
532 wxMenuItemList::compatibility_iterator node
;
534 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
536 item
= (wxMenuItem
*)node
->GetData();
537 wxMenu
* subMenu
= item
->GetSubMenu() ;
540 subMenu
->MacAfterDisplay( true ) ;
544 // no need to undo hidings
546 previousItem
= item
;
554 Mac Implementation note :
556 The Mac has only one global menubar, so we attempt to install the currently
557 active menubar from a frame, we currently don't take into account mdi-frames
558 which would ask for menu-merging
560 Secondly there is no mac api for changing a menubar that is not the current
561 menubar, so we have to wait for preparing the actual menubar until the
562 wxMenubar is to be used
564 We can in subsequent versions use MacInstallMenuBar to provide some sort of
565 auto-merge for MDI in case this will be necessary
569 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
570 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
571 bool wxMenuBar::s_macAutoWindowMenu
= true ;
572 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
574 void wxMenuBar::Init()
576 m_eventHandler
= this;
577 m_menuBarFrame
= NULL
;
578 m_invokingWindow
= (wxWindow
*) NULL
;
581 wxMenuBar::wxMenuBar()
586 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
592 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
596 m_titles
.Alloc(count
);
598 for ( size_t i
= 0; i
< count
; i
++ )
600 m_menus
.Append(menus
[i
]);
601 m_titles
.Add(titles
[i
]);
603 menus
[i
]->Attach(this);
607 wxMenuBar::~wxMenuBar()
609 if (s_macCommonMenuBar
== this)
610 s_macCommonMenuBar
= NULL
;
611 if (s_macInstalledMenuBar
== this)
614 s_macInstalledMenuBar
= NULL
;
619 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
621 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
626 void wxMenuBar::MacInstallMenuBar()
628 if ( s_macInstalledMenuBar
== this )
631 MenuBarHandle menubar
= NULL
;
632 #if TARGET_API_MAC_OSX
633 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
635 menubar
= NewHandleClear( 12 ) ;
636 (*menubar
)[3] = 0x0a ;
638 ::SetMenuBar( menubar
) ;
639 DisposeMenuBar( menubar
) ;
640 MenuHandle appleMenu
= NULL
;
641 char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph
, 0 } ;
643 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
644 verify_noerr( SetMenuTitle( appleMenu
, (ConstStr255Param
) appleMenuTitle
) );
646 // Add About/Preferences separator only on OS X
647 // KH/RN: Separator is always present on 10.3 but not on 10.2
648 // However, the change from 10.2 to 10.3 suggests it is preferred
649 #if TARGET_API_MAC_OSX
650 MacInsertMenuItem( appleMenu
, "\p-" , 0 ) ;
653 MacInsertMenuItem( appleMenu
, "\pAbout..." , 0 ) ;
654 MacInsertMenu( appleMenu
, 0 ) ;
656 // clean-up the help menu before adding new items
657 static MenuHandle mh
= NULL
;
661 MenuItemIndex firstUserHelpMenuItem
;
662 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
664 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
666 DeleteMenuItem( mh
, i
) ;
675 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
)
677 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
678 if ( item
== NULL
|| !(item
->IsEnabled()) )
679 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
681 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
683 // Unlike preferences which may or may not exist, the Quit item should be always
684 // enabled unless it is added by the application and then disabled, otherwise
685 // a program would be required to add an item with wxID_EXIT in order to get the
686 // Quit menu item to be enabled, which seems a bit burdensome.
687 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId
)
689 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
690 if ( item
!= NULL
&& !(item
->IsEnabled()) )
691 DisableMenuCommand( NULL
, kHICommandQuit
) ;
693 EnableMenuCommand( NULL
, kHICommandQuit
) ;
696 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
698 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
700 wxMenuItemList::compatibility_iterator node
;
703 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
705 if( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
707 for (pos
= 0 , node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
709 item
= (wxMenuItem
*)node
->GetData();
710 subMenu
= item
->GetSubMenu() ;
713 // we don't support hierarchical menus in the help menu yet
717 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
721 MenuItemIndex firstUserHelpMenuItem
;
722 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
732 if ( item
->IsSeparator() )
735 MacAppendMenu(mh
, "\p-" );
739 wxAcceleratorEntry
* entry
= wxGetAccelFromString( item
->GetText() ) ;
741 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
743 // this will be taken care of below
749 UMAAppendMenuItem(mh
, item
->GetText() , wxFont::GetDefaultEncoding(), entry
);
750 SetMenuItemCommandID( mh
, CountMenuItems(mh
) , item
->GetId() ) ;
751 SetMenuItemRefCon( mh
, CountMenuItems(mh
) , (UInt32
)item
) ;
762 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding() ) ;
763 menu
->MacBeforeDisplay(false) ;
764 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
767 // take care of the about menu item wherever it is
770 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
773 wxAcceleratorEntry
* entry
= wxGetAccelFromString( aboutMenuItem
->GetText() ) ;
774 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , aboutMenuItem
->GetText() , wxFont::GetDefaultEncoding() );
775 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
776 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , aboutMenuItem
->GetId() ) ;
777 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (UInt32
)aboutMenuItem
) ;
778 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
781 if ( GetAutoWindowMenu() )
783 if ( MacGetWindowMenuHMenu() == NULL
)
785 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
787 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
790 s_macInstalledMenuBar
= this;
793 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
795 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
796 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
800 bool wxMenuBar::Enable( bool enable
)
802 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
804 for (i
= 0; i
< GetMenuCount(); i
++)
806 EnableTop(i
, enable
);
811 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
813 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
815 m_titles
[pos
] = label
;
822 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
824 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
826 ::SetMenuBar( GetMenuBar() ) ;
831 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
833 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
834 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
836 return m_titles
[pos
];
839 int wxMenuBar::FindMenu(const wxString
& title
)
841 wxString menuTitle
= wxStripMenuCodes(title
);
843 size_t count
= GetMenuCount();
844 for ( size_t i
= 0; i
< count
; i
++ )
846 wxString title
= wxStripMenuCodes(m_titles
[i
]);
847 if ( menuTitle
== title
)
856 // ---------------------------------------------------------------------------
857 // wxMenuBar construction
858 // ---------------------------------------------------------------------------
860 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
862 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
865 m_titles
[pos
] = title
;
869 if (s_macInstalledMenuBar
== this)
871 menuOld
->MacAfterDisplay( false ) ;
872 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
874 menu
->MacBeforeDisplay( false ) ;
875 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
876 if ( pos
== m_menus
.GetCount() - 1)
878 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
882 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
889 if (m_invokingWindow
)
890 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
895 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
897 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
900 m_titles
.Insert(title
, pos
);
902 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
904 if ( IsAttached() && s_macInstalledMenuBar
== this )
906 if (s_macInstalledMenuBar
== this)
908 menu
->MacBeforeDisplay( false ) ;
909 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
911 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
915 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
920 if (m_invokingWindow
)
921 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
926 wxMenu
*wxMenuBar::Remove(size_t pos
)
928 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
934 if (s_macInstalledMenuBar
== this)
936 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
942 m_titles
.RemoveAt(pos
);
947 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
949 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
950 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
952 if ( !wxMenuBarBase::Append(menu
, title
) )
957 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
961 if (s_macInstalledMenuBar
== this)
963 menu
->MacBeforeDisplay( false ) ;
964 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
970 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
971 // adding menu later on.
972 if (m_invokingWindow
)
973 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
978 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
980 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
982 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
985 wxMenuItem
*menuitem
= node
->GetData();
986 if (menuitem
->IsSubMenu())
987 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
988 node
= node
->GetNext();
992 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
994 menu
->SetInvokingWindow( win
);
996 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
999 wxMenuItem
*menuitem
= node
->GetData();
1000 if (menuitem
->IsSubMenu())
1001 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
1002 node
= node
->GetNext();
1006 void wxMenuBar::UnsetInvokingWindow()
1008 m_invokingWindow
= (wxWindow
*) NULL
;
1009 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
1012 wxMenu
*menu
= node
->GetData();
1013 wxMenubarUnsetInvokingWindow( menu
);
1014 node
= node
->GetNext();
1018 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
1020 m_invokingWindow
= frame
;
1021 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
1024 wxMenu
*menu
= node
->GetData();
1025 wxMenubarSetInvokingWindow( menu
, frame
);
1026 node
= node
->GetNext();
1030 void wxMenuBar::Detach()
1032 wxMenuBarBase::Detach() ;
1035 void wxMenuBar::Attach(wxFrame
*frame
)
1037 wxMenuBarBase::Attach( frame
) ;
1039 // ---------------------------------------------------------------------------
1040 // wxMenuBar searching for menu items
1041 // ---------------------------------------------------------------------------
1043 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1044 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1045 const wxString
& itemString
) const
1047 wxString menuLabel
= wxStripMenuCodes(menuString
);
1048 size_t count
= GetMenuCount();
1049 for ( size_t i
= 0; i
< count
; i
++ )
1051 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1052 if ( menuLabel
== title
)
1053 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1059 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1064 wxMenuItem
*item
= NULL
;
1065 size_t count
= GetMenuCount();
1066 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1068 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);