]> git.saurik.com Git - wxWidgets.git/blob - src/mac/classic/menu.cpp
Include wx/cursor.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / mac / classic / menu.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/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 // ============================================================================
13 // headers & declarations
14 // ============================================================================
15
16 // wxWidgets headers
17 // -----------------
18
19 #include "wx/wxprec.h"
20
21 #include "wx/menu.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/log.h"
25 #include "wx/app.h"
26 #include "wx/utils.h"
27 #include "wx/window.h"
28 #include "wx/frame.h"
29 #endif
30
31 #include "wx/menuitem.h"
32
33 #include "wx/mac/uma.h"
34
35 // other standard headers
36 // ----------------------
37 #include <string.h>
38
39 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
40 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
41
42 // the (popup) menu title has this special id
43 static const int idMenuTitle = -2;
44 static MenuItemIndex firstUserHelpMenuItem = 0 ;
45
46 const short kwxMacMenuBarResource = 1 ;
47 const short kwxMacAppleMenuId = 1 ;
48
49 // ============================================================================
50 // implementation
51 // ============================================================================
52 static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;
53 static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );
54
55 // Menus
56
57 // Construct a menu with optional title (then use append)
58
59 #ifdef __DARWIN__
60 short wxMenu::s_macNextMenuId = 3 ;
61 #else
62 short wxMenu::s_macNextMenuId = 2 ;
63 #endif
64
65 void wxMenu::Init()
66 {
67 m_doBreak = false;
68 m_startRadioGroup = -1;
69
70 // create the menu
71 m_macMenuId = s_macNextMenuId++;
72 m_hMenu = UMANewMenu(m_macMenuId, m_title, wxFont::GetDefaultEncoding() );
73
74 if ( !m_hMenu )
75 {
76 wxLogLastError(wxT("UMANewMenu failed"));
77 }
78
79 // if we have a title, insert it in the beginning of the menu
80 if ( !m_title.empty() )
81 {
82 Append(idMenuTitle, m_title) ;
83 AppendSeparator() ;
84 }
85 }
86
87 wxMenu::~wxMenu()
88 {
89 if (MAC_WXHMENU(m_hMenu))
90 ::DisposeMenu(MAC_WXHMENU(m_hMenu));
91 }
92
93 void wxMenu::Break()
94 {
95 // not available on the mac platform
96 }
97
98 void wxMenu::Attach(wxMenuBarBase *menubar)
99 {
100 wxMenuBase::Attach(menubar);
101
102 EndRadioGroup();
103 }
104
105 // function appends a new item or submenu to the menu
106 // append a new item or submenu to the menu
107 bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
108 {
109 wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );
110
111 if ( pItem->IsSeparator() )
112 {
113 if ( pos == (size_t)-1 )
114 MacAppendMenu(MAC_WXHMENU(m_hMenu), "\p-");
115 else
116 MacInsertMenuItem(MAC_WXHMENU(m_hMenu), "\p-" , pos);
117 }
118 else
119 {
120 wxMenu *pSubMenu = pItem->GetSubMenu() ;
121 if ( pSubMenu != NULL )
122 {
123 wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added"));
124 pSubMenu->m_menuParent = this ;
125
126 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
127 {
128 pSubMenu->MacBeforeDisplay( true ) ;
129 }
130
131 if ( pos == (size_t)-1 )
132 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), wxFont::GetDefaultEncoding() , pSubMenu->m_macMenuId);
133 else
134 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), wxFont::GetDefaultEncoding() , 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), wxT("a") , wxFont::GetDefaultEncoding() );
143 pos = CountMenuItems(MAC_WXHMENU(m_hMenu)) ;
144 }
145 else
146 {
147 // MacOS counts menu items from 1 and inserts after, therefore having the
148 // same effect as wx 0 based and inserting before, we must correct pos
149 // after however for updates to be correct
150 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a"), wxFont::GetDefaultEncoding(), pos);
151 pos += 1 ;
152 }
153
154 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , pItem->GetId() ) ;
155 pItem->UpdateItemText() ;
156 pItem->UpdateItemBitmap() ;
157 pItem->UpdateItemStatus() ;
158
159 if ( pItem->GetId() == idMenuTitle )
160 {
161 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ;
162 }
163 }
164 }
165 // if we're already attached to the menubar, we must update it
166 if ( IsAttached() )
167 {
168 GetMenuBar()->Refresh();
169 }
170 return true ;
171 }
172
173 void wxMenu::EndRadioGroup()
174 {
175 // we're not inside a radio group any longer
176 m_startRadioGroup = -1;
177 }
178
179 wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
180 {
181 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
182
183 bool check = false;
184
185 if ( item->GetKind() == wxITEM_RADIO )
186 {
187 int count = GetMenuItemCount();
188
189 if ( m_startRadioGroup == -1 )
190 {
191 // start a new radio group
192 m_startRadioGroup = count;
193
194 // for now it has just one element
195 item->SetAsRadioGroupStart();
196 item->SetRadioGroupEnd(m_startRadioGroup);
197
198 // ensure that we have a checked item in the radio group
199 check = true;
200 }
201 else // extend the current radio group
202 {
203 // we need to update its end item
204 item->SetRadioGroupStart(m_startRadioGroup);
205 wxMenuItemList::Node *node = GetMenuItems().Item(m_startRadioGroup);
206
207 if ( node )
208 {
209 node->GetData()->SetRadioGroupEnd(count);
210 }
211 else
212 {
213 wxFAIL_MSG( _T("where is the radio group start item?") );
214 }
215 }
216 }
217 else // not a radio item
218 {
219 EndRadioGroup();
220 }
221
222 if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
223 {
224 return NULL;
225 }
226
227 if ( check )
228 {
229 // check the item initially
230 item->Check(true);
231 }
232
233 return item;
234 }
235
236 wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
237 {
238 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
239 return item;
240 else
241 return NULL;
242 }
243
244 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
245 {
246 // we need to find the items position in the child list
247 size_t pos;
248 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
249 for ( pos = 0; node; pos++ )
250 {
251 if ( node->GetData() == item )
252 break;
253
254 node = node->GetNext();
255 }
256
257 // DoRemove() (unlike Remove) can only be called for existing item!
258 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
259
260 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);
261
262 if ( IsAttached() )
263 {
264 // otherwise, the change won't be visible
265 GetMenuBar()->Refresh();
266 }
267
268 // and from internal data structures
269 return wxMenuBase::DoRemove(item);
270 }
271
272 void wxMenu::SetTitle(const wxString& label)
273 {
274 m_title = label ;
275 UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label , wxFont::GetDefaultEncoding() ) ;
276 }
277 bool wxMenu::ProcessCommand(wxCommandEvent & event)
278 {
279 bool processed = false;
280
281 // Try the menu's event handler
282 if ( !processed && GetEventHandler())
283 {
284 processed = GetEventHandler()->ProcessEvent(event);
285 }
286
287 // Try the window the menu was popped up from (and up through the
288 // hierarchy)
289 wxWindow *win = GetInvokingWindow();
290 if ( !processed && win )
291 processed = win->GetEventHandler()->ProcessEvent(event);
292
293 return processed;
294 }
295
296
297 // ---------------------------------------------------------------------------
298 // other
299 // ---------------------------------------------------------------------------
300
301 wxWindow *wxMenu::GetWindow() const
302 {
303 if ( m_invokingWindow != NULL )
304 return m_invokingWindow;
305 else if ( GetMenuBar() != NULL)
306 return (wxWindow *) GetMenuBar()->GetFrame();
307
308 return NULL;
309 }
310
311 // helper functions returning the mac menu position for a certain item, note that this is
312 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
313
314 int wxMenu::MacGetIndexFromId( int id )
315 {
316 size_t pos;
317 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
318 for ( pos = 0; node; pos++ )
319 {
320 if ( node->GetData()->GetId() == id )
321 break;
322
323 node = node->GetNext();
324 }
325
326 if (!node)
327 return 0;
328
329 return pos + 1 ;
330 }
331
332 int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
333 {
334 size_t pos;
335 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
336 for ( pos = 0; node; pos++ )
337 {
338 if ( node->GetData() == pItem )
339 break;
340
341 node = node->GetNext();
342 }
343
344 if (!node)
345 return 0;
346
347 return pos + 1 ;
348 }
349
350 void wxMenu::MacEnableMenu( bool bDoEnable )
351 {
352 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
353
354 ::DrawMenuBar() ;
355 }
356
357 // MacOS needs to know about submenus somewhere within this menu
358 // before it can be displayed , also hide special menu items like preferences
359 // that are handled by the OS
360 void wxMenu::MacBeforeDisplay( bool isSubMenu )
361 {
362 wxMenuItem* previousItem = NULL ;
363 size_t pos ;
364 wxMenuItemList::Node *node;
365 wxMenuItem *item;
366 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
367 {
368 item = (wxMenuItem *)node->GetData();
369 wxMenu* subMenu = item->GetSubMenu() ;
370 if (subMenu)
371 {
372 subMenu->MacBeforeDisplay( true ) ;
373 }
374 else
375 {
376 #if TARGET_CARBON
377 if ( UMAGetSystemVersion() >= 0x1000 )
378 {
379 if ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId)
380 {
381 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos + 1, kMenuItemAttrHidden, 0 );
382 if ( GetMenuItems().GetCount() == pos + 1 &&
383 previousItem != NULL &&
384 previousItem->IsSeparator() )
385 {
386 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 );
387 }
388 }
389 }
390 #endif
391 }
392 previousItem = item ;
393 }
394
395 if ( isSubMenu )
396 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
397
398 }
399 // undo all changes from the MacBeforeDisplay call
400 void wxMenu::MacAfterDisplay( bool isSubMenu )
401 {
402 if ( isSubMenu )
403 ::DeleteMenu(MacGetMenuId());
404
405 wxMenuItem* previousItem = NULL ;
406 int pos ;
407 wxMenuItemList::Node *node;
408 wxMenuItem *item;
409 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
410 {
411 item = (wxMenuItem *)node->GetData();
412 wxMenu* subMenu = item->GetSubMenu() ;
413 if (subMenu)
414 {
415 subMenu->MacAfterDisplay( true ) ;
416 }
417 else
418 {
419 // no need to undo hidings
420 }
421 previousItem = item ;
422 }
423 }
424
425 // Menu Bar
426
427 /*
428
429 Mac Implementation note :
430
431 The Mac has only one global menubar, so we attempt to install the currently
432 active menubar from a frame, we currently don't take into account mdi-frames
433 which would ask for menu-merging
434
435 Secondly there is no mac api for changing a menubar that is not the current
436 menubar, so we have to wait for preparing the actual menubar until the
437 wxMenubar is to be used
438
439 We can in subsequent versions use MacInstallMenuBar to provide some sort of
440 auto-merge for MDI in case this will be necessary
441
442 */
443
444 wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
445 wxMenuBar* wxMenuBar::s_macCommonMenuBar = 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(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
466 {
467 Init();
468
469 m_titles.Alloc(count);
470
471 for ( size_t 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_macCommonMenuBar == this)
483 s_macCommonMenuBar = NULL;
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() , wxFont::GetDefaultEncoding() );
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() , wxFont::GetDefaultEncoding(), 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], m_font.GetEncoding() ) ;
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 NULL;
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 , m_font.GetEncoding() ) ;
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 , m_font.GetEncoding() ) ;
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 Refresh();
747 }
748
749 m_titles.RemoveAt(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 , m_font.GetEncoding() ) ;
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 }