]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/menu.cpp
Applied patch [ 745983 ] Fix for memory leak in class wxPluginManager in dynload.cpp
[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 int 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 && previousItem != NULL && previousItem->IsSeparator() )
386 {
387 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 );
388 }
389 }
390 }
391 #endif
392 }
393 previousItem = item ;
394 }
395
396 if ( isSubMenu )
397 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
398
399 }
400 // undo all changes from the MacBeforeDisplay call
401 void wxMenu::MacAfterDisplay( bool isSubMenu )
402 {
403 if ( isSubMenu )
404 ::DeleteMenu(MacGetMenuId());
405
406 wxMenuItem* previousItem = NULL ;
407 int pos ;
408 wxMenuItemList::Node *node;
409 wxMenuItem *item;
410 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
411 {
412 item = (wxMenuItem *)node->GetData();
413 wxMenu* subMenu = item->GetSubMenu() ;
414 if (subMenu)
415 {
416 subMenu->MacAfterDisplay( true ) ;
417 }
418 else
419 {
420 // no need to undo hidings
421 }
422 previousItem = item ;
423 }
424 }
425
426 // Menu Bar
427
428 /*
429
430 Mac Implementation note :
431
432 The Mac has only one global menubar, so we attempt to install the currently
433 active menubar from a frame, we currently don't take into account mdi-frames
434 which would ask for menu-merging
435
436 Secondly there is no mac api for changing a menubar that is not the current
437 menubar, so we have to wait for preparing the actual menubar until the
438 wxMenubar is to be used
439
440 We can in subsequent versions use MacInstallMenuBar to provide some sort of
441 auto-merge for MDI in case this will be necessary
442
443 */
444
445 wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
446
447 void wxMenuBar::Init()
448 {
449 m_eventHandler = this;
450 m_menuBarFrame = NULL;
451 m_invokingWindow = (wxWindow*) NULL;
452 }
453
454 wxMenuBar::wxMenuBar()
455 {
456 Init();
457 }
458
459 wxMenuBar::wxMenuBar( long WXUNUSED(style) )
460 {
461 Init();
462 }
463
464
465 wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
466 {
467 Init();
468
469 m_titles.Alloc(count);
470
471 for ( int i = 0; i < count; i++ )
472 {
473 m_menus.Append(menus[i]);
474 m_titles.Add(titles[i]);
475
476 menus[i]->Attach(this);
477 }
478 }
479
480 wxMenuBar::~wxMenuBar()
481 {
482 if (s_macInstalledMenuBar == this)
483 {
484 ::ClearMenuBar();
485 s_macInstalledMenuBar = NULL;
486 }
487
488 }
489
490 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
491 {
492 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
493
494 DrawMenuBar();
495 }
496
497 void wxMenuBar::MacInstallMenuBar()
498 {
499 if ( s_macInstalledMenuBar == this )
500 return ;
501
502 wxStAppResource resload ;
503
504 Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ;
505 wxString message ;
506 wxCHECK_RET( menubar != NULL, wxT("can't read MBAR resource") );
507 ::SetMenuBar( menubar ) ;
508 #if TARGET_API_MAC_CARBON
509 ::DisposeMenuBar( menubar ) ;
510 #else
511 ::DisposeHandle( menubar ) ;
512 #endif
513
514 #if TARGET_API_MAC_OS8
515 MenuHandle menu = ::GetMenuHandle( kwxMacAppleMenuId ) ;
516 if ( CountMenuItems( menu ) == 2 )
517 {
518 ::AppendResMenu(menu, 'DRVR');
519 }
520 #endif
521
522 // clean-up the help menu before adding new items
523 MenuHandle mh = NULL ;
524 if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) == noErr )
525 {
526 for ( int i = CountMenuItems( mh ) ; i >= firstUserHelpMenuItem ; --i )
527 {
528 DeleteMenuItem( mh , i ) ;
529 }
530 }
531 else
532 {
533 mh = NULL ;
534 }
535 #if TARGET_CARBON
536 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId)
537 {
538 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
539 if ( item == NULL || !(item->IsEnabled()) )
540 DisableMenuCommand( NULL , kHICommandPreferences ) ;
541 else
542 EnableMenuCommand( NULL , kHICommandPreferences ) ;
543 }
544 #endif
545 for (size_t i = 0; i < m_menus.GetCount(); i++)
546 {
547 wxMenuItemList::Node *node;
548 wxMenuItem *item;
549 int pos ;
550 wxMenu* menu = m_menus[i] , *subMenu = NULL ;
551
552 if( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName )
553 {
554 if ( mh == NULL )
555 {
556 continue ;
557 }
558
559 for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
560 {
561 item = (wxMenuItem *)node->GetData();
562 subMenu = item->GetSubMenu() ;
563 if (subMenu)
564 {
565 // we don't support hierarchical menus in the help menu yet
566 }
567 else
568 {
569 if ( item->IsSeparator() )
570 {
571 if ( mh )
572 MacAppendMenu(mh, "\p-" );
573 }
574 else
575 {
576 wxAcceleratorEntry* entry = wxGetAccelFromString( item->GetText() ) ;
577
578 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
579 {
580 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetText() );
581 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
582 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetId() ) ;
583 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
584 }
585 else
586 {
587 if ( mh )
588 {
589 UMAAppendMenuItem(mh, item->GetText() , entry );
590 SetMenuItemCommandID( mh , CountMenuItems(mh) , item->GetId() ) ;
591 }
592 }
593
594 delete entry ;
595 }
596 }
597 }
598 }
599 else
600 {
601 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i] ) ;
602 m_menus[i]->MacBeforeDisplay(false) ;
603 ::InsertMenu(MAC_WXHMENU(m_menus[i]->GetHMenu()), 0);
604 }
605 }
606 ::DrawMenuBar() ;
607 s_macInstalledMenuBar = this;
608 }
609
610 void wxMenuBar::EnableTop(size_t pos, bool enable)
611 {
612 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
613 m_menus[pos]->MacEnableMenu( enable ) ;
614 Refresh();
615 }
616
617 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
618 {
619 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
620
621 m_titles[pos] = label;
622
623 if ( !IsAttached() )
624 {
625 return;
626 }
627
628 m_menus[pos]->SetTitle( label ) ;
629 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
630 {
631 ::SetMenuBar( GetMenuBar() ) ;
632 ::InvalMenuBar() ;
633 }
634 }
635
636 wxString wxMenuBar::GetLabelTop(size_t pos) const
637 {
638 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
639 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
640
641 return m_titles[pos];
642 }
643
644 int wxMenuBar::FindMenu(const wxString& title)
645 {
646 wxString menuTitle = wxStripMenuCodes(title);
647
648 size_t count = GetMenuCount();
649 for ( size_t i = 0; i < count; i++ )
650 {
651 wxString title = wxStripMenuCodes(m_titles[i]);
652 if ( menuTitle == title )
653 return i;
654 }
655
656 return wxNOT_FOUND;
657
658 }
659
660
661 // ---------------------------------------------------------------------------
662 // wxMenuBar construction
663 // ---------------------------------------------------------------------------
664
665 // ---------------------------------------------------------------------------
666 // wxMenuBar construction
667 // ---------------------------------------------------------------------------
668
669 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
670 {
671 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
672 if ( !menuOld )
673 return FALSE;
674 m_titles[pos] = title;
675
676 if ( IsAttached() )
677 {
678 if (s_macInstalledMenuBar == this)
679 {
680 menuOld->MacAfterDisplay( false ) ;
681 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
682 {
683 menu->MacBeforeDisplay( false ) ;
684 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
685 if ( pos == m_menus.GetCount() - 1)
686 {
687 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
688 }
689 else
690 {
691 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
692 }
693 }
694 }
695
696 Refresh();
697 }
698
699 return menuOld;
700 }
701
702 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
703 {
704 if ( !wxMenuBarBase::Insert(pos, menu, title) )
705 return FALSE;
706
707 m_titles.Insert(title, pos);
708
709 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
710
711 if ( IsAttached() && s_macInstalledMenuBar == this )
712 {
713 if (s_macInstalledMenuBar == this)
714 {
715 menu->MacBeforeDisplay( false ) ;
716 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
717 {
718 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
719 }
720 else
721 {
722 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
723 }
724 }
725 Refresh();
726 }
727
728 return TRUE;
729 }
730
731 wxMenu *wxMenuBar::Remove(size_t pos)
732 {
733 wxMenu *menu = wxMenuBarBase::Remove(pos);
734 if ( !menu )
735 return NULL;
736
737 if ( IsAttached() )
738 {
739 if (s_macInstalledMenuBar == this)
740 {
741 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
742 }
743
744 menu->Detach();
745
746 Refresh();
747 }
748
749 m_titles.Remove(pos);
750
751 return menu;
752 }
753
754 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
755 {
756 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
757 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
758
759 if ( !wxMenuBarBase::Append(menu, title) )
760 return FALSE;
761
762 m_titles.Add(title);
763
764 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
765
766 if ( IsAttached() )
767 {
768 if (s_macInstalledMenuBar == this)
769 {
770 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
771 }
772
773 Refresh();
774 }
775
776 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
777 // adding menu later on.
778 if (m_invokingWindow)
779 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
780
781 return TRUE;
782 }
783
784 static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
785 {
786 menu->SetInvokingWindow( (wxWindow*) NULL );
787
788 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
789 while (node)
790 {
791 wxMenuItem *menuitem = node->GetData();
792 if (menuitem->IsSubMenu())
793 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
794 node = node->GetNext();
795 }
796 }
797
798 static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
799 {
800 menu->SetInvokingWindow( win );
801
802 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
803 while (node)
804 {
805 wxMenuItem *menuitem = node->GetData();
806 if (menuitem->IsSubMenu())
807 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
808 node = node->GetNext();
809 }
810 }
811
812 void wxMenuBar::UnsetInvokingWindow()
813 {
814 m_invokingWindow = (wxWindow*) NULL;
815 wxMenuList::Node *node = m_menus.GetFirst();
816 while (node)
817 {
818 wxMenu *menu = node->GetData();
819 wxMenubarUnsetInvokingWindow( menu );
820 node = node->GetNext();
821 }
822 }
823
824 void wxMenuBar::SetInvokingWindow(wxFrame *frame)
825 {
826 m_invokingWindow = frame;
827 wxMenuList::Node *node = m_menus.GetFirst();
828 while (node)
829 {
830 wxMenu *menu = node->GetData();
831 wxMenubarSetInvokingWindow( menu, frame );
832 node = node->GetNext();
833 }
834 }
835
836 void wxMenuBar::Detach()
837 {
838 wxMenuBarBase::Detach() ;
839 }
840
841 void wxMenuBar::Attach(wxFrame *frame)
842 {
843 wxMenuBarBase::Attach( frame ) ;
844 }
845 // ---------------------------------------------------------------------------
846 // wxMenuBar searching for menu items
847 // ---------------------------------------------------------------------------
848
849 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
850 int wxMenuBar::FindMenuItem(const wxString& menuString,
851 const wxString& itemString) const
852 {
853 wxString menuLabel = wxStripMenuCodes(menuString);
854 size_t count = GetMenuCount();
855 for ( size_t i = 0; i < count; i++ )
856 {
857 wxString title = wxStripMenuCodes(m_titles[i]);
858 if ( menuString == title )
859 return m_menus[i]->FindItem(itemString);
860 }
861
862 return wxNOT_FOUND;
863 }
864
865 wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
866 {
867 if ( itemMenu )
868 *itemMenu = NULL;
869
870 wxMenuItem *item = NULL;
871 size_t count = GetMenuCount();
872 for ( size_t i = 0; !item && (i < count); i++ )
873 {
874 item = m_menus[i]->FindItem(id, itemMenu);
875 }
876
877 return item;
878 }
879
880