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