Whitelist wxID_NONE as valid menu item ID.
[wxWidgets.git] / src / common / menucmn.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/menucmn.cpp
3 // Purpose: wxMenu and wxMenuBar methods common to all ports
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 26.10.99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_MENUS
28
29 #ifndef WX_PRECOMP
30 #include "wx/intl.h"
31 #include "wx/log.h"
32 #include "wx/menu.h"
33 #include "wx/frame.h"
34 #endif
35
36 #include "wx/stockitem.h"
37
38 // ----------------------------------------------------------------------------
39 // template lists
40 // ----------------------------------------------------------------------------
41
42 #include "wx/listimpl.cpp"
43
44 WX_DEFINE_LIST(wxMenuList)
45 WX_DEFINE_LIST(wxMenuItemList)
46
47 // ============================================================================
48 // implementation
49 // ============================================================================
50
51 // ----------------------------------------------------------------------------
52 // wxMenuItemBase
53 // ----------------------------------------------------------------------------
54
55 wxMenuItemBase::wxMenuItemBase(wxMenu *parentMenu,
56 int id,
57 const wxString& text,
58 const wxString& help,
59 wxItemKind kind,
60 wxMenu *subMenu)
61 {
62 switch ( id )
63 {
64 case wxID_ANY:
65 m_id = wxWindow::NewControlId();
66 break;
67
68 case wxID_SEPARATOR:
69 m_id = wxID_SEPARATOR;
70
71 // there is a lot of existing code just doing Append(wxID_SEPARATOR)
72 // and it makes sense to omit the following optional parameters,
73 // including the kind one which doesn't default to wxITEM_SEPARATOR,
74 // of course, so override it here
75 kind = wxITEM_SEPARATOR;
76 break;
77
78 case wxID_NONE:
79 // (popup) menu titles in wxMSW use this ID to indicate that
80 // it's not a real menu item, so we don't want the check below to
81 // apply to it
82 m_id = id;
83 break;
84
85 default:
86 // ids are limited to 16 bits under MSW so portable code shouldn't
87 // use ids outside of this range (negative ids generated by wx are
88 // fine though)
89 wxASSERT_MSG( (id >= 0 && id < SHRT_MAX) ||
90 (id >= wxID_AUTO_LOWEST && id <= wxID_AUTO_HIGHEST),
91 wxS("invalid id value") );
92 m_id = id;
93 }
94
95 // notice that parentMenu can be NULL: the item can be attached to the menu
96 // later with SetMenu()
97
98 m_parentMenu = parentMenu;
99 m_subMenu = subMenu;
100 m_isEnabled = true;
101 m_isChecked = false;
102 m_id = id;
103 m_kind = kind;
104
105 SetItemLabel(text);
106 SetHelp(help);
107 }
108
109 wxMenuItemBase::~wxMenuItemBase()
110 {
111 delete m_subMenu;
112 }
113
114 #if wxUSE_ACCEL
115
116 wxAcceleratorEntry *wxMenuItemBase::GetAccel() const
117 {
118 return wxAcceleratorEntry::Create(GetItemLabel());
119 }
120
121 void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
122 {
123 wxString text = m_text.BeforeFirst(wxT('\t'));
124 if ( accel )
125 {
126 text += wxT('\t');
127 text += accel->ToString();
128 }
129
130 SetItemLabel(text);
131 }
132
133 #endif // wxUSE_ACCEL
134
135 void wxMenuItemBase::SetItemLabel(const wxString& str)
136 {
137 m_text = str;
138
139 if ( m_text.empty() && !IsSeparator() )
140 {
141 wxASSERT_MSG( wxIsStockID(GetId()),
142 wxT("A non-stock menu item with an empty label?") );
143 m_text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR |
144 wxSTOCK_WITH_MNEMONIC);
145 }
146 }
147
148 void wxMenuItemBase::SetHelp(const wxString& str)
149 {
150 m_help = str;
151
152 if ( m_help.empty() && !IsSeparator() && wxIsStockID(GetId()) )
153 {
154 // get a stock help string
155 m_help = wxGetStockHelpString(GetId());
156 }
157 }
158
159 #ifndef __WXPM__
160 wxString wxMenuItemBase::GetLabelText(const wxString& text)
161 {
162 return wxStripMenuCodes(text);
163 }
164 #endif
165
166 #if WXWIN_COMPATIBILITY_2_8
167 wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
168 {
169 return GetLabelText(text);
170 }
171 #endif
172
173 bool wxMenuBase::ms_locked = true;
174
175 // ----------------------------------------------------------------------------
176 // wxMenu ctor and dtor
177 // ----------------------------------------------------------------------------
178
179 void wxMenuBase::Init(long style)
180 {
181 m_menuBar = NULL;
182 m_menuParent = NULL;
183
184 m_invokingWindow = NULL;
185 m_style = style;
186 m_clientData = NULL;
187 m_eventHandler = this;
188 }
189
190 wxMenuBase::~wxMenuBase()
191 {
192 WX_CLEAR_LIST(wxMenuItemList, m_items);
193 }
194
195 // ----------------------------------------------------------------------------
196 // wxMenu item adding/removing
197 // ----------------------------------------------------------------------------
198
199 void wxMenuBase::AddSubMenu(wxMenu *submenu)
200 {
201 wxCHECK_RET( submenu, wxT("can't add a NULL submenu") );
202
203 submenu->SetParent((wxMenu *)this);
204 }
205
206 wxMenuItem* wxMenuBase::DoAppend(wxMenuItem *item)
207 {
208 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Append()") );
209
210 m_items.Append(item);
211 item->SetMenu((wxMenu*)this);
212 if ( item->IsSubMenu() )
213 {
214 AddSubMenu(item->GetSubMenu());
215 }
216
217 return item;
218 }
219
220 wxMenuItem* wxMenuBase::Insert(size_t pos, wxMenuItem *item)
221 {
222 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Insert") );
223
224 if ( pos == GetMenuItemCount() )
225 {
226 return DoAppend(item);
227 }
228 else
229 {
230 wxCHECK_MSG( pos < GetMenuItemCount(), NULL,
231 wxT("invalid index in wxMenu::Insert") );
232
233 return DoInsert(pos, item);
234 }
235 }
236
237 wxMenuItem* wxMenuBase::DoInsert(size_t pos, wxMenuItem *item)
238 {
239 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Insert()") );
240
241 wxMenuItemList::compatibility_iterator node = m_items.Item(pos);
242 wxCHECK_MSG( node, NULL, wxT("invalid index in wxMenu::Insert()") );
243
244 m_items.Insert(node, item);
245 item->SetMenu((wxMenu*)this);
246 if ( item->IsSubMenu() )
247 {
248 AddSubMenu(item->GetSubMenu());
249 }
250
251 return item;
252 }
253
254 wxMenuItem *wxMenuBase::Remove(wxMenuItem *item)
255 {
256 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Remove") );
257
258 return DoRemove(item);
259 }
260
261 wxMenuItem *wxMenuBase::DoRemove(wxMenuItem *item)
262 {
263 wxMenuItemList::compatibility_iterator node = m_items.Find(item);
264
265 // if we get here, the item is valid or one of Remove() functions is broken
266 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
267
268 // we detach the item, but we do delete the list node (i.e. don't call
269 // DetachNode() here!)
270 m_items.Erase(node);
271
272 // item isn't attached to anything any more
273 item->SetMenu(NULL);
274 wxMenu *submenu = item->GetSubMenu();
275 if ( submenu )
276 {
277 submenu->SetParent(NULL);
278 if ( submenu->IsAttached() )
279 submenu->Detach();
280 }
281
282 return item;
283 }
284
285 bool wxMenuBase::Delete(wxMenuItem *item)
286 {
287 wxCHECK_MSG( item, false, wxT("invalid item in wxMenu::Delete") );
288
289 return DoDelete(item);
290 }
291
292 bool wxMenuBase::DoDelete(wxMenuItem *item)
293 {
294 wxMenuItem *item2 = DoRemove(item);
295 wxCHECK_MSG( item2, false, wxT("failed to delete menu item") );
296
297 // don't delete the submenu
298 item2->SetSubMenu(NULL);
299
300 delete item2;
301
302 return true;
303 }
304
305 bool wxMenuBase::Destroy(wxMenuItem *item)
306 {
307 wxCHECK_MSG( item, false, wxT("invalid item in wxMenu::Destroy") );
308
309 return DoDestroy(item);
310 }
311
312 bool wxMenuBase::DoDestroy(wxMenuItem *item)
313 {
314 wxMenuItem *item2 = DoRemove(item);
315 wxCHECK_MSG( item2, false, wxT("failed to delete menu item") );
316
317 delete item2;
318
319 return true;
320 }
321
322 // ----------------------------------------------------------------------------
323 // wxMenu searching for items
324 // ----------------------------------------------------------------------------
325
326 // Finds the item id matching the given string, wxNOT_FOUND if not found.
327 int wxMenuBase::FindItem(const wxString& text) const
328 {
329 wxString label = wxMenuItem::GetLabelText(text);
330 for ( wxMenuItemList::compatibility_iterator node = m_items.GetFirst();
331 node;
332 node = node->GetNext() )
333 {
334 wxMenuItem *item = node->GetData();
335 if ( item->IsSubMenu() )
336 {
337 int rc = item->GetSubMenu()->FindItem(label);
338 if ( rc != wxNOT_FOUND )
339 return rc;
340 }
341
342 // we execute this code for submenus as well to alllow finding them by
343 // name just like the ordinary items
344 if ( !item->IsSeparator() )
345 {
346 if ( item->GetItemLabelText() == label )
347 return item->GetId();
348 }
349 }
350
351 return wxNOT_FOUND;
352 }
353
354 // recursive search for item by id
355 wxMenuItem *wxMenuBase::FindItem(int itemId, wxMenu **itemMenu) const
356 {
357 if ( itemMenu )
358 *itemMenu = NULL;
359
360 wxMenuItem *item = NULL;
361 for ( wxMenuItemList::compatibility_iterator node = m_items.GetFirst();
362 node && !item;
363 node = node->GetNext() )
364 {
365 item = node->GetData();
366
367 if ( item->GetId() == itemId )
368 {
369 if ( itemMenu )
370 *itemMenu = (wxMenu *)this;
371 }
372 else if ( item->IsSubMenu() )
373 {
374 item = item->GetSubMenu()->FindItem(itemId, itemMenu);
375 }
376 else
377 {
378 // don't exit the loop
379 item = NULL;
380 }
381 }
382
383 return item;
384 }
385
386 // non recursive search
387 wxMenuItem *wxMenuBase::FindChildItem(int id, size_t *ppos) const
388 {
389 wxMenuItem *item = NULL;
390 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
391
392 size_t pos;
393 for ( pos = 0; node; pos++ )
394 {
395 if ( node->GetData()->GetId() == id )
396 {
397 item = node->GetData();
398
399 break;
400 }
401
402 node = node->GetNext();
403 }
404
405 if ( ppos )
406 {
407 *ppos = item ? pos : (size_t)wxNOT_FOUND;
408 }
409
410 return item;
411 }
412
413 // find by position
414 wxMenuItem* wxMenuBase::FindItemByPosition(size_t position) const
415 {
416 wxCHECK_MSG( position < m_items.GetCount(), NULL,
417 wxT("wxMenu::FindItemByPosition(): invalid menu index") );
418
419 return m_items.Item( position )->GetData();
420 }
421
422 // ----------------------------------------------------------------------------
423 // wxMenu helpers used by derived classes
424 // ----------------------------------------------------------------------------
425
426 // Update a menu and all submenus recursively. source is the object that has
427 // the update event handlers defined for it. If NULL, the menu or associated
428 // window will be used.
429 void wxMenuBase::UpdateUI(wxEvtHandler* source)
430 {
431 if (GetInvokingWindow())
432 {
433 // Don't update menus if the parent
434 // frame is about to get deleted
435 wxWindow *tlw = wxGetTopLevelParent( GetInvokingWindow() );
436 if (tlw && wxPendingDelete.Member(tlw))
437 return;
438 }
439
440 if ( !source && GetInvokingWindow() )
441 source = GetInvokingWindow()->GetEventHandler();
442 if ( !source )
443 source = GetEventHandler();
444 if ( !source )
445 source = this;
446
447 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
448 while ( node )
449 {
450 wxMenuItem* item = node->GetData();
451 if ( !item->IsSeparator() )
452 {
453 wxWindowID id = item->GetId();
454 wxUpdateUIEvent event(id);
455 event.SetEventObject( source );
456
457 if ( source->ProcessEvent(event) )
458 {
459 // if anything changed, update the changed attribute
460 if (event.GetSetText())
461 SetLabel(id, event.GetText());
462 if (event.GetSetChecked())
463 Check(id, event.GetChecked());
464 if (event.GetSetEnabled())
465 Enable(id, event.GetEnabled());
466 }
467
468 // recurse to the submenus
469 if ( item->GetSubMenu() )
470 item->GetSubMenu()->UpdateUI(source);
471 }
472 //else: item is a separator (which doesn't process update UI events)
473
474 node = node->GetNext();
475 }
476 }
477
478 bool wxMenuBase::SendEvent(int id, int checked)
479 {
480 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
481 event.SetEventObject(this);
482 event.SetInt(checked);
483
484 bool processed = false;
485
486 // Try the menu's event handler first
487 wxEvtHandler *handler = GetEventHandler();
488 if ( handler )
489 processed = handler->SafelyProcessEvent(event);
490
491 // Try the window the menu was popped up from or its menu bar belongs to
492 if ( !processed )
493 {
494 wxWindow * const win = GetWindow();
495 if ( win )
496 processed = win->HandleWindowEvent(event);
497 }
498
499 return processed;
500 }
501
502 // ----------------------------------------------------------------------------
503 // wxMenu attaching/detaching to/from menu bar
504 // ----------------------------------------------------------------------------
505
506 wxMenuBar* wxMenuBase::GetMenuBar() const
507 {
508 if(GetParent())
509 return GetParent()->GetMenuBar();
510 return m_menuBar;
511 }
512
513 void wxMenuBase::Attach(wxMenuBarBase *menubar)
514 {
515 // use Detach() instead!
516 wxASSERT_MSG( menubar, wxT("menu can't be attached to NULL menubar") );
517
518 // use IsAttached() to prevent this from happening
519 wxASSERT_MSG( !m_menuBar, wxT("attaching menu twice?") );
520
521 m_menuBar = (wxMenuBar *)menubar;
522 }
523
524 void wxMenuBase::Detach()
525 {
526 // use IsAttached() to prevent this from happening
527 wxASSERT_MSG( m_menuBar, wxT("detaching unattached menu?") );
528
529 m_menuBar = NULL;
530 }
531
532 // ----------------------------------------------------------------------------
533 // wxMenu invoking window handling
534 // ----------------------------------------------------------------------------
535
536 void wxMenuBase::SetInvokingWindow(wxWindow *win)
537 {
538 wxASSERT_MSG( !GetParent(),
539 "should only be called for top level popup menus" );
540 wxASSERT_MSG( !IsAttached(),
541 "menus attached to menu bar can't have invoking window" );
542
543 m_invokingWindow = win;
544 }
545
546 wxWindow *wxMenuBase::GetWindow() const
547 {
548 // only the top level menus have non-NULL invoking window or a pointer to
549 // the menu bar so recurse upwards until we find it
550 const wxMenuBase *menu = this;
551 while ( menu->GetParent() )
552 {
553 menu = menu->GetParent();
554 }
555
556 return menu->GetMenuBar() ? menu->GetMenuBar()->GetFrame()
557 : menu->GetInvokingWindow();
558 }
559
560 // ----------------------------------------------------------------------------
561 // wxMenu functions forwarded to wxMenuItem
562 // ----------------------------------------------------------------------------
563
564 void wxMenuBase::Enable( int id, bool enable )
565 {
566 wxMenuItem *item = FindItem(id);
567
568 wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
569
570 item->Enable(enable);
571 }
572
573 bool wxMenuBase::IsEnabled( int id ) const
574 {
575 wxMenuItem *item = FindItem(id);
576
577 wxCHECK_MSG( item, false, wxT("wxMenu::IsEnabled: no such item") );
578
579 return item->IsEnabled();
580 }
581
582 void wxMenuBase::Check( int id, bool enable )
583 {
584 wxMenuItem *item = FindItem(id);
585
586 wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
587
588 item->Check(enable);
589 }
590
591 bool wxMenuBase::IsChecked( int id ) const
592 {
593 wxMenuItem *item = FindItem(id);
594
595 wxCHECK_MSG( item, false, wxT("wxMenu::IsChecked: no such item") );
596
597 return item->IsChecked();
598 }
599
600 void wxMenuBase::SetLabel( int id, const wxString &label )
601 {
602 wxMenuItem *item = FindItem(id);
603
604 wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
605
606 item->SetItemLabel(label);
607 }
608
609 wxString wxMenuBase::GetLabel( int id ) const
610 {
611 wxMenuItem *item = FindItem(id);
612
613 wxCHECK_MSG( item, wxEmptyString, wxT("wxMenu::GetLabel: no such item") );
614
615 return item->GetItemLabel();
616 }
617
618 void wxMenuBase::SetHelpString( int id, const wxString& helpString )
619 {
620 wxMenuItem *item = FindItem(id);
621
622 wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
623
624 item->SetHelp( helpString );
625 }
626
627 wxString wxMenuBase::GetHelpString( int id ) const
628 {
629 wxMenuItem *item = FindItem(id);
630
631 wxCHECK_MSG( item, wxEmptyString, wxT("wxMenu::GetHelpString: no such item") );
632
633 return item->GetHelp();
634 }
635
636 // ----------------------------------------------------------------------------
637 // wxMenuBarBase ctor and dtor
638 // ----------------------------------------------------------------------------
639
640 wxMenuBarBase::wxMenuBarBase()
641 {
642 // not attached yet
643 m_menuBarFrame = NULL;
644 }
645
646 wxMenuBarBase::~wxMenuBarBase()
647 {
648 WX_CLEAR_LIST(wxMenuList, m_menus);
649 }
650
651 // ----------------------------------------------------------------------------
652 // wxMenuBar item access: the base class versions manage m_menus list, the
653 // derived class should reflect the changes in the real menubar
654 // ----------------------------------------------------------------------------
655
656 wxMenu *wxMenuBarBase::GetMenu(size_t pos) const
657 {
658 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
659 wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::GetMenu()") );
660
661 return node->GetData();
662 }
663
664 bool wxMenuBarBase::Append(wxMenu *menu, const wxString& title)
665 {
666 wxCHECK_MSG( menu, false, wxT("can't append NULL menu") );
667 wxCHECK_MSG( !title.empty(), false, wxT("can't append menu with empty title") );
668
669 m_menus.Append(menu);
670 menu->Attach(this);
671
672 return true;
673 }
674
675 bool wxMenuBarBase::Insert(size_t pos, wxMenu *menu,
676 const wxString& title)
677 {
678 if ( pos == m_menus.GetCount() )
679 {
680 return wxMenuBarBase::Append(menu, title);
681 }
682 else // not at the end
683 {
684 wxCHECK_MSG( menu, false, wxT("can't insert NULL menu") );
685
686 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
687 wxCHECK_MSG( node, false, wxT("bad index in wxMenuBar::Insert()") );
688
689 m_menus.Insert(node, menu);
690 menu->Attach(this);
691
692 return true;
693 }
694 }
695
696 wxMenu *wxMenuBarBase::Replace(size_t pos, wxMenu *menu,
697 const wxString& WXUNUSED(title))
698 {
699 wxCHECK_MSG( menu, NULL, wxT("can't insert NULL menu") );
700
701 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
702 wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Replace()") );
703
704 wxMenu *menuOld = node->GetData();
705 node->SetData(menu);
706
707 menu->Attach(this);
708 menuOld->Detach();
709
710 return menuOld;
711 }
712
713 wxMenu *wxMenuBarBase::Remove(size_t pos)
714 {
715 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
716 wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Remove()") );
717
718 wxMenu *menu = node->GetData();
719 m_menus.Erase(node);
720 menu->Detach();
721
722 return menu;
723 }
724
725 int wxMenuBarBase::FindMenu(const wxString& title) const
726 {
727 wxString label = wxMenuItem::GetLabelText(title);
728
729 size_t count = GetMenuCount();
730 for ( size_t i = 0; i < count; i++ )
731 {
732 wxString title2 = GetMenuLabel(i);
733 if ( (title2 == title) ||
734 (wxMenuItem::GetLabelText(title2) == label) )
735 {
736 // found
737 return (int)i;
738 }
739 }
740
741 return wxNOT_FOUND;
742
743 }
744
745 // ----------------------------------------------------------------------------
746 // wxMenuBar attaching/detaching to/from the frame
747 // ----------------------------------------------------------------------------
748
749 void wxMenuBarBase::Attach(wxFrame *frame)
750 {
751 wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
752
753 m_menuBarFrame = frame;
754 }
755
756 void wxMenuBarBase::Detach()
757 {
758 wxASSERT_MSG( IsAttached(), wxT("detaching unattached menubar") );
759
760 m_menuBarFrame = NULL;
761 }
762
763 // ----------------------------------------------------------------------------
764 // wxMenuBar searching for items
765 // ----------------------------------------------------------------------------
766
767 wxMenuItem *wxMenuBarBase::FindItem(int id, wxMenu **menu) const
768 {
769 if ( menu )
770 *menu = NULL;
771
772 wxMenuItem *item = NULL;
773 size_t count = GetMenuCount(), i;
774 wxMenuList::const_iterator it;
775 for ( i = 0, it = m_menus.begin(); !item && (i < count); i++, it++ )
776 {
777 item = (*it)->FindItem(id, menu);
778 }
779
780 return item;
781 }
782
783 int wxMenuBarBase::FindMenuItem(const wxString& menu, const wxString& item) const
784 {
785 wxString label = wxMenuItem::GetLabelText(menu);
786
787 int i = 0;
788 wxMenuList::compatibility_iterator node;
789 for ( node = m_menus.GetFirst(); node; node = node->GetNext(), i++ )
790 {
791 if ( label == wxMenuItem::GetLabelText(GetMenuLabel(i)) )
792 return node->GetData()->FindItem(item);
793 }
794
795 return wxNOT_FOUND;
796 }
797
798 // ---------------------------------------------------------------------------
799 // wxMenuBar functions forwarded to wxMenuItem
800 // ---------------------------------------------------------------------------
801
802 void wxMenuBarBase::Enable(int id, bool enable)
803 {
804 wxMenuItem *item = FindItem(id);
805
806 wxCHECK_RET( item, wxT("attempt to enable an item which doesn't exist") );
807
808 item->Enable(enable);
809 }
810
811 void wxMenuBarBase::Check(int id, bool check)
812 {
813 wxMenuItem *item = FindItem(id);
814
815 wxCHECK_RET( item, wxT("attempt to check an item which doesn't exist") );
816 wxCHECK_RET( item->IsCheckable(), wxT("attempt to check an uncheckable item") );
817
818 item->Check(check);
819 }
820
821 bool wxMenuBarBase::IsChecked(int id) const
822 {
823 wxMenuItem *item = FindItem(id);
824
825 wxCHECK_MSG( item, false, wxT("wxMenuBar::IsChecked(): no such item") );
826
827 return item->IsChecked();
828 }
829
830 bool wxMenuBarBase::IsEnabled(int id) const
831 {
832 wxMenuItem *item = FindItem(id);
833
834 wxCHECK_MSG( item, false, wxT("wxMenuBar::IsEnabled(): no such item") );
835
836 return item->IsEnabled();
837 }
838
839 void wxMenuBarBase::SetLabel(int id, const wxString& label)
840 {
841 wxMenuItem *item = FindItem(id);
842
843 wxCHECK_RET( item, wxT("wxMenuBar::SetLabel(): no such item") );
844
845 item->SetItemLabel(label);
846 }
847
848 wxString wxMenuBarBase::GetLabel(int id) const
849 {
850 wxMenuItem *item = FindItem(id);
851
852 wxCHECK_MSG( item, wxEmptyString,
853 wxT("wxMenuBar::GetLabel(): no such item") );
854
855 return item->GetItemLabel();
856 }
857
858 void wxMenuBarBase::SetHelpString(int id, const wxString& helpString)
859 {
860 wxMenuItem *item = FindItem(id);
861
862 wxCHECK_RET( item, wxT("wxMenuBar::SetHelpString(): no such item") );
863
864 item->SetHelp(helpString);
865 }
866
867 wxString wxMenuBarBase::GetHelpString(int id) const
868 {
869 wxMenuItem *item = FindItem(id);
870
871 wxCHECK_MSG( item, wxEmptyString,
872 wxT("wxMenuBar::GetHelpString(): no such item") );
873
874 return item->GetHelp();
875 }
876
877 void wxMenuBarBase::UpdateMenus()
878 {
879 wxEvtHandler* source;
880 wxMenu* menu;
881 int nCount = GetMenuCount();
882 for (int n = 0; n < nCount; n++)
883 {
884 menu = GetMenu( n );
885 if (menu != NULL)
886 {
887 source = menu->GetEventHandler();
888 if (source != NULL)
889 menu->UpdateUI( source );
890 }
891 }
892 }
893
894 #if WXWIN_COMPATIBILITY_2_8
895 // get or change the label of the menu at given position
896 void wxMenuBarBase::SetLabelTop(size_t pos, const wxString& label)
897 {
898 SetMenuLabel(pos, label);
899 }
900
901 wxString wxMenuBarBase::GetLabelTop(size_t pos) const
902 {
903 return GetMenuLabelText(pos);
904 }
905 #endif
906
907 #endif // wxUSE_MENUS