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