]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/menu.cpp
Fix docs for Bind
[wxWidgets.git] / src / mac / carbon / menu.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: menu.cpp
3// Purpose: wxMenu, wxMenuBar, wxMenuItem
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
e40298d5 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
eb22f2a6
GD
12#ifdef __GNUG__
13#pragma implementation "menu.h"
14#pragma implementation "menuitem.h"
15#endif
16
e9576ca5
SC
17// ============================================================================
18// headers & declarations
19// ============================================================================
20
21// wxWindows headers
22// -----------------
23
03e11df5 24#include "wx/app.h"
e9576ca5
SC
25#include "wx/menu.h"
26#include "wx/menuitem.h"
03e11df5 27#include "wx/window.h"
e9576ca5
SC
28#include "wx/log.h"
29#include "wx/utils.h"
2b5f62a0 30#include "wx/frame.h"
e9576ca5 31
519cb848
SC
32#include "wx/mac/uma.h"
33
e9576ca5
SC
34// other standard headers
35// ----------------------
36#include <string.h>
37
2f1ae414 38#if !USE_SHARED_LIBRARY
e9576ca5
SC
39IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
40IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
2f1ae414 41#endif
e9576ca5 42
519cb848
SC
43// the (popup) menu title has this special id
44static const int idMenuTitle = -2;
b03e4fcd 45static MenuItemIndex firstUserHelpMenuItem = 0 ;
519cb848
SC
46
47const short kwxMacMenuBarResource = 1 ;
48const short kwxMacAppleMenuId = 1 ;
49
e9576ca5
SC
50// ============================================================================
51// implementation
52// ============================================================================
7c15086c
SC
53static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;
54static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );
519cb848 55
e9576ca5
SC
56// Menus
57
58// Construct a menu with optional title (then use append)
519cb848 59
f5c6eb5c 60#ifdef __DARWIN__
82ca6dbc
GD
61short wxMenu::s_macNextMenuId = 3 ;
62#else
519cb848 63short wxMenu::s_macNextMenuId = 2 ;
82ca6dbc 64#endif
519cb848 65
e7549107 66void wxMenu::Init()
e9576ca5 67{
e7549107 68 m_doBreak = FALSE;
7c15086c 69 m_startRadioGroup = -1;
e7549107
SC
70
71 // create the menu
58751a86 72 m_macMenuId = s_macNextMenuId++;
a9412f8f 73 m_hMenu = UMANewMenu(m_macMenuId, m_title, wxFont::GetDefaultEncoding() );
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 126
4224f059 127 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
d46342af
SC
128 {
129 pSubMenu->MacBeforeDisplay( true ) ;
130 }
58751a86 131
e40298d5 132 if ( pos == (size_t)-1 )
a9412f8f 133 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), wxFont::GetDefaultEncoding() , pSubMenu->m_macMenuId);
e40298d5 134 else
a9412f8f 135 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), wxFont::GetDefaultEncoding() , pos, pSubMenu->m_macMenuId);
e40298d5
JS
136 pItem->UpdateItemBitmap() ;
137 pItem->UpdateItemStatus() ;
138 }
139 else
140 {
141 if ( pos == (size_t)-1 )
142 {
a9412f8f 143 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") , wxFont::GetDefaultEncoding() );
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
a9412f8f 151 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a"), wxFont::GetDefaultEncoding(), 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 {
4224f059 169 GetMenuBar()->Refresh();
e7549107 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
9add9367 180wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
e9576ca5 181{
9add9367 182 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
7c15086c
SC
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 {
9add9367 225 return NULL;
7c15086c
SC
226 }
227
228 if ( check )
229 {
230 // check the item initially
231 item->Check(TRUE);
232 }
233
9add9367 234 return item;
e9576ca5
SC
235}
236
9add9367 237wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
e9576ca5 238{
9add9367
RD
239 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
240 return item;
241 else
242 return NULL;
e9576ca5
SC
243}
244
e7549107 245wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
e9576ca5 246{
e7549107
SC
247 // we need to find the items position in the child list
248 size_t pos;
249 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
250 for ( pos = 0; node; pos++ )
251 {
252 if ( node->GetData() == item )
253 break;
e9576ca5 254
e7549107 255 node = node->GetNext();
e9576ca5
SC
256 }
257
e7549107
SC
258 // DoRemove() (unlike Remove) can only be called for existing item!
259 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
519cb848 260
e40298d5 261 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);
e9576ca5 262
e7549107
SC
263 if ( IsAttached() )
264 {
7c15086c 265 // otherwise, the change won't be visible
4224f059 266 GetMenuBar()->Refresh();
e7549107 267 }
e9576ca5 268
e7549107
SC
269 // and from internal data structures
270 return wxMenuBase::DoRemove(item);
e9576ca5
SC
271}
272
e9576ca5
SC
273void wxMenu::SetTitle(const wxString& label)
274{
e40298d5 275 m_title = label ;
a9412f8f 276 UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label , wxFont::GetDefaultEncoding() ) ;
e9576ca5 277}
e7549107 278bool wxMenu::ProcessCommand(wxCommandEvent & event)
e9576ca5
SC
279{
280 bool processed = FALSE;
281
e9576ca5
SC
282 // Try the menu's event handler
283 if ( !processed && GetEventHandler())
284 {
e7549107 285 processed = GetEventHandler()->ProcessEvent(event);
e9576ca5 286 }
519cb848 287
e7549107
SC
288 // Try the window the menu was popped up from (and up through the
289 // hierarchy)
290 wxWindow *win = GetInvokingWindow();
291 if ( !processed && win )
292 processed = win->GetEventHandler()->ProcessEvent(event);
293
294 return processed;
295}
296
297
298// ---------------------------------------------------------------------------
299// other
300// ---------------------------------------------------------------------------
301
e7549107
SC
302wxWindow *wxMenu::GetWindow() const
303{
304 if ( m_invokingWindow != NULL )
305 return m_invokingWindow;
4224f059
DE
306 else if ( GetMenuBar() != NULL)
307 return (wxWindow *) GetMenuBar()->GetFrame();
e7549107
SC
308
309 return NULL;
310}
519cb848 311
58751a86 312// helper functions returning the mac menu position for a certain item, note that this is
519cb848
SC
313// mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
314
58751a86 315int wxMenu::MacGetIndexFromId( int id )
519cb848 316{
e7549107
SC
317 size_t pos;
318 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
319 for ( pos = 0; node; pos++ )
519cb848 320 {
e7549107
SC
321 if ( node->GetData()->GetId() == id )
322 break;
519cb848 323
e7549107
SC
324 node = node->GetNext();
325 }
58751a86 326
519cb848 327 if (!node)
e40298d5 328 return 0;
58751a86 329
e40298d5 330 return pos + 1 ;
519cb848
SC
331}
332
58751a86 333int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
519cb848 334{
e7549107
SC
335 size_t pos;
336 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
337 for ( pos = 0; node; pos++ )
519cb848 338 {
e7549107
SC
339 if ( node->GetData() == pItem )
340 break;
341
342 node = node->GetNext();
519cb848
SC
343 }
344
345 if (!node)
e40298d5 346 return 0;
58751a86 347
e40298d5 348 return pos + 1 ;
519cb848
SC
349}
350
58751a86 351void wxMenu::MacEnableMenu( bool bDoEnable )
519cb848 352{
e40298d5 353 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
58751a86 354
e40298d5 355 ::DrawMenuBar() ;
519cb848
SC
356}
357
d46342af
SC
358// MacOS needs to know about submenus somewhere within this menu
359// before it can be displayed , also hide special menu items like preferences
360// that are handled by the OS
58751a86 361void wxMenu::MacBeforeDisplay( bool isSubMenu )
d46342af
SC
362{
363 wxMenuItem* previousItem = NULL ;
5be55d56 364 size_t pos ;
d46342af
SC
365 wxMenuItemList::Node *node;
366 wxMenuItem *item;
58751a86 367 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
d46342af
SC
368 {
369 item = (wxMenuItem *)node->GetData();
370 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 371 if (subMenu)
d46342af
SC
372 {
373 subMenu->MacBeforeDisplay( true ) ;
374 }
375 else
376 {
377 #if TARGET_CARBON
378 if ( UMAGetSystemVersion() >= 0x1000 )
379 {
380 if ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId)
381 {
382 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos + 1, kMenuItemAttrHidden, 0 );
5be55d56
VZ
383 if ( GetMenuItems().GetCount() == pos + 1 &&
384 previousItem != NULL &&
385 previousItem->IsSeparator() )
d46342af
SC
386 {
387 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 );
388 }
389 }
390 }
58751a86 391 #endif
d46342af
SC
392 }
393 previousItem = item ;
394 }
395
396 if ( isSubMenu )
397 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
398
399}
400// undo all changes from the MacBeforeDisplay call
58751a86 401void wxMenu::MacAfterDisplay( bool isSubMenu )
d46342af
SC
402{
403 if ( isSubMenu )
404 ::DeleteMenu(MacGetMenuId());
405
406 wxMenuItem* previousItem = NULL ;
407 int pos ;
408 wxMenuItemList::Node *node;
409 wxMenuItem *item;
58751a86 410 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
d46342af
SC
411 {
412 item = (wxMenuItem *)node->GetData();
413 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 414 if (subMenu)
d46342af
SC
415 {
416 subMenu->MacAfterDisplay( true ) ;
417 }
418 else
419 {
420 // no need to undo hidings
421 }
422 previousItem = item ;
423 }
424}
425
e9576ca5 426// Menu Bar
519cb848 427
58751a86 428/*
519cb848
SC
429
430Mac Implementation note :
431
432The Mac has only one global menubar, so we attempt to install the currently
433active menubar from a frame, we currently don't take into account mdi-frames
434which would ask for menu-merging
435
58751a86 436Secondly there is no mac api for changing a menubar that is not the current
519cb848
SC
437menubar, so we have to wait for preparing the actual menubar until the
438wxMenubar is to be used
439
58751a86 440We can in subsequent versions use MacInstallMenuBar to provide some sort of
519cb848
SC
441auto-merge for MDI in case this will be necessary
442
443*/
444
445wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
1b1d2207 446wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
519cb848 447
e7549107 448void wxMenuBar::Init()
e9576ca5
SC
449{
450 m_eventHandler = this;
e9576ca5 451 m_menuBarFrame = NULL;
7c15086c 452 m_invokingWindow = (wxWindow*) NULL;
e9576ca5
SC
453}
454
51abe921
SC
455wxMenuBar::wxMenuBar()
456{
457 Init();
458}
459
460wxMenuBar::wxMenuBar( long WXUNUSED(style) )
461{
462 Init();
463}
464
e7549107
SC
465
466wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
e9576ca5 467{
e7549107
SC
468 Init();
469
470 m_titles.Alloc(count);
471
472 for ( int i = 0; i < count; i++ )
473 {
474 m_menus.Append(menus[i]);
475 m_titles.Add(titles[i]);
476
477 menus[i]->Attach(this);
478 }
e9576ca5
SC
479}
480
481wxMenuBar::~wxMenuBar()
482{
1b1d2207
DE
483 if (s_macCommonMenuBar == this)
484 s_macCommonMenuBar = NULL;
e40298d5
JS
485 if (s_macInstalledMenuBar == this)
486 {
487 ::ClearMenuBar();
488 s_macInstalledMenuBar = NULL;
489 }
519cb848 490
e7549107
SC
491}
492
6d6da89c 493void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
e7549107
SC
494{
495 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
e9576ca5 496
e7549107 497 DrawMenuBar();
e9576ca5
SC
498}
499
58751a86 500void wxMenuBar::MacInstallMenuBar()
519cb848 501{
2b8a6962
GD
502 if ( s_macInstalledMenuBar == this )
503 return ;
58751a86 504
d9e054bc 505 wxStAppResource resload ;
58751a86 506
53d92341
SC
507 MenuBarHandle menubar = NULL ;
508#if TARGET_API_MAC_OSX
509 menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
510#else
511 menubar = NewHandleClear( 12 ) ;
512 (*menubar)[3] = 0x0a ;
513#endif
2b8a6962 514 ::SetMenuBar( menubar ) ;
dd05f811 515 DisposeMenuBar( menubar ) ;
cda73c27
SC
516 MenuHandle appleMenu = NULL ;
517 char appleMenuTitle[3] = { 01 , kMenuAppleLogoFilledGlyph , 0 } ;
518
519 verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
520 verify_noerr( SetMenuTitle( appleMenu , (ConstStr255Param) appleMenuTitle ) );
521 MacInsertMenuItem( appleMenu , "\pAbout..." , 0 ) ;
522 MacInsertMenu( appleMenu , 0 ) ;
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 {
a9412f8f 582 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetText() , wxFont::GetDefaultEncoding() );
e40298d5
JS
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 {
a9412f8f 591 UMAAppendMenuItem(mh, item->GetText() , wxFont::GetDefaultEncoding(), entry);
e40298d5
JS
592 SetMenuItemCommandID( mh , CountMenuItems(mh) , item->GetId() ) ;
593 }
594 }
58751a86 595
e40298d5
JS
596 delete entry ;
597 }
598 }
599 }
600 }
601 else
602 {
a9412f8f 603 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], m_font.GetEncoding() ) ;
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
c393c740
JS
619bool wxMenuBar::Enable( bool enable)
620{
5059f192 621 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
c393c740
JS
622 size_t i;
623 for (i = 0; i < GetMenuCount(); i++)
624 {
625 EnableTop(i, enable);
626 }
627 return true;
628}
629
e7549107 630void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
e9576ca5 631{
e7549107 632 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 633
e7549107 634 m_titles[pos] = label;
e9576ca5 635
e7549107
SC
636 if ( !IsAttached() )
637 {
e9576ca5 638 return;
e7549107 639 }
e9576ca5 640
519cb848 641 m_menus[pos]->SetTitle( label ) ;
e40298d5
JS
642 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
643 {
644 ::SetMenuBar( GetMenuBar() ) ;
645 ::InvalMenuBar() ;
646 }
e9576ca5
SC
647}
648
e7549107 649wxString wxMenuBar::GetLabelTop(size_t pos) const
e9576ca5 650{
e7549107
SC
651 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
652 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
519cb848 653
e7549107 654 return m_titles[pos];
e9576ca5
SC
655}
656
e7549107 657int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 658{
e7549107 659 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 660
e7549107
SC
661 size_t count = GetMenuCount();
662 for ( size_t i = 0; i < count; i++ )
e9576ca5 663 {
e7549107
SC
664 wxString title = wxStripMenuCodes(m_titles[i]);
665 if ( menuTitle == title )
58751a86 666 return i;
e9576ca5 667 }
e9576ca5 668
e7549107 669 return wxNOT_FOUND;
e9576ca5 670
e9576ca5
SC
671}
672
e7549107
SC
673
674// ---------------------------------------------------------------------------
675// wxMenuBar construction
676// ---------------------------------------------------------------------------
677
678// ---------------------------------------------------------------------------
679// wxMenuBar construction
680// ---------------------------------------------------------------------------
681
682wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 683{
e7549107
SC
684 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
685 if ( !menuOld )
686 return FALSE;
687 m_titles[pos] = title;
e9576ca5 688
e7549107 689 if ( IsAttached() )
e9576ca5 690 {
e40298d5
JS
691 if (s_macInstalledMenuBar == this)
692 {
d46342af 693 menuOld->MacAfterDisplay( false ) ;
e40298d5
JS
694 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
695 {
d46342af 696 menu->MacBeforeDisplay( false ) ;
a9412f8f 697 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
e40298d5
JS
698 if ( pos == m_menus.GetCount() - 1)
699 {
700 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
701 }
702 else
703 {
704 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
705 }
706 }
707 }
e9576ca5 708
e7549107 709 Refresh();
e9576ca5 710 }
e9576ca5 711
e7549107 712 return menuOld;
e9576ca5
SC
713}
714
e7549107 715bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 716{
e7549107
SC
717 if ( !wxMenuBarBase::Insert(pos, menu, title) )
718 return FALSE;
e9576ca5 719
e7549107 720 m_titles.Insert(title, pos);
e9576ca5 721
a9412f8f 722 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
e7549107 723
d46342af 724 if ( IsAttached() && s_macInstalledMenuBar == this )
e9576ca5 725 {
d46342af 726 if (s_macInstalledMenuBar == this)
e40298d5 727 {
d46342af
SC
728 menu->MacBeforeDisplay( false ) ;
729 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
730 {
731 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
732 }
733 else
734 {
735 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
736 }
e40298d5 737 }
e7549107 738 Refresh();
e9576ca5 739 }
e7549107
SC
740
741 return TRUE;
e9576ca5
SC
742}
743
51abe921
SC
744wxMenu *wxMenuBar::Remove(size_t pos)
745{
746 wxMenu *menu = wxMenuBarBase::Remove(pos);
747 if ( !menu )
748 return NULL;
749
750 if ( IsAttached() )
751 {
e40298d5
JS
752 if (s_macInstalledMenuBar == this)
753 {
754 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
755 }
51abe921 756
51abe921
SC
757 Refresh();
758 }
759
5fe38474 760 m_titles.RemoveAt(pos);
51abe921
SC
761
762 return menu;
763}
764
765bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
766{
767 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
768 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
769
770 if ( !wxMenuBarBase::Append(menu, title) )
771 return FALSE;
772
51abe921 773 m_titles.Add(title);
58751a86 774
a9412f8f 775 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
51abe921
SC
776
777 if ( IsAttached() )
778 {
e40298d5
JS
779 if (s_macInstalledMenuBar == this)
780 {
781 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
782 }
51abe921
SC
783
784 Refresh();
785 }
786
7c15086c
SC
787 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
788 // adding menu later on.
789 if (m_invokingWindow)
790 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
791
51abe921
SC
792 return TRUE;
793}
794
2b5f62a0
VZ
795static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
796{
797 menu->SetInvokingWindow( (wxWindow*) NULL );
798
799 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
800 while (node)
801 {
802 wxMenuItem *menuitem = node->GetData();
803 if (menuitem->IsSubMenu())
804 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
805 node = node->GetNext();
806 }
807}
808
809static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
810{
811 menu->SetInvokingWindow( win );
812
813 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
814 while (node)
815 {
816 wxMenuItem *menuitem = node->GetData();
817 if (menuitem->IsSubMenu())
818 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
819 node = node->GetNext();
820 }
821}
822
823void wxMenuBar::UnsetInvokingWindow()
824{
7c15086c 825 m_invokingWindow = (wxWindow*) NULL;
2b5f62a0
VZ
826 wxMenuList::Node *node = m_menus.GetFirst();
827 while (node)
828 {
829 wxMenu *menu = node->GetData();
830 wxMenubarUnsetInvokingWindow( menu );
831 node = node->GetNext();
832 }
833}
834
835void wxMenuBar::SetInvokingWindow(wxFrame *frame)
836{
7c15086c 837 m_invokingWindow = frame;
2b5f62a0
VZ
838 wxMenuList::Node *node = m_menus.GetFirst();
839 while (node)
840 {
841 wxMenu *menu = node->GetData();
842 wxMenubarSetInvokingWindow( menu, frame );
843 node = node->GetNext();
844 }
845}
846
90b959ae 847void wxMenuBar::Detach()
2f1ae414 848{
90b959ae
SC
849 wxMenuBarBase::Detach() ;
850}
2f1ae414 851
90b959ae
SC
852void wxMenuBar::Attach(wxFrame *frame)
853{
854 wxMenuBarBase::Attach( frame ) ;
2f1ae414 855}
51abe921
SC
856// ---------------------------------------------------------------------------
857// wxMenuBar searching for menu items
858// ---------------------------------------------------------------------------
859
860// Find the itemString in menuString, and return the item id or wxNOT_FOUND
861int wxMenuBar::FindMenuItem(const wxString& menuString,
862 const wxString& itemString) const
863{
864 wxString menuLabel = wxStripMenuCodes(menuString);
865 size_t count = GetMenuCount();
866 for ( size_t i = 0; i < count; i++ )
867 {
868 wxString title = wxStripMenuCodes(m_titles[i]);
ef089805 869 if ( menuLabel == title )
51abe921
SC
870 return m_menus[i]->FindItem(itemString);
871 }
872
873 return wxNOT_FOUND;
874}
875
876wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
877{
878 if ( itemMenu )
879 *itemMenu = NULL;
880
881 wxMenuItem *item = NULL;
882 size_t count = GetMenuCount();
883 for ( size_t i = 0; !item && (i < count); i++ )
884 {
885 item = m_menus[i]->FindItem(id, itemMenu);
886 }
887
888 return item;
889}
890
891