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