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