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