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