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