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
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() ) ;
360 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
362 bool processed
= FALSE
;
364 // Try the menu's event handler
365 if ( !processed
&& GetEventHandler())
367 processed
= GetEventHandler()->ProcessEvent(event
);
370 // Try the window the menu was popped up from (and up through the
372 wxWindow
*win
= GetInvokingWindow();
373 if ( !processed
&& win
)
374 processed
= win
->GetEventHandler()->ProcessEvent(event
);
380 // ---------------------------------------------------------------------------
382 // ---------------------------------------------------------------------------
384 wxWindow
*wxMenu::GetWindow() const
386 if ( m_invokingWindow
!= NULL
)
387 return m_invokingWindow
;
388 else if ( GetMenuBar() != NULL
)
389 return (wxWindow
*) GetMenuBar()->GetFrame();
394 // helper functions returning the mac menu position for a certain item, note that this is
395 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
397 int wxMenu::MacGetIndexFromId( int id
)
400 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
401 for ( pos
= 0; node
; pos
++ )
403 if ( node
->GetData()->GetId() == id
)
406 node
= node
->GetNext();
415 int wxMenu::MacGetIndexFromItem( wxMenuItem
*pItem
)
418 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
419 for ( pos
= 0; node
; pos
++ )
421 if ( node
->GetData() == pItem
)
424 node
= node
->GetNext();
433 void wxMenu::MacEnableMenu( bool bDoEnable
)
435 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable
) ;
440 // MacOS needs to know about submenus somewhere within this menu
441 // before it can be displayed , also hide special menu items like preferences
442 // that are handled by the OS
443 void wxMenu::MacBeforeDisplay( bool isSubMenu
)
445 wxMenuItem
* previousItem
= NULL
;
447 wxMenuItemList::compatibility_iterator node
;
449 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
451 item
= (wxMenuItem
*)node
->GetData();
452 wxMenu
* subMenu
= item
->GetSubMenu() ;
455 subMenu
->MacBeforeDisplay( true ) ;
460 // what we do here is to hide the special items which are
461 // shown in the application menu anyhow -- it doesn't make
462 // sense to show them in their normal place as well
463 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
464 ( UMAGetSystemVersion() >= 0x1000 && (
465 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
466 item
->GetId() == wxApp::s_macExitMenuItemId
) ) )
469 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
470 pos
+ 1, kMenuItemAttrHidden
, 0 );
472 // also check for a separator which was used just to
473 // separate this item from the others, so don't leave
474 // separator at the menu start or end nor 2 consecutive
476 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
477 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
480 if ( !previousItem
&& next
&& next
->IsSeparator() )
482 // next (i.e. second as we must be first) item is
483 // the separator to hide
484 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
487 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
488 previousItem
!= NULL
&&
489 previousItem
->IsSeparator() )
491 // prev item is a trailing separator we want to hide
494 else if ( previousItem
&& previousItem
->IsSeparator() &&
495 next
&& next
->IsSeparator() )
497 // two consecutive separators, this is one too many
500 else // no separators to hide
507 // hide the separator as well
508 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
514 #endif // TARGET_CARBON
516 previousItem
= item
;
520 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
523 // undo all changes from the MacBeforeDisplay call
524 void wxMenu::MacAfterDisplay( bool isSubMenu
)
527 ::DeleteMenu(MacGetMenuId());
529 wxMenuItem
* previousItem
= NULL
;
531 wxMenuItemList::compatibility_iterator node
;
533 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
535 item
= (wxMenuItem
*)node
->GetData();
536 wxMenu
* subMenu
= item
->GetSubMenu() ;
539 subMenu
->MacAfterDisplay( true ) ;
543 // no need to undo hidings
545 previousItem
= item
;
553 Mac Implementation note :
555 The Mac has only one global menubar, so we attempt to install the currently
556 active menubar from a frame, we currently don't take into account mdi-frames
557 which would ask for menu-merging
559 Secondly there is no mac api for changing a menubar that is not the current
560 menubar, so we have to wait for preparing the actual menubar until the
561 wxMenubar is to be used
563 We can in subsequent versions use MacInstallMenuBar to provide some sort of
564 auto-merge for MDI in case this will be necessary
568 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
569 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
571 void wxMenuBar::Init()
573 m_eventHandler
= this;
574 m_menuBarFrame
= NULL
;
575 m_invokingWindow
= (wxWindow
*) NULL
;
578 wxMenuBar::wxMenuBar()
583 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
589 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
593 m_titles
.Alloc(count
);
595 for ( size_t i
= 0; i
< count
; i
++ )
597 m_menus
.Append(menus
[i
]);
598 m_titles
.Add(titles
[i
]);
600 menus
[i
]->Attach(this);
604 wxMenuBar::~wxMenuBar()
606 if (s_macCommonMenuBar
== this)
607 s_macCommonMenuBar
= NULL
;
608 if (s_macInstalledMenuBar
== this)
611 s_macInstalledMenuBar
= NULL
;
616 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
618 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
623 void wxMenuBar::MacInstallMenuBar()
625 if ( s_macInstalledMenuBar
== this )
628 MenuBarHandle menubar
= NULL
;
629 #if TARGET_API_MAC_OSX
630 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
632 menubar
= NewHandleClear( 12 ) ;
633 (*menubar
)[3] = 0x0a ;
635 ::SetMenuBar( menubar
) ;
636 DisposeMenuBar( menubar
) ;
637 MenuHandle appleMenu
= NULL
;
638 char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph
, 0 } ;
640 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
641 verify_noerr( SetMenuTitle( appleMenu
, (ConstStr255Param
) appleMenuTitle
) );
643 // Add About/Preferences separator only on OS X
644 // KH/RN: Separator is always present on 10.3 but not on 10.2
645 // However, the change from 10.2 to 10.3 suggests it is preferred
646 #if TARGET_API_MAC_OSX
647 MacInsertMenuItem( appleMenu
, "\p-" , 0 ) ;
650 MacInsertMenuItem( appleMenu
, "\pAbout..." , 0 ) ;
651 MacInsertMenu( appleMenu
, 0 ) ;
653 // clean-up the help menu before adding new items
654 static MenuHandle mh
= NULL
;
658 MenuItemIndex firstUserHelpMenuItem
;
659 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
661 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
663 DeleteMenuItem( mh
, i
) ;
672 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
)
674 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
675 if ( item
== NULL
|| !(item
->IsEnabled()) )
676 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
678 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
680 // Unlike preferences which may or may not exist, the Quit item should be always
681 // enabled unless it is added by the application and then disabled, otherwise
682 // a program would be required to add an item with wxID_EXIT in order to get the
683 // Quit menu item to be enabled, which seems a bit burdensome.
684 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId
)
686 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
687 if ( item
!= NULL
&& !(item
->IsEnabled()) )
688 DisableMenuCommand( NULL
, kHICommandQuit
) ;
690 EnableMenuCommand( NULL
, kHICommandQuit
) ;
693 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
695 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
697 wxMenuItemList::compatibility_iterator node
;
700 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
702 if( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
704 for (pos
= 0 , node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
706 item
= (wxMenuItem
*)node
->GetData();
707 subMenu
= item
->GetSubMenu() ;
710 // we don't support hierarchical menus in the help menu yet
714 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
718 MenuItemIndex firstUserHelpMenuItem
;
719 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
729 if ( item
->IsSeparator() )
732 MacAppendMenu(mh
, "\p-" );
736 wxAcceleratorEntry
* entry
= wxGetAccelFromString( item
->GetText() ) ;
738 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
740 // this will be taken care of below
746 UMAAppendMenuItem(mh
, item
->GetText() , wxFont::GetDefaultEncoding(), entry
);
747 SetMenuItemCommandID( mh
, CountMenuItems(mh
) , item
->GetId() ) ;
748 SetMenuItemRefCon( mh
, CountMenuItems(mh
) , (UInt32
)item
) ;
759 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding() ) ;
760 menu
->MacBeforeDisplay(false) ;
761 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
764 // take care of the about menu item wherever it is
767 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
770 wxAcceleratorEntry
* entry
= wxGetAccelFromString( aboutMenuItem
->GetText() ) ;
771 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , aboutMenuItem
->GetText() , wxFont::GetDefaultEncoding() );
772 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
773 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , aboutMenuItem
->GetId() ) ;
774 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (UInt32
)aboutMenuItem
) ;
775 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
779 s_macInstalledMenuBar
= this;
782 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
784 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
785 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
789 bool wxMenuBar::Enable( bool enable
)
791 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
793 for (i
= 0; i
< GetMenuCount(); i
++)
795 EnableTop(i
, enable
);
800 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
802 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
804 m_titles
[pos
] = label
;
811 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
813 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
815 ::SetMenuBar( GetMenuBar() ) ;
820 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
822 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
823 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
825 return m_titles
[pos
];
828 int wxMenuBar::FindMenu(const wxString
& title
)
830 wxString menuTitle
= wxStripMenuCodes(title
);
832 size_t count
= GetMenuCount();
833 for ( size_t i
= 0; i
< count
; i
++ )
835 wxString title
= wxStripMenuCodes(m_titles
[i
]);
836 if ( menuTitle
== title
)
845 // ---------------------------------------------------------------------------
846 // wxMenuBar construction
847 // ---------------------------------------------------------------------------
849 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
851 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
854 m_titles
[pos
] = title
;
858 if (s_macInstalledMenuBar
== this)
860 menuOld
->MacAfterDisplay( false ) ;
861 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
863 menu
->MacBeforeDisplay( false ) ;
864 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
865 if ( pos
== m_menus
.GetCount() - 1)
867 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
871 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
878 if (m_invokingWindow
)
879 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
884 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
886 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
889 m_titles
.Insert(title
, pos
);
891 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
893 if ( IsAttached() && s_macInstalledMenuBar
== this )
895 if (s_macInstalledMenuBar
== this)
897 menu
->MacBeforeDisplay( false ) ;
898 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
900 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
904 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
909 if (m_invokingWindow
)
910 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
915 wxMenu
*wxMenuBar::Remove(size_t pos
)
917 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
923 if (s_macInstalledMenuBar
== this)
925 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
931 m_titles
.RemoveAt(pos
);
936 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
938 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
939 wxCHECK_MSG( submenu
, FALSE
, wxT("can't append invalid menu to menubar") );
941 if ( !wxMenuBarBase::Append(menu
, title
) )
946 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
950 if (s_macInstalledMenuBar
== this)
952 menu
->MacBeforeDisplay( false ) ;
953 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
959 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
960 // adding menu later on.
961 if (m_invokingWindow
)
962 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
967 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
969 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
971 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
974 wxMenuItem
*menuitem
= node
->GetData();
975 if (menuitem
->IsSubMenu())
976 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
977 node
= node
->GetNext();
981 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
983 menu
->SetInvokingWindow( win
);
985 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
988 wxMenuItem
*menuitem
= node
->GetData();
989 if (menuitem
->IsSubMenu())
990 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
991 node
= node
->GetNext();
995 void wxMenuBar::UnsetInvokingWindow()
997 m_invokingWindow
= (wxWindow
*) NULL
;
998 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
1001 wxMenu
*menu
= node
->GetData();
1002 wxMenubarUnsetInvokingWindow( menu
);
1003 node
= node
->GetNext();
1007 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
1009 m_invokingWindow
= frame
;
1010 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
1013 wxMenu
*menu
= node
->GetData();
1014 wxMenubarSetInvokingWindow( menu
, frame
);
1015 node
= node
->GetNext();
1019 void wxMenuBar::Detach()
1021 wxMenuBarBase::Detach() ;
1024 void wxMenuBar::Attach(wxFrame
*frame
)
1026 wxMenuBarBase::Attach( frame
) ;
1028 // ---------------------------------------------------------------------------
1029 // wxMenuBar searching for menu items
1030 // ---------------------------------------------------------------------------
1032 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1033 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1034 const wxString
& itemString
) const
1036 wxString menuLabel
= wxStripMenuCodes(menuString
);
1037 size_t count
= GetMenuCount();
1038 for ( size_t i
= 0; i
< count
; i
++ )
1040 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1041 if ( menuLabel
== title
)
1042 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1048 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1053 wxMenuItem
*item
= NULL
;
1054 size_t count
= GetMenuCount();
1055 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1057 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);