]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/menu.cpp
Performance optimization
[wxWidgets.git] / src / mac / carbon / menu.cpp
CommitLineData
e9576ca5 1/////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/mac/carbon/menu.cpp
e9576ca5 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
e4db172a 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
e9576ca5
SC
12// ============================================================================
13// headers & declarations
14// ============================================================================
15
77ffb593 16// wxWidgets headers
e9576ca5
SC
17// -----------------
18
3d1a4878
SC
19#include "wx/wxprec.h"
20
e9576ca5 21#include "wx/menu.h"
e4db172a
WS
22
23#ifndef WX_PRECOMP
24 #include "wx/log.h"
670f9935 25 #include "wx/app.h"
de6185e2 26 #include "wx/utils.h"
76b49cf4 27 #include "wx/frame.h"
25466131 28 #include "wx/menuitem.h"
e4db172a
WS
29#endif
30
519cb848
SC
31#include "wx/mac/uma.h"
32
e9576ca5
SC
33// other standard headers
34// ----------------------
35#include <string.h>
36
e9576ca5
SC
37IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
38IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
e9576ca5 39
519cb848 40// the (popup) menu title has this special id
de5914a1 41static const int idMenuTitle = -3;
519cb848 42
716d0327 43static const short kwxMacAppleMenuId = 1 ;
519cb848 44
de5914a1
SC
45
46// Find an item given the Macintosh Menu Reference
47
71f2fb52
RN
48WX_DECLARE_HASH_MAP(MenuRef, wxMenu*, wxPointerHash, wxPointerEqual, MacMenuMap);
49
50static MacMenuMap wxWinMacMenuList;
51
52wxMenu *wxFindMenuFromMacMenu(MenuRef inMenuRef)
53{
54 MacMenuMap::iterator node = wxWinMacMenuList.find(inMenuRef);
55
56 return (node == wxWinMacMenuList.end()) ? NULL : node->second;
57}
58
59void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu) ;
60void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu)
61{
62 // adding NULL MenuRef is (first) surely a result of an error and
63 // (secondly) breaks menu command processing
64 wxCHECK_RET( inMenuRef != (MenuRef) NULL, wxT("attempt to add a NULL MenuRef to menu list") );
de5914a1 65
71f2fb52
RN
66 wxWinMacMenuList[inMenuRef] = menu;
67}
68
69void wxRemoveMacMenuAssociation(wxMenu *menu) ;
70void wxRemoveMacMenuAssociation(wxMenu *menu)
71{
72 // iterate over all the elements in the class
73 MacMenuMap::iterator it;
74 for ( it = wxWinMacMenuList.begin(); it != wxWinMacMenuList.end(); ++it )
75 {
76 if ( it->second == menu )
77 {
78 wxWinMacMenuList.erase(it);
79 break;
80 }
81 }
82}
de5914a1 83
e608ff58
KO
84void wxInsertMenuItemsInMenu(wxMenu* menu, MenuRef wm, MenuItemIndex insertAfter)
85{
86 wxMenuItemList::compatibility_iterator node;
87 wxMenuItem *item;
88 wxMenu *subMenu = NULL ;
89 bool newItems = false;
90
91 for (node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext())
92 {
93 item = (wxMenuItem *)node->GetData();
94 subMenu = item->GetSubMenu() ;
95 if (subMenu)
96 {
90f58090 97 wxInsertMenuItemsInMenu(subMenu, (MenuRef)subMenu->GetHMenu(), 0);
e608ff58
KO
98 }
99 if ( item->IsSeparator() )
100 {
101 if ( wm && newItems)
102 InsertMenuItemTextWithCFString( wm,
90f58090
VZ
103 CFSTR(""), insertAfter, kMenuItemAttrSeparator, 0);
104
e608ff58
KO
105 newItems = false;
106 }
107 else
108 {
109 wxAcceleratorEntry*
9a9c35d3 110 entry = wxAcceleratorEntry::Create( item->GetItemLabel() ) ;
e608ff58 111
90f58090
VZ
112 MenuItemIndex winListPos = (MenuItemIndex)-1;
113 OSStatus err = GetIndMenuItemWithCommandID(wm,
e608ff58 114 wxIdToMacCommand ( item->GetId() ), 1, NULL, &winListPos);
90f58090 115
e608ff58
KO
116 if ( wm && err == menuItemNotFoundErr )
117 {
118 // NB: the only way to determine whether or not we should add
119 // a separator is to know if we've added menu items to the menu
120 // before the separator.
121 newItems = true;
9a9c35d3 122 UMAInsertMenuItem(wm, wxStripMenuCodes(item->GetItemLabel()) , wxFont::GetDefaultEncoding(), insertAfter, entry);
e608ff58
KO
123 SetMenuItemCommandID( wm , insertAfter+1 , wxIdToMacCommand ( item->GetId() ) ) ;
124 SetMenuItemRefCon( wm , insertAfter+1 , (URefCon) item ) ;
125 }
126
127 delete entry ;
128 }
90f58090 129 }
e608ff58
KO
130}
131
e9576ca5
SC
132// ============================================================================
133// implementation
134// ============================================================================
7c15086c
SC
135static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;
136static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );
519cb848 137
e9576ca5
SC
138// Menus
139
140// Construct a menu with optional title (then use append)
519cb848 141
f5c6eb5c 142#ifdef __DARWIN__
82ca6dbc
GD
143short wxMenu::s_macNextMenuId = 3 ;
144#else
519cb848 145short wxMenu::s_macNextMenuId = 2 ;
82ca6dbc 146#endif
519cb848 147
71f2fb52
RN
148static
149wxMenu *
150_wxMenuAt(const wxMenuList &menuList, size_t pos)
151{
152 wxMenuList::compatibility_iterator menuIter = menuList.GetFirst();
902725ee 153
5977edb9
DS
154 while (pos-- > 0)
155 menuIter = menuIter->GetNext();
902725ee 156
71f2fb52
RN
157 return menuIter->GetData() ;
158}
159
e7549107 160void wxMenu::Init()
e9576ca5 161{
902725ee 162 m_doBreak = false;
7c15086c 163 m_startRadioGroup = -1;
e7549107
SC
164
165 // create the menu
58751a86 166 m_macMenuId = s_macNextMenuId++;
a9412f8f 167 m_hMenu = UMANewMenu(m_macMenuId, m_title, wxFont::GetDefaultEncoding() );
e7549107
SC
168
169 if ( !m_hMenu )
170 {
22026088 171 wxLogLastError(wxT("UMANewMenu failed"));
e7549107
SC
172 }
173
de5914a1
SC
174 wxAssociateMenuWithMacMenu( (MenuRef)m_hMenu , this ) ;
175
e7549107 176 // if we have a title, insert it in the beginning of the menu
902725ee 177 if ( !m_title.empty() )
e9576ca5 178 {
519cb848 179 Append(idMenuTitle, m_title) ;
e9576ca5
SC
180 AppendSeparator() ;
181 }
e7549107 182}
e9576ca5 183
e7549107
SC
184wxMenu::~wxMenu()
185{
de5914a1 186 wxRemoveMacMenuAssociation( this ) ;
e40298d5
JS
187 if (MAC_WXHMENU(m_hMenu))
188 ::DisposeMenu(MAC_WXHMENU(m_hMenu));
e9576ca5
SC
189}
190
e7549107 191void wxMenu::Break()
e9576ca5 192{
e40298d5 193 // not available on the mac platform
e7549107 194}
e9576ca5 195
7c15086c 196void wxMenu::Attach(wxMenuBarBase *menubar)
e7549107 197{
7c15086c 198 wxMenuBase::Attach(menubar);
e7549107 199
7c15086c 200 EndRadioGroup();
e9576ca5
SC
201}
202
e9576ca5 203// function appends a new item or submenu to the menu
e7549107
SC
204// append a new item or submenu to the menu
205bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
e9576ca5 206{
427ff662 207 wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );
e9576ca5 208
e40298d5
JS
209 if ( pItem->IsSeparator() )
210 {
211 if ( pos == (size_t)-1 )
4f74e0d1 212 AppendMenuItemTextWithCFString( MAC_WXHMENU(m_hMenu),
90f58090 213 CFSTR(""), kMenuItemAttrSeparator, 0,NULL);
e40298d5 214 else
4f74e0d1 215 InsertMenuItemTextWithCFString( MAC_WXHMENU(m_hMenu),
90f58090 216 CFSTR(""), pos, kMenuItemAttrSeparator, 0);
e40298d5 217 }
58751a86 218 else
e40298d5
JS
219 {
220 wxMenu *pSubMenu = pItem->GetSubMenu() ;
221 if ( pSubMenu != NULL )
222 {
5977edb9 223 wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added"));
e40298d5 224 pSubMenu->m_menuParent = this ;
58751a86 225
4224f059 226 if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
d46342af 227 pSubMenu->MacBeforeDisplay( true ) ;
58751a86 228
e40298d5 229 if ( pos == (size_t)-1 )
9a9c35d3 230 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), wxStripMenuCodes(pItem->GetItemLabel()), wxFont::GetDefaultEncoding(), pSubMenu->m_macMenuId);
e40298d5 231 else
9a9c35d3 232 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), wxStripMenuCodes(pItem->GetItemLabel()), wxFont::GetDefaultEncoding(), pos, pSubMenu->m_macMenuId);
5977edb9 233
e40298d5
JS
234 pItem->UpdateItemBitmap() ;
235 pItem->UpdateItemStatus() ;
236 }
237 else
238 {
239 if ( pos == (size_t)-1 )
240 {
a9412f8f 241 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") , wxFont::GetDefaultEncoding() );
e40298d5
JS
242 pos = CountMenuItems(MAC_WXHMENU(m_hMenu)) ;
243 }
244 else
245 {
4ab107d7
SC
246 // MacOS counts menu items from 1 and inserts after, therefore having the
247 // same effect as wx 0 based and inserting before, we must correct pos
248 // after however for updates to be correct
a9412f8f 249 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a"), wxFont::GetDefaultEncoding(), pos);
4ab107d7 250 pos += 1 ;
e40298d5 251 }
e4db172a 252
ca71e3ae 253 SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , wxIdToMacCommand ( pItem->GetId() ) ) ;
4f74e0d1 254 SetMenuItemRefCon( MAC_WXHMENU(m_hMenu) , pos , (URefCon) pItem ) ;
e40298d5
JS
255 pItem->UpdateItemText() ;
256 pItem->UpdateItemBitmap() ;
257 pItem->UpdateItemStatus() ;
258
5977edb9 259 if ( pItem->GetId() == idMenuTitle )
e40298d5 260 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ;
e40298d5
JS
261 }
262 }
5977edb9 263
e7549107 264 // if we're already attached to the menubar, we must update it
b6d4a1af 265 if ( IsAttached() && GetMenuBar()->IsAttached() )
4224f059 266 GetMenuBar()->Refresh();
5977edb9 267
902725ee 268 return true ;
e9576ca5
SC
269}
270
7c15086c
SC
271void wxMenu::EndRadioGroup()
272{
273 // we're not inside a radio group any longer
274 m_startRadioGroup = -1;
275}
276
9add9367 277wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
e9576ca5 278{
9add9367 279 wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
7c15086c 280
902725ee 281 bool check = false;
7c15086c
SC
282
283 if ( item->GetKind() == wxITEM_RADIO )
284 {
285 int count = GetMenuItemCount();
286
287 if ( m_startRadioGroup == -1 )
288 {
289 // start a new radio group
290 m_startRadioGroup = count;
291
292 // for now it has just one element
293 item->SetAsRadioGroupStart();
294 item->SetRadioGroupEnd(m_startRadioGroup);
295
296 // ensure that we have a checked item in the radio group
902725ee 297 check = true;
7c15086c
SC
298 }
299 else // extend the current radio group
300 {
301 // we need to update its end item
302 item->SetRadioGroupStart(m_startRadioGroup);
71f2fb52 303 wxMenuItemList::compatibility_iterator node = GetMenuItems().Item(m_startRadioGroup);
7c15086c
SC
304
305 if ( node )
306 {
307 node->GetData()->SetRadioGroupEnd(count);
308 }
309 else
310 {
311 wxFAIL_MSG( _T("where is the radio group start item?") );
312 }
313 }
314 }
315 else // not a radio item
316 {
317 EndRadioGroup();
318 }
319
320 if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
9add9367 321 return NULL;
7c15086c
SC
322
323 if ( check )
7c15086c 324 // check the item initially
902725ee 325 item->Check(true);
7c15086c 326
9add9367 327 return item;
e9576ca5
SC
328}
329
9add9367 330wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
e9576ca5 331{
9add9367
RD
332 if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
333 return item;
5977edb9
DS
334
335 return NULL;
e9576ca5
SC
336}
337
e7549107 338wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
e9576ca5 339{
e7549107
SC
340 // we need to find the items position in the child list
341 size_t pos;
71f2fb52 342 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
5977edb9 343
e7549107
SC
344 for ( pos = 0; node; pos++ )
345 {
346 if ( node->GetData() == item )
347 break;
e9576ca5 348
e7549107 349 node = node->GetNext();
e9576ca5
SC
350 }
351
e7549107
SC
352 // DoRemove() (unlike Remove) can only be called for existing item!
353 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
519cb848 354
e40298d5 355 ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);
e9576ca5 356
b6d4a1af 357 if ( IsAttached() && GetMenuBar()->IsAttached() )
7c15086c 358 // otherwise, the change won't be visible
4224f059 359 GetMenuBar()->Refresh();
e9576ca5 360
e7549107
SC
361 // and from internal data structures
362 return wxMenuBase::DoRemove(item);
e9576ca5
SC
363}
364
e9576ca5
SC
365void wxMenu::SetTitle(const wxString& label)
366{
902725ee 367 m_title = label ;
a9412f8f 368 UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label , wxFont::GetDefaultEncoding() ) ;
e9576ca5 369}
902725ee 370
e7549107 371bool wxMenu::ProcessCommand(wxCommandEvent & event)
e9576ca5 372{
902725ee 373 bool processed = false;
e9576ca5 374
e9576ca5 375 // Try the menu's event handler
902725ee 376 if ( /* !processed && */ GetEventHandler())
b4d9758e 377 processed = GetEventHandler()->SafelyProcessEvent(event);
519cb848 378
5977edb9
DS
379 // Try the window the menu was popped up from
380 // (and up through the hierarchy)
e7549107
SC
381 wxWindow *win = GetInvokingWindow();
382 if ( !processed && win )
937013e0 383 processed = win->HandleWindowEvent(event);
e7549107
SC
384
385 return processed;
386}
387
e7549107
SC
388// ---------------------------------------------------------------------------
389// other
390// ---------------------------------------------------------------------------
391
e7549107
SC
392wxWindow *wxMenu::GetWindow() const
393{
394 if ( m_invokingWindow != NULL )
395 return m_invokingWindow;
4224f059
DE
396 else if ( GetMenuBar() != NULL)
397 return (wxWindow *) GetMenuBar()->GetFrame();
e7549107
SC
398
399 return NULL;
400}
519cb848 401
58751a86 402// helper functions returning the mac menu position for a certain item, note that this is
519cb848
SC
403// mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
404
58751a86 405int wxMenu::MacGetIndexFromId( int id )
519cb848 406{
e7549107 407 size_t pos;
71f2fb52 408 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
e7549107 409 for ( pos = 0; node; pos++ )
519cb848 410 {
e7549107
SC
411 if ( node->GetData()->GetId() == id )
412 break;
519cb848 413
e7549107
SC
414 node = node->GetNext();
415 }
58751a86 416
519cb848 417 if (!node)
e40298d5 418 return 0;
58751a86 419
e40298d5 420 return pos + 1 ;
519cb848
SC
421}
422
58751a86 423int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
519cb848 424{
e7549107 425 size_t pos;
71f2fb52 426 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
e7549107 427 for ( pos = 0; node; pos++ )
519cb848 428 {
e7549107
SC
429 if ( node->GetData() == pItem )
430 break;
431
432 node = node->GetNext();
519cb848
SC
433 }
434
435 if (!node)
e40298d5 436 return 0;
58751a86 437
e40298d5 438 return pos + 1 ;
519cb848
SC
439}
440
58751a86 441void wxMenu::MacEnableMenu( bool bDoEnable )
519cb848 442{
e40298d5 443 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
58751a86 444
e40298d5 445 ::DrawMenuBar() ;
519cb848
SC
446}
447
d46342af 448// MacOS needs to know about submenus somewhere within this menu
5977edb9
DS
449// before it can be displayed, also hide special menu items
450// like preferences that are handled by the OS
58751a86 451void wxMenu::MacBeforeDisplay( bool isSubMenu )
d46342af
SC
452{
453 wxMenuItem* previousItem = NULL ;
5be55d56 454 size_t pos ;
71f2fb52 455 wxMenuItemList::compatibility_iterator node;
d46342af 456 wxMenuItem *item;
5977edb9 457
58751a86 458 for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
d46342af
SC
459 {
460 item = (wxMenuItem *)node->GetData();
461 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 462 if (subMenu)
d46342af
SC
463 {
464 subMenu->MacBeforeDisplay( true ) ;
465 }
fa4a6942 466 else // normal item
d46342af 467 {
6524e8f0
SC
468 // what we do here is to hide the special items which are
469 // shown in the application menu anyhow -- it doesn't make
470 // sense to show them in their normal place as well
471 if ( item->GetId() == wxApp::s_macAboutMenuItemId ||
6524e8f0 472 item->GetId() == wxApp::s_macPreferencesMenuItemId ||
03561a3c 473 item->GetId() == wxApp::s_macExitMenuItemId )
902725ee 474
d46342af 475 {
6524e8f0
SC
476 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
477 pos + 1, kMenuItemAttrHidden, 0 );
478
479 // also check for a separator which was used just to
480 // separate this item from the others, so don't leave
481 // separator at the menu start or end nor 2 consecutive
482 // separators
483 wxMenuItemList::compatibility_iterator nextNode = node->GetNext();
484 wxMenuItem *next = nextNode ? nextNode->GetData() : NULL;
485
486 size_t posSeptoHide;
487 if ( !previousItem && next && next->IsSeparator() )
d46342af 488 {
6524e8f0
SC
489 // next (i.e. second as we must be first) item is
490 // the separator to hide
491 wxASSERT_MSG( pos == 0, _T("should be the menu start") );
492 posSeptoHide = 2;
493 }
494 else if ( GetMenuItems().GetCount() == pos + 1 &&
495 previousItem != NULL &&
496 previousItem->IsSeparator() )
497 {
498 // prev item is a trailing separator we want to hide
499 posSeptoHide = pos;
500 }
501 else if ( previousItem && previousItem->IsSeparator() &&
502 next && next->IsSeparator() )
503 {
504 // two consecutive separators, this is one too many
505 posSeptoHide = pos;
506 }
507 else // no separators to hide
508 {
509 posSeptoHide = 0;
510 }
fa4a6942 511
6524e8f0
SC
512 if ( posSeptoHide )
513 {
514 // hide the separator as well
515 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
516 posSeptoHide,
517 kMenuItemAttrHidden,
518 0 );
d46342af
SC
519 }
520 }
d46342af 521 }
5977edb9 522
d46342af
SC
523 previousItem = item ;
524 }
525
526 if ( isSubMenu )
527 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
d46342af 528}
5977edb9 529
d46342af 530// undo all changes from the MacBeforeDisplay call
58751a86 531void wxMenu::MacAfterDisplay( bool isSubMenu )
d46342af
SC
532{
533 if ( isSubMenu )
534 ::DeleteMenu(MacGetMenuId());
535
71f2fb52 536 wxMenuItemList::compatibility_iterator node;
d46342af 537 wxMenuItem *item;
5977edb9 538
716d0327 539 for (node = GetMenuItems().GetFirst(); node; node = node->GetNext())
d46342af
SC
540 {
541 item = (wxMenuItem *)node->GetData();
542 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 543 if (subMenu)
d46342af
SC
544 {
545 subMenu->MacAfterDisplay( true ) ;
546 }
547 else
548 {
549 // no need to undo hidings
550 }
d46342af
SC
551 }
552}
553
6239ee05
SC
554wxInt32 wxMenu::MacHandleCommandProcess( wxMenuItem* item, int id, wxWindow* targetWindow )
555{
556 OSStatus result = eventNotHandledErr ;
557 if (item->IsCheckable())
558 item->Check( !item->IsChecked() ) ;
559
560 if ( SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) )
561 result = noErr ;
562 else
563 {
564 if ( targetWindow != NULL )
565 {
566 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED , id);
567 event.SetEventObject(targetWindow);
568 event.SetInt(item->IsCheckable() ? item->IsChecked() : -1);
569
937013e0 570 if ( targetWindow->HandleWindowEvent(event) )
6239ee05
SC
571 result = noErr ;
572 }
573 }
574 return result;
575}
576
31c1cbc7
VZ
577wxInt32 wxMenu::MacHandleCommandUpdateStatus(wxMenuItem* WXUNUSED(item),
578 int id,
579 wxWindow* targetWindow)
6239ee05
SC
580{
581 OSStatus result = eventNotHandledErr ;
582 wxUpdateUIEvent event(id);
583 event.SetEventObject( this );
584
585 bool processed = false;
586
587 // Try the menu's event handler
588 {
589 wxEvtHandler *handler = GetEventHandler();
590 if ( handler )
591 processed = handler->ProcessEvent(event);
592 }
593
594 // Try the window the menu was popped up from
595 // (and up through the hierarchy)
596 if ( !processed )
597 {
598 const wxMenuBase *menu = this;
599 while ( menu )
600 {
601 wxWindow *win = menu->GetInvokingWindow();
602 if ( win )
603 {
937013e0 604 processed = win->HandleWindowEvent(event);
6239ee05
SC
605 break;
606 }
607
608 menu = menu->GetParent();
609 }
610 }
611
612 if ( !processed && targetWindow != NULL)
613 {
937013e0 614 processed = targetWindow->HandleWindowEvent(event);
6239ee05 615 }
31c1cbc7 616
6239ee05
SC
617 if ( processed )
618 {
619 // if anything changed, update the changed attribute
620 if (event.GetSetText())
621 SetLabel(id, event.GetText());
622 if (event.GetSetChecked())
623 Check(id, event.GetChecked());
624 if (event.GetSetEnabled())
625 Enable(id, event.GetEnabled());
626
627 result = noErr ;
628 }
629 return result;
630}
631
e9576ca5 632// Menu Bar
519cb848 633
58751a86 634/*
519cb848
SC
635
636Mac Implementation note :
637
638The Mac has only one global menubar, so we attempt to install the currently
639active menubar from a frame, we currently don't take into account mdi-frames
640which would ask for menu-merging
641
58751a86 642Secondly there is no mac api for changing a menubar that is not the current
519cb848
SC
643menubar, so we have to wait for preparing the actual menubar until the
644wxMenubar is to be used
645
58751a86 646We can in subsequent versions use MacInstallMenuBar to provide some sort of
519cb848
SC
647auto-merge for MDI in case this will be necessary
648
649*/
650
651wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
1b1d2207 652wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
22e3c5bd
SC
653bool wxMenuBar::s_macAutoWindowMenu = true ;
654WXHMENU wxMenuBar::s_macWindowMenuHandle = NULL ;
519cb848 655
e7549107 656void wxMenuBar::Init()
e9576ca5
SC
657{
658 m_eventHandler = this;
e9576ca5 659 m_menuBarFrame = NULL;
7c15086c 660 m_invokingWindow = (wxWindow*) NULL;
e9576ca5
SC
661}
662
51abe921
SC
663wxMenuBar::wxMenuBar()
664{
665 Init();
666}
667
668wxMenuBar::wxMenuBar( long WXUNUSED(style) )
669{
670 Init();
671}
672
294ea16d 673wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
e9576ca5 674{
e7549107
SC
675 Init();
676
677 m_titles.Alloc(count);
678
d2103c8c 679 for ( size_t i = 0; i < count; i++ )
e7549107
SC
680 {
681 m_menus.Append(menus[i]);
682 m_titles.Add(titles[i]);
683
684 menus[i]->Attach(this);
685 }
e9576ca5
SC
686}
687
688wxMenuBar::~wxMenuBar()
689{
1b1d2207
DE
690 if (s_macCommonMenuBar == this)
691 s_macCommonMenuBar = NULL;
5977edb9 692
e40298d5
JS
693 if (s_macInstalledMenuBar == this)
694 {
695 ::ClearMenuBar();
696 s_macInstalledMenuBar = NULL;
697 }
e7549107
SC
698}
699
6d6da89c 700void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
e7549107
SC
701{
702 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
e9576ca5 703
e7549107 704 DrawMenuBar();
e9576ca5
SC
705}
706
58751a86 707void wxMenuBar::MacInstallMenuBar()
519cb848 708{
2b8a6962
GD
709 if ( s_macInstalledMenuBar == this )
710 return ;
58751a86 711
53d92341 712 MenuBarHandle menubar = NULL ;
5977edb9 713
53d92341 714 menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
5977edb9 715
2b8a6962 716 ::SetMenuBar( menubar ) ;
dd05f811 717 DisposeMenuBar( menubar ) ;
cda73c27 718 MenuHandle appleMenu = NULL ;
cda73c27
SC
719
720 verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
4f74e0d1 721 verify_noerr( SetMenuTitleWithCFString( appleMenu , CFSTR( "\x14" ) ) );
23c6ddc8 722
262ce38a
KH
723 // Add About/Preferences separator only on OS X
724 // KH/RN: Separator is always present on 10.3 but not on 10.2
725 // However, the change from 10.2 to 10.3 suggests it is preferred
4f74e0d1 726 InsertMenuItemTextWithCFString( appleMenu,
90f58090 727 CFSTR(""), 0, kMenuItemAttrSeparator, 0);
4f74e0d1 728 InsertMenuItemTextWithCFString( appleMenu,
90f58090 729 CFSTR("About..."), 0, 0, 0);
cda73c27
SC
730 MacInsertMenu( appleMenu , 0 ) ;
731
4dd25308
VZ
732 // if we have a mac help menu, clean it up before adding new items
733 MenuHandle helpMenuHandle ;
734 MenuItemIndex firstUserHelpMenuItem ;
902725ee 735
4dd25308 736 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) == noErr )
e40298d5 737 {
4dd25308
VZ
738 for ( int i = CountMenuItems( helpMenuHandle ) ; i >= firstUserHelpMenuItem ; --i )
739 DeleteMenuItem( helpMenuHandle , i ) ;
740 }
741 else
742 {
743 helpMenuHandle = NULL ;
e40298d5 744 }
5977edb9 745
03561a3c 746 if ( wxApp::s_macPreferencesMenuItemId)
e40298d5
JS
747 {
748 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
749 if ( item == NULL || !(item->IsEnabled()) )
750 DisableMenuCommand( NULL , kHICommandPreferences ) ;
751 else
752 EnableMenuCommand( NULL , kHICommandPreferences ) ;
753 }
5977edb9 754
3e275c2d
KH
755 // Unlike preferences which may or may not exist, the Quit item should be always
756 // enabled unless it is added by the application and then disabled, otherwise
757 // a program would be required to add an item with wxID_EXIT in order to get the
758 // Quit menu item to be enabled, which seems a bit burdensome.
03561a3c 759 if ( wxApp::s_macExitMenuItemId)
e9626c1b
KH
760 {
761 wxMenuItem *item = FindItem( wxApp::s_macExitMenuItemId , NULL ) ;
3e275c2d 762 if ( item != NULL && !(item->IsEnabled()) )
e9626c1b
KH
763 DisableMenuCommand( NULL , kHICommandQuit ) ;
764 else
765 EnableMenuCommand( NULL , kHICommandQuit ) ;
766 }
5977edb9 767
4dd25308
VZ
768 wxString strippedHelpMenuTitle = wxStripMenuCodes( wxApp::s_macHelpMenuTitleName ) ;
769 wxString strippedTranslatedHelpMenuTitle = wxStripMenuCodes( wxString( _("&Help") ) ) ;
6524e8f0 770 wxMenuList::compatibility_iterator menuIter = m_menus.GetFirst();
6524e8f0
SC
771 for (size_t i = 0; i < m_menus.GetCount(); i++, menuIter = menuIter->GetNext())
772 {
71f2fb52 773 wxMenuItemList::compatibility_iterator node;
2b5f62a0 774 wxMenuItem *item;
71f2fb52 775 wxMenu* menu = menuIter->GetData() , *subMenu = NULL ;
4dd25308 776 wxString strippedMenuTitle = wxStripMenuCodes(m_titles[i]);
e40298d5 777
4dd25308 778 if ( strippedMenuTitle == wxT("?") || strippedMenuTitle == strippedHelpMenuTitle || strippedMenuTitle == strippedTranslatedHelpMenuTitle )
e40298d5 779 {
716d0327 780 for (node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext())
e40298d5 781 {
6524e8f0
SC
782 item = (wxMenuItem *)node->GetData();
783 subMenu = item->GetSubMenu() ;
58751a86 784 if (subMenu)
e40298d5
JS
785 {
786 // we don't support hierarchical menus in the help menu yet
787 }
58751a86 788 else
e40298d5 789 {
6524e8f0
SC
790 if ( item->GetId() != wxApp::s_macAboutMenuItemId )
791 {
4dd25308
VZ
792 // we have found a user help menu and an item other than the about item,
793 // so we can create the mac help menu now, if we haven't created it yet
794 if ( helpMenuHandle == NULL )
6524e8f0 795 {
4dd25308 796 if ( UMAGetHelpMenu( &helpMenuHandle , &firstUserHelpMenuItem) != noErr )
6524e8f0 797 {
4dd25308 798 helpMenuHandle = NULL ;
6524e8f0 799 break ;
902725ee 800 }
6524e8f0
SC
801 }
802 }
5977edb9 803
e40298d5
JS
804 if ( item->IsSeparator() )
805 {
4dd25308
VZ
806 if ( helpMenuHandle )
807 AppendMenuItemTextWithCFString( helpMenuHandle,
90f58090 808 CFSTR(""), kMenuItemAttrSeparator, 0,NULL);
e40298d5
JS
809 }
810 else
811 {
90527a50 812 wxAcceleratorEntry*
9a9c35d3 813 entry = wxAcceleratorEntry::Create( item->GetItemLabel() ) ;
e40298d5
JS
814
815 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
58751a86 816 {
6524e8f0
SC
817 // this will be taken care of below
818 }
e40298d5
JS
819 else
820 {
4dd25308 821 if ( helpMenuHandle )
e40298d5 822 {
9a9c35d3 823 UMAAppendMenuItem(helpMenuHandle, wxStripMenuCodes(item->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry);
4dd25308
VZ
824 SetMenuItemCommandID( helpMenuHandle , CountMenuItems(helpMenuHandle) , wxIdToMacCommand ( item->GetId() ) ) ;
825 SetMenuItemRefCon( helpMenuHandle , CountMenuItems(helpMenuHandle) , (URefCon) item ) ;
e40298d5
JS
826 }
827 }
58751a86 828
e40298d5
JS
829 delete entry ;
830 }
831 }
832 }
833 }
90f58090
VZ
834
835 else if ( ( m_titles[i] == wxT("Window") || m_titles[i] == wxT("&Window") )
e608ff58 836 && GetAutoWindowMenu() )
90f58090 837 {
e608ff58
KO
838 if ( MacGetWindowMenuHMenu() == NULL )
839 {
840 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
841 }
90f58090 842
e608ff58
KO
843 MenuRef wm = (MenuRef)MacGetWindowMenuHMenu();
844 if ( wm == NULL )
845 break;
90f58090 846
e608ff58
KO
847 // get the insertion point in the standard menu
848 MenuItemIndex winListStart;
90f58090 849 GetIndMenuItemWithCommandID(wm,
e608ff58 850 kHICommandWindowListSeparator, 1, NULL, &winListStart);
90f58090 851
e608ff58
KO
852 // add a separator so that the standard items and the custom items
853 // aren't mixed together, but only if this is the first run
90f58090 854 OSStatus err = GetIndMenuItemWithCommandID(wm,
e608ff58 855 'WXWM', 1, NULL, NULL);
90f58090 856
e608ff58
KO
857 if ( err == menuItemNotFoundErr )
858 {
859 InsertMenuItemTextWithCFString( wm,
860 CFSTR(""), winListStart-1, kMenuItemAttrSeparator, 'WXWM');
861 }
90f58090
VZ
862
863 wxInsertMenuItemsInMenu(menu, wm, winListStart);
e608ff58 864 }
e40298d5
JS
865 else
866 {
a9412f8f 867 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], m_font.GetEncoding() ) ;
71f2fb52 868 menu->MacBeforeDisplay(false) ;
90f58090 869
71f2fb52 870 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus, i)->GetHMenu()), 0);
e40298d5
JS
871 }
872 }
5977edb9 873
6524e8f0
SC
874 // take care of the about menu item wherever it is
875 {
876 wxMenu* aboutMenu ;
877 wxMenuItem *aboutMenuItem = FindItem(wxApp::s_macAboutMenuItemId , &aboutMenu) ;
878 if ( aboutMenuItem )
879 {
90527a50 880 wxAcceleratorEntry*
9a9c35d3
JS
881 entry = wxAcceleratorEntry::Create( aboutMenuItem->GetItemLabel() ) ;
882 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , wxStripMenuCodes ( aboutMenuItem->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
6524e8f0 883 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
ca71e3ae 884 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , kHICommandAbout ) ;
4f74e0d1 885 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (URefCon)aboutMenuItem ) ;
6524e8f0
SC
886 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
887 }
888 }
5977edb9 889
22e3c5bd
SC
890 if ( GetAutoWindowMenu() )
891 {
892 if ( MacGetWindowMenuHMenu() == NULL )
22e3c5bd 893 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
5977edb9 894
22e3c5bd
SC
895 InsertMenu( (MenuHandle) MacGetWindowMenuHMenu() , 0 ) ;
896 }
5977edb9 897
e40298d5
JS
898 ::DrawMenuBar() ;
899 s_macInstalledMenuBar = this;
519cb848
SC
900}
901
e7549107 902void wxMenuBar::EnableTop(size_t pos, bool enable)
e9576ca5 903{
e7549107 904 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
5977edb9 905
71f2fb52 906 _wxMenuAt(m_menus, pos)->MacEnableMenu( enable ) ;
e7549107 907 Refresh();
e9576ca5
SC
908}
909
5977edb9 910bool wxMenuBar::Enable(bool enable)
c393c740 911{
5059f192 912 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
5977edb9 913
c393c740
JS
914 size_t i;
915 for (i = 0; i < GetMenuCount(); i++)
c393c740 916 EnableTop(i, enable);
5977edb9 917
c393c740
JS
918 return true;
919}
920
52af3158 921void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
e9576ca5 922{
e7549107 923 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 924
e7549107 925 m_titles[pos] = label;
e9576ca5 926
e7549107 927 if ( !IsAttached() )
e9576ca5
SC
928 return;
929
71f2fb52
RN
930 _wxMenuAt(m_menus, pos)->SetTitle( label ) ;
931
e40298d5
JS
932 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
933 {
934 ::SetMenuBar( GetMenuBar() ) ;
935 ::InvalMenuBar() ;
936 }
e9576ca5
SC
937}
938
52af3158 939wxString wxMenuBar::GetMenuLabel(size_t pos) const
e9576ca5 940{
e7549107 941 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
52af3158 942 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
519cb848 943
e7549107 944 return m_titles[pos];
e9576ca5
SC
945}
946
e7549107 947int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 948{
e7549107 949 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 950
e7549107
SC
951 size_t count = GetMenuCount();
952 for ( size_t i = 0; i < count; i++ )
e9576ca5 953 {
e7549107
SC
954 wxString title = wxStripMenuCodes(m_titles[i]);
955 if ( menuTitle == title )
58751a86 956 return i;
e9576ca5 957 }
e9576ca5 958
e7549107 959 return wxNOT_FOUND;
e9576ca5
SC
960}
961
e7549107
SC
962// ---------------------------------------------------------------------------
963// wxMenuBar construction
964// ---------------------------------------------------------------------------
965
966wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 967{
e7549107
SC
968 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
969 if ( !menuOld )
a8fb9ede 970 return NULL;
5977edb9 971
e7549107 972 m_titles[pos] = title;
e9576ca5 973
e7549107 974 if ( IsAttached() )
e9576ca5 975 {
e40298d5
JS
976 if (s_macInstalledMenuBar == this)
977 {
d46342af 978 menuOld->MacAfterDisplay( false ) ;
e40298d5 979 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
5977edb9
DS
980
981 menu->MacBeforeDisplay( false ) ;
982 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
983 if ( pos == m_menus.GetCount() - 1)
984 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
985 else
986 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos + 1)->MacGetMenuId() ) ;
e40298d5 987 }
e9576ca5 988
e7549107 989 Refresh();
e9576ca5 990 }
5977edb9 991
0f4c4140
SC
992 if (m_invokingWindow)
993 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
e9576ca5 994
e7549107 995 return menuOld;
e9576ca5
SC
996}
997
e7549107 998bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 999{
e7549107 1000 if ( !wxMenuBarBase::Insert(pos, menu, title) )
902725ee 1001 return false;
e9576ca5 1002
e7549107 1003 m_titles.Insert(title, pos);
e9576ca5 1004
a9412f8f 1005 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
e7549107 1006
d46342af 1007 if ( IsAttached() && s_macInstalledMenuBar == this )
e9576ca5 1008 {
d46342af 1009 if (s_macInstalledMenuBar == this)
e40298d5 1010 {
d46342af 1011 menu->MacBeforeDisplay( false ) ;
5977edb9 1012
d46342af 1013 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
d46342af 1014 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
d46342af 1015 else
71f2fb52 1016 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos+1)->MacGetMenuId() ) ;
e40298d5 1017 }
5977edb9 1018
e7549107 1019 Refresh();
e9576ca5 1020 }
5977edb9 1021
0f4c4140
SC
1022 if (m_invokingWindow)
1023 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
e7549107 1024
902725ee 1025 return true;
e9576ca5
SC
1026}
1027
51abe921
SC
1028wxMenu *wxMenuBar::Remove(size_t pos)
1029{
1030 wxMenu *menu = wxMenuBarBase::Remove(pos);
1031 if ( !menu )
1032 return NULL;
1033
1034 if ( IsAttached() )
1035 {
e40298d5 1036 if (s_macInstalledMenuBar == this)
e40298d5 1037 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
51abe921 1038
51abe921
SC
1039 Refresh();
1040 }
1041
5fe38474 1042 m_titles.RemoveAt(pos);
51abe921
SC
1043
1044 return menu;
1045}
1046
1047bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
1048{
1049 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
5977edb9 1050 wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
51abe921
SC
1051
1052 if ( !wxMenuBarBase::Append(menu, title) )
902725ee 1053 return false;
51abe921 1054
51abe921 1055 m_titles.Add(title);
58751a86 1056
a9412f8f 1057 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
51abe921
SC
1058
1059 if ( IsAttached() )
1060 {
e40298d5
JS
1061 if (s_macInstalledMenuBar == this)
1062 {
94c80d52 1063 menu->MacBeforeDisplay( false ) ;
e40298d5
JS
1064 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
1065 }
51abe921
SC
1066
1067 Refresh();
1068 }
1069
0f4c4140 1070 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
7c15086c
SC
1071 // adding menu later on.
1072 if (m_invokingWindow)
1073 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
1074
902725ee 1075 return true;
51abe921
SC
1076}
1077
2b5f62a0
VZ
1078static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
1079{
1080 menu->SetInvokingWindow( (wxWindow*) NULL );
71f2fb52 1081 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
5977edb9 1082
2b5f62a0
VZ
1083 while (node)
1084 {
1085 wxMenuItem *menuitem = node->GetData();
1086 if (menuitem->IsSubMenu())
1087 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
5977edb9 1088
2b5f62a0
VZ
1089 node = node->GetNext();
1090 }
1091}
1092
1093static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
1094{
1095 menu->SetInvokingWindow( win );
5977edb9 1096 wxMenuItem *menuitem;
71f2fb52 1097 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
5977edb9 1098
2b5f62a0
VZ
1099 while (node)
1100 {
5977edb9 1101 menuitem = node->GetData();
2b5f62a0
VZ
1102 if (menuitem->IsSubMenu())
1103 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
5977edb9 1104
2b5f62a0
VZ
1105 node = node->GetNext();
1106 }
1107}
1108
1109void wxMenuBar::UnsetInvokingWindow()
1110{
7c15086c 1111 m_invokingWindow = (wxWindow*) NULL;
5977edb9 1112 wxMenu *menu;
71f2fb52 1113 wxMenuList::compatibility_iterator node = m_menus.GetFirst();
5977edb9 1114
2b5f62a0
VZ
1115 while (node)
1116 {
5977edb9 1117 menu = node->GetData();
2b5f62a0 1118 wxMenubarUnsetInvokingWindow( menu );
5977edb9 1119
2b5f62a0
VZ
1120 node = node->GetNext();
1121 }
1122}
1123
1124void wxMenuBar::SetInvokingWindow(wxFrame *frame)
1125{
7c15086c 1126 m_invokingWindow = frame;
5977edb9 1127 wxMenu *menu;
71f2fb52 1128 wxMenuList::compatibility_iterator node = m_menus.GetFirst();
5977edb9 1129
2b5f62a0
VZ
1130 while (node)
1131 {
5977edb9 1132 menu = node->GetData();
2b5f62a0 1133 wxMenubarSetInvokingWindow( menu, frame );
5977edb9 1134
2b5f62a0
VZ
1135 node = node->GetNext();
1136 }
1137}
1138
90b959ae 1139void wxMenuBar::Detach()
2f1ae414 1140{
90b959ae
SC
1141 wxMenuBarBase::Detach() ;
1142}
2f1ae414 1143
90b959ae
SC
1144void wxMenuBar::Attach(wxFrame *frame)
1145{
1146 wxMenuBarBase::Attach( frame ) ;
2f1ae414 1147}
5977edb9 1148
51abe921
SC
1149// ---------------------------------------------------------------------------
1150// wxMenuBar searching for menu items
1151// ---------------------------------------------------------------------------
1152
1153// Find the itemString in menuString, and return the item id or wxNOT_FOUND
1154int wxMenuBar::FindMenuItem(const wxString& menuString,
1155 const wxString& itemString) const
1156{
1157 wxString menuLabel = wxStripMenuCodes(menuString);
1158 size_t count = GetMenuCount();
1159 for ( size_t i = 0; i < count; i++ )
1160 {
1161 wxString title = wxStripMenuCodes(m_titles[i]);
ef089805 1162 if ( menuLabel == title )
71f2fb52 1163 return _wxMenuAt(m_menus, i)->FindItem(itemString);
51abe921
SC
1164 }
1165
1166 return wxNOT_FOUND;
1167}
1168
1169wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
1170{
1171 if ( itemMenu )
1172 *itemMenu = NULL;
1173
1174 wxMenuItem *item = NULL;
1175 size_t count = GetMenuCount();
1176 for ( size_t i = 0; !item && (i < count); i++ )
71f2fb52 1177 item = _wxMenuAt(m_menus, i)->FindItem(id, itemMenu);
51abe921
SC
1178
1179 return item;
1180}