]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/menu.cpp
Border corrections
[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())
e7549107 377 processed = GetEventHandler()->ProcessEvent(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 )
383 processed = win->GetEventHandler()->ProcessEvent(event);
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 {
5977edb9 468#if TARGET_CARBON
6524e8f0
SC
469 // what we do here is to hide the special items which are
470 // shown in the application menu anyhow -- it doesn't make
471 // sense to show them in their normal place as well
472 if ( item->GetId() == wxApp::s_macAboutMenuItemId ||
473 ( UMAGetSystemVersion() >= 0x1000 && (
474 item->GetId() == wxApp::s_macPreferencesMenuItemId ||
475 item->GetId() == wxApp::s_macExitMenuItemId ) ) )
902725ee 476
d46342af 477 {
6524e8f0
SC
478 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
479 pos + 1, kMenuItemAttrHidden, 0 );
480
481 // also check for a separator which was used just to
482 // separate this item from the others, so don't leave
483 // separator at the menu start or end nor 2 consecutive
484 // separators
485 wxMenuItemList::compatibility_iterator nextNode = node->GetNext();
486 wxMenuItem *next = nextNode ? nextNode->GetData() : NULL;
487
488 size_t posSeptoHide;
489 if ( !previousItem && next && next->IsSeparator() )
d46342af 490 {
6524e8f0
SC
491 // next (i.e. second as we must be first) item is
492 // the separator to hide
493 wxASSERT_MSG( pos == 0, _T("should be the menu start") );
494 posSeptoHide = 2;
495 }
496 else if ( GetMenuItems().GetCount() == pos + 1 &&
497 previousItem != NULL &&
498 previousItem->IsSeparator() )
499 {
500 // prev item is a trailing separator we want to hide
501 posSeptoHide = pos;
502 }
503 else if ( previousItem && previousItem->IsSeparator() &&
504 next && next->IsSeparator() )
505 {
506 // two consecutive separators, this is one too many
507 posSeptoHide = pos;
508 }
509 else // no separators to hide
510 {
511 posSeptoHide = 0;
512 }
fa4a6942 513
6524e8f0
SC
514 if ( posSeptoHide )
515 {
516 // hide the separator as well
517 ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
518 posSeptoHide,
519 kMenuItemAttrHidden,
520 0 );
d46342af
SC
521 }
522 }
5977edb9 523#endif // TARGET_CARBON
d46342af 524 }
5977edb9 525
d46342af
SC
526 previousItem = item ;
527 }
528
529 if ( isSubMenu )
530 ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
d46342af 531}
5977edb9 532
d46342af 533// undo all changes from the MacBeforeDisplay call
58751a86 534void wxMenu::MacAfterDisplay( bool isSubMenu )
d46342af
SC
535{
536 if ( isSubMenu )
537 ::DeleteMenu(MacGetMenuId());
538
71f2fb52 539 wxMenuItemList::compatibility_iterator node;
d46342af 540 wxMenuItem *item;
5977edb9 541
716d0327 542 for (node = GetMenuItems().GetFirst(); node; node = node->GetNext())
d46342af
SC
543 {
544 item = (wxMenuItem *)node->GetData();
545 wxMenu* subMenu = item->GetSubMenu() ;
58751a86 546 if (subMenu)
d46342af
SC
547 {
548 subMenu->MacAfterDisplay( true ) ;
549 }
550 else
551 {
552 // no need to undo hidings
553 }
d46342af
SC
554 }
555}
556
6239ee05
SC
557wxInt32 wxMenu::MacHandleCommandProcess( wxMenuItem* item, int id, wxWindow* targetWindow )
558{
559 OSStatus result = eventNotHandledErr ;
560 if (item->IsCheckable())
561 item->Check( !item->IsChecked() ) ;
562
563 if ( SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) )
564 result = noErr ;
565 else
566 {
567 if ( targetWindow != NULL )
568 {
569 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED , id);
570 event.SetEventObject(targetWindow);
571 event.SetInt(item->IsCheckable() ? item->IsChecked() : -1);
572
573 if ( targetWindow->GetEventHandler()->ProcessEvent(event) )
574 result = noErr ;
575 }
576 }
577 return result;
578}
579
580wxInt32 wxMenu::MacHandleCommandUpdateStatus( wxMenuItem* item, int id, wxWindow* targetWindow )
581{
582 OSStatus result = eventNotHandledErr ;
583 wxUpdateUIEvent event(id);
584 event.SetEventObject( this );
585
586 bool processed = false;
587
588 // Try the menu's event handler
589 {
590 wxEvtHandler *handler = GetEventHandler();
591 if ( handler )
592 processed = handler->ProcessEvent(event);
593 }
594
595 // Try the window the menu was popped up from
596 // (and up through the hierarchy)
597 if ( !processed )
598 {
599 const wxMenuBase *menu = this;
600 while ( menu )
601 {
602 wxWindow *win = menu->GetInvokingWindow();
603 if ( win )
604 {
605 processed = win->GetEventHandler()->ProcessEvent(event);
606 break;
607 }
608
609 menu = menu->GetParent();
610 }
611 }
612
613 if ( !processed && targetWindow != NULL)
614 {
615 processed = targetWindow->GetEventHandler()->ProcessEvent(event);
616 }
617
618 if ( processed )
619 {
620 // if anything changed, update the changed attribute
621 if (event.GetSetText())
622 SetLabel(id, event.GetText());
623 if (event.GetSetChecked())
624 Check(id, event.GetChecked());
625 if (event.GetSetEnabled())
626 Enable(id, event.GetEnabled());
627
628 result = noErr ;
629 }
630 return result;
631}
632
e9576ca5 633// Menu Bar
519cb848 634
58751a86 635/*
519cb848
SC
636
637Mac Implementation note :
638
639The Mac has only one global menubar, so we attempt to install the currently
640active menubar from a frame, we currently don't take into account mdi-frames
641which would ask for menu-merging
642
58751a86 643Secondly there is no mac api for changing a menubar that is not the current
519cb848
SC
644menubar, so we have to wait for preparing the actual menubar until the
645wxMenubar is to be used
646
58751a86 647We can in subsequent versions use MacInstallMenuBar to provide some sort of
519cb848
SC
648auto-merge for MDI in case this will be necessary
649
650*/
651
652wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
1b1d2207 653wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
22e3c5bd
SC
654bool wxMenuBar::s_macAutoWindowMenu = true ;
655WXHMENU wxMenuBar::s_macWindowMenuHandle = NULL ;
519cb848 656
e7549107 657void wxMenuBar::Init()
e9576ca5
SC
658{
659 m_eventHandler = this;
e9576ca5 660 m_menuBarFrame = NULL;
7c15086c 661 m_invokingWindow = (wxWindow*) NULL;
e9576ca5
SC
662}
663
51abe921
SC
664wxMenuBar::wxMenuBar()
665{
666 Init();
667}
668
669wxMenuBar::wxMenuBar( long WXUNUSED(style) )
670{
671 Init();
672}
673
294ea16d 674wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
e9576ca5 675{
e7549107
SC
676 Init();
677
678 m_titles.Alloc(count);
679
d2103c8c 680 for ( size_t i = 0; i < count; i++ )
e7549107
SC
681 {
682 m_menus.Append(menus[i]);
683 m_titles.Add(titles[i]);
684
685 menus[i]->Attach(this);
686 }
e9576ca5
SC
687}
688
689wxMenuBar::~wxMenuBar()
690{
1b1d2207
DE
691 if (s_macCommonMenuBar == this)
692 s_macCommonMenuBar = NULL;
5977edb9 693
e40298d5
JS
694 if (s_macInstalledMenuBar == this)
695 {
696 ::ClearMenuBar();
697 s_macInstalledMenuBar = NULL;
698 }
e7549107
SC
699}
700
6d6da89c 701void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
e7549107
SC
702{
703 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
e9576ca5 704
e7549107 705 DrawMenuBar();
e9576ca5
SC
706}
707
58751a86 708void wxMenuBar::MacInstallMenuBar()
519cb848 709{
2b8a6962
GD
710 if ( s_macInstalledMenuBar == this )
711 return ;
58751a86 712
53d92341 713 MenuBarHandle menubar = NULL ;
5977edb9 714
53d92341
SC
715#if TARGET_API_MAC_OSX
716 menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
717#else
718 menubar = NewHandleClear( 12 ) ;
719 (*menubar)[3] = 0x0a ;
720#endif
5977edb9 721
2b8a6962 722 ::SetMenuBar( menubar ) ;
dd05f811 723 DisposeMenuBar( menubar ) ;
cda73c27 724 MenuHandle appleMenu = NULL ;
cda73c27
SC
725
726 verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
4f74e0d1 727 verify_noerr( SetMenuTitleWithCFString( appleMenu , CFSTR( "\x14" ) ) );
23c6ddc8 728
262ce38a
KH
729 // Add About/Preferences separator only on OS X
730 // KH/RN: Separator is always present on 10.3 but not on 10.2
731 // However, the change from 10.2 to 10.3 suggests it is preferred
732#if TARGET_API_MAC_OSX
4f74e0d1 733 InsertMenuItemTextWithCFString( appleMenu,
90f58090 734 CFSTR(""), 0, kMenuItemAttrSeparator, 0);
262ce38a 735#endif
4f74e0d1 736 InsertMenuItemTextWithCFString( appleMenu,
90f58090 737 CFSTR("About..."), 0, 0, 0);
cda73c27
SC
738 MacInsertMenu( appleMenu , 0 ) ;
739
4dd25308
VZ
740 // if we have a mac help menu, clean it up before adding new items
741 MenuHandle helpMenuHandle ;
742 MenuItemIndex firstUserHelpMenuItem ;
902725ee 743
4dd25308 744 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) == noErr )
e40298d5 745 {
4dd25308
VZ
746 for ( int i = CountMenuItems( helpMenuHandle ) ; i >= firstUserHelpMenuItem ; --i )
747 DeleteMenuItem( helpMenuHandle , i ) ;
748 }
749 else
750 {
751 helpMenuHandle = NULL ;
e40298d5 752 }
5977edb9 753
7c15086c 754#if TARGET_CARBON
e40298d5
JS
755 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId)
756 {
757 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
758 if ( item == NULL || !(item->IsEnabled()) )
759 DisableMenuCommand( NULL , kHICommandPreferences ) ;
760 else
761 EnableMenuCommand( NULL , kHICommandPreferences ) ;
762 }
5977edb9 763
3e275c2d
KH
764 // Unlike preferences which may or may not exist, the Quit item should be always
765 // enabled unless it is added by the application and then disabled, otherwise
766 // a program would be required to add an item with wxID_EXIT in order to get the
767 // Quit menu item to be enabled, which seems a bit burdensome.
e9626c1b
KH
768 if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId)
769 {
770 wxMenuItem *item = FindItem( wxApp::s_macExitMenuItemId , NULL ) ;
3e275c2d 771 if ( item != NULL && !(item->IsEnabled()) )
e9626c1b
KH
772 DisableMenuCommand( NULL , kHICommandQuit ) ;
773 else
774 EnableMenuCommand( NULL , kHICommandQuit ) ;
775 }
7c15086c 776#endif
5977edb9 777
4dd25308
VZ
778 wxString strippedHelpMenuTitle = wxStripMenuCodes( wxApp::s_macHelpMenuTitleName ) ;
779 wxString strippedTranslatedHelpMenuTitle = wxStripMenuCodes( wxString( _("&Help") ) ) ;
6524e8f0 780 wxMenuList::compatibility_iterator menuIter = m_menus.GetFirst();
6524e8f0
SC
781 for (size_t i = 0; i < m_menus.GetCount(); i++, menuIter = menuIter->GetNext())
782 {
71f2fb52 783 wxMenuItemList::compatibility_iterator node;
2b5f62a0 784 wxMenuItem *item;
71f2fb52 785 wxMenu* menu = menuIter->GetData() , *subMenu = NULL ;
4dd25308 786 wxString strippedMenuTitle = wxStripMenuCodes(m_titles[i]);
e40298d5 787
4dd25308 788 if ( strippedMenuTitle == wxT("?") || strippedMenuTitle == strippedHelpMenuTitle || strippedMenuTitle == strippedTranslatedHelpMenuTitle )
e40298d5 789 {
716d0327 790 for (node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext())
e40298d5 791 {
6524e8f0
SC
792 item = (wxMenuItem *)node->GetData();
793 subMenu = item->GetSubMenu() ;
58751a86 794 if (subMenu)
e40298d5
JS
795 {
796 // we don't support hierarchical menus in the help menu yet
797 }
58751a86 798 else
e40298d5 799 {
6524e8f0
SC
800 if ( item->GetId() != wxApp::s_macAboutMenuItemId )
801 {
4dd25308
VZ
802 // we have found a user help menu and an item other than the about item,
803 // so we can create the mac help menu now, if we haven't created it yet
804 if ( helpMenuHandle == NULL )
6524e8f0 805 {
4dd25308 806 if ( UMAGetHelpMenu( &helpMenuHandle , &firstUserHelpMenuItem) != noErr )
6524e8f0 807 {
4dd25308 808 helpMenuHandle = NULL ;
6524e8f0 809 break ;
902725ee 810 }
6524e8f0
SC
811 }
812 }
5977edb9 813
e40298d5
JS
814 if ( item->IsSeparator() )
815 {
4dd25308
VZ
816 if ( helpMenuHandle )
817 AppendMenuItemTextWithCFString( helpMenuHandle,
90f58090 818 CFSTR(""), kMenuItemAttrSeparator, 0,NULL);
e40298d5
JS
819 }
820 else
821 {
90527a50 822 wxAcceleratorEntry*
9a9c35d3 823 entry = wxAcceleratorEntry::Create( item->GetItemLabel() ) ;
e40298d5
JS
824
825 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
58751a86 826 {
6524e8f0
SC
827 // this will be taken care of below
828 }
e40298d5
JS
829 else
830 {
4dd25308 831 if ( helpMenuHandle )
e40298d5 832 {
9a9c35d3 833 UMAAppendMenuItem(helpMenuHandle, wxStripMenuCodes(item->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry);
4dd25308
VZ
834 SetMenuItemCommandID( helpMenuHandle , CountMenuItems(helpMenuHandle) , wxIdToMacCommand ( item->GetId() ) ) ;
835 SetMenuItemRefCon( helpMenuHandle , CountMenuItems(helpMenuHandle) , (URefCon) item ) ;
e40298d5
JS
836 }
837 }
58751a86 838
e40298d5
JS
839 delete entry ;
840 }
841 }
842 }
843 }
90f58090
VZ
844
845 else if ( ( m_titles[i] == wxT("Window") || m_titles[i] == wxT("&Window") )
e608ff58 846 && GetAutoWindowMenu() )
90f58090 847 {
e608ff58
KO
848 if ( MacGetWindowMenuHMenu() == NULL )
849 {
850 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
851 }
90f58090 852
e608ff58
KO
853 MenuRef wm = (MenuRef)MacGetWindowMenuHMenu();
854 if ( wm == NULL )
855 break;
90f58090 856
e608ff58
KO
857 // get the insertion point in the standard menu
858 MenuItemIndex winListStart;
90f58090 859 GetIndMenuItemWithCommandID(wm,
e608ff58 860 kHICommandWindowListSeparator, 1, NULL, &winListStart);
90f58090 861
e608ff58
KO
862 // add a separator so that the standard items and the custom items
863 // aren't mixed together, but only if this is the first run
90f58090 864 OSStatus err = GetIndMenuItemWithCommandID(wm,
e608ff58 865 'WXWM', 1, NULL, NULL);
90f58090 866
e608ff58
KO
867 if ( err == menuItemNotFoundErr )
868 {
869 InsertMenuItemTextWithCFString( wm,
870 CFSTR(""), winListStart-1, kMenuItemAttrSeparator, 'WXWM');
871 }
90f58090
VZ
872
873 wxInsertMenuItemsInMenu(menu, wm, winListStart);
e608ff58 874 }
e40298d5
JS
875 else
876 {
a9412f8f 877 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], m_font.GetEncoding() ) ;
71f2fb52 878 menu->MacBeforeDisplay(false) ;
90f58090 879
71f2fb52 880 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus, i)->GetHMenu()), 0);
e40298d5
JS
881 }
882 }
5977edb9 883
6524e8f0
SC
884 // take care of the about menu item wherever it is
885 {
886 wxMenu* aboutMenu ;
887 wxMenuItem *aboutMenuItem = FindItem(wxApp::s_macAboutMenuItemId , &aboutMenu) ;
888 if ( aboutMenuItem )
889 {
90527a50 890 wxAcceleratorEntry*
9a9c35d3
JS
891 entry = wxAcceleratorEntry::Create( aboutMenuItem->GetItemLabel() ) ;
892 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , wxStripMenuCodes ( aboutMenuItem->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
6524e8f0 893 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
ca71e3ae 894 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , kHICommandAbout ) ;
4f74e0d1 895 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (URefCon)aboutMenuItem ) ;
6524e8f0
SC
896 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
897 }
898 }
5977edb9 899
22e3c5bd
SC
900 if ( GetAutoWindowMenu() )
901 {
902 if ( MacGetWindowMenuHMenu() == NULL )
22e3c5bd 903 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
5977edb9 904
22e3c5bd
SC
905 InsertMenu( (MenuHandle) MacGetWindowMenuHMenu() , 0 ) ;
906 }
5977edb9 907
e40298d5
JS
908 ::DrawMenuBar() ;
909 s_macInstalledMenuBar = this;
519cb848
SC
910}
911
e7549107 912void wxMenuBar::EnableTop(size_t pos, bool enable)
e9576ca5 913{
e7549107 914 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
5977edb9 915
71f2fb52 916 _wxMenuAt(m_menus, pos)->MacEnableMenu( enable ) ;
e7549107 917 Refresh();
e9576ca5
SC
918}
919
5977edb9 920bool wxMenuBar::Enable(bool enable)
c393c740 921{
5059f192 922 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
5977edb9 923
c393c740
JS
924 size_t i;
925 for (i = 0; i < GetMenuCount(); i++)
c393c740 926 EnableTop(i, enable);
5977edb9 927
c393c740
JS
928 return true;
929}
930
52af3158 931void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
e9576ca5 932{
e7549107 933 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 934
e7549107 935 m_titles[pos] = label;
e9576ca5 936
e7549107 937 if ( !IsAttached() )
e9576ca5
SC
938 return;
939
71f2fb52
RN
940 _wxMenuAt(m_menus, pos)->SetTitle( label ) ;
941
e40298d5
JS
942 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
943 {
944 ::SetMenuBar( GetMenuBar() ) ;
945 ::InvalMenuBar() ;
946 }
e9576ca5
SC
947}
948
52af3158 949wxString wxMenuBar::GetMenuLabel(size_t pos) const
e9576ca5 950{
e7549107 951 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
52af3158 952 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
519cb848 953
e7549107 954 return m_titles[pos];
e9576ca5
SC
955}
956
e7549107 957int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 958{
e7549107 959 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 960
e7549107
SC
961 size_t count = GetMenuCount();
962 for ( size_t i = 0; i < count; i++ )
e9576ca5 963 {
e7549107
SC
964 wxString title = wxStripMenuCodes(m_titles[i]);
965 if ( menuTitle == title )
58751a86 966 return i;
e9576ca5 967 }
e9576ca5 968
e7549107 969 return wxNOT_FOUND;
e9576ca5
SC
970}
971
e7549107
SC
972// ---------------------------------------------------------------------------
973// wxMenuBar construction
974// ---------------------------------------------------------------------------
975
976wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 977{
e7549107
SC
978 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
979 if ( !menuOld )
a8fb9ede 980 return NULL;
5977edb9 981
e7549107 982 m_titles[pos] = title;
e9576ca5 983
e7549107 984 if ( IsAttached() )
e9576ca5 985 {
e40298d5
JS
986 if (s_macInstalledMenuBar == this)
987 {
d46342af 988 menuOld->MacAfterDisplay( false ) ;
e40298d5 989 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
5977edb9
DS
990
991 menu->MacBeforeDisplay( false ) ;
992 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
993 if ( pos == m_menus.GetCount() - 1)
994 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
995 else
996 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos + 1)->MacGetMenuId() ) ;
e40298d5 997 }
e9576ca5 998
e7549107 999 Refresh();
e9576ca5 1000 }
5977edb9 1001
0f4c4140
SC
1002 if (m_invokingWindow)
1003 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
e9576ca5 1004
e7549107 1005 return menuOld;
e9576ca5
SC
1006}
1007
e7549107 1008bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 1009{
e7549107 1010 if ( !wxMenuBarBase::Insert(pos, menu, title) )
902725ee 1011 return false;
e9576ca5 1012
e7549107 1013 m_titles.Insert(title, pos);
e9576ca5 1014
a9412f8f 1015 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
e7549107 1016
d46342af 1017 if ( IsAttached() && s_macInstalledMenuBar == this )
e9576ca5 1018 {
d46342af 1019 if (s_macInstalledMenuBar == this)
e40298d5 1020 {
d46342af 1021 menu->MacBeforeDisplay( false ) ;
5977edb9 1022
d46342af 1023 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
d46342af 1024 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
d46342af 1025 else
71f2fb52 1026 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos+1)->MacGetMenuId() ) ;
e40298d5 1027 }
5977edb9 1028
e7549107 1029 Refresh();
e9576ca5 1030 }
5977edb9 1031
0f4c4140
SC
1032 if (m_invokingWindow)
1033 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
e7549107 1034
902725ee 1035 return true;
e9576ca5
SC
1036}
1037
51abe921
SC
1038wxMenu *wxMenuBar::Remove(size_t pos)
1039{
1040 wxMenu *menu = wxMenuBarBase::Remove(pos);
1041 if ( !menu )
1042 return NULL;
1043
1044 if ( IsAttached() )
1045 {
e40298d5 1046 if (s_macInstalledMenuBar == this)
e40298d5 1047 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
51abe921 1048
51abe921
SC
1049 Refresh();
1050 }
1051
5fe38474 1052 m_titles.RemoveAt(pos);
51abe921
SC
1053
1054 return menu;
1055}
1056
1057bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
1058{
1059 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
5977edb9 1060 wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
51abe921
SC
1061
1062 if ( !wxMenuBarBase::Append(menu, title) )
902725ee 1063 return false;
51abe921 1064
51abe921 1065 m_titles.Add(title);
58751a86 1066
a9412f8f 1067 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
51abe921
SC
1068
1069 if ( IsAttached() )
1070 {
e40298d5
JS
1071 if (s_macInstalledMenuBar == this)
1072 {
94c80d52 1073 menu->MacBeforeDisplay( false ) ;
e40298d5
JS
1074 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
1075 }
51abe921
SC
1076
1077 Refresh();
1078 }
1079
0f4c4140 1080 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
7c15086c
SC
1081 // adding menu later on.
1082 if (m_invokingWindow)
1083 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
1084
902725ee 1085 return true;
51abe921
SC
1086}
1087
2b5f62a0
VZ
1088static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
1089{
1090 menu->SetInvokingWindow( (wxWindow*) NULL );
71f2fb52 1091 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
5977edb9 1092
2b5f62a0
VZ
1093 while (node)
1094 {
1095 wxMenuItem *menuitem = node->GetData();
1096 if (menuitem->IsSubMenu())
1097 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
5977edb9 1098
2b5f62a0
VZ
1099 node = node->GetNext();
1100 }
1101}
1102
1103static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
1104{
1105 menu->SetInvokingWindow( win );
5977edb9 1106 wxMenuItem *menuitem;
71f2fb52 1107 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
5977edb9 1108
2b5f62a0
VZ
1109 while (node)
1110 {
5977edb9 1111 menuitem = node->GetData();
2b5f62a0
VZ
1112 if (menuitem->IsSubMenu())
1113 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
5977edb9 1114
2b5f62a0
VZ
1115 node = node->GetNext();
1116 }
1117}
1118
1119void wxMenuBar::UnsetInvokingWindow()
1120{
7c15086c 1121 m_invokingWindow = (wxWindow*) NULL;
5977edb9 1122 wxMenu *menu;
71f2fb52 1123 wxMenuList::compatibility_iterator node = m_menus.GetFirst();
5977edb9 1124
2b5f62a0
VZ
1125 while (node)
1126 {
5977edb9 1127 menu = node->GetData();
2b5f62a0 1128 wxMenubarUnsetInvokingWindow( menu );
5977edb9 1129
2b5f62a0
VZ
1130 node = node->GetNext();
1131 }
1132}
1133
1134void wxMenuBar::SetInvokingWindow(wxFrame *frame)
1135{
7c15086c 1136 m_invokingWindow = frame;
5977edb9 1137 wxMenu *menu;
71f2fb52 1138 wxMenuList::compatibility_iterator node = m_menus.GetFirst();
5977edb9 1139
2b5f62a0
VZ
1140 while (node)
1141 {
5977edb9 1142 menu = node->GetData();
2b5f62a0 1143 wxMenubarSetInvokingWindow( menu, frame );
5977edb9 1144
2b5f62a0
VZ
1145 node = node->GetNext();
1146 }
1147}
1148
90b959ae 1149void wxMenuBar::Detach()
2f1ae414 1150{
90b959ae
SC
1151 wxMenuBarBase::Detach() ;
1152}
2f1ae414 1153
90b959ae
SC
1154void wxMenuBar::Attach(wxFrame *frame)
1155{
1156 wxMenuBarBase::Attach( frame ) ;
2f1ae414 1157}
5977edb9 1158
51abe921
SC
1159// ---------------------------------------------------------------------------
1160// wxMenuBar searching for menu items
1161// ---------------------------------------------------------------------------
1162
1163// Find the itemString in menuString, and return the item id or wxNOT_FOUND
1164int wxMenuBar::FindMenuItem(const wxString& menuString,
1165 const wxString& itemString) const
1166{
1167 wxString menuLabel = wxStripMenuCodes(menuString);
1168 size_t count = GetMenuCount();
1169 for ( size_t i = 0; i < count; i++ )
1170 {
1171 wxString title = wxStripMenuCodes(m_titles[i]);
ef089805 1172 if ( menuLabel == title )
71f2fb52 1173 return _wxMenuAt(m_menus, i)->FindItem(itemString);
51abe921
SC
1174 }
1175
1176 return wxNOT_FOUND;
1177}
1178
1179wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
1180{
1181 if ( itemMenu )
1182 *itemMenu = NULL;
1183
1184 wxMenuItem *item = NULL;
1185 size_t count = GetMenuCount();
1186 for ( size_t i = 0; !item && (i < count); i++ )
71f2fb52 1187 item = _wxMenuAt(m_menus, i)->FindItem(id, itemMenu);
51abe921
SC
1188
1189 return item;
1190}