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