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