]> git.saurik.com Git - wxWidgets.git/blame - src/osx/menu_osx.cpp
Don't use deprecated NSTableView selectRow:byExtendingSelection: method.
[wxWidgets.git] / src / osx / menu_osx.cpp
CommitLineData
524c47aa
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/menu_osx.cpp
3// Purpose: wxMenu, wxMenuBar, wxMenuItem
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
b5b208a1 7// RCS-ID: $Id$
524c47aa
SC
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// headers & declarations
14// ============================================================================
15
16// wxWidgets headers
17// -----------------
18
19#include "wx/wxprec.h"
20
11fed901
SC
21#if wxUSE_MENUS
22
524c47aa
SC
23#include "wx/menu.h"
24
25#ifndef WX_PRECOMP
26 #include "wx/log.h"
27 #include "wx/app.h"
28 #include "wx/utils.h"
29 #include "wx/frame.h"
42a81643 30 #include "wx/dialog.h"
524c47aa
SC
31 #include "wx/menuitem.h"
32#endif
33
34#include "wx/osx/private.h"
35
36// other standard headers
37// ----------------------
38#include <string.h>
39
40IMPLEMENT_ABSTRACT_CLASS( wxMenuImpl , wxObject )
41
42wxMenuImpl::~wxMenuImpl()
43{
44}
45
46IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
47IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
48
49// the (popup) menu title has this special id
50static const int idMenuTitle = -3;
51
52// ============================================================================
53// implementation
54// ============================================================================
524c47aa
SC
55
56// Menus
57
58// Construct a menu with optional title (then use append)
59
524c47aa
SC
60void wxMenu::Init()
61{
62 m_doBreak = false;
63 m_startRadioGroup = -1;
64 m_allowRearrange = true;
65 m_noEventsMode = false;
03647350 66
524c47aa
SC
67 m_peer = wxMenuImpl::Create( this, wxStripMenuCodes(m_title) );
68
69
70 // if we have a title, insert it in the beginning of the menu
71 if ( !m_title.empty() )
72 {
73 Append(idMenuTitle, m_title) ;
74 AppendSeparator() ;
75 }
76}
77
78wxMenu::~wxMenu()
79{
80 delete m_peer;
81}
82
83WXHMENU wxMenu::GetHMenu() const
84{
85 if ( m_peer )
86 return m_peer->GetHMenu();
87 return NULL;
88}
89
90void wxMenu::Break()
91{
92 // not available on the mac platform
93}
94
95void wxMenu::Attach(wxMenuBarBase *menubar)
96{
97 wxMenuBase::Attach(menubar);
98
99 EndRadioGroup();
100}
101
102void wxMenu::SetAllowRearrange( bool allow )
103{
104 m_allowRearrange = allow;
105}
106
107void wxMenu::SetNoEventsMode( bool noEvents )
108{
109 m_noEventsMode = noEvents;
110}
111
112// function appends a new item or submenu to the menu
113// append a new item or submenu to the menu
114bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
115{
116 wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );
117 m_peer->InsertOrAppend( pItem, pos );
118
119 if ( pItem->IsSeparator() )
120 {
121 // nothing to do here
122 }
123 else
124 {
125 wxMenu *pSubMenu = pItem->GetSubMenu() ;
126 if ( pSubMenu != NULL )
127 {
128 wxASSERT_MSG( pSubMenu->GetHMenu() != NULL , wxT("invalid submenu added"));
129 pSubMenu->m_menuParent = this ;
130
131 pSubMenu->DoRearrange();
132 }
133 else
03647350 134 {
524c47aa
SC
135 if ( pItem->GetId() == idMenuTitle )
136 pItem->GetMenu()->Enable( idMenuTitle, false );
137 }
138 }
139
140 // if we're already attached to the menubar, we must update it
141 if ( IsAttached() && GetMenuBar()->IsAttached() )
142 GetMenuBar()->Refresh();
143
144 return true ;
145}
146
147void wxMenu::EndRadioGroup()
148{
149 // we're not inside a radio group any longer
150 m_startRadioGroup = -1;
151}
152
153wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
154{
9a83f860 155 wxCHECK_MSG( item, NULL, wxT("NULL item in wxMenu::DoAppend") );
524c47aa
SC
156
157 bool check = false;
158
159 if ( item->GetKind() == wxITEM_RADIO )
160 {
161 int count = GetMenuItemCount();
162
163 if ( m_startRadioGroup == -1 )
164 {
165 // start a new radio group
166 m_startRadioGroup = count;
167
168 // for now it has just one element
169 item->SetAsRadioGroupStart();
170 item->SetRadioGroupEnd(m_startRadioGroup);
171
172 // ensure that we have a checked item in the radio group
173 check = true;
174 }
175 else // extend the current radio group
176 {
177 // we need to update its end item
178 item->SetRadioGroupStart(m_startRadioGroup);
179 wxMenuItemList::compatibility_iterator node = GetMenuItems().Item(m_startRadioGroup);
180
181 if ( node )
182 {
183 node->GetData()->SetRadioGroupEnd(count);
184 }
185 else
186 {
9a83f860 187 wxFAIL_MSG( wxT("where is the radio group start item?") );
524c47aa
SC
188 }
189 }
190 }
191 else // not a radio item
192 {
193 EndRadioGroup();
194 }
195
196 if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
197 return NULL;
198
199 if ( check )
200 // check the item initially
201 item->Check(true);
202
203 return item;
204}
205
206wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
207{
208 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
209 return item;
210
211 return NULL;
212}
213
214wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
215{
216/*
217 // we need to find the items position in the child list
218 size_t pos;
219 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
220
221 for ( pos = 0; node; pos++ )
222 {
223 if ( node->GetData() == item )
224 break;
225
226 node = node->GetNext();
227 }
228
229 // DoRemove() (unlike Remove) can only be called for existing item!
230 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
231
232 wxOSXMenuRemoveItem(m_hMenu , pos );
233 */
234 m_peer->Remove( item );
235 // and from internal data structures
236 return wxMenuBase::DoRemove(item);
237}
238
239void wxMenu::SetTitle(const wxString& label)
240{
241 m_title = label ;
242 m_peer->SetTitle( wxStripMenuCodes( label ) );
243}
244
245bool wxMenu::ProcessCommand(wxCommandEvent & event)
246{
247 bool processed = false;
248
249 // Try the menu's event handler
250 if ( /* !processed && */ GetEventHandler())
251 processed = GetEventHandler()->SafelyProcessEvent(event);
252
253 // Try the window the menu was popped up from
254 // (and up through the hierarchy)
6a57bd93 255 wxWindow *win = GetWindow();
524c47aa
SC
256 if ( !processed && win )
257 processed = win->HandleWindowEvent(event);
258
259 return processed;
260}
261
262// ---------------------------------------------------------------------------
263// other
264// ---------------------------------------------------------------------------
265
524c47aa
SC
266// MacOS needs to know about submenus somewhere within this menu
267// before it can be displayed, also hide special menu items
268// like preferences that are handled by the OS
269void wxMenu::DoRearrange()
270{
271 if ( !AllowRearrange() )
272 return;
03647350 273
524c47aa
SC
274 wxMenuItem* previousItem = NULL ;
275 size_t pos ;
276 wxMenuItemList::compatibility_iterator node;
277 wxMenuItem *item;
278
279 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
280 {
281 item = (wxMenuItem *)node->GetData();
282 wxMenu* subMenu = item->GetSubMenu() ;
283 if (subMenu)
284 {
285 // already done
286 }
287 else // normal item
288 {
289 // what we do here is to hide the special items which are
290 // shown in the application menu anyhow -- it doesn't make
291 // sense to show them in their normal place as well
292 if ( item->GetId() == wxApp::s_macAboutMenuItemId ||
293 item->GetId() == wxApp::s_macPreferencesMenuItemId ||
294 item->GetId() == wxApp::s_macExitMenuItemId )
295
296 {
297 item->GetPeer()->Hide( true );
298
299 // also check for a separator which was used just to
300 // separate this item from the others, so don't leave
301 // separator at the menu start or end nor 2 consecutive
302 // separators
303 wxMenuItemList::compatibility_iterator nextNode = node->GetNext();
304 wxMenuItem *next = nextNode ? nextNode->GetData() : NULL;
305
306 wxMenuItem *sepToHide = 0;
307 if ( !previousItem && next && next->IsSeparator() )
308 {
309 // next (i.e. second as we must be first) item is
310 // the separator to hide
9a83f860 311 wxASSERT_MSG( pos == 0, wxT("should be the menu start") );
524c47aa
SC
312 sepToHide = next;
313 }
314 else if ( GetMenuItems().GetCount() == pos + 1 &&
315 previousItem != NULL &&
316 previousItem->IsSeparator() )
317 {
318 // prev item is a trailing separator we want to hide
319 sepToHide = previousItem;
320 }
321 else if ( previousItem && previousItem->IsSeparator() &&
322 next && next->IsSeparator() )
323 {
324 // two consecutive separators, this is one too many
325 sepToHide = next;
326 }
327
328 if ( sepToHide )
329 {
330 // hide the separator as well
331 sepToHide->GetPeer()->Hide( true );
332 }
333 }
334 }
335
336 previousItem = item ;
337 }
338}
339
340
341bool wxMenu::HandleCommandUpdateStatus( wxMenuItem* item, wxWindow* senderWindow )
342{
343 int id = item ? item->GetId() : 0;
344 wxUpdateUIEvent event(id);
345 event.SetEventObject( this );
346
347 bool processed = false;
348
349 // Try the menu's event handler
350 {
351 wxEvtHandler *handler = GetEventHandler();
352 if ( handler )
353 processed = handler->ProcessEvent(event);
354 }
355
356 // Try the window the menu was popped up from
357 // (and up through the hierarchy)
358 if ( !processed )
359 {
6a57bd93
VZ
360 wxWindow *win = GetWindow();
361 if ( win )
362 processed = win->HandleWindowEvent(event);
524c47aa
SC
363 }
364
365 if ( !processed && senderWindow != NULL)
366 {
367 processed = senderWindow->HandleWindowEvent(event);
368 }
369
370 if ( processed )
371 {
372 // if anything changed, update the changed attribute
373 if (event.GetSetText())
374 SetLabel(id, event.GetText());
375 if (event.GetSetChecked())
376 Check(id, event.GetChecked());
377 if (event.GetSetEnabled())
378 Enable(id, event.GetEnabled());
379 }
6a57bd93 380 else
eb68a54a
SC
381 {
382#if wxOSX_USE_CARBON
383 // these two items are also managed by the Carbon Menu Manager, therefore we must
384 // always reset them ourselves
385 UInt32 cmd = 0;
6a57bd93 386
eb68a54a
SC
387 if ( id == wxApp::s_macExitMenuItemId )
388 {
389 cmd = kHICommandQuit;
390 }
391 else if (id == wxApp::s_macPreferencesMenuItemId )
392 {
393 cmd = kHICommandPreferences;
394 }
6a57bd93 395
eb68a54a
SC
396 if ( cmd != 0 )
397 {
398 if ( !item->IsEnabled() || wxDialog::OSXHasModalDialogsOpen() )
399 DisableMenuCommand( NULL , cmd ) ;
400 else
401 EnableMenuCommand( NULL , cmd ) ;
6a57bd93 402
eb68a54a
SC
403 }
404#endif
405 }
406
524c47aa
SC
407 return processed;
408}
409
410bool wxMenu::HandleCommandProcess( wxMenuItem* item, wxWindow* senderWindow )
411{
412 int id = item ? item->GetId() : 0;
413 bool processed = false;
414 if (item->IsCheckable())
415 item->Check( !item->IsChecked() ) ;
416
417 if ( SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) )
418 processed = true ;
419 else
420 {
421 if ( senderWindow != NULL )
422 {
423 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED , id);
424 event.SetEventObject(senderWindow);
425 event.SetInt(item->IsCheckable() ? item->IsChecked() : -1);
426
427 if ( senderWindow->HandleWindowEvent(event) )
428 processed = true ;
429 }
430 }
c46d0503
SC
431
432 if(!processed && item)
433 {
434 processed = item->GetPeer()->DoDefault();
435 }
436
524c47aa
SC
437 return processed;
438}
439
440void wxMenu::HandleMenuItemHighlighted( wxMenuItem* item )
441{
442 int id = item ? item->GetId() : 0;
443 wxMenuEvent wxevent(wxEVT_MENU_HIGHLIGHT, id, this);
444 DoHandleMenuEvent( wxevent );
445}
446
447void wxMenu::HandleMenuOpened()
448{
449 wxMenuEvent wxevent(wxEVT_MENU_OPEN, 0, this);
450 DoHandleMenuEvent( wxevent );
451}
452
453void wxMenu::HandleMenuClosed()
454{
455 wxMenuEvent wxevent(wxEVT_MENU_CLOSE, 0, this);
456 DoHandleMenuEvent( wxevent );
457}
458
459bool wxMenu::DoHandleMenuEvent(wxEvent& wxevent)
460{
461 wxevent.SetEventObject(this);
462 wxEvtHandler* handler = GetEventHandler();
463 if (handler && handler->ProcessEvent(wxevent))
464 {
465 return true;
466 }
467 else
468 {
6a57bd93 469 wxWindow *win = GetWindow();
524c47aa
SC
470 if (win)
471 {
472 if ( win->HandleWindowEvent(wxevent) )
473 return true;
474 }
475 }
476 return false;
477}
478
479// Menu Bar
480
481/*
482
483Mac Implementation note :
484
485The Mac has only one global menubar, so we attempt to install the currently
486active menubar from a frame, we currently don't take into account mdi-frames
487which would ask for menu-merging
488
489Secondly there is no mac api for changing a menubar that is not the current
490menubar, so we have to wait for preparing the actual menubar until the
491wxMenubar is to be used
492
493We can in subsequent versions use MacInstallMenuBar to provide some sort of
494auto-merge for MDI in case this will be necessary
495
496*/
497
498wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
499wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
500bool wxMenuBar::s_macAutoWindowMenu = true ;
501WXHMENU wxMenuBar::s_macWindowMenuHandle = NULL ;
502
503void wxMenuBar::Init()
504{
505 m_eventHandler = this;
506 m_menuBarFrame = NULL;
524c47aa 507 m_rootMenu = new wxMenu();
6a57bd93
VZ
508 m_rootMenu->Attach(this);
509
1ea5ef01
SC
510 m_appleMenu = new wxMenu();
511 m_appleMenu->SetAllowRearrange(false);
4f1b95ea
VZ
512
513 // Create standard items unless the application explicitly disabled this by
514 // setting the corresponding ids to wxID_NONE: although this is not
515 // recommended, sometimes these items really don't make sense.
516 if ( wxApp::s_macAboutMenuItemId != wxID_NONE )
517 {
c46d0503 518 wxString aboutLabel(_("About"));
c8bef6e3
VZ
519 if ( wxTheApp )
520 aboutLabel << ' ' << wxTheApp->GetAppDisplayName();
521 else
522 aboutLabel << "...";
523 m_appleMenu->Append( wxApp::s_macAboutMenuItemId, aboutLabel);
4f1b95ea
VZ
524 m_appleMenu->AppendSeparator();
525 }
526
1ea5ef01 527#if !wxOSX_USE_CARBON
4f1b95ea
VZ
528 if ( wxApp::s_macPreferencesMenuItemId != wxID_NONE )
529 {
86646f2a 530 m_appleMenu->Append( wxApp::s_macPreferencesMenuItemId,
c46d0503 531 _("Preferences...") + "\tCtrl+," );
4f1b95ea
VZ
532 m_appleMenu->AppendSeparator();
533 }
534
c46d0503
SC
535 // standard menu items, handled in wxMenu::HandleCommandProcess(), see above:
536 wxString hideLabel(_("Hide"));
537 if ( wxTheApp )
538 hideLabel << ' ' << wxTheApp->GetAppDisplayName();
539 hideLabel << "\tCtrl+H";
540 m_appleMenu->Append( wxID_OSX_HIDE, hideLabel );
541 m_appleMenu->Append( wxID_OSX_HIDEOTHERS, _("Hide Others")+"\tAlt+Ctrl+H" );
542 m_appleMenu->Append( wxID_OSX_SHOWALL, _("Show All") );
543 m_appleMenu->AppendSeparator();
544
4f1b95ea 545 // Do always add "Quit" item unconditionally however, it can't be disabled.
c46d0503
SC
546 wxString quitLabel(_("Quit"));
547 if ( wxTheApp )
548 quitLabel << ' ' << wxTheApp->GetAppDisplayName();
549 quitLabel << "\tCtrl+Q";
550 m_appleMenu->Append( wxApp::s_macExitMenuItemId, quitLabel );
4f1b95ea 551#endif // !wxOSX_USE_CARBON
524c47aa 552
1ea5ef01 553 m_rootMenu->AppendSubMenu(m_appleMenu, "\x14") ;
524c47aa
SC
554}
555
556wxMenuBar::wxMenuBar()
557{
558 Init();
559}
560
561wxMenuBar::wxMenuBar( long WXUNUSED(style) )
562{
563 Init();
564}
565
566wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
567{
568 Init();
569
524c47aa
SC
570 for ( size_t i = 0; i < count; i++ )
571 {
572 m_menus.Append(menus[i]);
524c47aa
SC
573
574 menus[i]->Attach(this);
575 Append( menus[i], titles[i] );
576 }
577}
578
579wxMenuBar::~wxMenuBar()
580{
581 if (s_macCommonMenuBar == this)
582 s_macCommonMenuBar = NULL;
583
584 if (s_macInstalledMenuBar == this)
585 {
586 s_macInstalledMenuBar = NULL;
587 }
588}
589
590void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
591{
592 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
593}
594
595void wxMenuBar::MacInstallMenuBar()
596{
597 if ( s_macInstalledMenuBar == this )
598 return ;
03647350 599
524c47aa 600 m_rootMenu->GetPeer()->MakeRoot();
eb68a54a 601
524c47aa
SC
602#if 0
603
604 MenuBarHandle menubar = NULL ;
605
606 menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
607
608 ::SetMenuBar( menubar ) ;
609 DisposeMenuBar( menubar ) ;
610 MenuHandle appleMenu = NULL ;
611
612 verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
613 verify_noerr( SetMenuTitleWithCFString( appleMenu , CFSTR( "\x14" ) ) );
614
615 // Add About/Preferences separator only on OS X
616 // KH/RN: Separator is always present on 10.3 but not on 10.2
617 // However, the change from 10.2 to 10.3 suggests it is preferred
618 InsertMenuItemTextWithCFString( appleMenu,
619 CFSTR(""), 0, kMenuItemAttrSeparator, 0);
620 InsertMenuItemTextWithCFString( appleMenu,
621 CFSTR("About..."), 0, 0, 0);
622 MacInsertMenu( appleMenu , 0 ) ;
623
624 // if we have a mac help menu, clean it up before adding new items
625 MenuHandle helpMenuHandle ;
626 MenuItemIndex firstUserHelpMenuItem ;
627
628 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) == noErr )
629 {
630 for ( int i = CountMenuItems( helpMenuHandle ) ; i >= firstUserHelpMenuItem ; --i )
631 DeleteMenuItem( helpMenuHandle , i ) ;
632 }
633 else
634 {
635 helpMenuHandle = NULL ;
636 }
637
638 if ( wxApp::s_macPreferencesMenuItemId)
639 {
640 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
641 if ( item == NULL || !(item->IsEnabled()) )
642 DisableMenuCommand( NULL , kHICommandPreferences ) ;
643 else
644 EnableMenuCommand( NULL , kHICommandPreferences ) ;
645 }
646
647 // Unlike preferences which may or may not exist, the Quit item should be always
648 // enabled unless it is added by the application and then disabled, otherwise
649 // a program would be required to add an item with wxID_EXIT in order to get the
650 // Quit menu item to be enabled, which seems a bit burdensome.
651 if ( wxApp::s_macExitMenuItemId)
652 {
653 wxMenuItem *item = FindItem( wxApp::s_macExitMenuItemId , NULL ) ;
654 if ( item != NULL && !(item->IsEnabled()) )
655 DisableMenuCommand( NULL , kHICommandQuit ) ;
656 else
657 EnableMenuCommand( NULL , kHICommandQuit ) ;
658 }
659
660 wxString strippedHelpMenuTitle = wxStripMenuCodes( wxApp::s_macHelpMenuTitleName ) ;
661 wxString strippedTranslatedHelpMenuTitle = wxStripMenuCodes( wxString( _("&Help") ) ) ;
662 wxMenuList::compatibility_iterator menuIter = m_menus.GetFirst();
663 for (size_t i = 0; i < m_menus.GetCount(); i++, menuIter = menuIter->GetNext())
664 {
665 wxMenuItemList::compatibility_iterator node;
666 wxMenuItem *item;
667 wxMenu* menu = menuIter->GetData() , *subMenu = NULL ;
668 wxString strippedMenuTitle = wxStripMenuCodes(m_titles[i]);
669
670 if ( strippedMenuTitle == wxT("?") || strippedMenuTitle == strippedHelpMenuTitle || strippedMenuTitle == strippedTranslatedHelpMenuTitle )
671 {
672 for (node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext())
673 {
674 item = (wxMenuItem *)node->GetData();
675 subMenu = item->GetSubMenu() ;
676 if (subMenu)
677 {
e8fdf364
JS
678 UMAAppendMenuItem(mh, wxStripMenuCodes(item->GetText()) , wxFont::GetDefaultEncoding() );
679 MenuItemIndex position = CountMenuItems(mh);
680 ::SetMenuItemHierarchicalMenu(mh, position, MAC_WXHMENU(subMenu->GetHMenu()));
524c47aa
SC
681 }
682 else
683 {
684 if ( item->GetId() != wxApp::s_macAboutMenuItemId )
685 {
686 // we have found a user help menu and an item other than the about item,
687 // so we can create the mac help menu now, if we haven't created it yet
688 if ( helpMenuHandle == NULL )
689 {
690 if ( UMAGetHelpMenu( &helpMenuHandle , &firstUserHelpMenuItem) != noErr )
691 {
692 helpMenuHandle = NULL ;
693 break ;
694 }
695 }
696 }
697
698 if ( item->IsSeparator() )
699 {
700 if ( helpMenuHandle )
701 AppendMenuItemTextWithCFString( helpMenuHandle,
702 CFSTR(""), kMenuItemAttrSeparator, 0,NULL);
703 }
704 else
705 {
706 wxAcceleratorEntry*
707 entry = wxAcceleratorEntry::Create( item->GetItemLabel() ) ;
708
709 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
710 {
711 // this will be taken care of below
712 }
713 else
714 {
715 if ( helpMenuHandle )
716 {
717 UMAAppendMenuItem(helpMenuHandle, wxStripMenuCodes(item->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry);
718 SetMenuItemCommandID( helpMenuHandle , CountMenuItems(helpMenuHandle) , wxIdToMacCommand ( item->GetId() ) ) ;
719 SetMenuItemRefCon( helpMenuHandle , CountMenuItems(helpMenuHandle) , (URefCon) item ) ;
720 }
721 }
722
723 delete entry ;
724 }
725 }
726 }
727 }
728
729 else if ( ( m_titles[i] == wxT("Window") || m_titles[i] == wxT("&Window") )
730 && GetAutoWindowMenu() )
731 {
732 if ( MacGetWindowMenuHMenu() == NULL )
733 {
734 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
735 }
736
737 MenuRef wm = (MenuRef)MacGetWindowMenuHMenu();
738 if ( wm == NULL )
739 break;
740
741 // get the insertion point in the standard menu
742 MenuItemIndex winListStart;
743 GetIndMenuItemWithCommandID(wm,
744 kHICommandWindowListSeparator, 1, NULL, &winListStart);
745
746 // add a separator so that the standard items and the custom items
747 // aren't mixed together, but only if this is the first run
748 OSStatus err = GetIndMenuItemWithCommandID(wm,
749 'WXWM', 1, NULL, NULL);
750
751 if ( err == menuItemNotFoundErr )
752 {
753 InsertMenuItemTextWithCFString( wm,
754 CFSTR(""), winListStart-1, kMenuItemAttrSeparator, 'WXWM');
755 }
756
757 wxInsertMenuItemsInMenu(menu, wm, winListStart);
758 }
759 else
760 {
761 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], GetFont().GetEncoding() ) ;
762 menu->MacBeforeDisplay(false) ;
763
8a145966 764 ::InsertMenu(MAC_WXHMENU(GetMenu(i)->GetHMenu()), 0);
524c47aa
SC
765 }
766 }
767
768 // take care of the about menu item wherever it is
769 {
770 wxMenu* aboutMenu ;
771 wxMenuItem *aboutMenuItem = FindItem(wxApp::s_macAboutMenuItemId , &aboutMenu) ;
772 if ( aboutMenuItem )
773 {
774 wxAcceleratorEntry*
775 entry = wxAcceleratorEntry::Create( aboutMenuItem->GetItemLabel() ) ;
776 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , wxStripMenuCodes ( aboutMenuItem->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
777 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
778 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , kHICommandAbout ) ;
779 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (URefCon)aboutMenuItem ) ;
780 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
781 delete entry;
782 }
783 }
784
785 if ( GetAutoWindowMenu() )
786 {
787 if ( MacGetWindowMenuHMenu() == NULL )
788 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
789
790 InsertMenu( (MenuHandle) MacGetWindowMenuHMenu() , 0 ) ;
791 }
792
793 ::DrawMenuBar() ;
794#endif
795
796 s_macInstalledMenuBar = this;
797}
798
799void wxMenuBar::EnableTop(size_t pos, bool enable)
800{
801 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
03647350 802
524c47aa
SC
803 m_rootMenu->FindItemByPosition( pos )->Enable(enable);
804
805 Refresh();
806}
807
808bool wxMenuBar::Enable(bool enable)
809{
810 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
811
812 size_t i;
813 for (i = 0; i < GetMenuCount(); i++)
814 EnableTop(i, enable);
815
816 return true;
817}
818
819void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
820{
821 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
822
8a145966 823 GetMenu(pos)->SetTitle( label ) ;
524c47aa
SC
824}
825
826wxString wxMenuBar::GetMenuLabel(size_t pos) const
827{
828 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
829 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
830
46405e36 831 return GetMenu(pos)->GetTitle();
524c47aa
SC
832}
833
834// ---------------------------------------------------------------------------
835// wxMenuBar construction
836// ---------------------------------------------------------------------------
837
838const int firstMenuPos = 1; // to account for the 0th application menu on mac
839
840wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
841{
842 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
843 if ( !menuOld )
844 return NULL;
845
524c47aa
SC
846 wxMenuItem* item = m_rootMenu->FindItemByPosition(pos+firstMenuPos);
847 m_rootMenu->Remove(item);
848 m_rootMenu->Insert( pos+firstMenuPos, wxMenuItem::New( m_rootMenu, wxID_ANY, title, "", wxITEM_NORMAL, menu ) );
849
524c47aa
SC
850 return menuOld;
851}
852
853bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
854{
855 if ( !wxMenuBarBase::Insert(pos, menu, title) )
856 return false;
857
524c47aa
SC
858 m_rootMenu->Insert( pos+firstMenuPos, wxMenuItem::New( m_rootMenu, wxID_ANY, title, "", wxITEM_NORMAL, menu ) );
859
524c47aa
SC
860 return true;
861}
862
863wxMenu *wxMenuBar::Remove(size_t pos)
864{
865 wxMenu *menu = wxMenuBarBase::Remove(pos);
866 if ( !menu )
867 return NULL;
868
869 wxMenuItem* item = m_rootMenu->FindItemByPosition(pos+firstMenuPos);
870 m_rootMenu->Remove(item);
871
524c47aa
SC
872 return menu;
873}
874
875bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
876{
877 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
878 wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
879
880 if ( !wxMenuBarBase::Append(menu, title) )
881 return false;
882
524c47aa 883 m_rootMenu->AppendSubMenu(menu, title);
46405e36 884 menu->SetTitle(title);
524c47aa 885
524c47aa
SC
886 return true;
887}
888
524c47aa
SC
889void wxMenuBar::Detach()
890{
891 wxMenuBarBase::Detach() ;
892}
893
894void wxMenuBar::Attach(wxFrame *frame)
895{
896 wxMenuBarBase::Attach( frame ) ;
897}
898
46405e36 899#endif // wxUSE_MENUS