]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/menu.cpp
no changes
[wxWidgets.git] / src / mac / carbon / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: menu.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 #ifdef __GNUG__
13 #pragma implementation "menu.h"
14 #pragma implementation "menuitem.h"
15 #endif
16
17 // ============================================================================
18 // headers & declarations
19 // ============================================================================
20
21 // wxWindows headers
22 // -----------------
23
24 #include "wx/app.h"
25 #include "wx/menu.h"
26 #include "wx/menuitem.h"
27 #include "wx/window.h"
28 #include "wx/log.h"
29 #include "wx/utils.h"
30 #include "wx/frame.h"
31
32 #include "wx/mac/uma.h"
33
34 // other standard headers
35 // ----------------------
36 #include <string.h>
37
38 #if !USE_SHARED_LIBRARY
39 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
40 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
41 #endif
42
43 // the (popup) menu title has this special id
44 static const int idMenuTitle = -2;
45 static MenuItemIndex firstUserHelpMenuItem = 0 ;
46
47 const short kwxMacMenuBarResource = 1 ;
48 const short kwxMacAppleMenuId = 1 ;
49
50 // ============================================================================
51 // implementation
52 // ============================================================================
53 static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;
54 static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );
55
56 // Menus
57
58 // Construct a menu with optional title (then use append)
59
60 #ifdef __DARWIN__
61 short wxMenu::s_macNextMenuId = 3 ;
62 #else
63 short wxMenu::s_macNextMenuId = 2 ;
64 #endif
65
66 void wxMenu::Init()
67 {
68 m_doBreak = FALSE;
69 m_startRadioGroup = -1;
70
71 // create the menu
72 m_macMenuId = s_macNextMenuId++;
73 m_hMenu = UMANewMenu(m_macMenuId, m_title);
74
75 if ( !m_hMenu )
76 {
77 wxLogLastError("UMANewMenu failed");
78 }
79
80 // if we have a title, insert it in the beginning of the menu
81 if ( !!m_title )
82 {
83 Append(idMenuTitle, m_title) ;
84 AppendSeparator() ;
85 }
86 }
87
88 wxMenu::~wxMenu()
89 {
90 if (MAC_WXHMENU(m_hMenu))
91 ::DisposeMenu(MAC_WXHMENU(m_hMenu));
92 }
93
94 void wxMenu::Break()
95 {
96 // not available on the mac platform
97 }
98
99 void wxMenu::Attach(wxMenuBarBase *menubar)
100 {
101 wxMenuBase::Attach(menubar);
102
103 EndRadioGroup();
104 }
105
106 // function appends a new item or submenu to the menu
107 // append a new item or submenu to the menu
108 bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
109 {
110 wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );
111
112 if ( pItem->IsSeparator() )
113 {
114 if ( pos == (size_t)-1 )
115 MacAppendMenu(MAC_WXHMENU(m_hMenu), "\p-");
116 else
117 MacInsertMenuItem(MAC_WXHMENU(m_hMenu), "\p-" , pos);
118 }
119 else
120 {
121 wxMenu *pSubMenu = pItem->GetSubMenu() ;
122 if ( pSubMenu != NULL )
123 {
124 wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added"));
125 pSubMenu->m_menuParent = this ;
126
127 if (wxMenuBar::MacGetInstalledMenuBar() == m_menuBar)
128 {
129 pSubMenu->MacBeforeDisplay( true ) ;
130 }
131
132 if ( pos == (size_t)-1 )
133 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), pSubMenu->m_macMenuId);
134 else
135 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText() , pos, pSubMenu->m_macMenuId);
136 pItem->UpdateItemBitmap() ;
137 pItem->UpdateItemStatus() ;
138 }
139 else
140 {
141 if ( pos == (size_t)-1 )
142 {
143 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") );
144 pos = CountMenuItems(MAC_WXHMENU(m_hMenu)) ;
145 }
146 else
147 {
148 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") , pos);
149 }
150
151 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , pItem->GetId() ) ;
152 pItem->UpdateItemText() ;
153 pItem->UpdateItemBitmap() ;
154 pItem->UpdateItemStatus() ;
155
156 if ( pItem->GetId() == idMenuTitle )
157 {
158 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ;
159 }
160 }
161 }
162 // if we're already attached to the menubar, we must update it
163 if ( IsAttached() )
164 {
165 m_menuBar->Refresh();
166 }
167 return TRUE ;
168 }
169
170 void wxMenu::EndRadioGroup()
171 {
172 // we're not inside a radio group any longer
173 m_startRadioGroup = -1;
174 }
175
176 bool wxMenu::DoAppend(wxMenuItem *item)
177 {
178 wxCHECK_MSG( item, FALSE, _T("NULL item in wxMenu::DoAppend") );
179
180 bool check = FALSE;
181
182 if ( item->GetKind() == wxITEM_RADIO )
183 {
184 int count = GetMenuItemCount();
185
186 if ( m_startRadioGroup == -1 )
187 {
188 // start a new radio group
189 m_startRadioGroup = count;
190
191 // for now it has just one element
192 item->SetAsRadioGroupStart();
193 item->SetRadioGroupEnd(m_startRadioGroup);
194
195 // ensure that we have a checked item in the radio group
196 check = TRUE;
197 }
198 else // extend the current radio group
199 {
200 // we need to update its end item
201 item->SetRadioGroupStart(m_startRadioGroup);
202 wxMenuItemList::Node *node = GetMenuItems().Item(m_startRadioGroup);
203
204 if ( node )
205 {
206 node->GetData()->SetRadioGroupEnd(count);
207 }
208 else
209 {
210 wxFAIL_MSG( _T("where is the radio group start item?") );
211 }
212 }
213 }
214 else // not a radio item
215 {
216 EndRadioGroup();
217 }
218
219 if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
220 {
221 return FALSE;
222 }
223
224 if ( check )
225 {
226 // check the item initially
227 item->Check(TRUE);
228 }
229
230 return TRUE;
231 }
232
233 bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
234 {
235 return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
236 }
237
238 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
239 {
240 // we need to find the items position in the child list
241 size_t pos;
242 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
243 for ( pos = 0; node; pos++ )
244 {
245 if ( node->GetData() == item )
246 break;
247
248 node = node->GetNext();
249 }
250
251 // DoRemove() (unlike Remove) can only be called for existing item!
252 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
253
254 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);
255
256 if ( IsAttached() )
257 {
258 // otherwise, the change won't be visible
259 m_menuBar->Refresh();
260 }
261
262 // and from internal data structures
263 return wxMenuBase::DoRemove(item);
264 }
265
266 void wxMenu::SetTitle(const wxString& label)
267 {
268 m_title = label ;
269 UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label ) ;
270 }
271 bool wxMenu::ProcessCommand(wxCommandEvent & event)
272 {
273 bool processed = FALSE;
274
275 #if WXWIN_COMPATIBILITY
276 // Try a callback
277 if (m_callback)
278 {
279 (void)(*(m_callback))(*this, event);
280 processed = TRUE;
281 }
282 #endif WXWIN_COMPATIBILITY
283
284 // Try the menu's event handler
285 if ( !processed && GetEventHandler())
286 {
287 processed = GetEventHandler()->ProcessEvent(event);
288 }
289
290 // Try the window the menu was popped up from (and up through the
291 // hierarchy)
292 wxWindow *win = GetInvokingWindow();
293 if ( !processed && win )
294 processed = win->GetEventHandler()->ProcessEvent(event);
295
296 return processed;
297 }
298
299
300 // ---------------------------------------------------------------------------
301 // other
302 // ---------------------------------------------------------------------------
303
304 wxWindow *wxMenu::GetWindow() const
305 {
306 if ( m_invokingWindow != NULL )
307 return m_invokingWindow;
308 else if ( m_menuBar != NULL)
309 return (wxWindow *) m_menuBar->GetFrame();
310
311 return NULL;
312 }
313
314 // helper functions returning the mac menu position for a certain item, note that this is
315 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
316
317 int wxMenu::MacGetIndexFromId( int id )
318 {
319 size_t pos;
320 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
321 for ( pos = 0; node; pos++ )
322 {
323 if ( node->GetData()->GetId() == id )
324 break;
325
326 node = node->GetNext();
327 }
328
329 if (!node)
330 return 0;
331
332 return pos + 1 ;
333 }
334
335 int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
336 {
337 size_t pos;
338 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
339 for ( pos = 0; node; pos++ )
340 {
341 if ( node->GetData() == pItem )
342 break;
343
344 node = node->GetNext();
345 }
346
347 if (!node)
348 return 0;
349
350 return pos + 1 ;
351 }
352
353 void wxMenu::MacEnableMenu( bool bDoEnable )
354 {
355 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
356
357 ::DrawMenuBar() ;
358 }
359
360 // MacOS needs to know about submenus somewhere within this menu
361 // before it can be displayed , also hide special menu items like preferences
362 // that are handled by the OS
363 void wxMenu::MacBeforeDisplay( bool isSubMenu )
364 {
365 wxMenuItem* previousItem = NULL ;
366 size_t pos ;
367 wxMenuItemList::Node *node;
368 wxMenuItem *item;
369 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
370 {
371 item = (wxMenuItem *)node->GetData();
372 wxMenu* subMenu = item->GetSubMenu() ;
373 if (subMenu)
374 {
375 subMenu->MacBeforeDisplay( true ) ;
376 }
377 else
378 {
379 #if TARGET_CARBON
380 if ( UMAGetSystemVersion() >= 0x1000 )
381 {
382 if ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId)
383 {
384 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos + 1, kMenuItemAttrHidden, 0 );
385 if ( GetMenuItems().GetCount() == pos + 1 &&
386 previousItem != NULL &&
387 previousItem->IsSeparator() )
388 {
389 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 );
390 }
391 }
392 }
393 #endif
394 }
395 previousItem = item ;
396 }
397
398 if ( isSubMenu )
399 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
400
401 }
402 // undo all changes from the MacBeforeDisplay call
403 void wxMenu::MacAfterDisplay( bool isSubMenu )
404 {
405 if ( isSubMenu )
406 ::DeleteMenu(MacGetMenuId());
407
408 wxMenuItem* previousItem = NULL ;
409 int pos ;
410 wxMenuItemList::Node *node;
411 wxMenuItem *item;
412 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
413 {
414 item = (wxMenuItem *)node->GetData();
415 wxMenu* subMenu = item->GetSubMenu() ;
416 if (subMenu)
417 {
418 subMenu->MacAfterDisplay( true ) ;
419 }
420 else
421 {
422 // no need to undo hidings
423 }
424 previousItem = item ;
425 }
426 }
427
428 // Menu Bar
429
430 /*
431
432 Mac Implementation note :
433
434 The Mac has only one global menubar, so we attempt to install the currently
435 active menubar from a frame, we currently don't take into account mdi-frames
436 which would ask for menu-merging
437
438 Secondly there is no mac api for changing a menubar that is not the current
439 menubar, so we have to wait for preparing the actual menubar until the
440 wxMenubar is to be used
441
442 We can in subsequent versions use MacInstallMenuBar to provide some sort of
443 auto-merge for MDI in case this will be necessary
444
445 */
446
447 wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
448
449 void wxMenuBar::Init()
450 {
451 m_eventHandler = this;
452 m_menuBarFrame = NULL;
453 m_invokingWindow = (wxWindow*) NULL;
454 }
455
456 wxMenuBar::wxMenuBar()
457 {
458 Init();
459 }
460
461 wxMenuBar::wxMenuBar( long WXUNUSED(style) )
462 {
463 Init();
464 }
465
466
467 wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
468 {
469 Init();
470
471 m_titles.Alloc(count);
472
473 for ( int i = 0; i < count; i++ )
474 {
475 m_menus.Append(menus[i]);
476 m_titles.Add(titles[i]);
477
478 menus[i]->Attach(this);
479 }
480 }
481
482 wxMenuBar::~wxMenuBar()
483 {
484 if (s_macInstalledMenuBar == this)
485 {
486 ::ClearMenuBar();
487 s_macInstalledMenuBar = NULL;
488 }
489
490 }
491
492 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
493 {
494 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
495
496 DrawMenuBar();
497 }
498
499 void wxMenuBar::MacInstallMenuBar()
500 {
501 if ( s_macInstalledMenuBar == this )
502 return ;
503
504 wxStAppResource resload ;
505
506 Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ;
507 wxString message ;
508 wxCHECK_RET( menubar != NULL, wxT("can't read MBAR resource") );
509 ::SetMenuBar( menubar ) ;
510 #if TARGET_API_MAC_CARBON
511 ::DisposeMenuBar( menubar ) ;
512 #else
513 ::DisposeHandle( menubar ) ;
514 #endif
515
516 #if TARGET_API_MAC_OS8
517 MenuHandle menu = ::GetMenuHandle( kwxMacAppleMenuId ) ;
518 if ( CountMenuItems( menu ) == 2 )
519 {
520 ::AppendResMenu(menu, 'DRVR');
521 }
522 #endif
523
524 // clean-up the help menu before adding new items
525 MenuHandle mh = NULL ;
526 if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) == noErr )
527 {
528 for ( int i = CountMenuItems( mh ) ; i >= firstUserHelpMenuItem ; --i )
529 {
530 DeleteMenuItem( mh , i ) ;
531 }
532 }
533 else
534 {
535 mh = NULL ;
536 }
537 #if TARGET_CARBON
538 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId)
539 {
540 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
541 if ( item == NULL || !(item->IsEnabled()) )
542 DisableMenuCommand( NULL , kHICommandPreferences ) ;
543 else
544 EnableMenuCommand( NULL , kHICommandPreferences ) ;
545 }
546 #endif
547 for (size_t i = 0; i < m_menus.GetCount(); i++)
548 {
549 wxMenuItemList::Node *node;
550 wxMenuItem *item;
551 int pos ;
552 wxMenu* menu = m_menus[i] , *subMenu = NULL ;
553
554 if( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName )
555 {
556 if ( mh == NULL )
557 {
558 continue ;
559 }
560
561 for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
562 {
563 item = (wxMenuItem *)node->GetData();
564 subMenu = item->GetSubMenu() ;
565 if (subMenu)
566 {
567 // we don't support hierarchical menus in the help menu yet
568 }
569 else
570 {
571 if ( item->IsSeparator() )
572 {
573 if ( mh )
574 MacAppendMenu(mh, "\p-" );
575 }
576 else
577 {
578 wxAcceleratorEntry* entry = wxGetAccelFromString( item->GetText() ) ;
579
580 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
581 {
582 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetText() );
583 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
584 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetId() ) ;
585 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
586 }
587 else
588 {
589 if ( mh )
590 {
591 UMAAppendMenuItem(mh, item->GetText() , entry );
592 SetMenuItemCommandID( mh , CountMenuItems(mh) , item->GetId() ) ;
593 }
594 }
595
596 delete entry ;
597 }
598 }
599 }
600 }
601 else
602 {
603 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i] ) ;
604 m_menus[i]->MacBeforeDisplay(false) ;
605 ::InsertMenu(MAC_WXHMENU(m_menus[i]->GetHMenu()), 0);
606 }
607 }
608 ::DrawMenuBar() ;
609 s_macInstalledMenuBar = this;
610 }
611
612 void wxMenuBar::EnableTop(size_t pos, bool enable)
613 {
614 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
615 m_menus[pos]->MacEnableMenu( enable ) ;
616 Refresh();
617 }
618
619 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
620 {
621 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
622
623 m_titles[pos] = label;
624
625 if ( !IsAttached() )
626 {
627 return;
628 }
629
630 m_menus[pos]->SetTitle( label ) ;
631 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
632 {
633 ::SetMenuBar( GetMenuBar() ) ;
634 ::InvalMenuBar() ;
635 }
636 }
637
638 wxString wxMenuBar::GetLabelTop(size_t pos) const
639 {
640 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
641 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
642
643 return m_titles[pos];
644 }
645
646 int wxMenuBar::FindMenu(const wxString& title)
647 {
648 wxString menuTitle = wxStripMenuCodes(title);
649
650 size_t count = GetMenuCount();
651 for ( size_t i = 0; i < count; i++ )
652 {
653 wxString title = wxStripMenuCodes(m_titles[i]);
654 if ( menuTitle == title )
655 return i;
656 }
657
658 return wxNOT_FOUND;
659
660 }
661
662
663 // ---------------------------------------------------------------------------
664 // wxMenuBar construction
665 // ---------------------------------------------------------------------------
666
667 // ---------------------------------------------------------------------------
668 // wxMenuBar construction
669 // ---------------------------------------------------------------------------
670
671 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
672 {
673 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
674 if ( !menuOld )
675 return FALSE;
676 m_titles[pos] = title;
677
678 if ( IsAttached() )
679 {
680 if (s_macInstalledMenuBar == this)
681 {
682 menuOld->MacAfterDisplay( false ) ;
683 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
684 {
685 menu->MacBeforeDisplay( false ) ;
686 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
687 if ( pos == m_menus.GetCount() - 1)
688 {
689 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
690 }
691 else
692 {
693 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
694 }
695 }
696 }
697
698 Refresh();
699 }
700
701 return menuOld;
702 }
703
704 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
705 {
706 if ( !wxMenuBarBase::Insert(pos, menu, title) )
707 return FALSE;
708
709 m_titles.Insert(title, pos);
710
711 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
712
713 if ( IsAttached() && s_macInstalledMenuBar == this )
714 {
715 if (s_macInstalledMenuBar == this)
716 {
717 menu->MacBeforeDisplay( false ) ;
718 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
719 {
720 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
721 }
722 else
723 {
724 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
725 }
726 }
727 Refresh();
728 }
729
730 return TRUE;
731 }
732
733 wxMenu *wxMenuBar::Remove(size_t pos)
734 {
735 wxMenu *menu = wxMenuBarBase::Remove(pos);
736 if ( !menu )
737 return NULL;
738
739 if ( IsAttached() )
740 {
741 if (s_macInstalledMenuBar == this)
742 {
743 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
744 }
745
746 menu->Detach();
747
748 Refresh();
749 }
750
751 m_titles.Remove(pos);
752
753 return menu;
754 }
755
756 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
757 {
758 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
759 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
760
761 if ( !wxMenuBarBase::Append(menu, title) )
762 return FALSE;
763
764 m_titles.Add(title);
765
766 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
767
768 if ( IsAttached() )
769 {
770 if (s_macInstalledMenuBar == this)
771 {
772 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
773 }
774
775 Refresh();
776 }
777
778 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
779 // adding menu later on.
780 if (m_invokingWindow)
781 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
782
783 return TRUE;
784 }
785
786 static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
787 {
788 menu->SetInvokingWindow( (wxWindow*) NULL );
789
790 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
791 while (node)
792 {
793 wxMenuItem *menuitem = node->GetData();
794 if (menuitem->IsSubMenu())
795 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
796 node = node->GetNext();
797 }
798 }
799
800 static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
801 {
802 menu->SetInvokingWindow( win );
803
804 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
805 while (node)
806 {
807 wxMenuItem *menuitem = node->GetData();
808 if (menuitem->IsSubMenu())
809 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
810 node = node->GetNext();
811 }
812 }
813
814 void wxMenuBar::UnsetInvokingWindow()
815 {
816 m_invokingWindow = (wxWindow*) NULL;
817 wxMenuList::Node *node = m_menus.GetFirst();
818 while (node)
819 {
820 wxMenu *menu = node->GetData();
821 wxMenubarUnsetInvokingWindow( menu );
822 node = node->GetNext();
823 }
824 }
825
826 void wxMenuBar::SetInvokingWindow(wxFrame *frame)
827 {
828 m_invokingWindow = frame;
829 wxMenuList::Node *node = m_menus.GetFirst();
830 while (node)
831 {
832 wxMenu *menu = node->GetData();
833 wxMenubarSetInvokingWindow( menu, frame );
834 node = node->GetNext();
835 }
836 }
837
838 void wxMenuBar::Detach()
839 {
840 wxMenuBarBase::Detach() ;
841 }
842
843 void wxMenuBar::Attach(wxFrame *frame)
844 {
845 wxMenuBarBase::Attach( frame ) ;
846 }
847 // ---------------------------------------------------------------------------
848 // wxMenuBar searching for menu items
849 // ---------------------------------------------------------------------------
850
851 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
852 int wxMenuBar::FindMenuItem(const wxString& menuString,
853 const wxString& itemString) const
854 {
855 wxString menuLabel = wxStripMenuCodes(menuString);
856 size_t count = GetMenuCount();
857 for ( size_t i = 0; i < count; i++ )
858 {
859 wxString title = wxStripMenuCodes(m_titles[i]);
860 if ( menuString == title )
861 return m_menus[i]->FindItem(itemString);
862 }
863
864 return wxNOT_FOUND;
865 }
866
867 wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
868 {
869 if ( itemMenu )
870 *itemMenu = NULL;
871
872 wxMenuItem *item = NULL;
873 size_t count = GetMenuCount();
874 for ( size_t i = 0; !item && (i < count); i++ )
875 {
876 item = m_menus[i]->FindItem(id, itemMenu);
877 }
878
879 return item;
880 }
881
882