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);
625 // Create standard items unless the application explicitly disabled this by
626 // setting the corresponding ids to wxID_NONE: although this is not
627 // recommended, sometimes these items really don't make sense.
628 if ( wxApp::s_macAboutMenuItemId
!= wxID_NONE
)
630 wxString
aboutLabel(_("About"));
632 aboutLabel
<< ' ' << wxTheApp
->GetAppDisplayName();
635 m_appleMenu
->Append( wxApp::s_macAboutMenuItemId
, aboutLabel
);
636 m_appleMenu
->AppendSeparator();
639 #if !wxOSX_USE_CARBON
640 if ( wxApp::s_macPreferencesMenuItemId
!= wxID_NONE
)
642 m_appleMenu
->Append( wxApp::s_macPreferencesMenuItemId
,
643 _("Preferences...") + "\tCtrl+," );
644 m_appleMenu
->AppendSeparator();
647 // standard menu items, handled in wxMenu::HandleCommandProcess(), see above:
649 hideLabel
= wxString::Format(_("Hide %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
650 m_appleMenu
->Append( wxID_OSX_HIDE
, hideLabel
+ "\tCtrl+H" );
651 m_appleMenu
->Append( wxID_OSX_HIDEOTHERS
, _("Hide Others")+"\tAlt+Ctrl+H" );
652 m_appleMenu
->Append( wxID_OSX_SHOWALL
, _("Show All") );
653 m_appleMenu
->AppendSeparator();
655 // Do always add "Quit" item unconditionally however, it can't be disabled.
657 quitLabel
= wxString::Format(_("Quit %s"), wxTheApp
? wxTheApp
->GetAppDisplayName() : _("Application"));
658 m_appleMenu
->Append( wxApp::s_macExitMenuItemId
, quitLabel
+ "\tCtrl+Q" );
659 #endif // !wxOSX_USE_CARBON
661 m_rootMenu
->AppendSubMenu(m_appleMenu
, "\x14") ;
664 wxMenuBar::wxMenuBar()
669 wxMenuBar::wxMenuBar( long WXUNUSED(style
) )
674 wxMenuBar::wxMenuBar(size_t count
, wxMenu
*menus
[], const wxString titles
[], long WXUNUSED(style
))
678 for ( size_t i
= 0; i
< count
; i
++ )
680 m_menus
.Append(menus
[i
]);
682 menus
[i
]->Attach(this);
683 Append( menus
[i
], titles
[i
] );
687 wxMenuBar::~wxMenuBar()
689 if (s_macCommonMenuBar
== this)
690 s_macCommonMenuBar
= NULL
;
692 if (s_macInstalledMenuBar
== this)
694 emptyMenuBar
->GetPeer()->MakeRoot();
695 s_macInstalledMenuBar
= NULL
;
697 wxDELETE( m_rootMenu
);
698 // apple menu is a submenu, therefore we don't have to delete it
701 // deleting the root menu also removes all its wxMenu* submenus, therefore
702 // we must avoid double deleting them in the superclass destructor
706 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect
*WXUNUSED(rect
))
708 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
711 void wxMenuBar::MacInstallMenuBar()
713 if ( s_macInstalledMenuBar
== this )
716 m_rootMenu
->GetPeer()->MakeRoot();
718 // hide items in the apple menu that don't exist in the wx menubar
720 wxMenuItem
* appleItem
= NULL
;
721 wxMenuItem
* wxItem
= NULL
;
723 int menuid
= wxApp::s_macAboutMenuItemId
;
724 appleItem
= m_appleMenu
->FindItem(menuid
);
725 wxItem
= FindItem(menuid
);
726 if ( appleItem
!= NULL
)
728 if ( wxItem
== NULL
)
729 appleItem
->GetPeer()->Hide();
731 appleItem
->SetItemLabel(wxItem
->GetItemLabel());
734 menuid
= wxApp::s_macPreferencesMenuItemId
;
735 appleItem
= m_appleMenu
->FindItem(menuid
);
736 wxItem
= FindItem(menuid
);
737 if ( appleItem
!= NULL
)
739 if ( wxItem
== NULL
)
740 appleItem
->GetPeer()->Hide();
742 appleItem
->SetItemLabel(wxItem
->GetItemLabel());
748 // if we have a mac help menu, clean it up before adding new items
749 MenuHandle helpMenuHandle
;
750 MenuItemIndex firstUserHelpMenuItem
;
752 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) == noErr
)
754 for ( int i
= CountMenuItems( helpMenuHandle
) ; i
>= firstUserHelpMenuItem
; --i
)
755 DeleteMenuItem( helpMenuHandle
, i
) ;
759 helpMenuHandle
= NULL
;
762 if ( wxApp::s_macPreferencesMenuItemId
)
764 wxMenuItem
*item
= FindItem( wxApp::s_macPreferencesMenuItemId
, NULL
) ;
765 if ( item
== NULL
|| !(item
->IsEnabled()) )
766 DisableMenuCommand( NULL
, kHICommandPreferences
) ;
768 EnableMenuCommand( NULL
, kHICommandPreferences
) ;
771 // Unlike preferences which may or may not exist, the Quit item should be always
772 // enabled unless it is added by the application and then disabled, otherwise
773 // a program would be required to add an item with wxID_EXIT in order to get the
774 // Quit menu item to be enabled, which seems a bit burdensome.
775 if ( wxApp::s_macExitMenuItemId
)
777 wxMenuItem
*item
= FindItem( wxApp::s_macExitMenuItemId
, NULL
) ;
778 if ( item
!= NULL
&& !(item
->IsEnabled()) )
779 DisableMenuCommand( NULL
, kHICommandQuit
) ;
781 EnableMenuCommand( NULL
, kHICommandQuit
) ;
784 wxString strippedHelpMenuTitle
= wxStripMenuCodes( wxApp::s_macHelpMenuTitleName
) ;
785 wxString strippedTranslatedHelpMenuTitle
= wxStripMenuCodes( wxString( _("&Help") ) ) ;
786 wxMenuList::compatibility_iterator menuIter
= m_menus
.GetFirst();
787 for (size_t i
= 0; i
< m_menus
.GetCount(); i
++, menuIter
= menuIter
->GetNext())
789 wxMenuItemList::compatibility_iterator node
;
791 wxMenu
* menu
= menuIter
->GetData() , *subMenu
= NULL
;
792 wxString strippedMenuTitle
= wxStripMenuCodes(m_titles
[i
]);
794 if ( strippedMenuTitle
== wxT("?") || strippedMenuTitle
== strippedHelpMenuTitle
|| strippedMenuTitle
== strippedTranslatedHelpMenuTitle
)
796 for (node
= menu
->GetMenuItems().GetFirst(); node
; node
= node
->GetNext())
798 item
= (wxMenuItem
*)node
->GetData();
799 subMenu
= item
->GetSubMenu() ;
802 UMAAppendMenuItem(mh
, wxStripMenuCodes(item
->GetText()) , wxFont::GetDefaultEncoding() );
803 MenuItemIndex position
= CountMenuItems(mh
);
804 ::SetMenuItemHierarchicalMenu(mh
, position
, MAC_WXHMENU(subMenu
->GetHMenu()));
808 if ( item
->GetId() != wxApp::s_macAboutMenuItemId
)
810 // we have found a user help menu and an item other than the about item,
811 // so we can create the mac help menu now, if we haven't created it yet
812 if ( helpMenuHandle
== NULL
)
814 if ( UMAGetHelpMenu( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
816 helpMenuHandle
= NULL
;
822 if ( item
->IsSeparator() )
824 if ( helpMenuHandle
)
825 AppendMenuItemTextWithCFString( helpMenuHandle
,
826 CFSTR(""), kMenuItemAttrSeparator
, 0,NULL
);
831 entry
= wxAcceleratorEntry::Create( item
->GetItemLabel() ) ;
833 if ( item
->GetId() == wxApp::s_macAboutMenuItemId
)
835 // this will be taken care of below
839 if ( helpMenuHandle
)
841 UMAAppendMenuItem(helpMenuHandle
, wxStripMenuCodes(item
->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry
);
842 SetMenuItemCommandID( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , wxIdToMacCommand ( item
->GetId() ) ) ;
843 SetMenuItemRefCon( helpMenuHandle
, CountMenuItems(helpMenuHandle
) , (URefCon
) item
) ;
853 else if ( ( m_titles
[i
] == wxT("Window") || m_titles
[i
] == wxT("&Window") )
854 && GetAutoWindowMenu() )
856 if ( MacGetWindowMenuHMenu() == NULL
)
858 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
861 MenuRef wm
= (MenuRef
)MacGetWindowMenuHMenu();
865 // get the insertion point in the standard menu
866 MenuItemIndex winListStart
;
867 GetIndMenuItemWithCommandID(wm
,
868 kHICommandWindowListSeparator
, 1, NULL
, &winListStart
);
870 // add a separator so that the standard items and the custom items
871 // aren't mixed together, but only if this is the first run
872 OSStatus err
= GetIndMenuItemWithCommandID(wm
,
873 'WXWM', 1, NULL
, NULL
);
875 if ( err
== menuItemNotFoundErr
)
877 InsertMenuItemTextWithCFString( wm
,
878 CFSTR(""), winListStart
-1, kMenuItemAttrSeparator
, 'WXWM');
881 wxInsertMenuItemsInMenu(menu
, wm
, winListStart
);
885 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], GetFont().GetEncoding() ) ;
886 menu
->MacBeforeDisplay(false) ;
888 ::InsertMenu(MAC_WXHMENU(GetMenu(i
)->GetHMenu()), 0);
892 // take care of the about menu item wherever it is
895 wxMenuItem
*aboutMenuItem
= FindItem(wxApp::s_macAboutMenuItemId
, &aboutMenu
) ;
899 entry
= wxAcceleratorEntry::Create( aboutMenuItem
->GetItemLabel() ) ;
900 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId
) , 1 , wxStripMenuCodes ( aboutMenuItem
->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
901 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId
) , 1 , true );
902 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId
) , 1 , kHICommandAbout
) ;
903 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId
) , 1 , (URefCon
)aboutMenuItem
) ;
904 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId
) , 1 , entry
) ;
909 if ( GetAutoWindowMenu() )
911 if ( MacGetWindowMenuHMenu() == NULL
)
912 CreateStandardWindowMenu( 0 , (MenuHandle
*) &s_macWindowMenuHandle
) ;
914 InsertMenu( (MenuHandle
) MacGetWindowMenuHMenu() , 0 ) ;
920 s_macInstalledMenuBar
= this;
923 void wxMenuBar::EnableTop(size_t pos
, bool enable
)
925 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
927 m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
)->Enable(enable
);
932 bool wxMenuBar::IsEnabledTop(size_t pos
) const
934 wxCHECK_MSG( IsAttached(), true,
935 wxT("doesn't work with unattached menubars") );
937 wxMenuItem
* const item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
938 wxCHECK_MSG( item
, false, wxT("invalid menu index") );
940 return item
->IsEnabled();
943 bool wxMenuBar::Enable(bool enable
)
945 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
948 for (i
= 0; i
< GetMenuCount(); i
++)
949 EnableTop(i
, enable
);
954 void wxMenuBar::SetMenuLabel(size_t pos
, const wxString
& label
)
956 wxCHECK_RET( pos
< GetMenuCount(), wxT("invalid menu index") );
958 GetMenu(pos
)->SetTitle( label
) ;
961 wxString
wxMenuBar::GetMenuLabel(size_t pos
) const
963 wxCHECK_MSG( pos
< GetMenuCount(), wxEmptyString
,
964 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
966 return GetMenu(pos
)->GetTitle();
969 // ---------------------------------------------------------------------------
970 // wxMenuBar construction
971 // ---------------------------------------------------------------------------
973 wxMenu
*wxMenuBar::Replace(size_t pos
, wxMenu
*menu
, const wxString
& title
)
975 wxMenu
*menuOld
= wxMenuBarBase::Replace(pos
, menu
, title
);
979 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
980 m_rootMenu
->Remove(item
);
981 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
986 bool wxMenuBar::Insert(size_t pos
, wxMenu
*menu
, const wxString
& title
)
988 if ( !wxMenuBarBase::Insert(pos
, menu
, title
) )
991 m_rootMenu
->Insert( pos
+firstMenuPos
, wxMenuItem::New( m_rootMenu
, wxID_ANY
, title
, "", wxITEM_NORMAL
, menu
) );
992 menu
->SetTitle(title
);
997 wxMenu
*wxMenuBar::Remove(size_t pos
)
999 wxMenu
*menu
= wxMenuBarBase::Remove(pos
);
1003 wxMenuItem
* item
= m_rootMenu
->FindItemByPosition(pos
+firstMenuPos
);
1004 m_rootMenu
->Remove(item
);
1009 bool wxMenuBar::Append(wxMenu
*menu
, const wxString
& title
)
1011 WXHMENU submenu
= menu
? menu
->GetHMenu() : 0;
1012 wxCHECK_MSG( submenu
, false, wxT("can't append invalid menu to menubar") );
1014 if ( !wxMenuBarBase::Append(menu
, title
) )
1017 m_rootMenu
->AppendSubMenu(menu
, title
);
1018 menu
->SetTitle(title
);
1023 void wxMenuBar::Detach()
1025 wxMenuBarBase::Detach() ;
1028 void wxMenuBar::Attach(wxFrame
*frame
)
1030 wxMenuBarBase::Attach( frame
) ;
1033 #endif // wxUSE_MENUS