]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/menu.cpp
updated mac sources (CW 5.3 working , CW6 still having code gen problems)
[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/menu.h"
26 #include "wx/menuitem.h"
27 #include "wx/log.h"
28 #include "wx/utils.h"
29
30 #include "wx/mac/uma.h"
31
32 // other standard headers
33 // ----------------------
34 #include <string.h>
35
36 #if !USE_SHARED_LIBRARY
37 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
38 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
39 #endif
40
41 // the (popup) menu title has this special id
42 static const int idMenuTitle = -2;
43 static int formerHelpMenuItems = 0 ;
44
45 const short kwxMacMenuBarResource = 1 ;
46 const short kwxMacAppleMenuId = 1 ;
47
48 // ============================================================================
49 // implementation
50 // ============================================================================
51
52
53 // Menus
54
55 // Construct a menu with optional title (then use append)
56
57 short wxMenu::s_macNextMenuId = 2 ;
58
59 void wxMenu::Init()
60 {
61 m_doBreak = FALSE;
62
63 // create the menu
64 Str255 label;
65 wxMenuItem::MacBuildMenuString( label, NULL , NULL , m_title , false );
66 m_macMenuId = s_macNextMenuId++;
67 wxCHECK_RET( s_macNextMenuId < 236 , "menu ids > 235 cannot be used for submenus on mac" );
68 m_hMenu = UMANewMenu(m_macMenuId, label);
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 )
77 {
78 Append(idMenuTitle, m_title) ;
79 AppendSeparator() ;
80 }
81 }
82
83 wxMenu::~wxMenu()
84 {
85 if (m_hMenu)
86 UMADisposeMenu(m_hMenu);
87
88 #if wxUSE_ACCEL
89 // delete accels
90 WX_CLEAR_ARRAY(m_accels);
91 #endif // wxUSE_ACCEL
92 }
93
94 void wxMenu::Break()
95 {
96 // not available on the mac platform
97 }
98
99 #if wxUSE_ACCEL
100
101 int 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;
108 }
109
110 return wxNOT_FOUND;
111 }
112
113 void wxMenu::UpdateAccel(wxMenuItem *item)
114 {
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 }
144 }
145
146 #endif // wxUSE_ACCEL
147
148 // function appends a new item or submenu to the menu
149 // append a new item or submenu to the menu
150 bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
151 {
152 wxASSERT_MSG( pItem != NULL, "can't append NULL item to the menu" );
153 #if wxUSE_ACCEL
154 UpdateAccel(pItem);
155 #endif // wxUSE_ACCEL
156
157 if ( pItem->IsSeparator() )
158 {
159 if ( pos == (size_t)-1 )
160 {
161 MacAppendMenu(m_hMenu, "\p-");
162 }
163 else
164 {
165 MacInsertMenuItem(m_hMenu, "\p-" , pos);
166 }
167 }
168 else
169 {
170 wxMenu *pSubMenu = pItem->GetSubMenu() ;
171 if ( pSubMenu != NULL )
172 {
173 Str255 label;
174 wxASSERT_MSG( pSubMenu->m_hMenu != NULL , "invalid submenu added");
175 pSubMenu->m_menuParent = this ;
176 wxMenuItem::MacBuildMenuString( label , NULL , NULL , pItem->GetText() ,false);
177
178 if (wxMenuBar::MacGetInstalledMenuBar() == m_menuBar)
179 {
180 UMAInsertMenu( pSubMenu->m_hMenu , -1 ) ;
181 }
182
183 if ( pos == (size_t)-1 )
184 {
185 UMAAppendSubMenuItem(m_hMenu, label, pSubMenu->m_macMenuId);
186 }
187 else
188 {
189 UMAInsertSubMenuItem(m_hMenu, label , pos, pSubMenu->m_macMenuId);
190 }
191 }
192 else
193 {
194 Str255 label ;
195 UInt8 modifiers ;
196 SInt16 key ;
197 wxMenuItem::MacBuildMenuString( label, &key , &modifiers , pItem->GetText(), pItem->GetId() == wxApp::s_macAboutMenuItemId);
198 if ( label[0] == 0 )
199 {
200 // we cannot add empty menus on mac
201 label[0] = 1 ;
202 label[1] = ' ' ;
203 }
204 if ( pos == (size_t)-1 )
205 {
206 UMAAppendMenuItem(m_hMenu, label,key,modifiers);
207 }
208 else
209 {
210 UMAInsertMenuItem(m_hMenu, label , pos,key,modifiers);
211 }
212 if ( pItem->GetId() == idMenuTitle )
213 {
214 if ( pos == (size_t)-1 )
215 {
216 UMADisableMenuItem( m_hMenu , CountMenuItems( m_hMenu ) ) ;
217 }
218 else
219 {
220 UMADisableMenuItem( m_hMenu , pos + 1 ) ;
221 }
222 }
223 }
224 }
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 ;
231 }
232
233 bool wxMenu::DoAppend(wxMenuItem *item)
234 {
235 return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
236 }
237
238 bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
239 {
240 return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
241 }
242
243 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
244 {
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;
252
253 node = node->GetNext();
254 }
255
256 // DoRemove() (unlike Remove) can only be called for existing item!
257 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
258
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];
265
266 m_accels.Remove(n);
267 }
268 //else: this item doesn't have an accel, nothing to do
269 #endif // wxUSE_ACCEL
270
271 ::DeleteMenuItem( m_hMenu , pos + 1);
272
273 if ( IsAttached() )
274 {
275 // otherwise, the chane won't be visible
276 m_menuBar->Refresh();
277 }
278
279 // and from internal data structures
280 return wxMenuBase::DoRemove(item);
281 }
282
283 // ---------------------------------------------------------------------------
284 // accelerator helpers
285 // ---------------------------------------------------------------------------
286
287 #if wxUSE_ACCEL
288
289 // create the wxAcceleratorEntries for our accels and put them into provided
290 // array - return the number of accels we have
291 size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
292 {
293 size_t count = GetAccelCount();
294 for ( size_t n = 0; n < count; n++ )
295 {
296 *accels++ = *m_accels[n];
297 }
298
299 return count;
300 }
301
302 #endif // wxUSE_ACCEL
303
304 void wxMenu::SetTitle(const wxString& label)
305 {
306 Str255 title ;
307 m_title = label ;
308 wxMenuItem::MacBuildMenuString( title, NULL , NULL , label , false );
309 UMASetMenuTitle( m_hMenu , title ) ;
310 }
311 bool wxMenu::ProcessCommand(wxCommandEvent & event)
312 {
313 bool processed = FALSE;
314
315 #if WXWIN_COMPATIBILITY
316 // Try a callback
317 if (m_callback)
318 {
319 (void)(*(m_callback))(*this, event);
320 processed = TRUE;
321 }
322 #endif WXWIN_COMPATIBILITY
323
324 // Try the menu's event handler
325 if ( !processed && GetEventHandler())
326 {
327 processed = GetEventHandler()->ProcessEvent(event);
328 }
329
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
344 void 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;
351 }
352
353 void 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
360 wxWindow *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 }
369
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
373 int wxMenu::MacGetIndexFromId( int id )
374 {
375 size_t pos;
376 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
377 for ( pos = 0; node; pos++ )
378 {
379 if ( node->GetData()->GetId() == id )
380 break;
381
382 node = node->GetNext();
383 }
384
385 if (!node)
386 return 0;
387
388 return pos + 1 ;
389 }
390
391 int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
392 {
393 size_t pos;
394 wxMenuItemList::Node *node = GetMenuItems().GetFirst();
395 for ( pos = 0; node; pos++ )
396 {
397 if ( node->GetData() == pItem )
398 break;
399
400 node = node->GetNext();
401 }
402
403 if (!node)
404 return 0;
405
406 return pos + 1 ;
407 }
408
409 void wxMenu::MacEnableMenu( bool bDoEnable )
410 {
411 if ( bDoEnable )
412 UMAEnableMenuItem( m_hMenu , 0 ) ;
413 else
414 UMADisableMenuItem( m_hMenu , 0 ) ;
415
416 ::DrawMenuBar() ;
417 }
418
419 bool wxMenu::MacMenuSelect( wxEvtHandler* handler, long when , int macMenuId, int macMenuItemNum )
420 {
421 int pos;
422 wxNode *node;
423
424 if ( m_macMenuId == macMenuId )
425 {
426 node = GetMenuItems().Nth(macMenuItemNum-1);
427 if (node)
428 {
429 wxMenuItem *pItem = (wxMenuItem*)node->Data();
430
431 if (pItem->IsCheckable())
432 pItem->Check(! pItem->IsChecked());
433
434 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, pItem->GetId());
435 event.m_timeStamp = when;
436 event.SetEventObject(handler);
437 event.SetInt( pItem->GetId() );
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 }
460 return true ;
461 }
462 }
463 else if ( macMenuId == kHMHelpMenuID )
464 {
465 int menuItem = formerHelpMenuItems ;
466 for (pos = 0, node = GetMenuItems().First(); node; node = node->Next(), pos++)
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);
484 event.SetInt( pItem->GetId() );
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 }
506 return true ;
507 }
508 }
509 }
510 }
511
512 for (pos = 0, node = GetMenuItems().First(); node; node = node->Next(), pos++)
513 {
514 wxMenuItem * pItem = (wxMenuItem *) node->Data() ;
515
516 wxMenu *pSubMenu = pItem->GetSubMenu() ;
517 if ( pSubMenu != NULL )
518 {
519 if ( pSubMenu->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
520 return true ;
521 }
522 }
523
524 return false ;
525 }
526
527 // Menu Bar
528
529 /*
530
531 Mac Implementation note :
532
533 The Mac has only one global menubar, so we attempt to install the currently
534 active menubar from a frame, we currently don't take into account mdi-frames
535 which would ask for menu-merging
536
537 Secondly there is no mac api for changing a menubar that is not the current
538 menubar, so we have to wait for preparing the actual menubar until the
539 wxMenubar is to be used
540
541 We can in subsequent versions use MacInstallMenuBar to provide some sort of
542 auto-merge for MDI in case this will be necessary
543
544 */
545
546 wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
547
548 void wxMenuBar::Init()
549 {
550 m_eventHandler = this;
551 m_menuBarFrame = NULL;
552 }
553
554 wxMenuBar::wxMenuBar()
555 {
556 Init();
557 }
558
559 wxMenuBar::wxMenuBar( long WXUNUSED(style) )
560 {
561 Init();
562 }
563
564
565 wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
566 {
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 }
578 }
579
580 wxMenuBar::~wxMenuBar()
581 {
582 if (s_macInstalledMenuBar == this)
583 {
584 ::ClearMenuBar();
585 s_macInstalledMenuBar = NULL;
586 }
587
588 }
589
590 void wxMenuBar::Refresh()
591 {
592 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
593
594 DrawMenuBar();
595 }
596
597 #if wxUSE_ACCEL
598
599 void 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
628 void 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
639 for (int i = 0; i < m_menus.GetCount(); i++)
640 {
641 Str255 label;
642 wxNode *node;
643 wxMenuItem *item;
644 int pos ;
645 wxMenu* menu = m_menus[i] , *subMenu = NULL ;
646
647 #if !TARGET_CARBON
648 /* the help menu does not exist in CARBON anymore */
649 if( m_titles[i] == "?" || m_titles[i] == "&?" || m_titles[i] == wxApp::s_macHelpMenuTitleName )
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
662 for (pos = 0 , node = menu->GetMenuItems().First(); node; node = node->Next(), pos++)
663 {
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 {
672 if ( item->IsSeparator() )
673 {
674 if ( mh )
675 UMAAppendMenuItem(mh, "\p-" );
676 }
677 else
678 {
679 Str255 label ;
680 UInt8 modifiers ;
681 SInt16 key ;
682 wxMenuItem::MacBuildMenuString( label, &key , &modifiers , item->GetText(), item->GetId() != wxApp::s_macAboutMenuItemId); // no shortcut in about menu
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 {
691 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , label );
692 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 );
693 }
694 else
695 {
696 if ( mh )
697 UMAAppendMenuItem(mh, label , key , modifiers );
698 }
699 }
700 }
701 }
702 }
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 }
732 #endif
733 else
734 {
735 wxMenuItem::MacBuildMenuString( label, NULL , NULL , m_titles[i] , false );
736 UMASetMenuTitle( menu->GetHMenu() , label ) ;
737 for (pos = 0, node = menu->GetMenuItems().First(); node; node = node->Next(), pos++)
738 {
739 item = (wxMenuItem *)node->Data();
740 subMenu = item->GetSubMenu() ;
741 if (subMenu)
742 {
743 UMAInsertMenu( subMenu->GetHMenu() , -1 ) ;
744 }
745 }
746 UMAInsertMenu(m_menus[i]->GetHMenu(), 0);
747 }
748 }
749 UMADrawMenuBar() ;
750
751 s_macInstalledMenuBar = this;
752 }
753
754 void wxMenuBar::EnableTop(size_t pos, bool enable)
755 {
756 wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
757 m_menus[pos]->MacEnableMenu( enable ) ;
758 Refresh();
759 }
760
761 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
762 {
763 wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
764
765 m_titles[pos] = label;
766
767 if ( !IsAttached() )
768 {
769 return;
770 }
771
772 m_menus[pos]->SetTitle( label ) ;
773 if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
774 {
775 ::SetMenuBar( GetMenuBar() ) ;
776 ::InvalMenuBar() ;
777 }
778 }
779
780 wxString wxMenuBar::GetLabelTop(size_t pos) const
781 {
782 wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
783 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
784
785 return m_titles[pos];
786 }
787
788 int wxMenuBar::FindMenu(const wxString& title)
789 {
790 wxString menuTitle = wxStripMenuCodes(title);
791
792 size_t count = GetMenuCount();
793 for ( size_t i = 0; i < count; i++ )
794 {
795 wxString title = wxStripMenuCodes(m_titles[i]);
796 if ( menuTitle == title )
797 return i;
798 }
799
800 return wxNOT_FOUND;
801
802 }
803
804
805 // ---------------------------------------------------------------------------
806 // wxMenuBar construction
807 // ---------------------------------------------------------------------------
808
809 // ---------------------------------------------------------------------------
810 // wxMenuBar construction
811 // ---------------------------------------------------------------------------
812
813 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
814 {
815 wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
816 if ( !menuOld )
817 return FALSE;
818 m_titles[pos] = title;
819
820 if ( IsAttached() )
821 {
822 if (s_macInstalledMenuBar == this)
823 {
824 UMADeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
825 {
826 Str255 label;
827 wxMenuItem::MacBuildMenuString( label, NULL , NULL , title , false );
828 UMASetMenuTitle( menu->GetHMenu() , label ) ;
829 if ( pos == m_menus.GetCount() - 1)
830 {
831 UMAInsertMenu( menu->GetHMenu() , 0 ) ;
832 }
833 else
834 {
835 UMAInsertMenu( menu->GetHMenu() , m_menus[pos+1]->MacGetMenuId() ) ;
836 }
837 }
838 }
839
840
841 #if wxUSE_ACCEL
842 if ( menuOld->HasAccels() || menu->HasAccels() )
843 {
844 // need to rebuild accell table
845 RebuildAccelTable();
846 }
847 #endif // wxUSE_ACCEL
848
849 Refresh();
850 }
851
852 return menuOld;
853 }
854
855 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
856 {
857 if ( !wxMenuBarBase::Insert(pos, menu, title) )
858 return FALSE;
859
860 m_titles.Insert(title, pos);
861
862 menu->Attach(this);
863
864 if ( IsAttached() )
865 {
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() )
877 {
878 // need to rebuild accell table
879 RebuildAccelTable();
880 }
881 #endif // wxUSE_ACCEL
882
883 Refresh();
884 }
885
886 return TRUE;
887 }
888
889 void 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 {
903 for (int i = 0; i < m_menus.GetCount() ; i++)
904 {
905 if ( m_menus[i]->MacGetMenuId() == macMenuId ||
906 ( macMenuId == kHMHelpMenuID && ( m_titles[i] == "?" || m_titles[i] == "&?" || m_titles[i] == wxApp::s_macHelpMenuTitleName ) )
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
919 for (int i = 0; i < m_menus.GetCount(); i++)
920 {
921 if ( m_menus[i]->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
922 {
923 break ;
924 }
925 }
926 }
927 }
928
929 wxMenu *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
960 bool 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
993 void 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 }
1003 // ---------------------------------------------------------------------------
1004 // wxMenuBar searching for menu items
1005 // ---------------------------------------------------------------------------
1006
1007 // Find the itemString in menuString, and return the item id or wxNOT_FOUND
1008 int 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
1023 wxMenuItem *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