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