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