1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/menu_osx.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"
30 #include "wx/dialog.h"
31 #include "wx/menuitem.h"
34 #include "wx/osx/private.h"
36 // other standard headers
37 // ----------------------
40 IMPLEMENT_ABSTRACT_CLASS( wxMenuImpl
, wxObject
)
42 wxMenuImpl::~wxMenuImpl()
46 // the (popup) menu title has this special menuid
47 static const int idMenuTitle
= -3;
49 // ============================================================================
51 // ============================================================================
55 // Construct a menu with optional title (then use append)
60 m_allowRearrange
= true;
61 m_noEventsMode
= false;
63 m_peer
= wxMenuImpl::Create( this, wxStripMenuCodes(m_title
) );
66 // if we have a title, insert it in the beginning of the menu
67 if ( !m_title
.empty() )
69 Append(idMenuTitle
, m_title
) ;
79 WXHMENU
wxMenu::GetHMenu() const
82 return m_peer
->GetHMenu();
88 // not available on the mac platform
91 void wxMenu::SetAllowRearrange( bool allow
)
93 m_allowRearrange
= allow
;
96 void wxMenu::SetNoEventsMode( bool noEvents
)
98 m_noEventsMode
= noEvents
;
101 // function appends a new item or submenu to the menu
102 // append a new item or submenu to the menu
103 bool wxMenu::DoInsertOrAppend(wxMenuItem
*item
, size_t pos
)
105 wxASSERT_MSG( item
!= NULL
, wxT("can't append NULL item to the menu") );
106 GetPeer()->InsertOrAppend( item
, pos
);
110 if ( item
->IsSeparator() )
112 // nothing to do here
116 wxMenu
*pSubMenu
= item
->GetSubMenu() ;
117 if ( pSubMenu
!= NULL
)
119 wxASSERT_MSG( pSubMenu
->GetHMenu() != NULL
, wxT("invalid submenu added"));
120 pSubMenu
->m_menuParent
= this ;
122 pSubMenu
->DoRearrange();
124 else if ( item
->IsRadio() )
126 // If a previous or next item is a radio button, add this radio
127 // button to the existing radio group. Otherwise start a new one
129 wxMenuItemList
& items
= GetMenuItems();
132 posItem
= pos
== (size_t)-1 ? items
.GetCount() - 1 : pos
;
134 wxMenuItemList::compatibility_iterator node
= items
.Item(posItem
);
135 wxCHECK_MSG( node
, false, wxS("New item must have been inserted") );
137 bool foundGroup
= false;
138 if ( node
->GetPrevious() )
140 wxMenuItem
* const prev
= node
->GetPrevious()->GetData();
142 if ( prev
->IsRadio() )
144 // This item is in the same group as the preceding one so
145 // we should use the same starting item, but getting it is
146 // a bit difficult as we can't query the start radio group
148 const int groupStart
= prev
->IsRadioGroupStart()
150 : prev
->GetRadioGroupStart();
151 item
->SetRadioGroupStart(groupStart
);
153 // We must also account for the new item by incrementing
154 // the index of the last item in this group.
155 wxMenuItem
* const first
= items
.Item(groupStart
)->GetData();
156 first
->SetRadioGroupEnd(first
->GetRadioGroupEnd() + 1);
162 if ( !foundGroup
&& node
->GetNext() )
164 wxMenuItem
* const next
= node
->GetNext()->GetData();
166 if ( next
->IsRadio() )
168 // This item is the new starting item of this group as the
169 // previous item is not a radio item.
170 wxASSERT_MSG( next
->IsRadioGroupStart(),
171 wxS("Where is the start of this group?") );
173 // The index of the last item of the radio group must be
174 // incremented to account for the new item.
175 item
->SetAsRadioGroupStart();
176 item
->SetRadioGroupEnd(next
->GetRadioGroupEnd() + 1);
178 // And the previous start item is not one any longer.
179 next
->SetAsRadioGroupStart(false);
187 // start a new radio group
188 item
->SetAsRadioGroupStart();
189 item
->SetRadioGroupEnd(posItem
);
191 // ensure that we have a checked item in the radio group
197 if ( item
->GetId() == idMenuTitle
)
198 item
->GetMenu()->Enable( idMenuTitle
, false );
202 // We also need to update the indices of radio group start and end we store
203 // in any existing radio items after this item.
204 if ( pos
< GetMenuItemCount() - 1 ) // takes into account pos == -1 case
206 for ( wxMenuItemList::compatibility_iterator
207 node
= GetMenuItems().Item(pos
+ 1);
209 node
= node
->GetNext() )
211 wxMenuItem
* const item
= node
->GetData();
212 if ( item
->IsRadio() )
214 if ( item
->IsRadioGroupStart() )
216 // If the starting item is after the just inserted one,
217 // then the end one must be after it too and needs to be
219 item
->SetRadioGroupEnd(item
->GetRadioGroupEnd() + 1);
221 else // Not the first radio group item.
223 // We need to update the start item index only if it is
224 // after the just inserted item.
225 const int groupStart
= item
->GetRadioGroupStart();
226 if ( (size_t)groupStart
> pos
)
227 item
->SetRadioGroupStart(groupStart
+ 1);
233 // if we're already attached to the menubar, we must update it
234 if ( IsAttached() && GetMenuBar()->IsAttached() )
235 GetMenuBar()->Refresh();
243 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
245 if (wxMenuBase::DoAppend(item
) && DoInsertOrAppend(item
) )
251 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
253 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
259 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
261 if ( item
->IsRadio() )
263 // Check if we're removing the item starting the radio group
264 if ( item
->IsRadioGroupStart() )
266 // Yes, we do, update the next radio group item, if any, to be the
268 const int endGroup
= item
->GetRadioGroupEnd();
270 wxMenuItemList::compatibility_iterator
271 node
= GetMenuItems().Item(endGroup
);
272 wxASSERT_MSG( node
, wxS("Should have valid radio group end") );
274 while ( node
->GetData() != item
)
276 const wxMenuItemList::compatibility_iterator
277 prevNode
= node
->GetPrevious();
278 wxMenuItem
* const prevItem
= prevNode
->GetData();
279 if ( prevItem
== item
)
281 prevItem
->SetAsRadioGroupStart();
282 prevItem
->SetRadioGroupEnd(endGroup
);
292 // we need to find the items position in the child list
294 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
296 for ( pos = 0; node; pos++ )
298 if ( node->GetData() == item )
301 node = node->GetNext();
304 // DoRemove() (unlike Remove) can only be called for existing item!
305 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
307 wxOSXMenuRemoveItem(m_hMenu , pos );
309 GetPeer()->Remove( item
);
310 // and from internal data structures
311 return wxMenuBase::DoRemove(item
);
314 void wxMenu::SetTitle(const wxString
& label
)
317 GetPeer()->SetTitle( wxStripMenuCodes( label
) );
320 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
322 bool processed
= false;
324 // Try the menu's event handler
325 if ( /* !processed && */ GetEventHandler())
326 processed
= GetEventHandler()->SafelyProcessEvent(event
);
328 // Try the window the menu was popped up from
329 // (and up through the hierarchy)
330 wxWindow
*win
= GetWindow();
331 if ( !processed
&& win
)
332 processed
= win
->HandleWindowEvent(event
);
337 // ---------------------------------------------------------------------------
339 // ---------------------------------------------------------------------------
341 // MacOS needs to know about submenus somewhere within this menu
342 // before it can be displayed, also hide special menu items
343 // like preferences that are handled by the OS
344 void wxMenu::DoRearrange()
346 if ( !AllowRearrange() )
349 wxMenuItem
* previousItem
= NULL
;
351 wxMenuItemList::compatibility_iterator node
;
354 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
356 item
= (wxMenuItem
*)node
->GetData();
357 wxMenu
* subMenu
= item
->GetSubMenu() ;
364 // what we do here is to hide the special items which are
365 // shown in the application menu anyhow -- it doesn't make
366 // sense to show them in their normal place as well
367 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
368 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
369 item
->GetId() == wxApp::s_macExitMenuItemId
)
372 item
->GetPeer()->Hide( true );
374 // also check for a separator which was used just to
375 // separate this item from the others, so don't leave
376 // separator at the menu start or end nor 2 consecutive
378 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
379 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
381 wxMenuItem
*sepToHide
= 0;
382 if ( !previousItem
&& next
&& next
->IsSeparator() )
384 // next (i.e. second as we must be first) item is
385 // the separator to hide
386 wxASSERT_MSG( pos
== 0, wxT("should be the menu start") );
389 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
390 previousItem
!= NULL
&&
391 previousItem
->IsSeparator() )
393 // prev item is a trailing separator we want to hide
394 sepToHide
= previousItem
;
396 else if ( previousItem
&& previousItem
->IsSeparator() &&
397 next
&& next
->IsSeparator() )
399 // two consecutive separators, this is one too many
405 // hide the separator as well
406 sepToHide
->GetPeer()->Hide( true );
411 previousItem
= item
;
416 bool wxMenu::HandleCommandUpdateStatus( wxMenuItem
* item
, wxWindow
* senderWindow
)
418 int menuid
= item
? item
->GetId() : 0;
419 wxUpdateUIEvent
event(menuid
);
420 event
.SetEventObject( this );
422 bool processed
= false;
424 // Try the menu's event handler
426 wxEvtHandler
*handler
= GetEventHandler();
428 processed
= handler
->ProcessEvent(event
);
431 // Try the window the menu was popped up from
432 // (and up through the hierarchy)
435 wxWindow
*win
= GetWindow();
437 processed
= win
->HandleWindowEvent(event
);
440 if ( !processed
&& senderWindow
!= NULL
)
442 processed
= senderWindow
->HandleWindowEvent(event
);
447 // if anything changed, update the changed attribute
448 if (event
.GetSetText())
449 SetLabel(menuid
, event
.GetText());
450 if (event
.GetSetChecked())
451 Check(menuid
, event
.GetChecked());
452 if (event
.GetSetEnabled())
453 Enable(menuid
, event
.GetEnabled());
458 // these two items are also managed by the Carbon Menu Manager, therefore we must
459 // always reset them ourselves
462 if ( menuid
== wxApp::s_macExitMenuItemId
)
464 cmd
= kHICommandQuit
;
466 else if (menuid
== wxApp::s_macPreferencesMenuItemId
)
468 cmd
= kHICommandPreferences
;
473 if ( !item
->IsEnabled() || wxDialog::OSXHasModalDialogsOpen() )
474 DisableMenuCommand( NULL
, cmd
) ;
476 EnableMenuCommand( NULL
, cmd
) ;
485 bool wxMenu::HandleCommandProcess( wxMenuItem
* item
, wxWindow
* senderWindow
)
487 int menuid
= item
? item
->GetId() : 0;
488 bool processed
= false;
489 if (item
->IsCheckable())
490 item
->Check( !item
->IsChecked() ) ;
492 if ( SendEvent( menuid
, item
->IsCheckable() ? item
->IsChecked() : -1 ) )
496 if ( senderWindow
!= NULL
)
498 wxCommandEvent
event(wxEVT_MENU
, menuid
);
499 event
.SetEventObject(this);
500 event
.SetInt(item
->IsCheckable() ? item
->IsChecked() : -1);
502 if ( senderWindow
->HandleWindowEvent(event
) )
507 if(!processed
&& item
)
509 processed
= item
->GetPeer()->DoDefault();
515 void wxMenu::HandleMenuItemHighlighted( wxMenuItem
* item
)
517 int menuid
= item
? item
->GetId() : 0;
518 wxMenuEvent
wxevent(wxEVT_MENU_HIGHLIGHT
, menuid
, this);
519 DoHandleMenuEvent( wxevent
);
522 void wxMenu::DoHandleMenuOpenedOrClosed(wxEventType evtType
)
524 // Popup menu being currently shown or NULL, defined in wincmn.cpp.
525 extern wxMenu
*wxCurrentPopupMenu
;
527 // Set the id to allow wxMenuEvent::IsPopup() to work correctly.
528 int menuid
= this == wxCurrentPopupMenu
? wxID_ANY
: 0;
529 wxMenuEvent
wxevent(evtType
, menuid
, this);
530 DoHandleMenuEvent( wxevent
);
533 void wxMenu::HandleMenuOpened()
535 DoHandleMenuOpenedOrClosed(wxEVT_MENU_OPEN
);
538 void wxMenu::HandleMenuClosed()
540 DoHandleMenuOpenedOrClosed(wxEVT_MENU_CLOSE
);
543 bool wxMenu::DoHandleMenuEvent(wxEvent
& wxevent
)
545 wxevent
.SetEventObject(this);
546 wxEvtHandler
* handler
= GetEventHandler();
547 if (handler
&& handler
->ProcessEvent(wxevent
))
553 wxWindow
*win
= GetWindow();
556 if ( win
->HandleWindowEvent(wxevent
) )
567 Mac Implementation note :
569 The Mac has only one global menubar, so we attempt to install the currently
570 active menubar from a frame, we currently don't take into account mdi-frames
571 which would ask for menu-merging
573 Secondly there is no mac api for changing a menubar that is not the current
574 menubar, so we have to wait for preparing the actual menubar until the
575 wxMenubar is to be used
577 We can in subsequent versions use MacInstallMenuBar to provide some sort of
578 auto-merge for MDI in case this will be necessary
582 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
583 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
584 bool wxMenuBar::s_macAutoWindowMenu
= true ;
585 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
588 wxMenu
* emptyMenuBar
= NULL
;
590 const int firstMenuPos
= 1; // to account for the 0th application menu on mac
592 void wxMenuBar::Init()
594 if ( emptyMenuBar
== NULL
)
596 emptyMenuBar
= new wxMenu();
598 wxMenu
* appleMenu
= new wxMenu();
599 appleMenu
->SetAllowRearrange(false);
600 #if !wxOSX_USE_CARBON
601 // standard menu items, handled in wxMenu::HandleCommandProcess(), see above:
603 hideLabel
= wxString::Format(_("Hide %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
604 appleMenu
->Append( wxID_OSX_HIDE
, hideLabel
+ "\tCtrl+H" );
605 appleMenu
->Append( wxID_OSX_HIDEOTHERS
, _("Hide Others")+"\tAlt+Ctrl+H" );
606 appleMenu
->Append( wxID_OSX_SHOWALL
, _("Show All") );
607 appleMenu
->AppendSeparator();
609 // Do always add "Quit" item unconditionally however, it can't be disabled.
611 quitLabel
= wxString::Format(_("Quit %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
612 appleMenu
->Append( wxApp::s_macExitMenuItemId
, quitLabel
+ "\tCtrl+Q" );
613 #endif // !wxOSX_USE_CARBON
615 emptyMenuBar
->AppendSubMenu(appleMenu
, "\x14") ;
618 m_eventHandler
= this;
619 m_menuBarFrame
= NULL
;
620 m_rootMenu
= new wxMenu();
621 m_rootMenu
->Attach(this);
623 m_appleMenu
= new wxMenu();
624 m_appleMenu
->SetAllowRearrange(false);
626 // Create standard items unless the application explicitly disabled this by
627 // setting the corresponding ids to wxID_NONE: although this is not
628 // recommended, sometimes these items really don't make sense.
629 if ( wxApp::s_macAboutMenuItemId
!= wxID_NONE
)
631 wxString
aboutLabel(_("About"));
633 aboutLabel
<< ' ' << wxTheApp
->GetAppDisplayName();
636 m_appleMenu
->Append( wxApp::s_macAboutMenuItemId
, aboutLabel
);
637 m_appleMenu
->AppendSeparator();
640 #if !wxOSX_USE_CARBON
641 if ( wxApp::s_macPreferencesMenuItemId
!= wxID_NONE
)
643 m_appleMenu
->Append( wxApp::s_macPreferencesMenuItemId
,
644 _("Preferences...") + "\tCtrl+," );
645 m_appleMenu
->AppendSeparator();
648 // standard menu items, handled in wxMenu::HandleCommandProcess(), see above:
650 hideLabel
= wxString::Format(_("Hide %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
651 m_appleMenu
->Append( wxID_OSX_HIDE
, hideLabel
+ "\tCtrl+H" );
652 m_appleMenu
->Append( wxID_OSX_HIDEOTHERS
, _("Hide Others")+"\tAlt+Ctrl+H" );
653 m_appleMenu
->Append( wxID_OSX_SHOWALL
, _("Show All") );
654 m_appleMenu
->AppendSeparator();
656 // Do always add "Quit" item unconditionally however, it can't be disabled.
658 quitLabel
= wxString::Format(_("Quit %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
659 m_appleMenu
->Append( wxApp::s_macExitMenuItemId
, quitLabel
+ "\tCtrl+Q" );
660 #endif // !wxOSX_USE_CARBON
662 m_rootMenu
->AppendSubMenu(m_appleMenu
, "\x14") ;
665 wxMenuBar::wxMenuBar()
670 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
675 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
679 for ( size_t i
= 0; i
< count
; i
++ )
681 m_menus
.Append(menus
[i
]);
683 menus
[i
]->Attach(this);
684 Append( menus
[i
], titles
[i
] );
688 wxMenuBar::~wxMenuBar()
690 if (s_macCommonMenuBar
== this)
691 s_macCommonMenuBar
= NULL
;
693 if (s_macInstalledMenuBar
== this)
695 emptyMenuBar
->GetPeer()->MakeRoot();
696 s_macInstalledMenuBar
= NULL
;
698 wxDELETE( m_rootMenu
);
699 // apple menu is a submenu, therefore we don't have to delete it
702 // deleting the root menu also removes all its wxMenu* submenus, therefore
703 // we must avoid double deleting them in the superclass destructor
707 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
709 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
712 void wxMenuBar::MacInstallMenuBar()
714 if ( s_macInstalledMenuBar
== this )
717 m_rootMenu
->GetPeer()->MakeRoot();
719 // hide items in the apple menu that don't exist in the wx menubar
721 wxMenuItem
* appleItem
= NULL
;
722 wxMenuItem
* wxItem
= NULL
;
724 int menuid
= wxApp::s_macAboutMenuItemId
;
725 appleItem
= m_appleMenu
->FindItem(menuid
);
726 wxItem
= FindItem(menuid
);
727 if ( appleItem
!= NULL
)
729 if ( wxItem
== NULL
)
730 appleItem
->GetPeer()->Hide();
732 appleItem
->SetItemLabel(wxItem
->GetItemLabel());
735 menuid
= wxApp::s_macPreferencesMenuItemId
;
736 appleItem
= m_appleMenu
->FindItem(menuid
);
737 wxItem
= FindItem(menuid
);
738 if ( appleItem
!= NULL
)
740 if ( wxItem
== NULL
)
741 appleItem
->GetPeer()->Hide();
743 appleItem
->SetItemLabel(wxItem
->GetItemLabel());
749 // if we have a mac help menu, clean it up before adding new items
750 MenuHandle helpMenuHandle
;
751 MenuItemIndex firstUserHelpMenuItem
;
753 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
755 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
756 DeleteMenuItem( helpMenuHandle
, i
) ;
760 helpMenuHandle
= NULL
;
763 if ( wxApp::s_macPreferencesMenuItemId
)
765 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
766 if ( item
== NULL
|| !(item
->IsEnabled()) )
767 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
769 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
772 // Unlike preferences which may or may not exist, the Quit item should be always
773 // enabled unless it is added by the application and then disabled, otherwise
774 // a program would be required to add an item with wxID_EXIT in order to get the
775 // Quit menu item to be enabled, which seems a bit burdensome.
776 if ( wxApp::s_macExitMenuItemId
)
778 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
779 if ( item
!= NULL
&& !(item
->IsEnabled()) )
780 DisableMenuCommand( NULL
, kHICommandQuit
) ;
782 EnableMenuCommand( NULL
, kHICommandQuit
) ;
785 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
786 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
787 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
788 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
790 wxMenuItemList::compatibility_iterator node
;
792 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
793 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
795 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
797 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
799 item
= (wxMenuItem
*)node
->GetData();
800 subMenu
= item
->GetSubMenu() ;
803 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding() );
804 MenuItemIndex position
= CountMenuItems(mh
);
805 ::SetMenuItemHierarchicalMenu(mh
, position
, MAC_WXHMENU(subMenu
->GetHMenu()));
809 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
811 // we have found a user help menu and an item other than the about item,
812 // so we can create the mac help menu now, if we haven't created it yet
813 if ( helpMenuHandle
== NULL
)
815 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
817 helpMenuHandle
= NULL
;
823 if ( item
->IsSeparator() )
825 if ( helpMenuHandle
)
826 AppendMenuItemTextWithCFString( helpMenuHandle
,
827 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
832 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
834 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
836 // this will be taken care of below
840 if ( helpMenuHandle
)
842 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
843 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
844 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
854 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
855 && GetAutoWindowMenu() )
857 if ( MacGetWindowMenuHMenu() == NULL
)
859 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
862 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
866 // get the insertion point in the standard menu
867 MenuItemIndex winListStart
;
868 GetIndMenuItemWithCommandID(wm
,
869 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
871 // add a separator so that the standard items and the custom items
872 // aren't mixed together, but only if this is the first run
873 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
874 'WXWM', 1, NULL
, NULL
);
876 if ( err
== menuItemNotFoundErr
)
878 InsertMenuItemTextWithCFString( wm
,
879 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
882 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
886 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
887 menu
->MacBeforeDisplay(false) ;
889 ::InsertMenu(MAC_WXHMENU(GetMenu(i
)->GetHMenu()), 0);
893 // take care of the about menu item wherever it is
896 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
900 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
901 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
902 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
903 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
904 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
905 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
910 if ( GetAutoWindowMenu() )
912 if ( MacGetWindowMenuHMenu() == NULL
)
913 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
915 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
921 s_macInstalledMenuBar
= this;
924 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
926 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
928 m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
)->Enable(enable
);
933 bool wxMenuBar::IsEnabledTop(size_t pos
) const
935 wxCHECK_MSG( IsAttached(), true,
936 wxT("doesn't work with unattached menubars") );
938 wxMenuItem
* const item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
939 wxCHECK_MSG( item
, false, wxT("invalid menu index") );
941 return item
->IsEnabled();
944 bool wxMenuBar::Enable(bool enable
)
946 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
949 for (i
= 0; i
< GetMenuCount(); i
++)
950 EnableTop(i
, enable
);
955 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
957 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
959 GetMenu(pos
)->SetTitle( label
) ;
962 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
964 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
965 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
967 return GetMenu(pos
)->GetTitle();
970 // ---------------------------------------------------------------------------
971 // wxMenuBar construction
972 // ---------------------------------------------------------------------------
974 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
976 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
980 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
981 m_rootMenu
->Remove(item
);
982 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
987 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
989 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
992 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
993 menu
->SetTitle(title
);
998 wxMenu
*wxMenuBar::Remove(size_t pos
)
1000 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
1004 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
1005 m_rootMenu
->Remove(item
);
1010 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
1012 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
1013 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
1015 if ( !wxMenuBarBase::Append(menu
, title
) )
1018 m_rootMenu
->AppendSubMenu(menu
, title
);
1019 menu
->SetTitle(title
);
1024 void wxMenuBar::Detach()
1026 wxMenuBarBase::Detach() ;
1029 void wxMenuBar::Attach(wxFrame
*frame
)
1031 wxMenuBarBase::Attach( frame
) ;
1034 #endif // wxUSE_MENUS