1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/menu_osx.cpp
3 // Purpose: wxMenu, wxMenuBar, wxMenuItem
4 // Author: Stefan Csomor
7 // Copyright: (c) Stefan Csomor
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
12 // headers & declarations
13 // ============================================================================
18 #include "wx/wxprec.h"
29 #include "wx/dialog.h"
30 #include "wx/menuitem.h"
33 #include "wx/osx/private.h"
35 // other standard headers
36 // ----------------------
39 IMPLEMENT_ABSTRACT_CLASS( wxMenuImpl
, wxObject
)
41 wxMenuImpl::~wxMenuImpl()
45 // the (popup) menu title has this special menuid
46 static const int idMenuTitle
= -3;
48 // ============================================================================
50 // ============================================================================
54 // Construct a menu with optional title (then use append)
59 m_allowRearrange
= true;
60 m_noEventsMode
= false;
62 m_peer
= wxMenuImpl::Create( this, wxStripMenuCodes(m_title
) );
65 // if we have a title, insert it in the beginning of the menu
66 if ( !m_title
.empty() )
68 Append(idMenuTitle
, m_title
) ;
78 WXHMENU
wxMenu::GetHMenu() const
81 return m_peer
->GetHMenu();
87 // not available on the mac platform
90 void wxMenu::SetAllowRearrange( bool allow
)
92 m_allowRearrange
= allow
;
95 void wxMenu::SetNoEventsMode( bool noEvents
)
97 m_noEventsMode
= noEvents
;
100 // function appends a new item or submenu to the menu
101 // append a new item or submenu to the menu
102 bool wxMenu::DoInsertOrAppend(wxMenuItem
*item
, size_t pos
)
104 wxASSERT_MSG( item
!= NULL
, wxT("can't append NULL item to the menu") );
105 GetPeer()->InsertOrAppend( item
, pos
);
109 if ( item
->IsSeparator() )
111 // nothing to do here
115 wxMenu
*pSubMenu
= item
->GetSubMenu() ;
116 if ( pSubMenu
!= NULL
)
118 wxASSERT_MSG( pSubMenu
->GetHMenu() != NULL
, wxT("invalid submenu added"));
119 pSubMenu
->m_menuParent
= this ;
121 pSubMenu
->DoRearrange();
123 else if ( item
->IsRadio() )
125 // If a previous or next item is a radio button, add this radio
126 // button to the existing radio group. Otherwise start a new one
128 wxMenuItemList
& items
= GetMenuItems();
131 posItem
= pos
== (size_t)-1 ? items
.GetCount() - 1 : pos
;
133 wxMenuItemList::compatibility_iterator node
= items
.Item(posItem
);
134 wxCHECK_MSG( node
, false, wxS("New item must have been inserted") );
136 bool foundGroup
= false;
137 if ( node
->GetPrevious() )
139 wxMenuItem
* const prev
= node
->GetPrevious()->GetData();
141 if ( prev
->IsRadio() )
143 // This item is in the same group as the preceding one so
144 // we should use the same starting item, but getting it is
145 // a bit difficult as we can't query the start radio group
147 const int groupStart
= prev
->IsRadioGroupStart()
149 : prev
->GetRadioGroupStart();
150 item
->SetRadioGroupStart(groupStart
);
152 // We must also account for the new item by incrementing
153 // the index of the last item in this group.
154 wxMenuItem
* const first
= items
.Item(groupStart
)->GetData();
155 first
->SetRadioGroupEnd(first
->GetRadioGroupEnd() + 1);
161 if ( !foundGroup
&& node
->GetNext() )
163 wxMenuItem
* const next
= node
->GetNext()->GetData();
165 if ( next
->IsRadio() )
167 // This item is the new starting item of this group as the
168 // previous item is not a radio item.
169 wxASSERT_MSG( next
->IsRadioGroupStart(),
170 wxS("Where is the start of this group?") );
172 // The index of the last item of the radio group must be
173 // incremented to account for the new item.
174 item
->SetAsRadioGroupStart();
175 item
->SetRadioGroupEnd(next
->GetRadioGroupEnd() + 1);
177 // And the previous start item is not one any longer.
178 next
->SetAsRadioGroupStart(false);
186 // start a new radio group
187 item
->SetAsRadioGroupStart();
188 item
->SetRadioGroupEnd(posItem
);
190 // ensure that we have a checked item in the radio group
196 if ( item
->GetId() == idMenuTitle
)
197 item
->GetMenu()->Enable( idMenuTitle
, false );
201 // We also need to update the indices of radio group start and end we store
202 // in any existing radio items after this item.
203 if ( pos
< GetMenuItemCount() - 1 ) // takes into account pos == -1 case
205 for ( wxMenuItemList::compatibility_iterator
206 node
= GetMenuItems().Item(pos
+ 1);
208 node
= node
->GetNext() )
210 wxMenuItem
* const item
= node
->GetData();
211 if ( item
->IsRadio() )
213 if ( item
->IsRadioGroupStart() )
215 // If the starting item is after the just inserted one,
216 // then the end one must be after it too and needs to be
218 item
->SetRadioGroupEnd(item
->GetRadioGroupEnd() + 1);
220 else // Not the first radio group item.
222 // We need to update the start item index only if it is
223 // after the just inserted item.
224 const int groupStart
= item
->GetRadioGroupStart();
225 if ( (size_t)groupStart
> pos
)
226 item
->SetRadioGroupStart(groupStart
+ 1);
232 // if we're already attached to the menubar, we must update it
233 if ( IsAttached() && GetMenuBar()->IsAttached() )
234 GetMenuBar()->Refresh();
242 wxMenuItem
* wxMenu::DoAppend(wxMenuItem
*item
)
244 if (wxMenuBase::DoAppend(item
) && DoInsertOrAppend(item
) )
250 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem
*item
)
252 if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
))
258 wxMenuItem
*wxMenu::DoRemove(wxMenuItem
*item
)
260 if ( item
->IsRadio() )
262 // Check if we're removing the item starting the radio group
263 if ( item
->IsRadioGroupStart() )
265 // Yes, we do, update the next radio group item, if any, to be the
267 const int endGroup
= item
->GetRadioGroupEnd();
269 wxMenuItemList::compatibility_iterator
270 node
= GetMenuItems().Item(endGroup
);
271 wxASSERT_MSG( node
, wxS("Should have valid radio group end") );
273 while ( node
->GetData() != item
)
275 const wxMenuItemList::compatibility_iterator
276 prevNode
= node
->GetPrevious();
277 wxMenuItem
* const prevItem
= prevNode
->GetData();
278 if ( prevItem
== item
)
280 prevItem
->SetAsRadioGroupStart();
281 prevItem
->SetRadioGroupEnd(endGroup
);
291 // we need to find the items position in the child list
293 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
295 for ( pos = 0; node; pos++ )
297 if ( node->GetData() == item )
300 node = node->GetNext();
303 // DoRemove() (unlike Remove) can only be called for existing item!
304 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
306 wxOSXMenuRemoveItem(m_hMenu , pos );
308 GetPeer()->Remove( item
);
309 // and from internal data structures
310 return wxMenuBase::DoRemove(item
);
313 void wxMenu::SetTitle(const wxString
& label
)
316 GetPeer()->SetTitle( wxStripMenuCodes( label
) );
319 bool wxMenu::ProcessCommand(wxCommandEvent
& event
)
321 bool processed
= false;
323 // Try the menu's event handler
324 if ( /* !processed && */ GetEventHandler())
325 processed
= GetEventHandler()->SafelyProcessEvent(event
);
327 // Try the window the menu was popped up from
328 // (and up through the hierarchy)
329 wxWindow
*win
= GetWindow();
330 if ( !processed
&& win
)
331 processed
= win
->HandleWindowEvent(event
);
336 // ---------------------------------------------------------------------------
338 // ---------------------------------------------------------------------------
340 // MacOS needs to know about submenus somewhere within this menu
341 // before it can be displayed, also hide special menu items
342 // like preferences that are handled by the OS
343 void wxMenu::DoRearrange()
345 if ( !AllowRearrange() )
348 wxMenuItem
* previousItem
= NULL
;
350 wxMenuItemList::compatibility_iterator node
;
353 for (pos
= 0, node
= GetMenuItems().GetFirst(); node
; node
= node
->GetNext(), pos
++)
355 item
= (wxMenuItem
*)node
->GetData();
356 wxMenu
* subMenu
= item
->GetSubMenu() ;
363 // what we do here is to hide the special items which are
364 // shown in the application menu anyhow -- it doesn't make
365 // sense to show them in their normal place as well
366 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
||
367 item
->GetId() == wxApp::s_macPreferencesMenuItemId
||
368 item
->GetId() == wxApp::s_macExitMenuItemId
)
371 item
->GetPeer()->Hide( true );
373 // also check for a separator which was used just to
374 // separate this item from the others, so don't leave
375 // separator at the menu start or end nor 2 consecutive
377 wxMenuItemList::compatibility_iterator nextNode
= node
->GetNext();
378 wxMenuItem
*next
= nextNode
? nextNode
->GetData() : NULL
;
380 wxMenuItem
*sepToHide
= 0;
381 if ( !previousItem
&& next
&& next
->IsSeparator() )
383 // next (i.e. second as we must be first) item is
384 // the separator to hide
385 wxASSERT_MSG( pos
== 0, wxT("should be the menu start") );
388 else if ( GetMenuItems().GetCount() == pos
+ 1 &&
389 previousItem
!= NULL
&&
390 previousItem
->IsSeparator() )
392 // prev item is a trailing separator we want to hide
393 sepToHide
= previousItem
;
395 else if ( previousItem
&& previousItem
->IsSeparator() &&
396 next
&& next
->IsSeparator() )
398 // two consecutive separators, this is one too many
404 // hide the separator as well
405 sepToHide
->GetPeer()->Hide( true );
410 previousItem
= item
;
415 bool wxMenu::HandleCommandUpdateStatus( wxMenuItem
* item
, wxWindow
* senderWindow
)
417 int menuid
= item
? item
->GetId() : 0;
418 wxUpdateUIEvent
event(menuid
);
419 event
.SetEventObject( this );
421 bool processed
= false;
423 // Try the menu's event handler
425 wxEvtHandler
*handler
= GetEventHandler();
427 processed
= handler
->ProcessEvent(event
);
430 // Try the window the menu was popped up from
431 // (and up through the hierarchy)
434 wxWindow
*win
= GetWindow();
436 processed
= win
->HandleWindowEvent(event
);
439 if ( !processed
&& senderWindow
!= NULL
)
441 processed
= senderWindow
->HandleWindowEvent(event
);
446 // if anything changed, update the changed attribute
447 if (event
.GetSetText())
448 SetLabel(menuid
, event
.GetText());
449 if (event
.GetSetChecked())
450 Check(menuid
, event
.GetChecked());
451 if (event
.GetSetEnabled())
452 Enable(menuid
, event
.GetEnabled());
457 // these two items are also managed by the Carbon Menu Manager, therefore we must
458 // always reset them ourselves
461 if ( menuid
== wxApp::s_macExitMenuItemId
)
463 cmd
= kHICommandQuit
;
465 else if (menuid
== wxApp::s_macPreferencesMenuItemId
)
467 cmd
= kHICommandPreferences
;
472 if ( !item
->IsEnabled() || wxDialog::OSXHasModalDialogsOpen() )
473 DisableMenuCommand( NULL
, cmd
) ;
475 EnableMenuCommand( NULL
, cmd
) ;
484 bool wxMenu::HandleCommandProcess( wxMenuItem
* item
, wxWindow
* senderWindow
)
486 int menuid
= item
? item
->GetId() : 0;
487 bool processed
= false;
488 if (item
->IsCheckable())
489 item
->Check( !item
->IsChecked() ) ;
491 if ( SendEvent( menuid
, item
->IsCheckable() ? item
->IsChecked() : -1 ) )
495 if ( senderWindow
!= NULL
)
497 wxCommandEvent
event(wxEVT_MENU
, menuid
);
498 event
.SetEventObject(this);
499 event
.SetInt(item
->IsCheckable() ? item
->IsChecked() : -1);
501 if ( senderWindow
->HandleWindowEvent(event
) )
506 if(!processed
&& item
)
508 processed
= item
->GetPeer()->DoDefault();
514 void wxMenu::HandleMenuItemHighlighted( wxMenuItem
* item
)
516 int menuid
= item
? item
->GetId() : 0;
517 wxMenuEvent
wxevent(wxEVT_MENU_HIGHLIGHT
, menuid
, this);
518 DoHandleMenuEvent( wxevent
);
521 void wxMenu::DoHandleMenuOpenedOrClosed(wxEventType evtType
)
523 // Popup menu being currently shown or NULL, defined in wincmn.cpp.
524 extern wxMenu
*wxCurrentPopupMenu
;
526 // Set the id to allow wxMenuEvent::IsPopup() to work correctly.
527 int menuid
= this == wxCurrentPopupMenu
? wxID_ANY
: 0;
528 wxMenuEvent
wxevent(evtType
, menuid
, this);
529 DoHandleMenuEvent( wxevent
);
532 void wxMenu::HandleMenuOpened()
534 DoHandleMenuOpenedOrClosed(wxEVT_MENU_OPEN
);
537 void wxMenu::HandleMenuClosed()
539 DoHandleMenuOpenedOrClosed(wxEVT_MENU_CLOSE
);
542 bool wxMenu::DoHandleMenuEvent(wxEvent
& wxevent
)
544 wxevent
.SetEventObject(this);
545 wxEvtHandler
* handler
= GetEventHandler();
546 if (handler
&& handler
->ProcessEvent(wxevent
))
552 wxWindow
*win
= GetWindow();
555 if ( win
->HandleWindowEvent(wxevent
) )
566 Mac Implementation note :
568 The Mac has only one global menubar, so we attempt to install the currently
569 active menubar from a frame, we currently don't take into account mdi-frames
570 which would ask for menu-merging
572 Secondly there is no mac api for changing a menubar that is not the current
573 menubar, so we have to wait for preparing the actual menubar until the
574 wxMenubar is to be used
576 We can in subsequent versions use MacInstallMenuBar to provide some sort of
577 auto-merge for MDI in case this will be necessary
581 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar
= NULL
;
582 wxMenuBar
* wxMenuBar::s_macCommonMenuBar
= NULL
;
583 bool wxMenuBar::s_macAutoWindowMenu
= true ;
584 WXHMENU
wxMenuBar::s_macWindowMenuHandle
= NULL
;
587 wxMenu
* emptyMenuBar
= NULL
;
589 const int firstMenuPos
= 1; // to account for the 0th application menu on mac
591 void wxMenuBar::Init()
593 if ( emptyMenuBar
== NULL
)
595 emptyMenuBar
= new wxMenu();
597 wxMenu
* appleMenu
= new wxMenu();
598 appleMenu
->SetAllowRearrange(false);
599 #if !wxOSX_USE_CARBON
600 // standard menu items, handled in wxMenu::HandleCommandProcess(), see above:
602 hideLabel
= wxString::Format(_("Hide %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
603 appleMenu
->Append( wxID_OSX_HIDE
, hideLabel
+ "\tCtrl+H" );
604 appleMenu
->Append( wxID_OSX_HIDEOTHERS
, _("Hide Others")+"\tAlt+Ctrl+H" );
605 appleMenu
->Append( wxID_OSX_SHOWALL
, _("Show All") );
606 appleMenu
->AppendSeparator();
608 // Do always add "Quit" item unconditionally however, it can't be disabled.
610 quitLabel
= wxString::Format(_("Quit %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
611 appleMenu
->Append( wxApp::s_macExitMenuItemId
, quitLabel
+ "\tCtrl+Q" );
612 #endif // !wxOSX_USE_CARBON
614 emptyMenuBar
->AppendSubMenu(appleMenu
, "\x14") ;
617 m_eventHandler
= this;
618 m_menuBarFrame
= NULL
;
619 m_rootMenu
= new wxMenu();
620 m_rootMenu
->Attach(this);
622 m_appleMenu
= new wxMenu();
623 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
663 m_rootMenu
->AppendSubMenu(m_appleMenu
, "\x14") ;
666 wxMenuBar::wxMenuBar()
671 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
676 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
680 for ( size_t i
= 0; i
< count
; i
++ )
682 m_menus
.Append(menus
[i
]);
684 menus
[i
]->Attach(this);
685 Append( menus
[i
], titles
[i
] );
689 wxMenuBar::~wxMenuBar()
691 if (s_macCommonMenuBar
== this)
692 s_macCommonMenuBar
= NULL
;
694 if (s_macInstalledMenuBar
== this)
696 emptyMenuBar
->GetPeer()->MakeRoot();
697 s_macInstalledMenuBar
= NULL
;
699 wxDELETE( m_rootMenu
);
700 // apple menu is a submenu, therefore we don't have to delete it
703 // deleting the root menu also removes all its wxMenu* submenus, therefore
704 // we must avoid double deleting them in the superclass destructor
708 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
710 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
713 void wxMenuBar::MacInstallMenuBar()
715 if ( s_macInstalledMenuBar
== this )
718 m_rootMenu
->GetPeer()->MakeRoot();
721 // hide items in the apple menu that don't exist in the wx menubar
723 wxMenuItem
* appleItem
= NULL
;
724 wxMenuItem
* wxItem
= NULL
;
726 int menuid
= wxApp::s_macAboutMenuItemId
;
727 appleItem
= m_appleMenu
->FindItem(menuid
);
728 wxItem
= FindItem(menuid
);
729 if ( appleItem
!= NULL
)
731 if ( wxItem
== NULL
)
732 appleItem
->GetPeer()->Hide();
734 appleItem
->SetItemLabel(wxItem
->GetItemLabel());
737 menuid
= wxApp::s_macPreferencesMenuItemId
;
738 appleItem
= m_appleMenu
->FindItem(menuid
);
739 wxItem
= FindItem(menuid
);
740 if ( appleItem
!= NULL
)
742 if ( wxItem
== NULL
)
743 appleItem
->GetPeer()->Hide();
745 appleItem
->SetItemLabel(wxItem
->GetItemLabel());
752 // if we have a mac help menu, clean it up before adding new items
753 MenuHandle helpMenuHandle
;
754 MenuItemIndex firstUserHelpMenuItem
;
756 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
758 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
759 DeleteMenuItem( helpMenuHandle
, i
) ;
763 helpMenuHandle
= NULL
;
766 if ( wxApp::s_macPreferencesMenuItemId
)
768 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
769 if ( item
== NULL
|| !(item
->IsEnabled()) )
770 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
772 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
775 // Unlike preferences which may or may not exist, the Quit item should be always
776 // enabled unless it is added by the application and then disabled, otherwise
777 // a program would be required to add an item with wxID_EXIT in order to get the
778 // Quit menu item to be enabled, which seems a bit burdensome.
779 if ( wxApp::s_macExitMenuItemId
)
781 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
782 if ( item
!= NULL
&& !(item
->IsEnabled()) )
783 DisableMenuCommand( NULL
, kHICommandQuit
) ;
785 EnableMenuCommand( NULL
, kHICommandQuit
) ;
788 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
789 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
790 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
791 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
793 wxMenuItemList::compatibility_iterator node
;
795 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
796 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
798 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
800 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
802 item
= (wxMenuItem
*)node
->GetData();
803 subMenu
= item
->GetSubMenu() ;
806 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding() );
807 MenuItemIndex position
= CountMenuItems(mh
);
808 ::SetMenuItemHierarchicalMenu(mh
, position
, MAC_WXHMENU(subMenu
->GetHMenu()));
812 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
814 // we have found a user help menu and an item other than the about item,
815 // so we can create the mac help menu now, if we haven't created it yet
816 if ( helpMenuHandle
== NULL
)
818 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
820 helpMenuHandle
= NULL
;
826 if ( item
->IsSeparator() )
828 if ( helpMenuHandle
)
829 AppendMenuItemTextWithCFString( helpMenuHandle
,
830 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
835 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
837 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
839 // this will be taken care of below
843 if ( helpMenuHandle
)
845 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
846 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
847 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
857 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
858 && GetAutoWindowMenu() )
860 if ( MacGetWindowMenuHMenu() == NULL
)
862 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
865 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
869 // get the insertion point in the standard menu
870 MenuItemIndex winListStart
;
871 GetIndMenuItemWithCommandID(wm
,
872 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
874 // add a separator so that the standard items and the custom items
875 // aren't mixed together, but only if this is the first run
876 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
877 'WXWM', 1, NULL
, NULL
);
879 if ( err
== menuItemNotFoundErr
)
881 InsertMenuItemTextWithCFString( wm
,
882 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
885 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
889 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
890 menu
->MacBeforeDisplay(false) ;
892 ::InsertMenu(MAC_WXHMENU(GetMenu(i
)->GetHMenu()), 0);
896 // take care of the about menu item wherever it is
899 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
903 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
904 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
905 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
906 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
907 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
908 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
913 if ( GetAutoWindowMenu() )
915 if ( MacGetWindowMenuHMenu() == NULL
)
916 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
918 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
924 s_macInstalledMenuBar
= this;
927 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
929 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
931 m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
)->Enable(enable
);
936 bool wxMenuBar::IsEnabledTop(size_t pos
) const
938 wxCHECK_MSG( IsAttached(), true,
939 wxT("doesn't work with unattached menubars") );
941 wxMenuItem
* const item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
942 wxCHECK_MSG( item
, false, wxT("invalid menu index") );
944 return item
->IsEnabled();
947 bool wxMenuBar::Enable(bool enable
)
949 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
952 for (i
= 0; i
< GetMenuCount(); i
++)
953 EnableTop(i
, enable
);
958 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
960 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
962 GetMenu(pos
)->SetTitle( label
) ;
965 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
967 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
968 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
970 return GetMenu(pos
)->GetTitle();
973 // ---------------------------------------------------------------------------
974 // wxMenuBar construction
975 // ---------------------------------------------------------------------------
977 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
979 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
983 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
984 m_rootMenu
->Remove(item
);
985 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
990 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
992 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
995 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
996 menu
->SetTitle(title
);
1001 wxMenu
*wxMenuBar::Remove(size_t pos
)
1003 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
1007 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
1008 m_rootMenu
->Remove(item
);
1013 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
1015 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
1016 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
1018 if ( !wxMenuBarBase::Append(menu
, title
) )
1021 m_rootMenu
->AppendSubMenu(menu
, title
);
1022 menu
->SetTitle(title
);
1027 void wxMenuBar::Detach()
1029 wxMenuBarBase::Detach() ;
1032 void wxMenuBar::Attach(wxFrame
*frame
)
1034 wxMenuBarBase::Attach( frame
) ;
1037 #endif // wxUSE_MENUS