]> git.saurik.com Git - wxWidgets.git/blame - src/osx/menu_osx.cpp
Remove unused variables in wxOSX code.
[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
524c47aa
SC
46// the (popup) menu title has this special id
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") );
114 m_peer->InsertOrAppend( pItem, pos );
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 */
231 m_peer->Remove( item );
232 // and from internal data structures
233 return wxMenuBase::DoRemove(item);
234}
235
236void wxMenu::SetTitle(const wxString& label)
237{
238 m_title = label ;
239 m_peer->SetTitle( wxStripMenuCodes( label ) );
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{
340 int id = item ? item->GetId() : 0;
341 wxUpdateUIEvent event(id);
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())
371 SetLabel(id, event.GetText());
372 if (event.GetSetChecked())
373 Check(id, event.GetChecked());
374 if (event.GetSetEnabled())
375 Enable(id, event.GetEnabled());
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
eb68a54a
SC
384 if ( id == wxApp::s_macExitMenuItemId )
385 {
386 cmd = kHICommandQuit;
387 }
388 else if (id == wxApp::s_macPreferencesMenuItemId )
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{
409 int id = item ? item->GetId() : 0;
410 bool processed = false;
411 if (item->IsCheckable())
412 item->Check( !item->IsChecked() ) ;
413
414 if ( SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) )
415 processed = true ;
416 else
417 {
418 if ( senderWindow != NULL )
419 {
420 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED , id);
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{
439 int id = item ? item->GetId() : 0;
440 wxMenuEvent wxevent(wxEVT_MENU_HIGHLIGHT, id, this);
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
500void wxMenuBar::Init()
501{
502 m_eventHandler = this;
503 m_menuBarFrame = NULL;
524c47aa 504 m_rootMenu = new wxMenu();
6a57bd93
VZ
505 m_rootMenu->Attach(this);
506
1ea5ef01
SC
507 m_appleMenu = new wxMenu();
508 m_appleMenu->SetAllowRearrange(false);
4f1b95ea
VZ
509
510 // Create standard items unless the application explicitly disabled this by
511 // setting the corresponding ids to wxID_NONE: although this is not
512 // recommended, sometimes these items really don't make sense.
513 if ( wxApp::s_macAboutMenuItemId != wxID_NONE )
514 {
c46d0503 515 wxString aboutLabel(_("About"));
c8bef6e3
VZ
516 if ( wxTheApp )
517 aboutLabel << ' ' << wxTheApp->GetAppDisplayName();
518 else
519 aboutLabel << "...";
520 m_appleMenu->Append( wxApp::s_macAboutMenuItemId, aboutLabel);
4f1b95ea
VZ
521 m_appleMenu->AppendSeparator();
522 }
523
1ea5ef01 524#if !wxOSX_USE_CARBON
4f1b95ea
VZ
525 if ( wxApp::s_macPreferencesMenuItemId != wxID_NONE )
526 {
86646f2a 527 m_appleMenu->Append( wxApp::s_macPreferencesMenuItemId,
c46d0503 528 _("Preferences...") + "\tCtrl+," );
4f1b95ea
VZ
529 m_appleMenu->AppendSeparator();
530 }
531
c46d0503
SC
532 // standard menu items, handled in wxMenu::HandleCommandProcess(), see above:
533 wxString hideLabel(_("Hide"));
534 if ( wxTheApp )
535 hideLabel << ' ' << wxTheApp->GetAppDisplayName();
536 hideLabel << "\tCtrl+H";
537 m_appleMenu->Append( wxID_OSX_HIDE, hideLabel );
538 m_appleMenu->Append( wxID_OSX_HIDEOTHERS, _("Hide Others")+"\tAlt+Ctrl+H" );
539 m_appleMenu->Append( wxID_OSX_SHOWALL, _("Show All") );
540 m_appleMenu->AppendSeparator();
541
4f1b95ea 542 // Do always add "Quit" item unconditionally however, it can't be disabled.
c46d0503
SC
543 wxString quitLabel(_("Quit"));
544 if ( wxTheApp )
545 quitLabel << ' ' << wxTheApp->GetAppDisplayName();
546 quitLabel << "\tCtrl+Q";
547 m_appleMenu->Append( wxApp::s_macExitMenuItemId, quitLabel );
4f1b95ea 548#endif // !wxOSX_USE_CARBON
524c47aa 549
1ea5ef01 550 m_rootMenu->AppendSubMenu(m_appleMenu, "\x14") ;
524c47aa
SC
551}
552
553wxMenuBar::wxMenuBar()
554{
555 Init();
556}
557
558wxMenuBar::wxMenuBar( long WXUNUSED(style) )
559{
560 Init();
561}
562
563wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
564{
565 Init();
566
524c47aa
SC
567 for ( size_t i = 0; i < count; i++ )
568 {
569 m_menus.Append(menus[i]);
524c47aa
SC
570
571 menus[i]->Attach(this);
572 Append( menus[i], titles[i] );
573 }
574}
575
576wxMenuBar::~wxMenuBar()
577{
578 if (s_macCommonMenuBar == this)
579 s_macCommonMenuBar = NULL;
580
581 if (s_macInstalledMenuBar == this)
582 {
583 s_macInstalledMenuBar = NULL;
584 }
585}
586
587void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
588{
589 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
590}
591
592void wxMenuBar::MacInstallMenuBar()
593{
594 if ( s_macInstalledMenuBar == this )
595 return ;
03647350 596
524c47aa 597 m_rootMenu->GetPeer()->MakeRoot();
cc5fe8d4
SC
598
599 // hide items in the apple menu that don't exist in the wx menubar
600
601 int id = 0;
602 wxMenuItem* appleItem = NULL;
aa3e3741 603 wxMenuItem* wxItem = NULL;
eb68a54a 604
cc5fe8d4
SC
605 id = wxApp::s_macAboutMenuItemId;
606 appleItem = m_appleMenu->FindItem(id);
aa3e3741 607 wxItem = FindItem(id);
cc5fe8d4 608 if ( appleItem != NULL )
aa3e3741
SC
609 {
610 if ( wxItem == NULL )
611 appleItem->GetPeer()->Hide();
612 else
613 appleItem->SetItemLabel(wxItem->GetItemLabel());
614 }
cc5fe8d4
SC
615
616 id = wxApp::s_macPreferencesMenuItemId;
617 appleItem = m_appleMenu->FindItem(id);
aa3e3741 618 wxItem = FindItem(id);
cc5fe8d4 619 if ( appleItem != NULL )
aa3e3741
SC
620 {
621 if ( wxItem == NULL )
622 appleItem->GetPeer()->Hide();
623 else
624 appleItem->SetItemLabel(wxItem->GetItemLabel());
625 }
cc5fe8d4
SC
626
627
524c47aa
SC
628#if 0
629
630 MenuBarHandle menubar = NULL ;
631
632 menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
633
634 ::SetMenuBar( menubar ) ;
635 DisposeMenuBar( menubar ) ;
636 MenuHandle appleMenu = NULL ;
637
638 verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
639 verify_noerr( SetMenuTitleWithCFString( appleMenu , CFSTR( "\x14" ) ) );
640
641 // Add About/Preferences separator only on OS X
642 // KH/RN: Separator is always present on 10.3 but not on 10.2
643 // However, the change from 10.2 to 10.3 suggests it is preferred
644 InsertMenuItemTextWithCFString( appleMenu,
645 CFSTR(""), 0, kMenuItemAttrSeparator, 0);
646 InsertMenuItemTextWithCFString( appleMenu,
647 CFSTR("About..."), 0, 0, 0);
648 MacInsertMenu( appleMenu , 0 ) ;
649
650 // if we have a mac help menu, clean it up before adding new items
651 MenuHandle helpMenuHandle ;
652 MenuItemIndex firstUserHelpMenuItem ;
653
654 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) == noErr )
655 {
656 for ( int i = CountMenuItems( helpMenuHandle ) ; i >= firstUserHelpMenuItem ; --i )
657 DeleteMenuItem( helpMenuHandle , i ) ;
658 }
659 else
660 {
661 helpMenuHandle = NULL ;
662 }
663
664 if ( wxApp::s_macPreferencesMenuItemId)
665 {
666 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
667 if ( item == NULL || !(item->IsEnabled()) )
668 DisableMenuCommand( NULL , kHICommandPreferences ) ;
669 else
670 EnableMenuCommand( NULL , kHICommandPreferences ) ;
671 }
672
673 // Unlike preferences which may or may not exist, the Quit item should be always
674 // enabled unless it is added by the application and then disabled, otherwise
675 // a program would be required to add an item with wxID_EXIT in order to get the
676 // Quit menu item to be enabled, which seems a bit burdensome.
677 if ( wxApp::s_macExitMenuItemId)
678 {
679 wxMenuItem *item = FindItem( wxApp::s_macExitMenuItemId , NULL ) ;
680 if ( item != NULL && !(item->IsEnabled()) )
681 DisableMenuCommand( NULL , kHICommandQuit ) ;
682 else
683 EnableMenuCommand( NULL , kHICommandQuit ) ;
684 }
685
686 wxString strippedHelpMenuTitle = wxStripMenuCodes( wxApp::s_macHelpMenuTitleName ) ;
687 wxString strippedTranslatedHelpMenuTitle = wxStripMenuCodes( wxString( _("&Help") ) ) ;
688 wxMenuList::compatibility_iterator menuIter = m_menus.GetFirst();
689 for (size_t i = 0; i < m_menus.GetCount(); i++, menuIter = menuIter->GetNext())
690 {
691 wxMenuItemList::compatibility_iterator node;
692 wxMenuItem *item;
693 wxMenu* menu = menuIter->GetData() , *subMenu = NULL ;
694 wxString strippedMenuTitle = wxStripMenuCodes(m_titles[i]);
695
696 if ( strippedMenuTitle == wxT("?") || strippedMenuTitle == strippedHelpMenuTitle || strippedMenuTitle == strippedTranslatedHelpMenuTitle )
697 {
698 for (node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext())
699 {
700 item = (wxMenuItem *)node->GetData();
701 subMenu = item->GetSubMenu() ;
702 if (subMenu)
703 {
e8fdf364
JS
704 UMAAppendMenuItem(mh, wxStripMenuCodes(item->GetText()) , wxFont::GetDefaultEncoding() );
705 MenuItemIndex position = CountMenuItems(mh);
706 ::SetMenuItemHierarchicalMenu(mh, position, MAC_WXHMENU(subMenu->GetHMenu()));
524c47aa
SC
707 }
708 else
709 {
710 if ( item->GetId() != wxApp::s_macAboutMenuItemId )
711 {
712 // we have found a user help menu and an item other than the about item,
713 // so we can create the mac help menu now, if we haven't created it yet
714 if ( helpMenuHandle == NULL )
715 {
716 if ( UMAGetHelpMenu( &helpMenuHandle , &firstUserHelpMenuItem) != noErr )
717 {
718 helpMenuHandle = NULL ;
719 break ;
720 }
721 }
722 }
723
724 if ( item->IsSeparator() )
725 {
726 if ( helpMenuHandle )
727 AppendMenuItemTextWithCFString( helpMenuHandle,
728 CFSTR(""), kMenuItemAttrSeparator, 0,NULL);
729 }
730 else
731 {
732 wxAcceleratorEntry*
733 entry = wxAcceleratorEntry::Create( item->GetItemLabel() ) ;
734
735 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
736 {
737 // this will be taken care of below
738 }
739 else
740 {
741 if ( helpMenuHandle )
742 {
743 UMAAppendMenuItem(helpMenuHandle, wxStripMenuCodes(item->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry);
744 SetMenuItemCommandID( helpMenuHandle , CountMenuItems(helpMenuHandle) , wxIdToMacCommand ( item->GetId() ) ) ;
745 SetMenuItemRefCon( helpMenuHandle , CountMenuItems(helpMenuHandle) , (URefCon) item ) ;
746 }
747 }
748
749 delete entry ;
750 }
751 }
752 }
753 }
754
755 else if ( ( m_titles[i] == wxT("Window") || m_titles[i] == wxT("&Window") )
756 && GetAutoWindowMenu() )
757 {
758 if ( MacGetWindowMenuHMenu() == NULL )
759 {
760 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
761 }
762
763 MenuRef wm = (MenuRef)MacGetWindowMenuHMenu();
764 if ( wm == NULL )
765 break;
766
767 // get the insertion point in the standard menu
768 MenuItemIndex winListStart;
769 GetIndMenuItemWithCommandID(wm,
770 kHICommandWindowListSeparator, 1, NULL, &winListStart);
771
772 // add a separator so that the standard items and the custom items
773 // aren't mixed together, but only if this is the first run
774 OSStatus err = GetIndMenuItemWithCommandID(wm,
775 'WXWM', 1, NULL, NULL);
776
777 if ( err == menuItemNotFoundErr )
778 {
779 InsertMenuItemTextWithCFString( wm,
780 CFSTR(""), winListStart-1, kMenuItemAttrSeparator, 'WXWM');
781 }
782
783 wxInsertMenuItemsInMenu(menu, wm, winListStart);
784 }
785 else
786 {
787 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], GetFont().GetEncoding() ) ;
788 menu->MacBeforeDisplay(false) ;
789
8a145966 790 ::InsertMenu(MAC_WXHMENU(GetMenu(i)->GetHMenu()), 0);
524c47aa
SC
791 }
792 }
793
794 // take care of the about menu item wherever it is
795 {
796 wxMenu* aboutMenu ;
797 wxMenuItem *aboutMenuItem = FindItem(wxApp::s_macAboutMenuItemId , &aboutMenu) ;
798 if ( aboutMenuItem )
799 {
800 wxAcceleratorEntry*
801 entry = wxAcceleratorEntry::Create( aboutMenuItem->GetItemLabel() ) ;
802 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , wxStripMenuCodes ( aboutMenuItem->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
803 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
804 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , kHICommandAbout ) ;
805 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (URefCon)aboutMenuItem ) ;
806 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
807 delete entry;
808 }
809 }
810
811 if ( GetAutoWindowMenu() )
812 {
813 if ( MacGetWindowMenuHMenu() == NULL )
814 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
815
816 InsertMenu( (MenuHandle) MacGetWindowMenuHMenu() , 0 ) ;
817 }
818
819 ::DrawMenuBar() ;
820#endif
821
822 s_macInstalledMenuBar = this;
823}
824
825void wxMenuBar::EnableTop(size_t pos, bool enable)
826{
827 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
03647350 828
524c47aa
SC
829 m_rootMenu->FindItemByPosition( pos )->Enable(enable);
830
831 Refresh();
832}
833
834bool wxMenuBar::Enable(bool enable)
835{
836 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
837
838 size_t i;
839 for (i = 0; i < GetMenuCount(); i++)
840 EnableTop(i, enable);
841
842 return true;
843}
844
845void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
846{
847 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
848
8a145966 849 GetMenu(pos)->SetTitle( label ) ;
524c47aa
SC
850}
851
852wxString wxMenuBar::GetMenuLabel(size_t pos) const
853{
854 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
855 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
856
46405e36 857 return GetMenu(pos)->GetTitle();
524c47aa
SC
858}
859
860// ---------------------------------------------------------------------------
861// wxMenuBar construction
862// ---------------------------------------------------------------------------
863
864const int firstMenuPos = 1; // to account for the 0th application menu on mac
865
866wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
867{
868 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
869 if ( !menuOld )
870 return NULL;
871
524c47aa
SC
872 wxMenuItem* item = m_rootMenu->FindItemByPosition(pos+firstMenuPos);
873 m_rootMenu->Remove(item);
874 m_rootMenu->Insert( pos+firstMenuPos, wxMenuItem::New( m_rootMenu, wxID_ANY, title, "", wxITEM_NORMAL, menu ) );
875
524c47aa
SC
876 return menuOld;
877}
878
879bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
880{
881 if ( !wxMenuBarBase::Insert(pos, menu, title) )
882 return false;
883
524c47aa
SC
884 m_rootMenu->Insert( pos+firstMenuPos, wxMenuItem::New( m_rootMenu, wxID_ANY, title, "", wxITEM_NORMAL, menu ) );
885
524c47aa
SC
886 return true;
887}
888
889wxMenu *wxMenuBar::Remove(size_t pos)
890{
891 wxMenu *menu = wxMenuBarBase::Remove(pos);
892 if ( !menu )
893 return NULL;
894
895 wxMenuItem* item = m_rootMenu->FindItemByPosition(pos+firstMenuPos);
896 m_rootMenu->Remove(item);
897
524c47aa
SC
898 return menu;
899}
900
901bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
902{
903 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
904 wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
905
906 if ( !wxMenuBarBase::Append(menu, title) )
907 return false;
908
524c47aa 909 m_rootMenu->AppendSubMenu(menu, title);
46405e36 910 menu->SetTitle(title);
524c47aa 911
524c47aa
SC
912 return true;
913}
914
524c47aa
SC
915void wxMenuBar::Detach()
916{
917 wxMenuBarBase::Detach() ;
918}
919
920void wxMenuBar::Attach(wxFrame *frame)
921{
922 wxMenuBarBase::Attach( frame ) ;
923}
924
46405e36 925#endif // wxUSE_MENUS