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 #if !USE_SHARED_LIBRARY
41 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
)
42 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
)
45 // the (popup) menu title has this special id
46 static const int idMenuTitle
= -3;
48 const short kwxMacMenuBarResource
= 1 ;
49 const short kwxMacAppleMenuId
= 1 ;
52 // Find an item given the Macintosh Menu Reference
54 #if KEY_wxList_DEPRECATED
55 wxList
wxWinMacMenuList(wxKEY_INTEGER
);
56 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
58 wxNode
*node
= wxWinMacMenuList
.Find((long)inMenuRef
);
61 return (wxMenu
*)node
->GetData();
64 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
65 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
67 // adding NULL MenuRef is (first) surely a result of an error and
68 // (secondly) breaks menu command processing
69 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
71 if ( !wxWinMacMenuList
.Find((long)inMenuRef
) )
72 wxWinMacMenuList
.Append((long)inMenuRef
, menu
);
75 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
76 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
78 wxWinMacMenuList
.DeleteObject(menu
);
82 WX_DECLARE_HASH_MAP(MenuRef
, wxMenu
*, wxPointerHash
, wxPointerEqual
, MacMenuMap
);
84 static MacMenuMap wxWinMacMenuList
;
86 wxMenu
*wxFindMenuFromMacMenu(MenuRef inMenuRef
)
88 MacMenuMap::iterator node
= wxWinMacMenuList
.find(inMenuRef
);
90 return (node
== wxWinMacMenuList
.end()) ? NULL
: node
->second
;
93 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
) ;
94 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu
*menu
)
96 // adding NULL MenuRef is (first) surely a result of an error and
97 // (secondly) breaks menu command processing
98 wxCHECK_RET( inMenuRef
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") );
100 wxWinMacMenuList
[inMenuRef
] = menu
;
103 void wxRemoveMacMenuAssociation(wxMenu
*menu
) ;
104 void wxRemoveMacMenuAssociation(wxMenu
*menu
)
106 // iterate over all the elements in the class
107 MacMenuMap::iterator it
;
108 for ( it
= wxWinMacMenuList
.begin(); it
!= wxWinMacMenuList
.end(); ++it
)
110 if ( it
->second
== menu
)
112 wxWinMacMenuList
.erase(it
);
117 #endif // deprecated wxList
119 // ============================================================================
121 // ============================================================================
122 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
) ;
123 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
);
127 // Construct a menu with optional title (then use append)
130 short wxMenu::s_macNextMenuId
= 3 ;
132 short wxMenu::s_macNextMenuId
= 2 ;
137 _wxMenuAt(const wxMenuList
&menuList
, size_t pos
)
139 wxMenuList::compatibility_iterator menuIter
= menuList
.GetFirst();
141 while (pos
-- > 0) menuIter
= menuIter
->GetNext();
143 return menuIter
->GetData() ;
149 m_startRadioGroup
= -1;
152 m_macMenuId
= s_macNextMenuId
++;
153 m_hMenu
= UMANewMenu(m_macMenuId
, m_title
, wxFont::GetDefaultEncoding() );
157 wxLogLastError(wxT("UMANewMenu failed"));
160 wxAssociateMenuWithMacMenu( (MenuRef
)m_hMenu
, this ) ;
162 // if we have a title, insert it in the beginning of the menu
165 Append(idMenuTitle
, m_title
) ;
172 wxRemoveMacMenuAssociation( this ) ;
173 if (MAC_WXHMENU(m_hMenu
))
174 ::DisposeMenu(MAC_WXHMENU(m_hMenu
));
179 // not available on the mac platform
182 void wxMenu::Attach(wxMenuBarBase
*menubar
)
184 wxMenuBase::Attach(menubar
);
189 // function appends a new item or submenu to the menu
190 // append a new item or submenu to the menu
191 bool wxMenu::DoInsertOrAppend(wxMenuItem
*pItem
, size_t pos
)
193 wxASSERT_MSG( pItem
!= NULL
, wxT("can't append NULL item to the menu") );
195 if ( pItem
->IsSeparator() )
197 if ( pos
== (size_t)-1 )
198 MacAppendMenu(MAC_WXHMENU(m_hMenu
), "\p-");
200 MacInsertMenuItem(MAC_WXHMENU(m_hMenu
), "\p-" , pos
);
204 wxMenu
*pSubMenu
= pItem
->GetSubMenu() ;
205 if ( pSubMenu
!= NULL
)
207 wxASSERT_MSG( pSubMenu
->m_hMenu
!= NULL
, wxT("invalid submenu added"));
208 pSubMenu
->m_menuParent
= this ;
210 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
212 pSubMenu
->MacBeforeDisplay( true ) ;
215 if ( pos
== (size_t)-1 )
216 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu
), pItem
->GetText(), wxFont::GetDefaultEncoding() , pSubMenu
->m_macMenuId
);
218 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu
), pItem
->GetText(), wxFont::GetDefaultEncoding() , pos
, pSubMenu
->m_macMenuId
);
219 pItem
->UpdateItemBitmap() ;
220 pItem
->UpdateItemStatus() ;
224 if ( pos
== (size_t)-1 )
226 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a") , wxFont::GetDefaultEncoding() );
227 pos
= CountMenuItems(MAC_WXHMENU(m_hMenu
)) ;
231 // MacOS counts menu items from 1 and inserts after, therefore having the
232 // same effect as wx 0 based and inserting before, we must correct pos
233 // after however for updates to be correct
234 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a"), wxFont::GetDefaultEncoding(), pos
);
238 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu
) , pos
, pItem
->GetId() ) ;
239 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu
) , pos
, (UInt32
) pItem
) ;
240 pItem
->UpdateItemText() ;
241 pItem
->UpdateItemBitmap() ;
242 pItem
->UpdateItemStatus() ;
244 if ( pItem
->GetId() == idMenuTitle
)
246 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , pos
, false ) ;
250 // if we're already attached to the menubar, we must update it
253 GetMenuBar()->Refresh();
258 void wxMenu::EndRadioGroup()
260 // we're not inside a radio group any longer
261 m_startRadioGroup
= -1;
264 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
266 wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") );
270 if ( item
->GetKind() == wxITEM_RADIO
)
272 int count
= GetMenuItemCount();
274 if ( m_startRadioGroup
== -1 )
276 // start a new radio group
277 m_startRadioGroup
= count
;
279 // for now it has just one element
280 item
->SetAsRadioGroupStart();
281 item
->SetRadioGroupEnd(m_startRadioGroup
);
283 // ensure that we have a checked item in the radio group
286 else // extend the current radio group
288 // we need to update its end item
289 item
->SetRadioGroupStart(m_startRadioGroup
);
290 wxMenuItemList::compatibility_iterator node
= GetMenuItems().Item(m_startRadioGroup
);
294 node
->GetData()->SetRadioGroupEnd(count
);
298 wxFAIL_MSG( _T("where is the radio group start item?") );
302 else // not a radio item
307 if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) )
314 // check the item initially
321 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
323 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
329 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
331 // we need to find the items position in the child list
333 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
334 for ( pos
= 0; node
; pos
++ )
336 if ( node
->GetData() == item
)
339 node
= node
->GetNext();
342 // DoRemove() (unlike Remove) can only be called for existing item!
343 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
345 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu
) , pos
+ 1);
349 // otherwise, the change won't be visible
350 GetMenuBar()->Refresh();
353 // and from internal data structures
354 return wxMenuBase::DoRemove(item
);
357 void wxMenu::SetTitle(const wxString
& label
)
360 UMASetMenuTitle(MAC_WXHMENU(m_hMenu
) , label
, wxFont::GetDefaultEncoding() ) ;
362 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
364 bool processed
= FALSE
;
366 // Try the menu's event handler
367 if ( !processed
&& GetEventHandler())
369 processed
= GetEventHandler()->ProcessEvent(event
);
372 // Try the window the menu was popped up from (and up through the
374 wxWindow
*win
= GetInvokingWindow();
375 if ( !processed
&& win
)
376 processed
= win
->GetEventHandler()->ProcessEvent(event
);
382 // ---------------------------------------------------------------------------
384 // ---------------------------------------------------------------------------
386 wxWindow
*wxMenu::GetWindow() const
388 if ( m_invokingWindow
!= NULL
)
389 return m_invokingWindow
;
390 else if ( GetMenuBar() != NULL
)
391 return (wxWindow
*) GetMenuBar()->GetFrame();
396 // helper functions returning the mac menu position for a certain item, note that this is
397 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
399 int wxMenu::MacGetIndexFromId( int id
)
402 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
403 for ( pos
= 0; node
; pos
++ )
405 if ( node
->GetData()->GetId() == id
)
408 node
= node
->GetNext();
417 int wxMenu::MacGetIndexFromItem( wxMenuItem
*pItem
)
420 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
421 for ( pos
= 0; node
; pos
++ )
423 if ( node
->GetData() == pItem
)
426 node
= node
->GetNext();
435 void wxMenu::MacEnableMenu( bool bDoEnable
)
437 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable
) ;
442 // MacOS needs to know about submenus somewhere within this menu
443 // before it can be displayed , also hide special menu items like preferences
444 // that are handled by the OS
445 void wxMenu::MacBeforeDisplay( bool isSubMenu
)
447 wxMenuItem
* previousItem
= NULL
;
449 wxMenuItemList::compatibility_iterator node
;
451 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
453 item
= (wxMenuItem
*)node
->GetData();
454 wxMenu
* subMenu
= item
->GetSubMenu() ;
457 subMenu
->MacBeforeDisplay( true ) ;
462 // what we do here is to hide the special items which are
463 // shown in the application menu anyhow -- it doesn't make
464 // sense to show them in their normal place as well
465 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
466 ( UMAGetSystemVersion() >= 0x1000 && (
467 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
468 item
->GetId() == wxApp::s_macExitMenuItemId
) ) )
471 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
472 pos
+ 1, kMenuItemAttrHidden
, 0 );
474 // also check for a separator which was used just to
475 // separate this item from the others, so don't leave
476 // separator at the menu start or end nor 2 consecutive
478 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
479 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
482 if ( !previousItem
&& next
&& next
->IsSeparator() )
484 // next (i.e. second as we must be first) item is
485 // the separator to hide
486 wxASSERT_MSG( pos
== 0, _T("should be the menu start") );
489 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
490 previousItem
!= NULL
&&
491 previousItem
->IsSeparator() )
493 // prev item is a trailing separator we want to hide
496 else if ( previousItem
&& previousItem
->IsSeparator() &&
497 next
&& next
->IsSeparator() )
499 // two consecutive separators, this is one too many
502 else // no separators to hide
509 // hide the separator as well
510 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
516 #endif // TARGET_CARBON
518 previousItem
= item
;
522 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
525 // undo all changes from the MacBeforeDisplay call
526 void wxMenu::MacAfterDisplay( bool isSubMenu
)
529 ::DeleteMenu(MacGetMenuId());
531 wxMenuItem
* previousItem
= NULL
;
533 wxMenuItemList::compatibility_iterator node
;
535 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
537 item
= (wxMenuItem
*)node
->GetData();
538 wxMenu
* subMenu
= item
->GetSubMenu() ;
541 subMenu
->MacAfterDisplay( true ) ;
545 // no need to undo hidings
547 previousItem
= item
;
555 Mac Implementation note :
557 The Mac has only one global menubar, so we attempt to install the currently
558 active menubar from a frame, we currently don't take into account mdi-frames
559 which would ask for menu-merging
561 Secondly there is no mac api for changing a menubar that is not the current
562 menubar, so we have to wait for preparing the actual menubar until the
563 wxMenubar is to be used
565 We can in subsequent versions use MacInstallMenuBar to provide some sort of
566 auto-merge for MDI in case this will be necessary
570 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
571 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
573 void wxMenuBar::Init()
575 m_eventHandler
= this;
576 m_menuBarFrame
= NULL
;
577 m_invokingWindow
= (wxWindow
*) NULL
;
580 wxMenuBar::wxMenuBar()
585 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
591 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
595 m_titles
.Alloc(count
);
597 for ( size_t i
= 0; i
< count
; i
++ )
599 m_menus
.Append(menus
[i
]);
600 m_titles
.Add(titles
[i
]);
602 menus
[i
]->Attach(this);
606 wxMenuBar::~wxMenuBar()
608 if (s_macCommonMenuBar
== this)
609 s_macCommonMenuBar
= NULL
;
610 if (s_macInstalledMenuBar
== this)
613 s_macInstalledMenuBar
= NULL
;
618 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
620 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
625 void wxMenuBar::MacInstallMenuBar()
627 if ( s_macInstalledMenuBar
== this )
630 MenuBarHandle menubar
= NULL
;
631 #if TARGET_API_MAC_OSX
632 menubar
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
634 menubar
= NewHandleClear( 12 ) ;
635 (*menubar
)[3] = 0x0a ;
637 ::SetMenuBar( menubar
) ;
638 DisposeMenuBar( menubar
) ;
639 MenuHandle appleMenu
= NULL
;
640 char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph
, 0 } ;
642 verify_noerr( CreateNewMenu( kwxMacAppleMenuId
, 0 , &appleMenu
) ) ;
643 verify_noerr( SetMenuTitle( appleMenu
, (ConstStr255Param
) appleMenuTitle
) );
645 // Add About/Preferences separator only on OS X
646 // KH/RN: Separator is always present on 10.3 but not on 10.2
647 // However, the change from 10.2 to 10.3 suggests it is preferred
648 #if TARGET_API_MAC_OSX
649 MacInsertMenuItem( appleMenu
, "\p-" , 0 ) ;
652 MacInsertMenuItem( appleMenu
, "\pAbout..." , 0 ) ;
653 MacInsertMenu( appleMenu
, 0 ) ;
655 // clean-up the help menu before adding new items
656 MenuHandle mh
= NULL
;
660 MenuItemIndex firstUserHelpMenuItem
;
661 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
663 for ( int i
= CountMenuItems( mh
) ; i
>= firstUserHelpMenuItem
; --i
)
665 DeleteMenuItem( mh
, i
) ;
674 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
)
676 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
677 if ( item
== NULL
|| !(item
->IsEnabled()) )
678 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
680 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
682 // Unlike preferences which may or may not exist, the Quit item should be always
683 // enabled unless it is added by the application and then disabled, otherwise
684 // a program would be required to add an item with wxID_EXIT in order to get the
685 // Quit menu item to be enabled, which seems a bit burdensome.
686 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId
)
688 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
689 if ( item
!= NULL
&& !(item
->IsEnabled()) )
690 DisableMenuCommand( NULL
, kHICommandQuit
) ;
692 EnableMenuCommand( NULL
, kHICommandQuit
) ;
695 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
697 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
699 wxMenuItemList::compatibility_iterator node
;
702 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
704 if( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?") || m_titles
[i
] == wxApp::s_macHelpMenuTitleName
)
706 for (pos
= 0 , node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
708 item
= (wxMenuItem
*)node
->GetData();
709 subMenu
= item
->GetSubMenu() ;
712 // we don't support hierarchical menus in the help menu yet
716 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
720 MenuItemIndex firstUserHelpMenuItem
;
721 if ( UMAGetHelpMenu( &mh
, &firstUserHelpMenuItem
) == noErr
)
731 if ( item
->IsSeparator() )
734 MacAppendMenu(mh
, "\p-" );
738 wxAcceleratorEntry
* entry
= wxGetAccelFromString( item
->GetText() ) ;
740 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
742 // this will be taken care of below
748 UMAAppendMenuItem(mh
, item
->GetText() , wxFont::GetDefaultEncoding(), entry
);
749 SetMenuItemCommandID( mh
, CountMenuItems(mh
) , item
->GetId() ) ;
750 SetMenuItemRefCon( mh
, CountMenuItems(mh
) , (UInt32
)item
) ;
761 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding() ) ;
762 menu
->MacBeforeDisplay(false) ;
763 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0);
766 // take care of the about menu item wherever it is
769 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
772 wxAcceleratorEntry
* entry
= wxGetAccelFromString( aboutMenuItem
->GetText() ) ;
773 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , aboutMenuItem
->GetText() , wxFont::GetDefaultEncoding() );
774 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
775 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , aboutMenuItem
->GetId() ) ;
776 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (UInt32
)aboutMenuItem
) ;
777 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
781 s_macInstalledMenuBar
= this;
784 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
786 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
787 _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable
) ;
791 bool wxMenuBar::Enable( bool enable
)
793 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
795 for (i
= 0; i
< GetMenuCount(); i
++)
797 EnableTop(i
, enable
);
802 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
)
804 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
806 m_titles
[pos
] = label
;
813 _wxMenuAt(m_menus
, pos
)->SetTitle( label
) ;
815 if (wxMenuBar::s_macInstalledMenuBar
== this) // are we currently installed ?
817 ::SetMenuBar( GetMenuBar() ) ;
822 wxString
wxMenuBar::GetLabelTop(size_t pos
) const
824 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
825 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
827 return m_titles
[pos
];
830 int wxMenuBar::FindMenu(const wxString
& title
)
832 wxString menuTitle
= wxStripMenuCodes(title
);
834 size_t count
= GetMenuCount();
835 for ( size_t i
= 0; i
< count
; i
++ )
837 wxString title
= wxStripMenuCodes(m_titles
[i
]);
838 if ( menuTitle
== title
)
847 // ---------------------------------------------------------------------------
848 // wxMenuBar construction
849 // ---------------------------------------------------------------------------
851 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
853 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
856 m_titles
[pos
] = title
;
860 if (s_macInstalledMenuBar
== this)
862 menuOld
->MacAfterDisplay( false ) ;
863 ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
865 menu
->MacBeforeDisplay( false ) ;
866 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
867 if ( pos
== m_menus
.GetCount() - 1)
869 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
873 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
880 if (m_invokingWindow
)
881 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
886 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
888 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
891 m_titles
.Insert(title
, pos
);
893 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
895 if ( IsAttached() && s_macInstalledMenuBar
== this )
897 if (s_macInstalledMenuBar
== this)
899 menu
->MacBeforeDisplay( false ) ;
900 if ( pos
== (size_t) -1 || pos
+ 1 == m_menus
.GetCount() )
902 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
906 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ;
911 if (m_invokingWindow
)
912 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
917 wxMenu
*wxMenuBar::Remove(size_t pos
)
919 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
925 if (s_macInstalledMenuBar
== this)
927 ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
933 m_titles
.RemoveAt(pos
);
938 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
940 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
941 wxCHECK_MSG( submenu
, FALSE
, wxT("can't append invalid menu to menubar") );
943 if ( !wxMenuBarBase::Append(menu
, title
) )
948 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title
, m_font
.GetEncoding() ) ;
952 if (s_macInstalledMenuBar
== this)
954 menu
->MacBeforeDisplay( false ) ;
955 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ;
961 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
962 // adding menu later on.
963 if (m_invokingWindow
)
964 wxMenubarSetInvokingWindow( menu
, m_invokingWindow
);
969 static void wxMenubarUnsetInvokingWindow( wxMenu
*menu
)
971 menu
->SetInvokingWindow( (wxWindow
*) NULL
);
973 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
976 wxMenuItem
*menuitem
= node
->GetData();
977 if (menuitem
->IsSubMenu())
978 wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() );
979 node
= node
->GetNext();
983 static void wxMenubarSetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
985 menu
->SetInvokingWindow( win
);
987 wxMenuItemList::compatibility_iterator node
= menu
->GetMenuItems().GetFirst();
990 wxMenuItem
*menuitem
= node
->GetData();
991 if (menuitem
->IsSubMenu())
992 wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win
);
993 node
= node
->GetNext();
997 void wxMenuBar::UnsetInvokingWindow()
999 m_invokingWindow
= (wxWindow
*) NULL
;
1000 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
1003 wxMenu
*menu
= node
->GetData();
1004 wxMenubarUnsetInvokingWindow( menu
);
1005 node
= node
->GetNext();
1009 void wxMenuBar::SetInvokingWindow(wxFrame
*frame
)
1011 m_invokingWindow
= frame
;
1012 wxMenuList::compatibility_iterator node
= m_menus
.GetFirst();
1015 wxMenu
*menu
= node
->GetData();
1016 wxMenubarSetInvokingWindow( menu
, frame
);
1017 node
= node
->GetNext();
1021 void wxMenuBar::Detach()
1023 wxMenuBarBase::Detach() ;
1026 void wxMenuBar::Attach(wxFrame
*frame
)
1028 wxMenuBarBase::Attach( frame
) ;
1030 // ---------------------------------------------------------------------------
1031 // wxMenuBar searching for menu items
1032 // ---------------------------------------------------------------------------
1034 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1035 int wxMenuBar::FindMenuItem(const wxString
& menuString
,
1036 const wxString
& itemString
) const
1038 wxString menuLabel
= wxStripMenuCodes(menuString
);
1039 size_t count
= GetMenuCount();
1040 for ( size_t i
= 0; i
< count
; i
++ )
1042 wxString title
= wxStripMenuCodes(m_titles
[i
]);
1043 if ( menuLabel
== title
)
1044 return _wxMenuAt(m_menus
, i
)->FindItem(itemString
);
1050 wxMenuItem
*wxMenuBar::FindItem(int id
, wxMenu
**itemMenu
) const
1055 wxMenuItem
*item
= NULL
;
1056 size_t count
= GetMenuCount();
1057 for ( size_t i
= 0; !item
&& (i
< count
); i
++ )
1059 item
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);