]> git.saurik.com Git - wxWidgets.git/blame - src/mac/menu.cpp
implemented IsModified() and DiscardEdits()
[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 {
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
SC
743
744 menu->Detach();
745
51abe921
SC
746 Refresh();
747 }
748
5fe38474 749 m_titles.RemoveAt(pos);
51abe921
SC
750
751 return menu;
752}
753
754bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
755{
756 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
757 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
758
759 if ( !wxMenuBarBase::Append(menu, title) )
760 return FALSE;
761
51abe921 762 m_titles.Add(title);
58751a86 763
e40298d5 764 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
51abe921
SC
765
766 if ( IsAttached() )
767 {
e40298d5
JS
768 if (s_macInstalledMenuBar == this)
769 {
770 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
771 }
51abe921
SC
772
773 Refresh();
774 }
775
7c15086c
SC
776 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
777 // adding menu later on.
778 if (m_invokingWindow)
779 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
780
51abe921
SC
781 return TRUE;
782}
783
2b5f62a0
VZ
784static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
785{
786 menu->SetInvokingWindow( (wxWindow*) NULL );
787
788 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
789 while (node)
790 {
791 wxMenuItem *menuitem = node->GetData();
792 if (menuitem->IsSubMenu())
793 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
794 node = node->GetNext();
795 }
796}
797
798static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
799{
800 menu->SetInvokingWindow( win );
801
802 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
803 while (node)
804 {
805 wxMenuItem *menuitem = node->GetData();
806 if (menuitem->IsSubMenu())
807 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
808 node = node->GetNext();
809 }
810}
811
812void wxMenuBar::UnsetInvokingWindow()
813{
7c15086c 814 m_invokingWindow = (wxWindow*) NULL;
2b5f62a0
VZ
815 wxMenuList::Node *node = m_menus.GetFirst();
816 while (node)
817 {
818 wxMenu *menu = node->GetData();
819 wxMenubarUnsetInvokingWindow( menu );
820 node = node->GetNext();
821 }
822}
823
824void wxMenuBar::SetInvokingWindow(wxFrame *frame)
825{
7c15086c 826 m_invokingWindow = frame;
2b5f62a0
VZ
827 wxMenuList::Node *node = m_menus.GetFirst();
828 while (node)
829 {
830 wxMenu *menu = node->GetData();
831 wxMenubarSetInvokingWindow( menu, frame );
832 node = node->GetNext();
833 }
834}
835
90b959ae 836void wxMenuBar::Detach()
2f1ae414 837{
90b959ae
SC
838 wxMenuBarBase::Detach() ;
839}
2f1ae414 840
90b959ae
SC
841void wxMenuBar::Attach(wxFrame *frame)
842{
843 wxMenuBarBase::Attach( frame ) ;
2f1ae414 844}
51abe921
SC
845// ---------------------------------------------------------------------------
846// wxMenuBar searching for menu items
847// ---------------------------------------------------------------------------
848
849// Find the itemString in menuString, and return the item id or wxNOT_FOUND
850int wxMenuBar::FindMenuItem(const wxString& menuString,
851 const wxString& itemString) const
852{
853 wxString menuLabel = wxStripMenuCodes(menuString);
854 size_t count = GetMenuCount();
855 for ( size_t i = 0; i < count; i++ )
856 {
857 wxString title = wxStripMenuCodes(m_titles[i]);
858 if ( menuString == title )
859 return m_menus[i]->FindItem(itemString);
860 }
861
862 return wxNOT_FOUND;
863}
864
865wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
866{
867 if ( itemMenu )
868 *itemMenu = NULL;
869
870 wxMenuItem *item = NULL;
871 size_t count = GetMenuCount();
872 for ( size_t i = 0; !item && (i < count); i++ )
873 {
874 item = m_menus[i]->FindItem(id, itemMenu);
875 }
876
877 return item;
878}
879
880