]> git.saurik.com Git - wxWidgets.git/blame - src/mac/menu.cpp
1. added wxAssertIsEqual() function to be used in wxASSERT()
[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
13// ============================================================================
14// headers & declarations
15// ============================================================================
16
17// wxWindows headers
18// -----------------
19
20#ifdef __GNUG__
21#pragma implementation "menu.h"
22#pragma implementation "menuitem.h"
23#endif
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"
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;
45static int formerHelpMenuItems = 0 ;
46
47const short kwxMacMenuBarResource = 1 ;
48const short kwxMacAppleMenuId = 1 ;
49
e9576ca5
SC
50// ============================================================================
51// implementation
52// ============================================================================
53
519cb848 54
e9576ca5
SC
55// Menus
56
57// Construct a menu with optional title (then use append)
519cb848 58
82ca6dbc
GD
59#ifdef __UNIX__
60short wxMenu::s_macNextMenuId = 3 ;
61#else
519cb848 62short wxMenu::s_macNextMenuId = 2 ;
82ca6dbc 63#endif
519cb848 64
e7549107 65void wxMenu::Init()
e9576ca5 66{
e7549107
SC
67 m_doBreak = FALSE;
68
69 // create the menu
70 Str255 label;
2f1ae414 71 wxMenuItem::MacBuildMenuString( label, NULL , NULL , m_title , false );
e7549107
SC
72 m_macMenuId = s_macNextMenuId++;
73 wxCHECK_RET( s_macNextMenuId < 236 , "menu ids > 235 cannot be used for submenus on mac" );
2f1ae414 74 m_hMenu = UMANewMenu(m_macMenuId, label);
e7549107
SC
75
76 if ( !m_hMenu )
77 {
78 wxLogLastError("CreatePopupMenu");
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{
91 if (m_hMenu)
2f1ae414 92 UMADisposeMenu(m_hMenu);
e9576ca5 93
e7549107
SC
94#if wxUSE_ACCEL
95 // delete accels
96 WX_CLEAR_ARRAY(m_accels);
97#endif // wxUSE_ACCEL
e9576ca5
SC
98}
99
e7549107 100void wxMenu::Break()
e9576ca5 101{
e7549107
SC
102 // not available on the mac platform
103}
e9576ca5 104
e7549107 105#if wxUSE_ACCEL
e9576ca5 106
e7549107
SC
107int wxMenu::FindAccel(int id) const
108{
109 size_t n, count = m_accels.GetCount();
110 for ( n = 0; n < count; n++ )
111 {
112 if ( m_accels[n]->m_command == id )
113 return n;
e9576ca5 114 }
e7549107
SC
115
116 return wxNOT_FOUND;
e9576ca5
SC
117}
118
e7549107 119void wxMenu::UpdateAccel(wxMenuItem *item)
e9576ca5 120{
e7549107
SC
121 // find the (new) accel for this item
122 wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
123 if ( accel )
124 accel->m_command = item->GetId();
125
126 // find the old one
127 int n = FindAccel(item->GetId());
128 if ( n == wxNOT_FOUND )
129 {
130 // no old, add new if any
131 if ( accel )
132 m_accels.Add(accel);
133 else
134 return; // skipping RebuildAccelTable() below
135 }
136 else
137 {
138 // replace old with new or just remove the old one if no new
139 delete m_accels[n];
140 if ( accel )
141 m_accels[n] = accel;
142 else
143 m_accels.Remove(n);
144 }
145
146 if ( IsAttached() )
147 {
148 m_menuBar->RebuildAccelTable();
149 }
e9576ca5
SC
150}
151
e7549107
SC
152#endif // wxUSE_ACCEL
153
e9576ca5 154// function appends a new item or submenu to the menu
e7549107
SC
155// append a new item or submenu to the menu
156bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
e9576ca5 157{
e7549107
SC
158 wxASSERT_MSG( pItem != NULL, "can't append NULL item to the menu" );
159#if wxUSE_ACCEL
160 UpdateAccel(pItem);
161#endif // wxUSE_ACCEL
e9576ca5 162
519cb848
SC
163 if ( pItem->IsSeparator() )
164 {
e7549107
SC
165 if ( pos == (size_t)-1 )
166 {
167 MacAppendMenu(m_hMenu, "\p-");
168 }
169 else
170 {
171 MacInsertMenuItem(m_hMenu, "\p-" , pos);
172 }
519cb848
SC
173 }
174 else
175 {
176 wxMenu *pSubMenu = pItem->GetSubMenu() ;
177 if ( pSubMenu != NULL )
178 {
179 Str255 label;
e7549107
SC
180 wxASSERT_MSG( pSubMenu->m_hMenu != NULL , "invalid submenu added");
181 pSubMenu->m_menuParent = this ;
2f1ae414 182 wxMenuItem::MacBuildMenuString( label , NULL , NULL , pItem->GetText() ,false);
519cb848 183
e7549107 184 if (wxMenuBar::MacGetInstalledMenuBar() == m_menuBar)
519cb848 185 {
2f1ae414 186 UMAInsertMenu( pSubMenu->m_hMenu , -1 ) ;
519cb848
SC
187 }
188
e7549107
SC
189 if ( pos == (size_t)-1 )
190 {
2f1ae414 191 UMAAppendSubMenuItem(m_hMenu, label, pSubMenu->m_macMenuId);
e7549107
SC
192 }
193 else
194 {
2f1ae414 195 UMAInsertSubMenuItem(m_hMenu, label , pos, pSubMenu->m_macMenuId);
e7549107 196 }
519cb848
SC
197 }
198 else
199 {
200 Str255 label ;
2f1ae414
SC
201 UInt8 modifiers ;
202 SInt16 key ;
203 wxMenuItem::MacBuildMenuString( label, &key , &modifiers , pItem->GetText(), pItem->GetId() == wxApp::s_macAboutMenuItemId);
519cb848
SC
204 if ( label[0] == 0 )
205 {
206 // we cannot add empty menus on mac
207 label[0] = 1 ;
208 label[1] = ' ' ;
209 }
e7549107
SC
210 if ( pos == (size_t)-1 )
211 {
2f1ae414 212 UMAAppendMenuItem(m_hMenu, label,key,modifiers);
e7549107
SC
213 }
214 else
215 {
2f1ae414 216 UMAInsertMenuItem(m_hMenu, label , pos,key,modifiers);
e7549107 217 }
519cb848
SC
218 if ( pItem->GetId() == idMenuTitle )
219 {
e7549107
SC
220 if ( pos == (size_t)-1 )
221 {
2f1ae414 222 UMADisableMenuItem( m_hMenu , CountMenuItems( m_hMenu ) ) ;
e7549107
SC
223 }
224 else
225 {
226 UMADisableMenuItem( m_hMenu , pos + 1 ) ;
227 }
519cb848
SC
228 }
229 }
230 }
e7549107
SC
231 // if we're already attached to the menubar, we must update it
232 if ( IsAttached() )
233 {
234 m_menuBar->Refresh();
235 }
236 return TRUE ;
e9576ca5
SC
237}
238
e7549107 239bool wxMenu::DoAppend(wxMenuItem *item)
e9576ca5 240{
e7549107 241 return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
e9576ca5
SC
242}
243
e7549107 244bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
e9576ca5 245{
e7549107 246 return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
e9576ca5
SC
247}
248
e7549107 249wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
e9576ca5 250{
e7549107
SC
251 // we need to find the items position in the child list
252 size_t pos;
253 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
254 for ( pos = 0; node; pos++ )
255 {
256 if ( node->GetData() == item )
257 break;
e9576ca5 258
e7549107 259 node = node->GetNext();
e9576ca5
SC
260 }
261
e7549107
SC
262 // DoRemove() (unlike Remove) can only be called for existing item!
263 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
519cb848 264
e7549107
SC
265#if wxUSE_ACCEL
266 // remove the corresponding accel from the accel table
267 int n = FindAccel(item->GetId());
268 if ( n != wxNOT_FOUND )
269 {
270 delete m_accels[n];
519cb848 271
e7549107
SC
272 m_accels.Remove(n);
273 }
274 //else: this item doesn't have an accel, nothing to do
275#endif // wxUSE_ACCEL
e9576ca5 276
e7549107 277 ::DeleteMenuItem( m_hMenu , pos + 1);
e9576ca5 278
e7549107
SC
279 if ( IsAttached() )
280 {
281 // otherwise, the chane won't be visible
282 m_menuBar->Refresh();
283 }
e9576ca5 284
e7549107
SC
285 // and from internal data structures
286 return wxMenuBase::DoRemove(item);
e9576ca5
SC
287}
288
e7549107
SC
289// ---------------------------------------------------------------------------
290// accelerator helpers
291// ---------------------------------------------------------------------------
e9576ca5 292
e7549107 293#if wxUSE_ACCEL
e9576ca5 294
e7549107
SC
295// create the wxAcceleratorEntries for our accels and put them into provided
296// array - return the number of accels we have
297size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
e9576ca5 298{
e7549107
SC
299 size_t count = GetAccelCount();
300 for ( size_t n = 0; n < count; n++ )
301 {
302 *accels++ = *m_accels[n];
303 }
e9576ca5 304
e7549107 305 return count;
e9576ca5
SC
306}
307
e7549107 308#endif // wxUSE_ACCEL
e9576ca5
SC
309
310void wxMenu::SetTitle(const wxString& label)
311{
519cb848 312 Str255 title ;
e9576ca5 313 m_title = label ;
2f1ae414 314 wxMenuItem::MacBuildMenuString( title, NULL , NULL , label , false );
e7549107 315 UMASetMenuTitle( m_hMenu , title ) ;
e9576ca5 316}
e7549107 317bool wxMenu::ProcessCommand(wxCommandEvent & event)
e9576ca5
SC
318{
319 bool processed = FALSE;
320
e7549107 321#if WXWIN_COMPATIBILITY
e9576ca5
SC
322 // Try a callback
323 if (m_callback)
324 {
e7549107
SC
325 (void)(*(m_callback))(*this, event);
326 processed = TRUE;
e9576ca5 327 }
e7549107 328#endif WXWIN_COMPATIBILITY
e9576ca5
SC
329
330 // Try the menu's event handler
331 if ( !processed && GetEventHandler())
332 {
e7549107 333 processed = GetEventHandler()->ProcessEvent(event);
e9576ca5 334 }
519cb848 335
e7549107
SC
336 // Try the window the menu was popped up from (and up through the
337 // hierarchy)
338 wxWindow *win = GetInvokingWindow();
339 if ( !processed && win )
340 processed = win->GetEventHandler()->ProcessEvent(event);
341
342 return processed;
343}
344
345
346// ---------------------------------------------------------------------------
347// other
348// ---------------------------------------------------------------------------
349
350void wxMenu::Attach(wxMenuBar *menubar)
351{
352 // menu can be in at most one menubar because otherwise they would both
353 // delete the menu pointer
354 wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") );
355
356 m_menuBar = menubar;
e9576ca5
SC
357}
358
e7549107
SC
359void wxMenu::Detach()
360{
361 wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
362
363 m_menuBar = NULL;
364}
365
366wxWindow *wxMenu::GetWindow() const
367{
368 if ( m_invokingWindow != NULL )
369 return m_invokingWindow;
370 else if ( m_menuBar != NULL)
03e11df5 371 return (wxWindow *) m_menuBar->GetFrame();
e7549107
SC
372
373 return NULL;
374}
519cb848 375
519cb848
SC
376// helper functions returning the mac menu position for a certain item, note that this is
377// mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
378
379int wxMenu::MacGetIndexFromId( int id )
380{
e7549107
SC
381 size_t pos;
382 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
383 for ( pos = 0; node; pos++ )
519cb848 384 {
e7549107
SC
385 if ( node->GetData()->GetId() == id )
386 break;
519cb848 387
e7549107
SC
388 node = node->GetNext();
389 }
390
519cb848
SC
391 if (!node)
392 return 0;
393
394 return pos + 1 ;
395}
396
397int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
398{
e7549107
SC
399 size_t pos;
400 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
401 for ( pos = 0; node; pos++ )
519cb848 402 {
e7549107
SC
403 if ( node->GetData() == pItem )
404 break;
405
406 node = node->GetNext();
519cb848
SC
407 }
408
409 if (!node)
410 return 0;
411
412 return pos + 1 ;
413}
414
415void wxMenu::MacEnableMenu( bool bDoEnable )
416{
519cb848 417 if ( bDoEnable )
e7549107 418 UMAEnableMenuItem( m_hMenu , 0 ) ;
519cb848 419 else
e7549107 420 UMADisableMenuItem( m_hMenu , 0 ) ;
519cb848
SC
421
422 ::DrawMenuBar() ;
423}
424
425bool wxMenu::MacMenuSelect( wxEvtHandler* handler, long when , int macMenuId, int macMenuItemNum )
426{
427 int pos;
428 wxNode *node;
429
430 if ( m_macMenuId == macMenuId )
431 {
e7549107 432 node = GetMenuItems().Nth(macMenuItemNum-1);
519cb848
SC
433 if (node)
434 {
435 wxMenuItem *pItem = (wxMenuItem*)node->Data();
2f1ae414
SC
436
437 if (pItem->IsCheckable())
438 pItem->Check(! pItem->IsChecked());
439
519cb848
SC
440 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, pItem->GetId());
441 event.m_timeStamp = when;
442 event.SetEventObject(handler);
e7549107 443 event.SetInt( pItem->GetId() );
51abe921
SC
444 {
445 bool processed = false ;
446
447#if WXWIN_COMPATIBILITY
448 // Try a callback
449 if (m_callback)
450 {
451 (void) (*(m_callback)) (*this, event);
452 processed = TRUE;
453 }
454#endif
455 // Try the menu's event handler
456 if ( !processed && handler)
457 {
458 processed = handler->ProcessEvent(event);
459 }
460
461 // Try the window the menu was popped up from (and up
462 // through the hierarchy)
463 if ( !processed && GetInvokingWindow())
464 processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event);
465 }
519cb848
SC
466 return true ;
467 }
468 }
03e11df5 469#ifndef __WXMAC_X__
519cb848
SC
470 else if ( macMenuId == kHMHelpMenuID )
471 {
472 int menuItem = formerHelpMenuItems ;
e7549107 473 for (pos = 0, node = GetMenuItems().First(); node; node = node->Next(), pos++)
519cb848
SC
474 {
475 wxMenuItem * pItem = (wxMenuItem *) node->Data() ;
476
477 wxMenu *pSubMenu = pItem->GetSubMenu() ;
478 if ( pSubMenu != NULL )
479 {
480 }
481 else
482 {
483 if ( pItem->GetId() != wxApp::s_macAboutMenuItemId )
484 ++menuItem ;
485
486 if ( menuItem == macMenuItemNum )
487 {
488 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, pItem->GetId());
489 event.m_timeStamp = when;
490 event.SetEventObject(handler);
e7549107 491 event.SetInt( pItem->GetId() );
51abe921
SC
492 {
493 bool processed = false ;
494#if WXWIN_COMPATIBILITY
495 // Try a callback
496 if (m_callback)
497 {
498 (void) (*(m_callback)) (*this, event);
499 processed = TRUE;
500 }
501#endif
502 // Try the menu's event handler
503 if ( !processed && handler)
504 {
505 processed = handler->ProcessEvent(event);
506 }
507
508 // Try the window the menu was popped up from (and up
509 // through the hierarchy)
510 if ( !processed && GetInvokingWindow())
511 processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event);
512 }
519cb848
SC
513 return true ;
514 }
515 }
516 }
517 }
03e11df5 518#endif // __WXMAC_X__
519cb848 519
e7549107 520 for (pos = 0, node = GetMenuItems().First(); node; node = node->Next(), pos++)
519cb848 521 {
e7549107 522 wxMenuItem * pItem = (wxMenuItem *) node->Data() ;
519cb848 523
e7549107 524 wxMenu *pSubMenu = pItem->GetSubMenu() ;
519cb848
SC
525 if ( pSubMenu != NULL )
526 {
527 if ( pSubMenu->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
528 return true ;
529 }
530 }
531
532 return false ;
e9576ca5
SC
533}
534
535// Menu Bar
519cb848
SC
536
537/*
538
539Mac Implementation note :
540
541The Mac has only one global menubar, so we attempt to install the currently
542active menubar from a frame, we currently don't take into account mdi-frames
543which would ask for menu-merging
544
545Secondly there is no mac api for changing a menubar that is not the current
546menubar, so we have to wait for preparing the actual menubar until the
547wxMenubar is to be used
548
549We can in subsequent versions use MacInstallMenuBar to provide some sort of
550auto-merge for MDI in case this will be necessary
551
552*/
553
554wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
555
e7549107 556void wxMenuBar::Init()
e9576ca5
SC
557{
558 m_eventHandler = this;
e9576ca5 559 m_menuBarFrame = NULL;
e9576ca5
SC
560}
561
51abe921
SC
562wxMenuBar::wxMenuBar()
563{
564 Init();
565}
566
567wxMenuBar::wxMenuBar( long WXUNUSED(style) )
568{
569 Init();
570}
571
e7549107
SC
572
573wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
e9576ca5 574{
e7549107
SC
575 Init();
576
577 m_titles.Alloc(count);
578
579 for ( int i = 0; i < count; i++ )
580 {
581 m_menus.Append(menus[i]);
582 m_titles.Add(titles[i]);
583
584 menus[i]->Attach(this);
585 }
e9576ca5
SC
586}
587
588wxMenuBar::~wxMenuBar()
589{
519cb848
SC
590 if (s_macInstalledMenuBar == this)
591 {
592 ::ClearMenuBar();
593 s_macInstalledMenuBar = NULL;
594 }
595
e7549107
SC
596}
597
598void wxMenuBar::Refresh()
599{
600 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
e9576ca5 601
e7549107 602 DrawMenuBar();
e9576ca5
SC
603}
604
51abe921
SC
605#if wxUSE_ACCEL
606
607void wxMenuBar::RebuildAccelTable()
608{
609 // merge the accelerators of all menus into one accel table
610 size_t nAccelCount = 0;
611 size_t i, count = GetMenuCount();
612 for ( i = 0; i < count; i++ )
613 {
614 nAccelCount += m_menus[i]->GetAccelCount();
615 }
616
617 if ( nAccelCount )
618 {
619 wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount];
620
621 nAccelCount = 0;
622 for ( i = 0; i < count; i++ )
623 {
624 nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]);
625 }
626
627 m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries);
628
629 delete [] accelEntries;
630 }
631}
632
633#endif // wxUSE_ACCEL
634
635
519cb848
SC
636void wxMenuBar::MacInstallMenuBar()
637{
41f38f4d
SC
638 if ( s_macInstalledMenuBar == this )
639 return ;
640
519cb848
SC
641 Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ;
642 wxString message ;
643 wxCHECK_RET( menubar != NULL, "can't read MBAR resource" );
644 ::SetMenuBar( menubar ) ;
645 ::DisposeHandle( menubar ) ;
646
647 MenuHandle menu = ::GetMenuHandle( kwxMacAppleMenuId ) ;
648 ::AppendResMenu(menu, 'DRVR');
649
e7549107 650 for (int i = 0; i < m_menus.GetCount(); i++)
519cb848
SC
651 {
652 Str255 label;
653 wxNode *node;
654 wxMenuItem *item;
655 int pos ;
656 wxMenu* menu = m_menus[i] , *subMenu = NULL ;
657
2f1ae414
SC
658#if !TARGET_CARBON
659 /* the help menu does not exist in CARBON anymore */
8208e181 660 if( m_titles[i] == "?" || m_titles[i] == "&?" || m_titles[i] == wxApp::s_macHelpMenuTitleName )
519cb848
SC
661 {
662 MenuHandle mh = NULL ;
663 if ( HMGetHelpMenuHandle( &mh ) != noErr )
664 {
665 continue ;
666 }
667 if ( formerHelpMenuItems == 0 )
668 {
669 if( mh )
670 formerHelpMenuItems = CountMenuItems( mh ) ;
671 }
672
2f1ae414
SC
673 for (pos = 0 , node = menu->GetMenuItems().First(); node; node = node->Next(), pos++)
674 {
519cb848
SC
675 item = (wxMenuItem *)node->Data();
676 subMenu = item->GetSubMenu() ;
677 if (subMenu)
678 {
679 // we don't support hierarchical menus in the help menu yet
680 }
681 else
682 {
8208e181 683 if ( item->IsSeparator() )
519cb848 684 {
8208e181 685 if ( mh )
2f1ae414 686 UMAAppendMenuItem(mh, "\p-" );
519cb848 687 }
519cb848
SC
688 else
689 {
8208e181 690 Str255 label ;
2f1ae414
SC
691 UInt8 modifiers ;
692 SInt16 key ;
693 wxMenuItem::MacBuildMenuString( label, &key , &modifiers , item->GetText(), item->GetId() != wxApp::s_macAboutMenuItemId); // no shortcut in about menu
8208e181
SC
694 if ( label[0] == 0 )
695 {
696 // we cannot add empty menus on mac
697 label[0] = 1 ;
698 label[1] = ' ' ;
699 }
700 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
701 {
2f1ae414
SC
702 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , label );
703 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 );
8208e181
SC
704 }
705 else
706 {
707 if ( mh )
2f1ae414 708 UMAAppendMenuItem(mh, label , key , modifiers );
8208e181 709 }
519cb848
SC
710 }
711 }
712 }
713 }
5b781a67
SC
714#else
715 if( m_titles[i] == "?" || m_titles[i] == "&?" || m_titles[i] == wxApp::s_macHelpMenuTitleName )
716 {
717 wxMenuItem::MacBuildMenuString( label, NULL , NULL , m_titles[i] , false );
718 UMASetMenuTitle( menu->GetHMenu() , label ) ;
719
720 for (pos = 0 , node = menu->GetMenuItems().First(); node; node = node->Next(), pos++)
721 {
722 item = (wxMenuItem *)node->Data();
723 subMenu = item->GetSubMenu() ;
724 if (subMenu)
725 {
726 UMAInsertMenu( subMenu->GetHMenu() , -1 ) ;
727 }
728 else
729 {
730 if ( item->GetId() == wxApp::s_macAboutMenuItemId )
731 {
732 Str255 label ;
733 UInt8 modifiers ;
734 SInt16 key ;
735 wxMenuItem::MacBuildMenuString( label, &key , &modifiers , item->GetText(), item->GetId() != wxApp::s_macAboutMenuItemId); // no shortcut in about menu
736 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , label );
737 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 );
738 }
739 }
740 }
741 UMAInsertMenu(m_menus[i]->GetHMenu(), 0);
742 }
2f1ae414 743#endif
5b781a67 744 else
519cb848 745 {
2f1ae414 746 wxMenuItem::MacBuildMenuString( label, NULL , NULL , m_titles[i] , false );
e7549107 747 UMASetMenuTitle( menu->GetHMenu() , label ) ;
2f1ae414
SC
748 for (pos = 0, node = menu->GetMenuItems().First(); node; node = node->Next(), pos++)
749 {
519cb848
SC
750 item = (wxMenuItem *)node->Data();
751 subMenu = item->GetSubMenu() ;
752 if (subMenu)
753 {
2f1ae414 754 UMAInsertMenu( subMenu->GetHMenu() , -1 ) ;
519cb848
SC
755 }
756 }
2f1ae414 757 UMAInsertMenu(m_menus[i]->GetHMenu(), 0);
519cb848
SC
758 }
759 }
2f1ae414 760 UMADrawMenuBar() ;
519cb848
SC
761
762 s_macInstalledMenuBar = this;
763}
764
e7549107 765void wxMenuBar::EnableTop(size_t pos, bool enable)
e9576ca5 766{
e7549107
SC
767 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
768 m_menus[pos]->MacEnableMenu( enable ) ;
769 Refresh();
e9576ca5
SC
770}
771
e7549107 772void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
e9576ca5 773{
e7549107 774 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
e9576ca5 775
e7549107 776 m_titles[pos] = label;
e9576ca5 777
e7549107
SC
778 if ( !IsAttached() )
779 {
e9576ca5 780 return;
e7549107 781 }
e9576ca5 782
519cb848 783 m_menus[pos]->SetTitle( label ) ;
e7549107 784 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
519cb848 785 {
e7549107 786 ::SetMenuBar( GetMenuBar() ) ;
519cb848 787 ::InvalMenuBar() ;
519cb848 788 }
e9576ca5
SC
789}
790
e7549107 791wxString wxMenuBar::GetLabelTop(size_t pos) const
e9576ca5 792{
e7549107
SC
793 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
794 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
519cb848 795
e7549107 796 return m_titles[pos];
e9576ca5
SC
797}
798
e7549107 799int wxMenuBar::FindMenu(const wxString& title)
e9576ca5 800{
e7549107 801 wxString menuTitle = wxStripMenuCodes(title);
e9576ca5 802
e7549107
SC
803 size_t count = GetMenuCount();
804 for ( size_t i = 0; i < count; i++ )
e9576ca5 805 {
e7549107
SC
806 wxString title = wxStripMenuCodes(m_titles[i]);
807 if ( menuTitle == title )
808 return i;
e9576ca5 809 }
e9576ca5 810
e7549107 811 return wxNOT_FOUND;
e9576ca5 812
e9576ca5
SC
813}
814
e7549107
SC
815
816// ---------------------------------------------------------------------------
817// wxMenuBar construction
818// ---------------------------------------------------------------------------
819
820// ---------------------------------------------------------------------------
821// wxMenuBar construction
822// ---------------------------------------------------------------------------
823
824wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 825{
e7549107
SC
826 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
827 if ( !menuOld )
828 return FALSE;
829 m_titles[pos] = title;
e9576ca5 830
e7549107 831 if ( IsAttached() )
e9576ca5 832 {
e7549107
SC
833 if (s_macInstalledMenuBar == this)
834 {
2f1ae414 835 UMADeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
e7549107
SC
836 {
837 Str255 label;
2f1ae414 838 wxMenuItem::MacBuildMenuString( label, NULL , NULL , title , false );
e7549107
SC
839 UMASetMenuTitle( menu->GetHMenu() , label ) ;
840 if ( pos == m_menus.GetCount() - 1)
841 {
2f1ae414 842 UMAInsertMenu( menu->GetHMenu() , 0 ) ;
e7549107
SC
843 }
844 else
845 {
2f1ae414 846 UMAInsertMenu( menu->GetHMenu() , m_menus[pos+1]->MacGetMenuId() ) ;
e7549107
SC
847 }
848 }
849 }
e9576ca5 850
e9576ca5 851
e7549107
SC
852#if wxUSE_ACCEL
853 if ( menuOld->HasAccels() || menu->HasAccels() )
854 {
855 // need to rebuild accell table
856 RebuildAccelTable();
857 }
858#endif // wxUSE_ACCEL
e9576ca5 859
e7549107 860 Refresh();
e9576ca5 861 }
e9576ca5 862
e7549107 863 return menuOld;
e9576ca5
SC
864}
865
e7549107 866bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
e9576ca5 867{
e7549107
SC
868 if ( !wxMenuBarBase::Insert(pos, menu, title) )
869 return FALSE;
e9576ca5 870
e7549107 871 m_titles.Insert(title, pos);
e9576ca5 872
e7549107
SC
873 menu->Attach(this);
874
875 if ( IsAttached() )
e9576ca5 876 {
e7549107
SC
877 if ( pos == (size_t) -1 )
878 {
879 ::InsertMenu( menu->GetHMenu() , 0 ) ;
880 }
881 else
882 {
883 ::InsertMenu( menu->GetHMenu() , m_menus[pos+1]->MacGetMenuId() ) ;
884 }
885
886#if wxUSE_ACCEL
887 if ( menu->HasAccels() )
e9576ca5 888 {
e7549107
SC
889 // need to rebuild accell table
890 RebuildAccelTable();
e9576ca5 891 }
e7549107 892#endif // wxUSE_ACCEL
e9576ca5 893
e7549107 894 Refresh();
e9576ca5 895 }
e7549107
SC
896
897 return TRUE;
e9576ca5
SC
898}
899
519cb848
SC
900void wxMenuBar::MacMenuSelect(wxEvtHandler* handler, long when , int macMenuId, int macMenuItemNum)
901{
902 // first scan fast for direct commands, i.e. menus which have these commands directly in their own list
903
904 if ( macMenuId == kwxMacAppleMenuId && macMenuItemNum == 1 )
905 {
906 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, wxApp::s_macAboutMenuItemId );
907 event.m_timeStamp = when;
908 event.SetEventObject(handler);
909 event.SetInt( wxApp::s_macAboutMenuItemId );
910 handler->ProcessEvent(event);
911 }
912 else
913 {
e7549107 914 for (int i = 0; i < m_menus.GetCount() ; i++)
519cb848 915 {
03e11df5
GD
916 if ( m_menus[i]->MacGetMenuId() == macMenuId
917#ifndef __WXMAC_X__
918 ||
8208e181 919 ( macMenuId == kHMHelpMenuID && ( m_titles[i] == "?" || m_titles[i] == "&?" || m_titles[i] == wxApp::s_macHelpMenuTitleName ) )
03e11df5 920#endif
519cb848
SC
921 )
922 {
923 if ( m_menus[i]->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
924 return ;
925 else
926 {
927 //TODO flag this as an error since it must contain the item
928 return ;
929 }
930 }
931 }
932
e7549107 933 for (int i = 0; i < m_menus.GetCount(); i++)
519cb848
SC
934 {
935 if ( m_menus[i]->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
936 {
937 break ;
938 }
51abe921 939 }
519cb848
SC
940 }
941}
e9576ca5 942
51abe921
SC
943wxMenu *wxMenuBar::Remove(size_t pos)
944{
945 wxMenu *menu = wxMenuBarBase::Remove(pos);
946 if ( !menu )
947 return NULL;
948
949 if ( IsAttached() )
950 {
951 if (s_macInstalledMenuBar == this)
952 {
953 ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
954 }
955
956 menu->Detach();
957
958#if wxUSE_ACCEL
959 if ( menu->HasAccels() )
960 {
961 // need to rebuild accell table
962 RebuildAccelTable();
963 }
964#endif // wxUSE_ACCEL
965
966 Refresh();
967 }
968
969 m_titles.Remove(pos);
970
971 return menu;
972}
973
974bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
975{
976 WXHMENU submenu = menu ? menu->GetHMenu() : 0;
977 wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
978
979 if ( !wxMenuBarBase::Append(menu, title) )
980 return FALSE;
981
982 menu->Attach(this);
983
984 m_titles.Add(title);
985
986 if ( IsAttached() )
987 {
988 if (s_macInstalledMenuBar == this)
989 {
990 ::InsertMenu( menu->GetHMenu() , 0 ) ;
991 }
992
993#if wxUSE_ACCEL
994 if ( menu->HasAccels() )
995 {
996 // need to rebuild accell table
997 RebuildAccelTable();
998 }
999#endif // wxUSE_ACCEL
1000
1001 Refresh();
1002 }
1003
1004 return TRUE;
1005}
1006
2f1ae414
SC
1007void wxMenuBar::Attach(wxFrame *frame)
1008{
1009// wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
1010
1011 m_menuBarFrame = frame;
1012
1013#if wxUSE_ACCEL
1014 RebuildAccelTable();
1015#endif // wxUSE_ACCEL
1016}
51abe921
SC
1017// ---------------------------------------------------------------------------
1018// wxMenuBar searching for menu items
1019// ---------------------------------------------------------------------------
1020
1021// Find the itemString in menuString, and return the item id or wxNOT_FOUND
1022int wxMenuBar::FindMenuItem(const wxString& menuString,
1023 const wxString& itemString) const
1024{
1025 wxString menuLabel = wxStripMenuCodes(menuString);
1026 size_t count = GetMenuCount();
1027 for ( size_t i = 0; i < count; i++ )
1028 {
1029 wxString title = wxStripMenuCodes(m_titles[i]);
1030 if ( menuString == title )
1031 return m_menus[i]->FindItem(itemString);
1032 }
1033
1034 return wxNOT_FOUND;
1035}
1036
1037wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
1038{
1039 if ( itemMenu )
1040 *itemMenu = NULL;
1041
1042 wxMenuItem *item = NULL;
1043 size_t count = GetMenuCount();
1044 for ( size_t i = 0; !item && (i < count); i++ )
1045 {
1046 item = m_menus[i]->FindItem(id, itemMenu);
1047 }
1048
1049 return item;
1050}
1051
1052