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