]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/menu.cpp
don't include headers not needed when wxUSE_GUI == 0
[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
65571936 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
77ffb593 21// wxWidgets headers
e9576ca5
SC
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 43// the (popup) menu title has this special id
de5914a1 44static const int idMenuTitle = -3;
b03e4fcd 45static MenuItemIndex firstUserHelpMenuItem = 0 ;
519cb848
SC
46
47const short kwxMacMenuBarResource = 1 ;
48const short kwxMacAppleMenuId = 1 ;
49
de5914a1
SC
50
51// Find an item given the Macintosh Menu Reference
52
53wxList wxWinMacMenuList(wxKEY_INTEGER);
54wxMenu *wxFindMenuFromMacMenu(MenuRef inMenuRef)
55{
56 wxNode *node = wxWinMacMenuList.Find((long)inMenuRef);
57 if (!node)
58 return NULL;
59 return (wxMenu *)node->GetData();
60}
61
62void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu) ;
63void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu)
64{
65 // adding NULL MenuRef is (first) surely a result of an error and
66 // (secondly) breaks menu command processing
67 wxCHECK_RET( inMenuRef != (MenuRef) NULL, wxT("attempt to add a NULL MenuRef to menu list") );
68
69 if ( !wxWinMacMenuList.Find((long)inMenuRef) )
70 wxWinMacMenuList.Append((long)inMenuRef, menu);
71}
72
73void wxRemoveMacMenuAssociation(wxMenu *menu) ;
74void wxRemoveMacMenuAssociation(wxMenu *menu)
75{
76 wxWinMacMenuList.DeleteObject(menu);
77}
78
79
e9576ca5
SC
80// ============================================================================
81// implementation
82// ============================================================================
7c15086c
SC
83static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;
84static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );
519cb848 85
e9576ca5
SC
86// Menus
87
88// Construct a menu with optional title (then use append)
519cb848 89
f5c6eb5c 90#ifdef __DARWIN__
82ca6dbc
GD
91short wxMenu::s_macNextMenuId = 3 ;
92#else
519cb848 93short wxMenu::s_macNextMenuId = 2 ;
82ca6dbc 94#endif
519cb848 95
e7549107 96void wxMenu::Init()
e9576ca5 97{
e7549107 98 m_doBreak = FALSE;
7c15086c 99 m_startRadioGroup = -1;
e7549107
SC
100
101 // create the menu
58751a86 102 m_macMenuId = s_macNextMenuId++;
a9412f8f 103 m_hMenu = UMANewMenu(m_macMenuId, m_title, wxFont::GetDefaultEncoding() );
e7549107
SC
104
105 if ( !m_hMenu )
106 {
22026088 107 wxLogLastError(wxT("UMANewMenu failed"));
e7549107
SC
108 }
109
de5914a1
SC
110 wxAssociateMenuWithMacMenu( (MenuRef)m_hMenu , this ) ;
111
e7549107
SC
112 // if we have a title, insert it in the beginning of the menu
113 if ( !!m_title )
e9576ca5 114 {
519cb848 115 Append(idMenuTitle, m_title) ;
e9576ca5
SC
116 AppendSeparator() ;
117 }
e7549107 118}
e9576ca5 119
e7549107
SC
120wxMenu::~wxMenu()
121{
de5914a1 122 wxRemoveMacMenuAssociation( this ) ;
e40298d5
JS
123 if (MAC_WXHMENU(m_hMenu))
124 ::DisposeMenu(MAC_WXHMENU(m_hMenu));
e9576ca5
SC
125}
126
e7549107 127void wxMenu::Break()
e9576ca5 128{
e40298d5 129 // not available on the mac platform
e7549107 130}
e9576ca5 131
7c15086c 132void wxMenu::Attach(wxMenuBarBase *menubar)
e7549107 133{
7c15086c 134 wxMenuBase::Attach(menubar);
e7549107 135
7c15086c 136 EndRadioGroup();
e9576ca5
SC
137}
138
e9576ca5 139// function appends a new item or submenu to the menu
e7549107
SC
140// append a new item or submenu to the menu
141bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
e9576ca5 142{
427ff662 143 wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );
e9576ca5 144
e40298d5
JS
145 if ( pItem->IsSeparator() )
146 {
147 if ( pos == (size_t)-1 )
148 MacAppendMenu(MAC_WXHMENU(m_hMenu), "\p-");
149 else
150 MacInsertMenuItem(MAC_WXHMENU(m_hMenu), "\p-" , pos);
151 }
58751a86 152 else
e40298d5
JS
153 {
154 wxMenu *pSubMenu = pItem->GetSubMenu() ;
155 if ( pSubMenu != NULL )
156 {
427ff662 157 wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added"));
e40298d5 158 pSubMenu->m_menuParent = this ;
58751a86 159
4224f059 160 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
d46342af
SC
161 {
162 pSubMenu->MacBeforeDisplay( true ) ;
163 }
58751a86 164
e40298d5 165 if ( pos == (size_t)-1 )
a9412f8f 166 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), wxFont::GetDefaultEncoding() , pSubMenu->m_macMenuId);
e40298d5 167 else
a9412f8f 168 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), wxFont::GetDefaultEncoding() , pos, pSubMenu->m_macMenuId);
e40298d5
JS
169 pItem->UpdateItemBitmap() ;
170 pItem->UpdateItemStatus() ;
171 }
172 else
173 {
174 if ( pos == (size_t)-1 )
175 {
a9412f8f 176 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") , wxFont::GetDefaultEncoding() );
e40298d5
JS
177 pos = CountMenuItems(MAC_WXHMENU(m_hMenu)) ;
178 }
179 else
180 {
4ab107d7
SC
181 // MacOS counts menu items from 1 and inserts after, therefore having the
182 // same effect as wx 0 based and inserting before, we must correct pos
183 // after however for updates to be correct
a9412f8f 184 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a"), wxFont::GetDefaultEncoding(), pos);
4ab107d7 185 pos += 1 ;
e40298d5
JS
186 }
187
4ab107d7 188 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , pItem->GetId() ) ;
de5914a1 189 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu) , pos , (UInt32) pItem ) ;
e40298d5
JS
190 pItem->UpdateItemText() ;
191 pItem->UpdateItemBitmap() ;
192 pItem->UpdateItemStatus() ;
193
58751a86 194 if ( pItem->GetId() == idMenuTitle )
e40298d5
JS
195 {
196 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ;
197 }
198 }
199 }
e7549107
SC
200 // if we're already attached to the menubar, we must update it
201 if ( IsAttached() )
202 {
4224f059 203 GetMenuBar()->Refresh();
e7549107 204 }
e40298d5 205 return TRUE ;
e9576ca5
SC
206}
207
7c15086c
SC
208void wxMenu::EndRadioGroup()
209{
210 // we're not inside a radio group any longer
211 m_startRadioGroup = -1;
212}
213
9add9367 214wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
e9576ca5 215{
9add9367 216 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
7c15086c
SC
217
218 bool check = FALSE;
219
220 if ( item->GetKind() == wxITEM_RADIO )
221 {
222 int count = GetMenuItemCount();
223
224 if ( m_startRadioGroup == -1 )
225 {
226 // start a new radio group
227 m_startRadioGroup = count;
228
229 // for now it has just one element
230 item->SetAsRadioGroupStart();
231 item->SetRadioGroupEnd(m_startRadioGroup);
232
233 // ensure that we have a checked item in the radio group
234 check = TRUE;
235 }
236 else // extend the current radio group
237 {
238 // we need to update its end item
239 item->SetRadioGroupStart(m_startRadioGroup);
240 wxMenuItemList::Node *node = GetMenuItems().Item(m_startRadioGroup);
241
242 if ( node )
243 {
244 node->GetData()->SetRadioGroupEnd(count);
245 }
246 else
247 {
248 wxFAIL_MSG( _T("where is the radio group start item?") );
249 }
250 }
251 }
252 else // not a radio item
253 {
254 EndRadioGroup();
255 }
256
257 if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
258 {
9add9367 259 return NULL;
7c15086c
SC
260 }
261
262 if ( check )
263 {
264 // check the item initially
265 item->Check(TRUE);
266 }
267
9add9367 268 return item;
e9576ca5
SC
269}
270
9add9367 271wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
e9576ca5 272{
9add9367
RD
273 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
274 return item;
275 else
276 return NULL;
e9576ca5
SC
277}
278
e7549107 279wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
e9576ca5 280{
e7549107
SC
281 // we need to find the items position in the child list
282 size_t pos;
283 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
284 for ( pos = 0; node; pos++ )
285 {
286 if ( node->GetData() == item )
287 break;
e9576ca5 288
e7549107 289 node = node->GetNext();
e9576ca5
SC
290 }
291
e7549107
SC
292 // DoRemove() (unlike Remove) can only be called for existing item!
293 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
519cb848 294
e40298d5 295 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);
e9576ca5 296
e7549107
SC
297 if ( IsAttached() )
298 {
7c15086c 299 // otherwise, the change won't be visible
4224f059 300 GetMenuBar()->Refresh();
e7549107 301 }
e9576ca5 302
e7549107
SC
303 // and from internal data structures
304 return wxMenuBase::DoRemove(item);
e9576ca5
SC
305}
306
e9576ca5
SC
307void wxMenu::SetTitle(const wxString& label)
308{
e40298d5 309 m_title = label ;
a9412f8f 310 UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label , wxFont::GetDefaultEncoding() ) ;
e9576ca5 311}
e7549107 312bool wxMenu::ProcessCommand(wxCommandEvent & event)
e9576ca5
SC
313{
314 bool processed = FALSE;
315
e9576ca5
SC
316 // Try the menu's event handler
317 if ( !processed && GetEventHandler())
318 {
e7549107 319 processed = GetEventHandler()->ProcessEvent(event);
e9576ca5 320 }
519cb848 321
e7549107
SC
322 // Try the window the menu was popped up from (and up through the
323 // hierarchy)
324 wxWindow *win = GetInvokingWindow();
325 if ( !processed && win )
326 processed = win->GetEventHandler()->ProcessEvent(event);
327
328 return processed;
329}
330
331
332// ---------------------------------------------------------------------------
333// other
334// ---------------------------------------------------------------------------
335
e7549107
SC
336wxWindow *wxMenu::GetWindow() const
337{
338 if ( m_invokingWindow != NULL )
339 return m_invokingWindow;
4224f059
DE
340 else if ( GetMenuBar() != NULL)
341 return (wxWindow *) GetMenuBar()->GetFrame();
e7549107
SC
342
343 return NULL;
344}
519cb848 345
58751a86 346// helper functions returning the mac menu position for a certain item, note that this is
519cb848
SC
347// mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
348
58751a86 349int wxMenu::MacGetIndexFromId( int id )
519cb848 350{
e7549107
SC
351 size_t pos;
352 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
353 for ( pos = 0; node; pos++ )
519cb848 354 {
e7549107
SC
355 if ( node->GetData()->GetId() == id )
356 break;
519cb848 357
e7549107
SC
358 node = node->GetNext();
359 }
58751a86 360
519cb848 361 if (!node)
e40298d5 362 return 0;
58751a86 363
e40298d5 364 return pos + 1 ;
519cb848
SC
365}
366
58751a86 367int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
519cb848 368{
e7549107
SC
369 size_t pos;
370 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
371 for ( pos = 0; node; pos++ )
519cb848 372 {
e7549107
SC
373 if ( node->GetData() == pItem )
374 break;
375
376 node = node->GetNext();
519cb848
SC
377 }
378
379 if (!node)
e40298d5 380 return 0;
58751a86 381
e40298d5 382 return pos + 1 ;
519cb848
SC
383}
384
58751a86 385void wxMenu::MacEnableMenu( bool bDoEnable )
519cb848 386{
e40298d5 387 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
58751a86 388
e40298d5 389 ::DrawMenuBar() ;
519cb848
SC
390}
391
d46342af
SC
392// MacOS needs to know about submenus somewhere within this menu
393// before it can be displayed , also hide special menu items like preferences
394// that are handled by the OS
58751a86 395void wxMenu::MacBeforeDisplay( bool isSubMenu )
d46342af
SC
396{
397 wxMenuItem* previousItem = NULL ;
5be55d56 398 size_t pos ;
d46342af
SC
399 wxMenuItemList::Node *node;
400 wxMenuItem *item;
58751a86 401 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
d46342af
SC
402 {
403 item = (wxMenuItem *)node->GetData();
404 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 405 if (subMenu)
d46342af
SC
406 {
407 subMenu->MacBeforeDisplay( true ) ;
408 }
409 else
410 {
411 #if TARGET_CARBON
412 if ( UMAGetSystemVersion() >= 0x1000 )
413 {
414 if ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId)
415 {
416 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos + 1, kMenuItemAttrHidden, 0 );
5be55d56
VZ
417 if ( GetMenuItems().GetCount() == pos + 1 &&
418 previousItem != NULL &&
419 previousItem->IsSeparator() )
d46342af
SC
420 {
421 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 );
422 }
423 }
424 }
58751a86 425 #endif
d46342af
SC
426 }
427 previousItem = item ;
428 }
429
430 if ( isSubMenu )
431 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
432
433}
434// undo all changes from the MacBeforeDisplay call
58751a86 435void wxMenu::MacAfterDisplay( bool isSubMenu )
d46342af
SC
436{
437 if ( isSubMenu )
438 ::DeleteMenu(MacGetMenuId());
439
440 wxMenuItem* previousItem = NULL ;
441 int pos ;
442 wxMenuItemList::Node *node;
443 wxMenuItem *item;
58751a86 444 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
d46342af
SC
445 {
446 item = (wxMenuItem *)node->GetData();
447 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 448 if (subMenu)
d46342af
SC
449 {
450 subMenu->MacAfterDisplay( true ) ;
451 }
452 else
453 {
454 // no need to undo hidings
455 }
456 previousItem = item ;
457 }
458}
459
e9576ca5 460// Menu Bar
519cb848 461
58751a86 462/*
519cb848
SC
463
464Mac Implementation note :
465
466The Mac has only one global menubar, so we attempt to install the currently
467active menubar from a frame, we currently don't take into account mdi-frames
468which would ask for menu-merging
469
58751a86 470Secondly there is no mac api for changing a menubar that is not the current
519cb848
SC
471menubar, so we have to wait for preparing the actual menubar until the
472wxMenubar is to be used
473
58751a86 474We can in subsequent versions use MacInstallMenuBar to provide some sort of
519cb848
SC
475auto-merge for MDI in case this will be necessary
476
477*/
478
479wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
1b1d2207 480wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
519cb848 481
e7549107 482void wxMenuBar::Init()
e9576ca5
SC
483{
484 m_eventHandler = this;
e9576ca5 485 m_menuBarFrame = NULL;
7c15086c 486 m_invokingWindow = (wxWindow*) NULL;
e9576ca5
SC
487}
488
51abe921
SC
489wxMenuBar::wxMenuBar()
490{
491 Init();
492}
493
494wxMenuBar::wxMenuBar( long WXUNUSED(style) )
495{
496 Init();
497}
498
e7549107
SC
499
500wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
e9576ca5 501{
e7549107
SC
502 Init();
503
504 m_titles.Alloc(count);
505
506 for ( int i = 0; i < count; i++ )
507 {
508 m_menus.Append(menus[i]);
509 m_titles.Add(titles[i]);
510
511 menus[i]->Attach(this);
512 }
e9576ca5
SC
513}
514
515wxMenuBar::~wxMenuBar()
516{
1b1d2207
DE
517 if (s_macCommonMenuBar == this)
518 s_macCommonMenuBar = NULL;
e40298d5
JS
519 if (s_macInstalledMenuBar == this)
520 {
521 ::ClearMenuBar();
522 s_macInstalledMenuBar = NULL;
523 }
519cb848 524
e7549107
SC
525}
526
6d6da89c 527void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
e7549107
SC
528{
529 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
e9576ca5 530
e7549107 531 DrawMenuBar();
e9576ca5
SC
532}
533
58751a86 534void wxMenuBar::MacInstallMenuBar()
519cb848 535{
2b8a6962
GD
536 if ( s_macInstalledMenuBar == this )
537 return ;
58751a86 538
53d92341
SC
539 MenuBarHandle menubar = NULL ;
540#if TARGET_API_MAC_OSX
541 menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
542#else
543 menubar = NewHandleClear( 12 ) ;
544 (*menubar)[3] = 0x0a ;
545#endif
2b8a6962 546 ::SetMenuBar( menubar ) ;
dd05f811 547 DisposeMenuBar( menubar ) ;
cda73c27
SC
548 MenuHandle appleMenu = NULL ;
549 char appleMenuTitle[3] = { 01 , kMenuAppleLogoFilledGlyph , 0 } ;
550
551 verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
552 verify_noerr( SetMenuTitle( appleMenu , (ConstStr255Param) appleMenuTitle ) );
23c6ddc8 553
dcac1565
RN
554//RN: under 10.3 it is a standard to include a seperator between About and Preferences
555// 10.2 and less are inconsistant about this, but in the interest of being more
556// consistant with future OS's, we're choosing to include the seperator.
e957d41c 557 MacInsertMenuItem( appleMenu , "\p-" , 0 ) ;
cda73c27
SC
558 MacInsertMenuItem( appleMenu , "\pAbout..." , 0 ) ;
559 MacInsertMenu( appleMenu , 0 ) ;
560
7c15086c 561 // clean-up the help menu before adding new items
e40298d5
JS
562 MenuHandle mh = NULL ;
563 if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) == noErr )
564 {
565 for ( int i = CountMenuItems( mh ) ; i >= firstUserHelpMenuItem ; --i )
566 {
567 DeleteMenuItem( mh , i ) ;
568 }
569 }
570 else
571 {
572 mh = NULL ;
573 }
7c15086c 574#if TARGET_CARBON
e40298d5
JS
575 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId)
576 {
577 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
578 if ( item == NULL || !(item->IsEnabled()) )
579 DisableMenuCommand( NULL , kHICommandPreferences ) ;
580 else
581 EnableMenuCommand( NULL , kHICommandPreferences ) ;
582 }
7c15086c 583#endif
e40298d5
JS
584 for (size_t i = 0; i < m_menus.GetCount(); i++)
585 {
f823cacb 586 wxMenuItemList::Node *node;
2b5f62a0
VZ
587 wxMenuItem *item;
588 int pos ;
e40298d5
JS
589 wxMenu* menu = m_menus[i] , *subMenu = NULL ;
590
427ff662 591 if( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?") || m_titles[i] == wxApp::s_macHelpMenuTitleName )
e40298d5
JS
592 {
593 if ( mh == NULL )
594 {
595 continue ;
596 }
58751a86
RD
597
598 for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
e40298d5
JS
599 {
600 item = (wxMenuItem *)node->GetData();
601 subMenu = item->GetSubMenu() ;
58751a86 602 if (subMenu)
e40298d5
JS
603 {
604 // we don't support hierarchical menus in the help menu yet
605 }
58751a86 606 else
e40298d5
JS
607 {
608 if ( item->IsSeparator() )
609 {
610 if ( mh )
611 MacAppendMenu(mh, "\p-" );
612 }
613 else
614 {
615 wxAcceleratorEntry* entry = wxGetAccelFromString( item->GetText() ) ;
616
617 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
58751a86 618 {
a9412f8f 619 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetText() , wxFont::GetDefaultEncoding() );
e40298d5
JS
620 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
621 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetId() ) ;
de5914a1 622 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (UInt32)item ) ;
e40298d5
JS
623 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
624 }
625 else
626 {
627 if ( mh )
628 {
a9412f8f 629 UMAAppendMenuItem(mh, item->GetText() , wxFont::GetDefaultEncoding(), entry);
e40298d5 630 SetMenuItemCommandID( mh , CountMenuItems(mh) , item->GetId() ) ;
de5914a1 631 SetMenuItemRefCon( mh , CountMenuItems(mh) , (UInt32)item ) ;
e40298d5
JS
632 }
633 }
58751a86 634
e40298d5
JS
635 delete entry ;
636 }
637 }
638 }
639 }
640 else
641 {
a9412f8f 642 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], m_font.GetEncoding() ) ;
d46342af 643 m_menus[i]->MacBeforeDisplay(false) ;
e40298d5 644 ::InsertMenu(MAC_WXHMENU(m_menus[i]->GetHMenu()), 0);
e40298d5
JS
645 }
646 }
647 ::DrawMenuBar() ;
648 s_macInstalledMenuBar = this;
519cb848
SC
649}
650
e7549107 651void wxMenuBar::EnableTop(size_t pos, bool enable)
e9576ca5 652{
e7549107 653 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
e40298d5 654 m_menus[pos]->MacEnableMenu( enable ) ;
e7549107 655 Refresh();
e9576ca5
SC
656}
657
c393c740
JS
658bool wxMenuBar::Enable( bool enable)
659{
5059f192 660 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
c393c740
JS
661 size_t i;
662 for (i = 0; i < GetMenuCount(); i++)
663 {
664 EnableTop(i, enable);
665 }
666 return true;
667}
668
e7549107 669void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
e9576ca5 670{
e7549107 671 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 672
e7549107 673 m_titles[pos] = label;
e9576ca5 674
e7549107
SC
675 if ( !IsAttached() )
676 {
e9576ca5 677 return;
e7549107 678 }
e9576ca5 679
519cb848 680 m_menus[pos]->SetTitle( label ) ;
e40298d5
JS
681 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
682 {
683 ::SetMenuBar( GetMenuBar() ) ;
684 ::InvalMenuBar() ;
685 }
e9576ca5
SC
686}
687
e7549107 688wxString wxMenuBar::GetLabelTop(size_t pos) const
e9576ca5 689{
e7549107
SC
690 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
691 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
519cb848 692
e7549107 693 return m_titles[pos];
e9576ca5
SC
694}
695
e7549107 696int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 697{
e7549107 698 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 699
e7549107
SC
700 size_t count = GetMenuCount();
701 for ( size_t i = 0; i < count; i++ )
e9576ca5 702 {
e7549107
SC
703 wxString title = wxStripMenuCodes(m_titles[i]);
704 if ( menuTitle == title )
58751a86 705 return i;
e9576ca5 706 }
e9576ca5 707
e7549107 708 return wxNOT_FOUND;
e9576ca5 709
e9576ca5
SC
710}
711
e7549107
SC
712
713// ---------------------------------------------------------------------------
714// wxMenuBar construction
715// ---------------------------------------------------------------------------
716
717// ---------------------------------------------------------------------------
718// wxMenuBar construction
719// ---------------------------------------------------------------------------
720
721wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 722{
e7549107
SC
723 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
724 if ( !menuOld )
725 return FALSE;
726 m_titles[pos] = title;
e9576ca5 727
e7549107 728 if ( IsAttached() )
e9576ca5 729 {
e40298d5
JS
730 if (s_macInstalledMenuBar == this)
731 {
d46342af 732 menuOld->MacAfterDisplay( false ) ;
e40298d5
JS
733 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
734 {
d46342af 735 menu->MacBeforeDisplay( false ) ;
a9412f8f 736 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
e40298d5
JS
737 if ( pos == m_menus.GetCount() - 1)
738 {
739 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
740 }
741 else
742 {
743 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
744 }
745 }
746 }
e9576ca5 747
e7549107 748 Refresh();
e9576ca5 749 }
e9576ca5 750
e7549107 751 return menuOld;
e9576ca5
SC
752}
753
e7549107 754bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 755{
e7549107
SC
756 if ( !wxMenuBarBase::Insert(pos, menu, title) )
757 return FALSE;
e9576ca5 758
e7549107 759 m_titles.Insert(title, pos);
e9576ca5 760
a9412f8f 761 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
e7549107 762
d46342af 763 if ( IsAttached() && s_macInstalledMenuBar == this )
e9576ca5 764 {
d46342af 765 if (s_macInstalledMenuBar == this)
e40298d5 766 {
d46342af
SC
767 menu->MacBeforeDisplay( false ) ;
768 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
769 {
770 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
771 }
772 else
773 {
774 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
775 }
e40298d5 776 }
e7549107 777 Refresh();
e9576ca5 778 }
e7549107
SC
779
780 return TRUE;
e9576ca5
SC
781}
782
51abe921
SC
783wxMenu *wxMenuBar::Remove(size_t pos)
784{
785 wxMenu *menu = wxMenuBarBase::Remove(pos);
786 if ( !menu )
787 return NULL;
788
789 if ( IsAttached() )
790 {
e40298d5
JS
791 if (s_macInstalledMenuBar == this)
792 {
793 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
794 }
51abe921 795
51abe921
SC
796 Refresh();
797 }
798
5fe38474 799 m_titles.RemoveAt(pos);
51abe921
SC
800
801 return menu;
802}
803
804bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
805{
806 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
807 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
808
809 if ( !wxMenuBarBase::Append(menu, title) )
810 return FALSE;
811
51abe921 812 m_titles.Add(title);
58751a86 813
a9412f8f 814 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
51abe921
SC
815
816 if ( IsAttached() )
817 {
e40298d5
JS
818 if (s_macInstalledMenuBar == this)
819 {
820 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
821 }
51abe921
SC
822
823 Refresh();
824 }
825
7c15086c
SC
826 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
827 // adding menu later on.
828 if (m_invokingWindow)
829 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
830
51abe921
SC
831 return TRUE;
832}
833
2b5f62a0
VZ
834static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
835{
836 menu->SetInvokingWindow( (wxWindow*) NULL );
837
838 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
839 while (node)
840 {
841 wxMenuItem *menuitem = node->GetData();
842 if (menuitem->IsSubMenu())
843 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
844 node = node->GetNext();
845 }
846}
847
848static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
849{
850 menu->SetInvokingWindow( win );
851
852 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
853 while (node)
854 {
855 wxMenuItem *menuitem = node->GetData();
856 if (menuitem->IsSubMenu())
857 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
858 node = node->GetNext();
859 }
860}
861
862void wxMenuBar::UnsetInvokingWindow()
863{
7c15086c 864 m_invokingWindow = (wxWindow*) NULL;
2b5f62a0
VZ
865 wxMenuList::Node *node = m_menus.GetFirst();
866 while (node)
867 {
868 wxMenu *menu = node->GetData();
869 wxMenubarUnsetInvokingWindow( menu );
870 node = node->GetNext();
871 }
872}
873
874void wxMenuBar::SetInvokingWindow(wxFrame *frame)
875{
7c15086c 876 m_invokingWindow = frame;
2b5f62a0
VZ
877 wxMenuList::Node *node = m_menus.GetFirst();
878 while (node)
879 {
880 wxMenu *menu = node->GetData();
881 wxMenubarSetInvokingWindow( menu, frame );
882 node = node->GetNext();
883 }
884}
885
90b959ae 886void wxMenuBar::Detach()
2f1ae414 887{
90b959ae
SC
888 wxMenuBarBase::Detach() ;
889}
2f1ae414 890
90b959ae
SC
891void wxMenuBar::Attach(wxFrame *frame)
892{
893 wxMenuBarBase::Attach( frame ) ;
2f1ae414 894}
51abe921
SC
895// ---------------------------------------------------------------------------
896// wxMenuBar searching for menu items
897// ---------------------------------------------------------------------------
898
899// Find the itemString in menuString, and return the item id or wxNOT_FOUND
900int wxMenuBar::FindMenuItem(const wxString& menuString,
901 const wxString& itemString) const
902{
903 wxString menuLabel = wxStripMenuCodes(menuString);
904 size_t count = GetMenuCount();
905 for ( size_t i = 0; i < count; i++ )
906 {
907 wxString title = wxStripMenuCodes(m_titles[i]);
ef089805 908 if ( menuLabel == title )
51abe921
SC
909 return m_menus[i]->FindItem(itemString);
910 }
911
912 return wxNOT_FOUND;
913}
914
915wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
916{
917 if ( itemMenu )
918 *itemMenu = NULL;
919
920 wxMenuItem *item = NULL;
921 size_t count = GetMenuCount();
922 for ( size_t i = 0; !item && (i < count); i++ )
923 {
924 item = m_menus[i]->FindItem(id, itemMenu);
925 }
926
927 return item;
928}
929
930