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