]> git.saurik.com Git - wxWidgets.git/blame - src/mac/classic/menu.cpp
& operator should be &&
[wxWidgets.git] / src / mac / classic / menu.cpp
CommitLineData
2646f485 1/////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/mac/classic/menu.cpp
2646f485
SC
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
e4db172a 9// Licence: wxWindows licence
2646f485
SC
10/////////////////////////////////////////////////////////////////////////////
11
2646f485
SC
12// ============================================================================
13// headers & declarations
14// ============================================================================
15
77ffb593 16// wxWidgets headers
2646f485
SC
17// -----------------
18
e4db172a
WS
19#include "wx/wxprec.h"
20
2646f485 21#include "wx/menu.h"
e4db172a
WS
22
23#ifndef WX_PRECOMP
24 #include "wx/log.h"
670f9935 25 #include "wx/app.h"
e4db172a
WS
26#endif
27
2646f485
SC
28#include "wx/menuitem.h"
29#include "wx/window.h"
2646f485
SC
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
2646f485
SC
39IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
40IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
2646f485
SC
41
42// the (popup) menu title has this special id
43static const int idMenuTitle = -2;
44static MenuItemIndex firstUserHelpMenuItem = 0 ;
45
46const short kwxMacMenuBarResource = 1 ;
47const short kwxMacAppleMenuId = 1 ;
48
49// ============================================================================
50// implementation
51// ============================================================================
52static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;
53static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );
54
55// Menus
56
57// Construct a menu with optional title (then use append)
58
59#ifdef __DARWIN__
60short wxMenu::s_macNextMenuId = 3 ;
61#else
62short wxMenu::s_macNextMenuId = 2 ;
63#endif
64
65void wxMenu::Init()
66{
670f9935 67 m_doBreak = false;
2646f485
SC
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
e4db172a 80 if ( !m_title.empty() )
2646f485
SC
81 {
82 Append(idMenuTitle, m_title) ;
83 AppendSeparator() ;
84 }
85}
86
87wxMenu::~wxMenu()
88{
89 if (MAC_WXHMENU(m_hMenu))
90 ::DisposeMenu(MAC_WXHMENU(m_hMenu));
91}
92
93void wxMenu::Break()
94{
95 // not available on the mac platform
96}
97
98void 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
107bool 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
4224f059 126 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
2646f485
SC
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 {
4224f059 168 GetMenuBar()->Refresh();
2646f485 169 }
670f9935 170 return true ;
2646f485
SC
171}
172
173void wxMenu::EndRadioGroup()
174{
175 // we're not inside a radio group any longer
176 m_startRadioGroup = -1;
177}
178
179wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
180{
181 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
182
670f9935 183 bool check = false;
2646f485
SC
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
670f9935 199 check = true;
2646f485
SC
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
670f9935 230 item->Check(true);
2646f485
SC
231 }
232
233 return item;
234}
235
236wxMenuItem* 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
244wxMenuItem *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
4224f059 265 GetMenuBar()->Refresh();
2646f485
SC
266 }
267
268 // and from internal data structures
269 return wxMenuBase::DoRemove(item);
270}
271
272void wxMenu::SetTitle(const wxString& label)
273{
274 m_title = label ;
275 UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label , wxFont::GetDefaultEncoding() ) ;
276}
277bool wxMenu::ProcessCommand(wxCommandEvent & event)
278{
670f9935 279 bool processed = false;
2646f485
SC
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
301wxWindow *wxMenu::GetWindow() const
302{
303 if ( m_invokingWindow != NULL )
304 return m_invokingWindow;
4224f059
DE
305 else if ( GetMenuBar() != NULL)
306 return (wxWindow *) GetMenuBar()->GetFrame();
2646f485
SC
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
314int 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
332int 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
350void 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
360void 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
400void 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
429Mac Implementation note :
430
431The Mac has only one global menubar, so we attempt to install the currently
432active menubar from a frame, we currently don't take into account mdi-frames
433which would ask for menu-merging
434
435Secondly there is no mac api for changing a menubar that is not the current
436menubar, so we have to wait for preparing the actual menubar until the
437wxMenubar is to be used
438
439We can in subsequent versions use MacInstallMenuBar to provide some sort of
440auto-merge for MDI in case this will be necessary
441
442*/
443
444wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
445wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
446
447void wxMenuBar::Init()
448{
449 m_eventHandler = this;
450 m_menuBarFrame = NULL;
451 m_invokingWindow = (wxWindow*) NULL;
452}
453
454wxMenuBar::wxMenuBar()
455{
456 Init();
457}
458
459wxMenuBar::wxMenuBar( long WXUNUSED(style) )
460{
461 Init();
462}
463
464
294ea16d 465wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
2646f485
SC
466{
467 Init();
468
469 m_titles.Alloc(count);
470
d2103c8c 471 for ( size_t i = 0; i < count; i++ )
2646f485
SC
472 {
473 m_menus.Append(menus[i]);
474 m_titles.Add(titles[i]);
475
476 menus[i]->Attach(this);
477 }
478}
479
480wxMenuBar::~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
492void 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
499void 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
612void 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
619void 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
638wxString 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
646int 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
671wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
672{
673 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
674 if ( !menuOld )
670f9935 675 return NULL;
2646f485
SC
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
704bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
705{
706 if ( !wxMenuBarBase::Insert(pos, menu, title) )
670f9935 707 return false;
2646f485
SC
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
670f9935 730 return true;
2646f485
SC
731}
732
733wxMenu *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
754bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
755{
756 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
670f9935 757 wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
2646f485
SC
758
759 if ( !wxMenuBarBase::Append(menu, title) )
670f9935 760 return false;
2646f485
SC
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
670f9935 781 return true;
2646f485
SC
782}
783
784static 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
798static 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
812void 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
824void 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
836void wxMenuBar::Detach()
837{
838 wxMenuBarBase::Detach() ;
839}
840
841void 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
850int 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
865wxMenuItem *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}