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