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