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