]> git.saurik.com Git - wxWidgets.git/blame - src/mac/menu.cpp
GTK_TOOLBAR_BOTH_HORIZ is GTK 2 only (it would have been nice if the patch mentioned...
[wxWidgets.git] / src / mac / 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 {
7c15086c 77 wxLogLastError("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
e7549107 279#if WXWIN_COMPATIBILITY
e9576ca5
SC
280 // Try a callback
281 if (m_callback)
282 {
e7549107
SC
283 (void)(*(m_callback))(*this, event);
284 processed = TRUE;
e9576ca5 285 }
e7549107 286#endif WXWIN_COMPATIBILITY
e9576ca5
SC
287
288 // Try the menu's event handler
289 if ( !processed && GetEventHandler())
290 {
e7549107 291 processed = GetEventHandler()->ProcessEvent(event);
e9576ca5 292 }
519cb848 293
e7549107
SC
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
e7549107
SC
308wxWindow *wxMenu::GetWindow() const
309{
310 if ( m_invokingWindow != NULL )
311 return m_invokingWindow;
312 else if ( m_menuBar != NULL)
03e11df5 313 return (wxWindow *) m_menuBar->GetFrame();
e7549107
SC
314
315 return NULL;
316}
519cb848 317
58751a86 318// helper functions returning the mac menu position for a certain item, note that this is
519cb848
SC
319// mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
320
58751a86 321int wxMenu::MacGetIndexFromId( int id )
519cb848 322{
e7549107
SC
323 size_t pos;
324 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
325 for ( pos = 0; node; pos++ )
519cb848 326 {
e7549107
SC
327 if ( node->GetData()->GetId() == id )
328 break;
519cb848 329
e7549107
SC
330 node = node->GetNext();
331 }
58751a86 332
519cb848 333 if (!node)
e40298d5 334 return 0;
58751a86 335
e40298d5 336 return pos + 1 ;
519cb848
SC
337}
338
58751a86 339int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
519cb848 340{
e7549107
SC
341 size_t pos;
342 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
343 for ( pos = 0; node; pos++ )
519cb848 344 {
e7549107
SC
345 if ( node->GetData() == pItem )
346 break;
347
348 node = node->GetNext();
519cb848
SC
349 }
350
351 if (!node)
e40298d5 352 return 0;
58751a86 353
e40298d5 354 return pos + 1 ;
519cb848
SC
355}
356
58751a86 357void wxMenu::MacEnableMenu( bool bDoEnable )
519cb848 358{
e40298d5 359 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
58751a86 360
e40298d5 361 ::DrawMenuBar() ;
519cb848
SC
362}
363
d46342af
SC
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
58751a86 367void wxMenu::MacBeforeDisplay( bool isSubMenu )
d46342af
SC
368{
369 wxMenuItem* previousItem = NULL ;
5be55d56 370 size_t pos ;
d46342af
SC
371 wxMenuItemList::Node *node;
372 wxMenuItem *item;
58751a86 373 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
d46342af
SC
374 {
375 item = (wxMenuItem *)node->GetData();
376 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 377 if (subMenu)
d46342af
SC
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 );
5be55d56
VZ
389 if ( GetMenuItems().GetCount() == pos + 1 &&
390 previousItem != NULL &&
391 previousItem->IsSeparator() )
d46342af
SC
392 {
393 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 );
394 }
395 }
396 }
58751a86 397 #endif
d46342af
SC
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
58751a86 407void wxMenu::MacAfterDisplay( bool isSubMenu )
d46342af
SC
408{
409 if ( isSubMenu )
410 ::DeleteMenu(MacGetMenuId());
411
412 wxMenuItem* previousItem = NULL ;
413 int pos ;
414 wxMenuItemList::Node *node;
415 wxMenuItem *item;
58751a86 416 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
d46342af
SC
417 {
418 item = (wxMenuItem *)node->GetData();
419 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 420 if (subMenu)
d46342af
SC
421 {
422 subMenu->MacAfterDisplay( true ) ;
423 }
424 else
425 {
426 // no need to undo hidings
427 }
428 previousItem = item ;
429 }
430}
431
e9576ca5 432// Menu Bar
519cb848 433
58751a86 434/*
519cb848
SC
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
58751a86 442Secondly there is no mac api for changing a menubar that is not the current
519cb848
SC
443menubar, so we have to wait for preparing the actual menubar until the
444wxMenubar is to be used
445
58751a86 446We can in subsequent versions use MacInstallMenuBar to provide some sort of
519cb848
SC
447auto-merge for MDI in case this will be necessary
448
449*/
450
451wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
1b1d2207 452wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
519cb848 453
e7549107 454void wxMenuBar::Init()
e9576ca5
SC
455{
456 m_eventHandler = this;
e9576ca5 457 m_menuBarFrame = NULL;
7c15086c 458 m_invokingWindow = (wxWindow*) NULL;
e9576ca5
SC
459}
460
51abe921
SC
461wxMenuBar::wxMenuBar()
462{
463 Init();
464}
465
466wxMenuBar::wxMenuBar( long WXUNUSED(style) )
467{
468 Init();
469}
470
e7549107
SC
471
472wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
e9576ca5 473{
e7549107
SC
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 }
e9576ca5
SC
485}
486
487wxMenuBar::~wxMenuBar()
488{
1b1d2207
DE
489 if (s_macCommonMenuBar == this)
490 s_macCommonMenuBar = NULL;
e40298d5
JS
491 if (s_macInstalledMenuBar == this)
492 {
493 ::ClearMenuBar();
494 s_macInstalledMenuBar = NULL;
495 }
519cb848 496
e7549107
SC
497}
498
6d6da89c 499void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
e7549107
SC
500{
501 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
e9576ca5 502
e7549107 503 DrawMenuBar();
e9576ca5
SC
504}
505
58751a86 506void wxMenuBar::MacInstallMenuBar()
519cb848 507{
2b8a6962
GD
508 if ( s_macInstalledMenuBar == this )
509 return ;
58751a86 510
d9e054bc 511 wxStAppResource resload ;
58751a86 512
2b8a6962
GD
513 Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ;
514 wxString message ;
427ff662 515 wxCHECK_RET( menubar != NULL, wxT("can't read MBAR resource") );
2b8a6962 516 ::SetMenuBar( menubar ) ;
a3590de1
SC
517#if TARGET_API_MAC_CARBON
518 ::DisposeMenuBar( menubar ) ;
519#else
2b8a6962 520 ::DisposeHandle( menubar ) ;
a3590de1 521#endif
519cb848 522
a3590de1 523#if TARGET_API_MAC_OS8
2b8a6962 524 MenuHandle menu = ::GetMenuHandle( kwxMacAppleMenuId ) ;
d9e054bc
SC
525 if ( CountMenuItems( menu ) == 2 )
526 {
2b8a6962
GD
527 ::AppendResMenu(menu, 'DRVR');
528 }
a3590de1 529#endif
58751a86 530
7c15086c 531 // clean-up the help menu before adding new items
e40298d5
JS
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 }
7c15086c 544#if TARGET_CARBON
e40298d5
JS
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 }
7c15086c 553#endif
e40298d5
JS
554 for (size_t i = 0; i < m_menus.GetCount(); i++)
555 {
f823cacb 556 wxMenuItemList::Node *node;
2b5f62a0
VZ
557 wxMenuItem *item;
558 int pos ;
e40298d5
JS
559 wxMenu* menu = m_menus[i] , *subMenu = NULL ;
560
427ff662 561 if( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName )
e40298d5
JS
562 {
563 if ( mh == NULL )
564 {
565 continue ;
566 }
58751a86
RD
567
568 for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
e40298d5
JS
569 {
570 item = (wxMenuItem *)node->GetData();
571 subMenu = item->GetSubMenu() ;
58751a86 572 if (subMenu)
e40298d5
JS
573 {
574 // we don't support hierarchical menus in the help menu yet
575 }
58751a86 576 else
e40298d5
JS
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 )
58751a86 588 {
e40298d5
JS
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 }
58751a86 602
e40298d5
JS
603 delete entry ;
604 }
605 }
606 }
607 }
608 else
609 {
610 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i] ) ;
d46342af 611 m_menus[i]->MacBeforeDisplay(false) ;
e40298d5 612 ::InsertMenu(MAC_WXHMENU(m_menus[i]->GetHMenu()), 0);
e40298d5
JS
613 }
614 }
615 ::DrawMenuBar() ;
616 s_macInstalledMenuBar = this;
519cb848
SC
617}
618
e7549107 619void wxMenuBar::EnableTop(size_t pos, bool enable)
e9576ca5 620{
e7549107 621 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
e40298d5 622 m_menus[pos]->MacEnableMenu( enable ) ;
e7549107 623 Refresh();
e9576ca5
SC
624}
625
e7549107 626void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
e9576ca5 627{
e7549107 628 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 629
e7549107 630 m_titles[pos] = label;
e9576ca5 631
e7549107
SC
632 if ( !IsAttached() )
633 {
e9576ca5 634 return;
e7549107 635 }
e9576ca5 636
519cb848 637 m_menus[pos]->SetTitle( label ) ;
e40298d5
JS
638 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
639 {
640 ::SetMenuBar( GetMenuBar() ) ;
641 ::InvalMenuBar() ;
642 }
e9576ca5
SC
643}
644
e7549107 645wxString wxMenuBar::GetLabelTop(size_t pos) const
e9576ca5 646{
e7549107
SC
647 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
648 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
519cb848 649
e7549107 650 return m_titles[pos];
e9576ca5
SC
651}
652
e7549107 653int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 654{
e7549107 655 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 656
e7549107
SC
657 size_t count = GetMenuCount();
658 for ( size_t i = 0; i < count; i++ )
e9576ca5 659 {
e7549107
SC
660 wxString title = wxStripMenuCodes(m_titles[i]);
661 if ( menuTitle == title )
58751a86 662 return i;
e9576ca5 663 }
e9576ca5 664
e7549107 665 return wxNOT_FOUND;
e9576ca5 666
e9576ca5
SC
667}
668
e7549107
SC
669
670// ---------------------------------------------------------------------------
671// wxMenuBar construction
672// ---------------------------------------------------------------------------
673
674// ---------------------------------------------------------------------------
675// wxMenuBar construction
676// ---------------------------------------------------------------------------
677
678wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 679{
e7549107
SC
680 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
681 if ( !menuOld )
682 return FALSE;
683 m_titles[pos] = title;
e9576ca5 684
e7549107 685 if ( IsAttached() )
e9576ca5 686 {
e40298d5
JS
687 if (s_macInstalledMenuBar == this)
688 {
d46342af 689 menuOld->MacAfterDisplay( false ) ;
e40298d5
JS
690 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
691 {
d46342af 692 menu->MacBeforeDisplay( false ) ;
e40298d5
JS
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 }
e9576ca5 704
e7549107 705 Refresh();
e9576ca5 706 }
e9576ca5 707
e7549107 708 return menuOld;
e9576ca5
SC
709}
710
e7549107 711bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 712{
e7549107
SC
713 if ( !wxMenuBarBase::Insert(pos, menu, title) )
714 return FALSE;
e9576ca5 715
e7549107 716 m_titles.Insert(title, pos);
e9576ca5 717
e40298d5 718 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
e7549107 719
d46342af 720 if ( IsAttached() && s_macInstalledMenuBar == this )
e9576ca5 721 {
d46342af 722 if (s_macInstalledMenuBar == this)
e40298d5 723 {
d46342af
SC
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 }
e40298d5 733 }
e7549107 734 Refresh();
e9576ca5 735 }
e7549107
SC
736
737 return TRUE;
e9576ca5
SC
738}
739
51abe921
SC
740wxMenu *wxMenuBar::Remove(size_t pos)
741{
742 wxMenu *menu = wxMenuBarBase::Remove(pos);
743 if ( !menu )
744 return NULL;
745
746 if ( IsAttached() )
747 {
e40298d5
JS
748 if (s_macInstalledMenuBar == this)
749 {
750 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
751 }
51abe921
SC
752
753 menu->Detach();
754
51abe921
SC
755 Refresh();
756 }
757
5fe38474 758 m_titles.RemoveAt(pos);
51abe921
SC
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
51abe921 771 m_titles.Add(title);
58751a86 772
e40298d5 773 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
51abe921
SC
774
775 if ( IsAttached() )
776 {
e40298d5
JS
777 if (s_macInstalledMenuBar == this)
778 {
779 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
780 }
51abe921
SC
781
782 Refresh();
783 }
784
7c15086c
SC
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
51abe921
SC
790 return TRUE;
791}
792
2b5f62a0
VZ
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{
7c15086c 823 m_invokingWindow = (wxWindow*) NULL;
2b5f62a0
VZ
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{
7c15086c 835 m_invokingWindow = frame;
2b5f62a0
VZ
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
90b959ae 845void wxMenuBar::Detach()
2f1ae414 846{
90b959ae
SC
847 wxMenuBarBase::Detach() ;
848}
2f1ae414 849
90b959ae
SC
850void wxMenuBar::Attach(wxFrame *frame)
851{
852 wxMenuBarBase::Attach( frame ) ;
2f1ae414 853}
51abe921
SC
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