]> git.saurik.com Git - wxWidgets.git/blame - src/mac/menu.cpp
Added 'Go' button for quickly saving setup or configure file
[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 ;
452
e7549107 453void wxMenuBar::Init()
e9576ca5
SC
454{
455 m_eventHandler = this;
e9576ca5 456 m_menuBarFrame = NULL;
7c15086c 457 m_invokingWindow = (wxWindow*) NULL;
e9576ca5
SC
458}
459
51abe921
SC
460wxMenuBar::wxMenuBar()
461{
462 Init();
463}
464
465wxMenuBar::wxMenuBar( long WXUNUSED(style) )
466{
467 Init();
468}
469
e7549107
SC
470
471wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
e9576ca5 472{
e7549107
SC
473 Init();
474
475 m_titles.Alloc(count);
476
477 for ( int i = 0; i < count; i++ )
478 {
479 m_menus.Append(menus[i]);
480 m_titles.Add(titles[i]);
481
482 menus[i]->Attach(this);
483 }
e9576ca5
SC
484}
485
486wxMenuBar::~wxMenuBar()
487{
e40298d5
JS
488 if (s_macInstalledMenuBar == this)
489 {
490 ::ClearMenuBar();
491 s_macInstalledMenuBar = NULL;
492 }
519cb848 493
e7549107
SC
494}
495
6d6da89c 496void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
e7549107
SC
497{
498 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
e9576ca5 499
e7549107 500 DrawMenuBar();
e9576ca5
SC
501}
502
58751a86 503void wxMenuBar::MacInstallMenuBar()
519cb848 504{
2b8a6962
GD
505 if ( s_macInstalledMenuBar == this )
506 return ;
58751a86 507
d9e054bc 508 wxStAppResource resload ;
58751a86 509
2b8a6962
GD
510 Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ;
511 wxString message ;
427ff662 512 wxCHECK_RET( menubar != NULL, wxT("can't read MBAR resource") );
2b8a6962 513 ::SetMenuBar( menubar ) ;
a3590de1
SC
514#if TARGET_API_MAC_CARBON
515 ::DisposeMenuBar( menubar ) ;
516#else
2b8a6962 517 ::DisposeHandle( menubar ) ;
a3590de1 518#endif
519cb848 519
a3590de1 520#if TARGET_API_MAC_OS8
2b8a6962 521 MenuHandle menu = ::GetMenuHandle( kwxMacAppleMenuId ) ;
d9e054bc
SC
522 if ( CountMenuItems( menu ) == 2 )
523 {
2b8a6962
GD
524 ::AppendResMenu(menu, 'DRVR');
525 }
a3590de1 526#endif
58751a86 527
7c15086c 528 // clean-up the help menu before adding new items
e40298d5
JS
529 MenuHandle mh = NULL ;
530 if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) == noErr )
531 {
532 for ( int i = CountMenuItems( mh ) ; i >= firstUserHelpMenuItem ; --i )
533 {
534 DeleteMenuItem( mh , i ) ;
535 }
536 }
537 else
538 {
539 mh = NULL ;
540 }
7c15086c 541#if TARGET_CARBON
e40298d5
JS
542 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId)
543 {
544 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
545 if ( item == NULL || !(item->IsEnabled()) )
546 DisableMenuCommand( NULL , kHICommandPreferences ) ;
547 else
548 EnableMenuCommand( NULL , kHICommandPreferences ) ;
549 }
7c15086c 550#endif
e40298d5
JS
551 for (size_t i = 0; i < m_menus.GetCount(); i++)
552 {
f823cacb 553 wxMenuItemList::Node *node;
2b5f62a0
VZ
554 wxMenuItem *item;
555 int pos ;
e40298d5
JS
556 wxMenu* menu = m_menus[i] , *subMenu = NULL ;
557
427ff662 558 if( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName )
e40298d5
JS
559 {
560 if ( mh == NULL )
561 {
562 continue ;
563 }
58751a86
RD
564
565 for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
e40298d5
JS
566 {
567 item = (wxMenuItem *)node->GetData();
568 subMenu = item->GetSubMenu() ;
58751a86 569 if (subMenu)
e40298d5
JS
570 {
571 // we don't support hierarchical menus in the help menu yet
572 }
58751a86 573 else
e40298d5
JS
574 {
575 if ( item->IsSeparator() )
576 {
577 if ( mh )
578 MacAppendMenu(mh, "\p-" );
579 }
580 else
581 {
582 wxAcceleratorEntry* entry = wxGetAccelFromString( item->GetText() ) ;
583
584 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
58751a86 585 {
e40298d5
JS
586 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetText() );
587 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
588 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetId() ) ;
589 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
590 }
591 else
592 {
593 if ( mh )
594 {
595 UMAAppendMenuItem(mh, item->GetText() , entry );
596 SetMenuItemCommandID( mh , CountMenuItems(mh) , item->GetId() ) ;
597 }
598 }
58751a86 599
e40298d5
JS
600 delete entry ;
601 }
602 }
603 }
604 }
605 else
606 {
607 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i] ) ;
d46342af 608 m_menus[i]->MacBeforeDisplay(false) ;
e40298d5 609 ::InsertMenu(MAC_WXHMENU(m_menus[i]->GetHMenu()), 0);
e40298d5
JS
610 }
611 }
612 ::DrawMenuBar() ;
613 s_macInstalledMenuBar = this;
519cb848
SC
614}
615
e7549107 616void wxMenuBar::EnableTop(size_t pos, bool enable)
e9576ca5 617{
e7549107 618 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
e40298d5 619 m_menus[pos]->MacEnableMenu( enable ) ;
e7549107 620 Refresh();
e9576ca5
SC
621}
622
e7549107 623void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
e9576ca5 624{
e7549107 625 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 626
e7549107 627 m_titles[pos] = label;
e9576ca5 628
e7549107
SC
629 if ( !IsAttached() )
630 {
e9576ca5 631 return;
e7549107 632 }
e9576ca5 633
519cb848 634 m_menus[pos]->SetTitle( label ) ;
e40298d5
JS
635 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
636 {
637 ::SetMenuBar( GetMenuBar() ) ;
638 ::InvalMenuBar() ;
639 }
e9576ca5
SC
640}
641
e7549107 642wxString wxMenuBar::GetLabelTop(size_t pos) const
e9576ca5 643{
e7549107
SC
644 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
645 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
519cb848 646
e7549107 647 return m_titles[pos];
e9576ca5
SC
648}
649
e7549107 650int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 651{
e7549107 652 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 653
e7549107
SC
654 size_t count = GetMenuCount();
655 for ( size_t i = 0; i < count; i++ )
e9576ca5 656 {
e7549107
SC
657 wxString title = wxStripMenuCodes(m_titles[i]);
658 if ( menuTitle == title )
58751a86 659 return i;
e9576ca5 660 }
e9576ca5 661
e7549107 662 return wxNOT_FOUND;
e9576ca5 663
e9576ca5
SC
664}
665
e7549107
SC
666
667// ---------------------------------------------------------------------------
668// wxMenuBar construction
669// ---------------------------------------------------------------------------
670
671// ---------------------------------------------------------------------------
672// wxMenuBar construction
673// ---------------------------------------------------------------------------
674
675wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 676{
e7549107
SC
677 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
678 if ( !menuOld )
679 return FALSE;
680 m_titles[pos] = title;
e9576ca5 681
e7549107 682 if ( IsAttached() )
e9576ca5 683 {
e40298d5
JS
684 if (s_macInstalledMenuBar == this)
685 {
d46342af 686 menuOld->MacAfterDisplay( false ) ;
e40298d5
JS
687 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
688 {
d46342af 689 menu->MacBeforeDisplay( false ) ;
e40298d5
JS
690 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
691 if ( pos == m_menus.GetCount() - 1)
692 {
693 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
694 }
695 else
696 {
697 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
698 }
699 }
700 }
e9576ca5 701
e7549107 702 Refresh();
e9576ca5 703 }
e9576ca5 704
e7549107 705 return menuOld;
e9576ca5
SC
706}
707
e7549107 708bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 709{
e7549107
SC
710 if ( !wxMenuBarBase::Insert(pos, menu, title) )
711 return FALSE;
e9576ca5 712
e7549107 713 m_titles.Insert(title, pos);
e9576ca5 714
e40298d5 715 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
e7549107 716
d46342af 717 if ( IsAttached() && s_macInstalledMenuBar == this )
e9576ca5 718 {
d46342af 719 if (s_macInstalledMenuBar == this)
e40298d5 720 {
d46342af
SC
721 menu->MacBeforeDisplay( false ) ;
722 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
723 {
724 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
725 }
726 else
727 {
728 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
729 }
e40298d5 730 }
e7549107 731 Refresh();
e9576ca5 732 }
e7549107
SC
733
734 return TRUE;
e9576ca5
SC
735}
736
51abe921
SC
737wxMenu *wxMenuBar::Remove(size_t pos)
738{
739 wxMenu *menu = wxMenuBarBase::Remove(pos);
740 if ( !menu )
741 return NULL;
742
743 if ( IsAttached() )
744 {
e40298d5
JS
745 if (s_macInstalledMenuBar == this)
746 {
747 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
748 }
51abe921
SC
749
750 menu->Detach();
751
51abe921
SC
752 Refresh();
753 }
754
755 m_titles.Remove(pos);
756
757 return menu;
758}
759
760bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
761{
762 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
763 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
764
765 if ( !wxMenuBarBase::Append(menu, title) )
766 return FALSE;
767
51abe921 768 m_titles.Add(title);
58751a86 769
e40298d5 770 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
51abe921
SC
771
772 if ( IsAttached() )
773 {
e40298d5
JS
774 if (s_macInstalledMenuBar == this)
775 {
776 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
777 }
51abe921
SC
778
779 Refresh();
780 }
781
7c15086c
SC
782 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
783 // adding menu later on.
784 if (m_invokingWindow)
785 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
786
51abe921
SC
787 return TRUE;
788}
789
2b5f62a0
VZ
790static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
791{
792 menu->SetInvokingWindow( (wxWindow*) NULL );
793
794 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
795 while (node)
796 {
797 wxMenuItem *menuitem = node->GetData();
798 if (menuitem->IsSubMenu())
799 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
800 node = node->GetNext();
801 }
802}
803
804static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
805{
806 menu->SetInvokingWindow( win );
807
808 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
809 while (node)
810 {
811 wxMenuItem *menuitem = node->GetData();
812 if (menuitem->IsSubMenu())
813 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
814 node = node->GetNext();
815 }
816}
817
818void wxMenuBar::UnsetInvokingWindow()
819{
7c15086c 820 m_invokingWindow = (wxWindow*) NULL;
2b5f62a0
VZ
821 wxMenuList::Node *node = m_menus.GetFirst();
822 while (node)
823 {
824 wxMenu *menu = node->GetData();
825 wxMenubarUnsetInvokingWindow( menu );
826 node = node->GetNext();
827 }
828}
829
830void wxMenuBar::SetInvokingWindow(wxFrame *frame)
831{
7c15086c 832 m_invokingWindow = frame;
2b5f62a0
VZ
833 wxMenuList::Node *node = m_menus.GetFirst();
834 while (node)
835 {
836 wxMenu *menu = node->GetData();
837 wxMenubarSetInvokingWindow( menu, frame );
838 node = node->GetNext();
839 }
840}
841
90b959ae 842void wxMenuBar::Detach()
2f1ae414 843{
90b959ae
SC
844 wxMenuBarBase::Detach() ;
845}
2f1ae414 846
90b959ae
SC
847void wxMenuBar::Attach(wxFrame *frame)
848{
849 wxMenuBarBase::Attach( frame ) ;
2f1ae414 850}
51abe921
SC
851// ---------------------------------------------------------------------------
852// wxMenuBar searching for menu items
853// ---------------------------------------------------------------------------
854
855// Find the itemString in menuString, and return the item id or wxNOT_FOUND
856int wxMenuBar::FindMenuItem(const wxString& menuString,
857 const wxString& itemString) const
858{
859 wxString menuLabel = wxStripMenuCodes(menuString);
860 size_t count = GetMenuCount();
861 for ( size_t i = 0; i < count; i++ )
862 {
863 wxString title = wxStripMenuCodes(m_titles[i]);
864 if ( menuString == title )
865 return m_menus[i]->FindItem(itemString);
866 }
867
868 return wxNOT_FOUND;
869}
870
871wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
872{
873 if ( itemMenu )
874 *itemMenu = NULL;
875
876 wxMenuItem *item = NULL;
877 size_t count = GetMenuCount();
878 for ( size_t i = 0; !item && (i < count); i++ )
879 {
880 item = m_menus[i]->FindItem(id, itemMenu);
881 }
882
883 return item;
884}
885
886