]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/menu.cpp
Document the cfstring.h/cfstring.cpp as being used by all Darwin ports (it's
[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 {
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
570 if ( targetWindow->GetEventHandler()->ProcessEvent(event) )
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 {
604 processed = win->GetEventHandler()->ProcessEvent(event);
605 break;
606 }
607
608 menu = menu->GetParent();
609 }
610 }
611
612 if ( !processed && targetWindow != NULL)
613 {
614 processed = targetWindow->GetEventHandler()->ProcessEvent(event);
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
SC
714#if TARGET_API_MAC_OSX
715 menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
716#else
717 menubar = NewHandleClear( 12 ) ;
718 (*menubar)[3] = 0x0a ;
719#endif
5977edb9 720
2b8a6962 721 ::SetMenuBar( menubar ) ;
dd05f811 722 DisposeMenuBar( menubar ) ;
cda73c27 723 MenuHandle appleMenu = NULL ;
cda73c27
SC
724
725 verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
4f74e0d1 726 verify_noerr( SetMenuTitleWithCFString( appleMenu , CFSTR( "\x14" ) ) );
23c6ddc8 727
262ce38a
KH
728 // Add About/Preferences separator only on OS X
729 // KH/RN: Separator is always present on 10.3 but not on 10.2
730 // However, the change from 10.2 to 10.3 suggests it is preferred
731#if TARGET_API_MAC_OSX
4f74e0d1 732 InsertMenuItemTextWithCFString( appleMenu,
90f58090 733 CFSTR(""), 0, kMenuItemAttrSeparator, 0);
262ce38a 734#endif
4f74e0d1 735 InsertMenuItemTextWithCFString( appleMenu,
90f58090 736 CFSTR("About..."), 0, 0, 0);
cda73c27
SC
737 MacInsertMenu( appleMenu , 0 ) ;
738
4dd25308
VZ
739 // if we have a mac help menu, clean it up before adding new items
740 MenuHandle helpMenuHandle ;
741 MenuItemIndex firstUserHelpMenuItem ;
902725ee 742
4dd25308 743 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) == noErr )
e40298d5 744 {
4dd25308
VZ
745 for ( int i = CountMenuItems( helpMenuHandle ) ; i >= firstUserHelpMenuItem ; --i )
746 DeleteMenuItem( helpMenuHandle , i ) ;
747 }
748 else
749 {
750 helpMenuHandle = NULL ;
e40298d5 751 }
5977edb9 752
03561a3c 753 if ( wxApp::s_macPreferencesMenuItemId)
e40298d5
JS
754 {
755 wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
756 if ( item == NULL || !(item->IsEnabled()) )
757 DisableMenuCommand( NULL , kHICommandPreferences ) ;
758 else
759 EnableMenuCommand( NULL , kHICommandPreferences ) ;
760 }
5977edb9 761
3e275c2d
KH
762 // Unlike preferences which may or may not exist, the Quit item should be always
763 // enabled unless it is added by the application and then disabled, otherwise
764 // a program would be required to add an item with wxID_EXIT in order to get the
765 // Quit menu item to be enabled, which seems a bit burdensome.
03561a3c 766 if ( wxApp::s_macExitMenuItemId)
e9626c1b
KH
767 {
768 wxMenuItem *item = FindItem( wxApp::s_macExitMenuItemId , NULL ) ;
3e275c2d 769 if ( item != NULL && !(item->IsEnabled()) )
e9626c1b
KH
770 DisableMenuCommand( NULL , kHICommandQuit ) ;
771 else
772 EnableMenuCommand( NULL , kHICommandQuit ) ;
773 }
5977edb9 774
4dd25308
VZ
775 wxString strippedHelpMenuTitle = wxStripMenuCodes( wxApp::s_macHelpMenuTitleName ) ;
776 wxString strippedTranslatedHelpMenuTitle = wxStripMenuCodes( wxString( _("&Help") ) ) ;
6524e8f0 777 wxMenuList::compatibility_iterator menuIter = m_menus.GetFirst();
6524e8f0
SC
778 for (size_t i = 0; i < m_menus.GetCount(); i++, menuIter = menuIter->GetNext())
779 {
71f2fb52 780 wxMenuItemList::compatibility_iterator node;
2b5f62a0 781 wxMenuItem *item;
71f2fb52 782 wxMenu* menu = menuIter->GetData() , *subMenu = NULL ;
4dd25308 783 wxString strippedMenuTitle = wxStripMenuCodes(m_titles[i]);
e40298d5 784
4dd25308 785 if ( strippedMenuTitle == wxT("?") || strippedMenuTitle == strippedHelpMenuTitle || strippedMenuTitle == strippedTranslatedHelpMenuTitle )
e40298d5 786 {
716d0327 787 for (node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext())
e40298d5 788 {
6524e8f0
SC
789 item = (wxMenuItem *)node->GetData();
790 subMenu = item->GetSubMenu() ;
58751a86 791 if (subMenu)
e40298d5
JS
792 {
793 // we don't support hierarchical menus in the help menu yet
794 }
58751a86 795 else
e40298d5 796 {
6524e8f0
SC
797 if ( item->GetId() != wxApp::s_macAboutMenuItemId )
798 {
4dd25308
VZ
799 // we have found a user help menu and an item other than the about item,
800 // so we can create the mac help menu now, if we haven't created it yet
801 if ( helpMenuHandle == NULL )
6524e8f0 802 {
4dd25308 803 if ( UMAGetHelpMenu( &helpMenuHandle , &firstUserHelpMenuItem) != noErr )
6524e8f0 804 {
4dd25308 805 helpMenuHandle = NULL ;
6524e8f0 806 break ;
902725ee 807 }
6524e8f0
SC
808 }
809 }
5977edb9 810
e40298d5
JS
811 if ( item->IsSeparator() )
812 {
4dd25308
VZ
813 if ( helpMenuHandle )
814 AppendMenuItemTextWithCFString( helpMenuHandle,
90f58090 815 CFSTR(""), kMenuItemAttrSeparator, 0,NULL);
e40298d5
JS
816 }
817 else
818 {
90527a50 819 wxAcceleratorEntry*
9a9c35d3 820 entry = wxAcceleratorEntry::Create( item->GetItemLabel() ) ;
e40298d5
JS
821
822 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
58751a86 823 {
6524e8f0
SC
824 // this will be taken care of below
825 }
e40298d5
JS
826 else
827 {
4dd25308 828 if ( helpMenuHandle )
e40298d5 829 {
9a9c35d3 830 UMAAppendMenuItem(helpMenuHandle, wxStripMenuCodes(item->GetItemLabel()) , wxFont::GetDefaultEncoding(), entry);
4dd25308
VZ
831 SetMenuItemCommandID( helpMenuHandle , CountMenuItems(helpMenuHandle) , wxIdToMacCommand ( item->GetId() ) ) ;
832 SetMenuItemRefCon( helpMenuHandle , CountMenuItems(helpMenuHandle) , (URefCon) item ) ;
e40298d5
JS
833 }
834 }
58751a86 835
e40298d5
JS
836 delete entry ;
837 }
838 }
839 }
840 }
90f58090
VZ
841
842 else if ( ( m_titles[i] == wxT("Window") || m_titles[i] == wxT("&Window") )
e608ff58 843 && GetAutoWindowMenu() )
90f58090 844 {
e608ff58
KO
845 if ( MacGetWindowMenuHMenu() == NULL )
846 {
847 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
848 }
90f58090 849
e608ff58
KO
850 MenuRef wm = (MenuRef)MacGetWindowMenuHMenu();
851 if ( wm == NULL )
852 break;
90f58090 853
e608ff58
KO
854 // get the insertion point in the standard menu
855 MenuItemIndex winListStart;
90f58090 856 GetIndMenuItemWithCommandID(wm,
e608ff58 857 kHICommandWindowListSeparator, 1, NULL, &winListStart);
90f58090 858
e608ff58
KO
859 // add a separator so that the standard items and the custom items
860 // aren't mixed together, but only if this is the first run
90f58090 861 OSStatus err = GetIndMenuItemWithCommandID(wm,
e608ff58 862 'WXWM', 1, NULL, NULL);
90f58090 863
e608ff58
KO
864 if ( err == menuItemNotFoundErr )
865 {
866 InsertMenuItemTextWithCFString( wm,
867 CFSTR(""), winListStart-1, kMenuItemAttrSeparator, 'WXWM');
868 }
90f58090
VZ
869
870 wxInsertMenuItemsInMenu(menu, wm, winListStart);
e608ff58 871 }
e40298d5
JS
872 else
873 {
a9412f8f 874 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], m_font.GetEncoding() ) ;
71f2fb52 875 menu->MacBeforeDisplay(false) ;
90f58090 876
71f2fb52 877 ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus, i)->GetHMenu()), 0);
e40298d5
JS
878 }
879 }
5977edb9 880
6524e8f0
SC
881 // take care of the about menu item wherever it is
882 {
883 wxMenu* aboutMenu ;
884 wxMenuItem *aboutMenuItem = FindItem(wxApp::s_macAboutMenuItemId , &aboutMenu) ;
885 if ( aboutMenuItem )
886 {
90527a50 887 wxAcceleratorEntry*
9a9c35d3
JS
888 entry = wxAcceleratorEntry::Create( aboutMenuItem->GetItemLabel() ) ;
889 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , wxStripMenuCodes ( aboutMenuItem->GetItemLabel() ) , wxFont::GetDefaultEncoding() );
6524e8f0 890 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
ca71e3ae 891 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , kHICommandAbout ) ;
4f74e0d1 892 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (URefCon)aboutMenuItem ) ;
6524e8f0
SC
893 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
894 }
895 }
5977edb9 896
22e3c5bd
SC
897 if ( GetAutoWindowMenu() )
898 {
899 if ( MacGetWindowMenuHMenu() == NULL )
22e3c5bd 900 CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
5977edb9 901
22e3c5bd
SC
902 InsertMenu( (MenuHandle) MacGetWindowMenuHMenu() , 0 ) ;
903 }
5977edb9 904
e40298d5
JS
905 ::DrawMenuBar() ;
906 s_macInstalledMenuBar = this;
519cb848
SC
907}
908
e7549107 909void wxMenuBar::EnableTop(size_t pos, bool enable)
e9576ca5 910{
e7549107 911 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
5977edb9 912
71f2fb52 913 _wxMenuAt(m_menus, pos)->MacEnableMenu( enable ) ;
e7549107 914 Refresh();
e9576ca5
SC
915}
916
5977edb9 917bool wxMenuBar::Enable(bool enable)
c393c740 918{
5059f192 919 wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
5977edb9 920
c393c740
JS
921 size_t i;
922 for (i = 0; i < GetMenuCount(); i++)
c393c740 923 EnableTop(i, enable);
5977edb9 924
c393c740
JS
925 return true;
926}
927
52af3158 928void wxMenuBar::SetMenuLabel(size_t pos, const wxString& label)
e9576ca5 929{
e7549107 930 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 931
e7549107 932 m_titles[pos] = label;
e9576ca5 933
e7549107 934 if ( !IsAttached() )
e9576ca5
SC
935 return;
936
71f2fb52
RN
937 _wxMenuAt(m_menus, pos)->SetTitle( label ) ;
938
e40298d5
JS
939 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
940 {
941 ::SetMenuBar( GetMenuBar() ) ;
942 ::InvalMenuBar() ;
943 }
e9576ca5
SC
944}
945
52af3158 946wxString wxMenuBar::GetMenuLabel(size_t pos) const
e9576ca5 947{
e7549107 948 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
52af3158 949 wxT("invalid menu index in wxMenuBar::GetMenuLabel") );
519cb848 950
e7549107 951 return m_titles[pos];
e9576ca5
SC
952}
953
e7549107 954int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 955{
e7549107 956 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 957
e7549107
SC
958 size_t count = GetMenuCount();
959 for ( size_t i = 0; i < count; i++ )
e9576ca5 960 {
e7549107
SC
961 wxString title = wxStripMenuCodes(m_titles[i]);
962 if ( menuTitle == title )
58751a86 963 return i;
e9576ca5 964 }
e9576ca5 965
e7549107 966 return wxNOT_FOUND;
e9576ca5
SC
967}
968
e7549107
SC
969// ---------------------------------------------------------------------------
970// wxMenuBar construction
971// ---------------------------------------------------------------------------
972
973wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 974{
e7549107
SC
975 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
976 if ( !menuOld )
a8fb9ede 977 return NULL;
5977edb9 978
e7549107 979 m_titles[pos] = title;
e9576ca5 980
e7549107 981 if ( IsAttached() )
e9576ca5 982 {
e40298d5
JS
983 if (s_macInstalledMenuBar == this)
984 {
d46342af 985 menuOld->MacAfterDisplay( false ) ;
e40298d5 986 ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
5977edb9
DS
987
988 menu->MacBeforeDisplay( false ) ;
989 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
990 if ( pos == m_menus.GetCount() - 1)
991 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
992 else
993 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos + 1)->MacGetMenuId() ) ;
e40298d5 994 }
e9576ca5 995
e7549107 996 Refresh();
e9576ca5 997 }
5977edb9 998
0f4c4140
SC
999 if (m_invokingWindow)
1000 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
e9576ca5 1001
e7549107 1002 return menuOld;
e9576ca5
SC
1003}
1004
e7549107 1005bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 1006{
e7549107 1007 if ( !wxMenuBarBase::Insert(pos, menu, title) )
902725ee 1008 return false;
e9576ca5 1009
e7549107 1010 m_titles.Insert(title, pos);
e9576ca5 1011
a9412f8f 1012 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
e7549107 1013
d46342af 1014 if ( IsAttached() && s_macInstalledMenuBar == this )
e9576ca5 1015 {
d46342af 1016 if (s_macInstalledMenuBar == this)
e40298d5 1017 {
d46342af 1018 menu->MacBeforeDisplay( false ) ;
5977edb9 1019
d46342af 1020 if ( pos == (size_t) -1 || pos + 1 == m_menus.GetCount() )
d46342af 1021 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
d46342af 1022 else
71f2fb52 1023 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos+1)->MacGetMenuId() ) ;
e40298d5 1024 }
5977edb9 1025
e7549107 1026 Refresh();
e9576ca5 1027 }
5977edb9 1028
0f4c4140
SC
1029 if (m_invokingWindow)
1030 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
e7549107 1031
902725ee 1032 return true;
e9576ca5
SC
1033}
1034
51abe921
SC
1035wxMenu *wxMenuBar::Remove(size_t pos)
1036{
1037 wxMenu *menu = wxMenuBarBase::Remove(pos);
1038 if ( !menu )
1039 return NULL;
1040
1041 if ( IsAttached() )
1042 {
e40298d5 1043 if (s_macInstalledMenuBar == this)
e40298d5 1044 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
51abe921 1045
51abe921
SC
1046 Refresh();
1047 }
1048
5fe38474 1049 m_titles.RemoveAt(pos);
51abe921
SC
1050
1051 return menu;
1052}
1053
1054bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
1055{
1056 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
5977edb9 1057 wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
51abe921
SC
1058
1059 if ( !wxMenuBarBase::Append(menu, title) )
902725ee 1060 return false;
51abe921 1061
51abe921 1062 m_titles.Add(title);
58751a86 1063
a9412f8f 1064 UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
51abe921
SC
1065
1066 if ( IsAttached() )
1067 {
e40298d5
JS
1068 if (s_macInstalledMenuBar == this)
1069 {
94c80d52 1070 menu->MacBeforeDisplay( false ) ;
e40298d5
JS
1071 ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
1072 }
51abe921
SC
1073
1074 Refresh();
1075 }
1076
0f4c4140 1077 // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
7c15086c
SC
1078 // adding menu later on.
1079 if (m_invokingWindow)
1080 wxMenubarSetInvokingWindow( menu, m_invokingWindow );
1081
902725ee 1082 return true;
51abe921
SC
1083}
1084
2b5f62a0
VZ
1085static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
1086{
1087 menu->SetInvokingWindow( (wxWindow*) NULL );
71f2fb52 1088 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
5977edb9 1089
2b5f62a0
VZ
1090 while (node)
1091 {
1092 wxMenuItem *menuitem = node->GetData();
1093 if (menuitem->IsSubMenu())
1094 wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
5977edb9 1095
2b5f62a0
VZ
1096 node = node->GetNext();
1097 }
1098}
1099
1100static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
1101{
1102 menu->SetInvokingWindow( win );
5977edb9 1103 wxMenuItem *menuitem;
71f2fb52 1104 wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
5977edb9 1105
2b5f62a0
VZ
1106 while (node)
1107 {
5977edb9 1108 menuitem = node->GetData();
2b5f62a0
VZ
1109 if (menuitem->IsSubMenu())
1110 wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
5977edb9 1111
2b5f62a0
VZ
1112 node = node->GetNext();
1113 }
1114}
1115
1116void wxMenuBar::UnsetInvokingWindow()
1117{
7c15086c 1118 m_invokingWindow = (wxWindow*) NULL;
5977edb9 1119 wxMenu *menu;
71f2fb52 1120 wxMenuList::compatibility_iterator node = m_menus.GetFirst();
5977edb9 1121
2b5f62a0
VZ
1122 while (node)
1123 {
5977edb9 1124 menu = node->GetData();
2b5f62a0 1125 wxMenubarUnsetInvokingWindow( menu );
5977edb9 1126
2b5f62a0
VZ
1127 node = node->GetNext();
1128 }
1129}
1130
1131void wxMenuBar::SetInvokingWindow(wxFrame *frame)
1132{
7c15086c 1133 m_invokingWindow = frame;
5977edb9 1134 wxMenu *menu;
71f2fb52 1135 wxMenuList::compatibility_iterator node = m_menus.GetFirst();
5977edb9 1136
2b5f62a0
VZ
1137 while (node)
1138 {
5977edb9 1139 menu = node->GetData();
2b5f62a0 1140 wxMenubarSetInvokingWindow( menu, frame );
5977edb9 1141
2b5f62a0
VZ
1142 node = node->GetNext();
1143 }
1144}
1145
90b959ae 1146void wxMenuBar::Detach()
2f1ae414 1147{
90b959ae
SC
1148 wxMenuBarBase::Detach() ;
1149}
2f1ae414 1150
90b959ae
SC
1151void wxMenuBar::Attach(wxFrame *frame)
1152{
1153 wxMenuBarBase::Attach( frame ) ;
2f1ae414 1154}
5977edb9 1155
51abe921
SC
1156// ---------------------------------------------------------------------------
1157// wxMenuBar searching for menu items
1158// ---------------------------------------------------------------------------
1159
1160// Find the itemString in menuString, and return the item id or wxNOT_FOUND
1161int wxMenuBar::FindMenuItem(const wxString& menuString,
1162 const wxString& itemString) const
1163{
1164 wxString menuLabel = wxStripMenuCodes(menuString);
1165 size_t count = GetMenuCount();
1166 for ( size_t i = 0; i < count; i++ )
1167 {
1168 wxString title = wxStripMenuCodes(m_titles[i]);
ef089805 1169 if ( menuLabel == title )
71f2fb52 1170 return _wxMenuAt(m_menus, i)->FindItem(itemString);
51abe921
SC
1171 }
1172
1173 return wxNOT_FOUND;
1174}
1175
1176wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
1177{
1178 if ( itemMenu )
1179 *itemMenu = NULL;
1180
1181 wxMenuItem *item = NULL;
1182 size_t count = GetMenuCount();
1183 for ( size_t i = 0; !item && (i < count); i++ )
71f2fb52 1184 item = _wxMenuAt(m_menus, i)->FindItem(id, itemMenu);
51abe921
SC
1185
1186 return item;
1187}