]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/menucmn.cpp
overload operator<<() for wchar_t too (if applicable/possible); this fixes the proble...
[wxWidgets.git] / src / common / menucmn.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: 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#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "menubase.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#if wxUSE_MENUS
32
33#include <ctype.h>
34
35#ifndef WX_PRECOMP
36 #include "wx/intl.h"
37 #include "wx/log.h"
38 #include "wx/menu.h"
39#endif
40
41// ----------------------------------------------------------------------------
42// template lists
43// ----------------------------------------------------------------------------
44
45#include "wx/listimpl.cpp"
46
47WX_DEFINE_LIST(wxMenuList);
48WX_DEFINE_LIST(wxMenuItemList);
49
50// ============================================================================
51// implementation
52// ============================================================================
53
54// ----------------------------------------------------------------------------
55// wxMenuItem
56// ----------------------------------------------------------------------------
57
58wxMenuItemBase::wxMenuItemBase(wxMenu *parentMenu,
59 int id,
60 const wxString& text,
61 const wxString& help,
62 wxItemKind kind,
63 wxMenu *subMenu)
64 : m_text(text),
65 m_help(help)
66{
67 wxASSERT_MSG( parentMenu != NULL, wxT("menuitem should have a menu") );
68
69 m_parentMenu = parentMenu;
70 m_subMenu = subMenu;
71 m_isEnabled = TRUE;
72 m_isChecked = FALSE;
73 m_id = id;
74 m_kind = kind;
75 if (m_id == wxID_ANY)
76 m_id = wxNewId();
77 if (m_id == wxID_SEPARATOR)
78 m_kind = wxITEM_SEPARATOR;
79}
80
81wxMenuItemBase::~wxMenuItemBase()
82{
83 delete m_subMenu;
84}
85
86#if wxUSE_ACCEL
87
88static inline bool CompareAccelString(const wxString& str, const wxChar *accel)
89{
90#if wxUSE_INTL
91 return str == accel || str == wxGetTranslation(accel);
92#else
93 return str == accel;
94#endif
95}
96
97// return wxAcceleratorEntry for the given menu string or NULL if none
98// specified
99wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
100{
101 // wxPrintf( wxT("label %s\n"), label.c_str() );
102
103 // check for accelerators: they are given after '\t'
104 int posTab = label.Find(wxT('\t'));
105 if ( posTab != wxNOT_FOUND ) {
106 // parse the accelerator string
107 int keyCode = 0;
108 int accelFlags = wxACCEL_NORMAL;
109 wxString current;
110 for ( size_t n = (size_t)posTab + 1; n < label.Len(); n++ ) {
111 if ( (label[n] == '+') || (label[n] == '-') ) {
112 if ( CompareAccelString(current, wxTRANSLATE("ctrl")) )
113 accelFlags |= wxACCEL_CTRL;
114 else if ( CompareAccelString(current, wxTRANSLATE("alt")) )
115 accelFlags |= wxACCEL_ALT;
116 else if ( CompareAccelString(current, wxTRANSLATE("shift")) )
117 accelFlags |= wxACCEL_SHIFT;
118 else {
119 // we may have "Ctrl-+", for example, but we still want to
120 // catch typos like "Crtl-A" so only give the warning if we
121 // have something before the current '+' or '-', else take
122 // it as a literal symbol
123 if ( current.empty() )
124 {
125 current += label[n];
126
127 // skip clearing it below
128 continue;
129 }
130 else
131 {
132 wxLogDebug(wxT("Unknown accel modifier: '%s'"),
133 current.c_str());
134 }
135 }
136
137 current.clear();
138 }
139 else {
140 current += (wxChar) wxTolower(label[n]);
141 }
142 }
143
144 if ( current.IsEmpty() ) {
145 wxLogDebug(wxT("No accel key found, accel string ignored."));
146 }
147 else {
148 if ( current.Len() == 1 ) {
149 // it's a letter
150 keyCode = current[0U];
151
152 // Only call wxToupper if control, alt, or shift is held down,
153 // otherwise lower case accelerators won't work.
154 if (accelFlags != wxACCEL_NORMAL) {
155 keyCode = wxToupper(keyCode);
156 }
157 }
158 else {
159 // is it a function key?
160 if ( current[0U] == 'f' && wxIsdigit(current[1U]) &&
161 (current.Len() == 2 ||
162 (current.Len() == 3 && wxIsdigit(current[2U]))) ) {
163 int n;
164 wxSscanf(current.c_str() + 1, wxT("%d"), &n);
165
166 keyCode = WXK_F1 + n - 1;
167 }
168 else {
169 // several special cases
170 current.MakeUpper();
171 if ( current == wxT("DEL") )
172 keyCode = WXK_DELETE;
173 else if ( current == wxT("DELETE") )
174 keyCode = WXK_DELETE;
175 else if ( current == wxT("BACK") )
176 keyCode = WXK_BACK;
177 else if ( current == wxT("INS") )
178 keyCode = WXK_INSERT;
179 else if ( current == wxT("INSERT") )
180 keyCode = WXK_INSERT;
181 else if ( current == wxT("ENTER") || current == wxT("RETURN") )
182 keyCode = WXK_RETURN;
183 else if ( current == wxT("PGUP") )
184 keyCode = WXK_PRIOR;
185 else if ( current == wxT("PGDN") )
186 keyCode = WXK_NEXT;
187 else if ( current == wxT("LEFT") )
188 keyCode = WXK_LEFT;
189 else if ( current == wxT("RIGHT") )
190 keyCode = WXK_RIGHT;
191 else if ( current == wxT("UP") )
192 keyCode = WXK_UP;
193 else if ( current == wxT("DOWN") )
194 keyCode = WXK_DOWN;
195 else if ( current == wxT("HOME") )
196 keyCode = WXK_HOME;
197 else if ( current == wxT("END") )
198 keyCode = WXK_END;
199 else if ( current == wxT("SPACE") )
200 keyCode = WXK_SPACE;
201 else if ( current == wxT("TAB") )
202 keyCode = WXK_TAB;
203 else if ( current == wxT("ESC") || current == wxT("ESCAPE") )
204 keyCode = WXK_ESCAPE;
205 else
206 {
207 wxLogDebug(wxT("Unrecognized accel key '%s', accel string ignored."),
208 current.c_str());
209 }
210 }
211 }
212 }
213
214 if ( keyCode ) {
215 // we do have something
216 return new wxAcceleratorEntry(accelFlags, keyCode);
217 }
218 }
219
220 return (wxAcceleratorEntry *)NULL;
221}
222
223wxAcceleratorEntry *wxMenuItemBase::GetAccel() const
224{
225 return wxGetAccelFromString(GetText());
226}
227
228void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
229{
230 wxString text = m_text.BeforeFirst(wxT('\t'));
231 if ( accel )
232 {
233 text += wxT('\t');
234
235 int flags = accel->GetFlags();
236 if ( flags & wxACCEL_ALT )
237 text += wxT("Alt-");
238 if ( flags & wxACCEL_CTRL )
239 text += wxT("Ctrl-");
240 if ( flags & wxACCEL_SHIFT )
241 text += wxT("Shift-");
242
243 int code = accel->GetKeyCode();
244 switch ( code )
245 {
246 case WXK_F1:
247 case WXK_F2:
248 case WXK_F3:
249 case WXK_F4:
250 case WXK_F5:
251 case WXK_F6:
252 case WXK_F7:
253 case WXK_F8:
254 case WXK_F9:
255 case WXK_F10:
256 case WXK_F11:
257 case WXK_F12:
258 text << wxT('F') << code - WXK_F1 + 1;
259 break;
260
261 // if there are any other keys wxGetAccelFromString() may return,
262 // we should process them here
263
264 default:
265 if ( wxIsalnum(code) )
266 {
267 text << (wxChar)code;
268
269 break;
270 }
271
272 wxFAIL_MSG( wxT("unknown keyboard accel") );
273 }
274 }
275
276 SetText(text);
277}
278
279#endif // wxUSE_ACCEL
280
281bool wxMenuBase::ms_locked = true;
282
283// ----------------------------------------------------------------------------
284// wxMenu ctor and dtor
285// ----------------------------------------------------------------------------
286
287void wxMenuBase::Init(long style)
288{
289 m_menuBar = (wxMenuBar *)NULL;
290 m_menuParent = (wxMenu *)NULL;
291
292 m_invokingWindow = (wxWindow *)NULL;
293 m_style = style;
294 m_clientData = (void *)NULL;
295 m_eventHandler = this;
296}
297
298wxMenuBase::~wxMenuBase()
299{
300 WX_CLEAR_LIST(wxMenuItemList, m_items);
301
302 // Actually, in GTK, the submenus have to get deleted first.
303}
304
305// ----------------------------------------------------------------------------
306// wxMenu item adding/removing
307// ----------------------------------------------------------------------------
308
309void wxMenuBase::AddSubMenu(wxMenu *submenu)
310{
311 wxCHECK_RET( submenu, _T("can't add a NULL submenu") );
312
313 submenu->SetParent((wxMenu *)this);
314}
315
316wxMenuItem* wxMenuBase::DoAppend(wxMenuItem *item)
317{
318 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Append()") );
319
320 m_items.Append(item);
321 item->SetMenu((wxMenu*)this);
322 if ( item->IsSubMenu() )
323 {
324 AddSubMenu(item->GetSubMenu());
325 }
326
327 return item;
328}
329
330wxMenuItem* wxMenuBase::Insert(size_t pos, wxMenuItem *item)
331{
332 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Insert") );
333
334 if ( pos == GetMenuItemCount() )
335 {
336 return DoAppend(item);
337 }
338 else
339 {
340 wxCHECK_MSG( pos < GetMenuItemCount(), FALSE,
341 wxT("invalid index in wxMenu::Insert") );
342
343 return DoInsert(pos, item);
344 }
345}
346
347wxMenuItem* wxMenuBase::DoInsert(size_t pos, wxMenuItem *item)
348{
349 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Insert()") );
350
351 wxMenuItemList::compatibility_iterator node = m_items.Item(pos);
352 wxCHECK_MSG( node, FALSE, wxT("invalid index in wxMenu::Insert()") );
353
354 m_items.Insert(node, item);
355 item->SetMenu((wxMenu*)this);
356 if ( item->IsSubMenu() )
357 {
358 AddSubMenu(item->GetSubMenu());
359 }
360
361 return item;
362}
363
364wxMenuItem *wxMenuBase::Remove(wxMenuItem *item)
365{
366 wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Remove") );
367
368 return DoRemove(item);
369}
370
371wxMenuItem *wxMenuBase::DoRemove(wxMenuItem *item)
372{
373 wxMenuItemList::compatibility_iterator node = m_items.Find(item);
374
375 // if we get here, the item is valid or one of Remove() functions is broken
376 wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
377
378 // we detach the item, but we do delete the list node (i.e. don't call
379 // DetachNode() here!)
380 m_items.Erase(node);
381
382 // item isn't attached to anything any more
383 item->SetMenu((wxMenu *)NULL);
384 wxMenu *submenu = item->GetSubMenu();
385 if ( submenu )
386 {
387 submenu->SetParent((wxMenu *)NULL);
388 if ( submenu->IsAttached() )
389 submenu->Detach();
390 }
391
392 return item;
393}
394
395bool wxMenuBase::Delete(wxMenuItem *item)
396{
397 wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Delete") );
398
399 return DoDelete(item);
400}
401
402bool wxMenuBase::DoDelete(wxMenuItem *item)
403{
404 wxMenuItem *item2 = DoRemove(item);
405 wxCHECK_MSG( item2, FALSE, wxT("failed to delete menu item") );
406
407 // don't delete the submenu
408 item2->SetSubMenu((wxMenu *)NULL);
409
410 delete item2;
411
412 return TRUE;
413}
414
415bool wxMenuBase::Destroy(wxMenuItem *item)
416{
417 wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Destroy") );
418
419 return DoDestroy(item);
420}
421
422bool wxMenuBase::DoDestroy(wxMenuItem *item)
423{
424 wxMenuItem *item2 = DoRemove(item);
425 wxCHECK_MSG( item2, FALSE, wxT("failed to delete menu item") );
426
427 delete item2;
428
429 return TRUE;
430}
431
432// ----------------------------------------------------------------------------
433// wxMenu searching for items
434// ----------------------------------------------------------------------------
435
436// Finds the item id matching the given string, -1 if not found.
437int wxMenuBase::FindItem(const wxString& text) const
438{
439 wxString label = wxMenuItem::GetLabelFromText(text);
440 for ( wxMenuItemList::compatibility_iterator node = m_items.GetFirst();
441 node;
442 node = node->GetNext() )
443 {
444 wxMenuItem *item = node->GetData();
445 if ( item->IsSubMenu() )
446 {
447 int rc = item->GetSubMenu()->FindItem(label);
448 if ( rc != wxNOT_FOUND )
449 return rc;
450 }
451
452 // we execute this code for submenus as well to alllow finding them by
453 // name just like the ordinary items
454 if ( !item->IsSeparator() )
455 {
456 if ( item->GetLabel() == label )
457 return item->GetId();
458 }
459 }
460
461 return wxNOT_FOUND;
462}
463
464// recursive search for item by id
465wxMenuItem *wxMenuBase::FindItem(int itemId, wxMenu **itemMenu) const
466{
467 if ( itemMenu )
468 *itemMenu = NULL;
469
470 wxMenuItem *item = NULL;
471 for ( wxMenuItemList::compatibility_iterator node = m_items.GetFirst();
472 node && !item;
473 node = node->GetNext() )
474 {
475 item = node->GetData();
476
477 if ( item->GetId() == itemId )
478 {
479 if ( itemMenu )
480 *itemMenu = (wxMenu *)this;
481 }
482 else if ( item->IsSubMenu() )
483 {
484 item = item->GetSubMenu()->FindItem(itemId, itemMenu);
485 }
486 else
487 {
488 // don't exit the loop
489 item = NULL;
490 }
491 }
492
493 return item;
494}
495
496// non recursive search
497wxMenuItem *wxMenuBase::FindChildItem(int id, size_t *ppos) const
498{
499 wxMenuItem *item = (wxMenuItem *)NULL;
500 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
501
502 size_t pos;
503 for ( pos = 0; node; pos++ )
504 {
505 if ( node->GetData()->GetId() == id )
506 {
507 item = node->GetData();
508
509 break;
510 }
511
512 node = node->GetNext();
513 }
514
515 if ( ppos )
516 {
517 *ppos = item ? pos : (size_t)wxNOT_FOUND;
518 }
519
520 return item;
521}
522
523// find by position
524wxMenuItem* wxMenuBase::FindItemByPosition(size_t position) const
525{
526 wxCHECK_MSG( position < m_items.GetCount(), NULL,
527 _T("wxMenu::FindItemByPosition(): invalid menu index") );
528
529 return m_items.Item( position )->GetData();
530}
531
532// ----------------------------------------------------------------------------
533// wxMenu helpers used by derived classes
534// ----------------------------------------------------------------------------
535
536// Update a menu and all submenus recursively. source is the object that has
537// the update event handlers defined for it. If NULL, the menu or associated
538// window will be used.
539void wxMenuBase::UpdateUI(wxEvtHandler* source)
540{
541 if (GetInvokingWindow())
542 {
543 // Don't update menus if the parent
544 // frame is about to get deleted
545 wxWindow *tlw = wxGetTopLevelParent( GetInvokingWindow() );
546 if (tlw && wxPendingDelete.Member(tlw))
547 return;
548 }
549
550 if ( !source && GetInvokingWindow() )
551 source = GetInvokingWindow()->GetEventHandler();
552 if ( !source )
553 source = GetEventHandler();
554 if ( !source )
555 source = this;
556
557 wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
558 while ( node )
559 {
560 wxMenuItem* item = node->GetData();
561 if ( !item->IsSeparator() )
562 {
563 wxWindowID id = item->GetId();
564 wxUpdateUIEvent event(id);
565 event.SetEventObject( source );
566
567 if ( source->ProcessEvent(event) )
568 {
569 // if anything changed, update the changed attribute
570 if (event.GetSetText())
571 SetLabel(id, event.GetText());
572 if (event.GetSetChecked())
573 Check(id, event.GetChecked());
574 if (event.GetSetEnabled())
575 Enable(id, event.GetEnabled());
576 }
577
578 // recurse to the submenus
579 if ( item->GetSubMenu() )
580 item->GetSubMenu()->UpdateUI(source);
581 }
582 //else: item is a separator (which doesn't process update UI events)
583
584 node = node->GetNext();
585 }
586}
587
588bool wxMenuBase::SendEvent(int id, int checked)
589{
590 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
591 event.SetEventObject(this);
592 event.SetInt(checked);
593
594 bool processed = FALSE;
595
596 // Try the menu's event handler
597 if ( !processed )
598 {
599 wxEvtHandler *handler = GetEventHandler();
600 if ( handler )
601 processed = handler->ProcessEvent(event);
602 }
603
604 // Try the window the menu was popped up from (and up through the
605 // hierarchy)
606 if ( !processed )
607 {
608 const wxMenuBase *menu = this;
609 while ( menu )
610 {
611 wxWindow *win = menu->GetInvokingWindow();
612 if ( win )
613 {
614 processed = win->GetEventHandler()->ProcessEvent(event);
615 break;
616 }
617
618 menu = menu->GetParent();
619 }
620 }
621
622 return processed;
623}
624
625// ----------------------------------------------------------------------------
626// wxMenu attaching/detaching to/from menu bar
627// ----------------------------------------------------------------------------
628
629wxMenuBar* wxMenuBase::GetMenuBar() const
630{
631 if(GetParent())
632 return GetParent()->GetMenuBar();
633 return m_menuBar;
634}
635
636void wxMenuBase::Attach(wxMenuBarBase *menubar)
637{
638 // use Detach() instead!
639 wxASSERT_MSG( menubar, _T("menu can't be attached to NULL menubar") );
640
641 // use IsAttached() to prevent this from happening
642 wxASSERT_MSG( !m_menuBar, _T("attaching menu twice?") );
643
644 m_menuBar = (wxMenuBar *)menubar;
645}
646
647void wxMenuBase::Detach()
648{
649 // use IsAttached() to prevent this from happening
650 wxASSERT_MSG( m_menuBar, _T("detaching unattached menu?") );
651
652 m_menuBar = NULL;
653}
654
655// ----------------------------------------------------------------------------
656// wxMenu functions forwarded to wxMenuItem
657// ----------------------------------------------------------------------------
658
659void wxMenuBase::Enable( int id, bool enable )
660{
661 wxMenuItem *item = FindItem(id);
662
663 wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
664
665 item->Enable(enable);
666}
667
668bool wxMenuBase::IsEnabled( int id ) const
669{
670 wxMenuItem *item = FindItem(id);
671
672 wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsEnabled: no such item") );
673
674 return item->IsEnabled();
675}
676
677void wxMenuBase::Check( int id, bool enable )
678{
679 wxMenuItem *item = FindItem(id);
680
681 wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
682
683 item->Check(enable);
684}
685
686bool wxMenuBase::IsChecked( int id ) const
687{
688 wxMenuItem *item = FindItem(id);
689
690 wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsChecked: no such item") );
691
692 return item->IsChecked();
693}
694
695void wxMenuBase::SetLabel( int id, const wxString &label )
696{
697 wxMenuItem *item = FindItem(id);
698
699 wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
700
701 item->SetText(label);
702}
703
704wxString wxMenuBase::GetLabel( int id ) const
705{
706 wxMenuItem *item = FindItem(id);
707
708 wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetLabel: no such item") );
709
710 return item->GetText();
711}
712
713void wxMenuBase::SetHelpString( int id, const wxString& helpString )
714{
715 wxMenuItem *item = FindItem(id);
716
717 wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
718
719 item->SetHelp( helpString );
720}
721
722wxString wxMenuBase::GetHelpString( int id ) const
723{
724 wxMenuItem *item = FindItem(id);
725
726 wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetHelpString: no such item") );
727
728 return item->GetHelp();
729}
730
731// ----------------------------------------------------------------------------
732// wxMenuBarBase ctor and dtor
733// ----------------------------------------------------------------------------
734
735wxMenuBarBase::wxMenuBarBase()
736{
737 // not attached yet
738 m_menuBarFrame = NULL;
739}
740
741wxMenuBarBase::~wxMenuBarBase()
742{
743 WX_CLEAR_LIST(wxMenuList, m_menus);
744}
745
746// ----------------------------------------------------------------------------
747// wxMenuBar item access: the base class versions manage m_menus list, the
748// derived class should reflect the changes in the real menubar
749// ----------------------------------------------------------------------------
750
751wxMenu *wxMenuBarBase::GetMenu(size_t pos) const
752{
753 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
754 wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::GetMenu()") );
755
756 return node->GetData();
757}
758
759bool wxMenuBarBase::Append(wxMenu *menu, const wxString& WXUNUSED(title))
760{
761 wxCHECK_MSG( menu, FALSE, wxT("can't append NULL menu") );
762
763 m_menus.Append(menu);
764 menu->Attach(this);
765
766 return TRUE;
767}
768
769bool wxMenuBarBase::Insert(size_t pos, wxMenu *menu,
770 const wxString& title)
771{
772 if ( pos == m_menus.GetCount() )
773 {
774 return wxMenuBarBase::Append(menu, title);
775 }
776 else // not at the end
777 {
778 wxCHECK_MSG( menu, FALSE, wxT("can't insert NULL menu") );
779
780 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
781 wxCHECK_MSG( node, FALSE, wxT("bad index in wxMenuBar::Insert()") );
782
783 m_menus.Insert(node, menu);
784 menu->Attach(this);
785
786 return TRUE;
787 }
788}
789
790wxMenu *wxMenuBarBase::Replace(size_t pos, wxMenu *menu,
791 const wxString& WXUNUSED(title))
792{
793 wxCHECK_MSG( menu, NULL, wxT("can't insert NULL menu") );
794
795 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
796 wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Replace()") );
797
798 wxMenu *menuOld = node->GetData();
799 node->SetData(menu);
800
801 menu->Attach(this);
802 menuOld->Detach();
803
804 return menuOld;
805}
806
807wxMenu *wxMenuBarBase::Remove(size_t pos)
808{
809 wxMenuList::compatibility_iterator node = m_menus.Item(pos);
810 wxCHECK_MSG( node, NULL, wxT("bad index in wxMenuBar::Remove()") );
811
812 wxMenu *menu = node->GetData();
813 m_menus.Erase(node);
814 menu->Detach();
815
816 return menu;
817}
818
819int wxMenuBarBase::FindMenu(const wxString& title) const
820{
821 wxString label = wxMenuItem::GetLabelFromText(title);
822
823 size_t count = GetMenuCount();
824 for ( size_t i = 0; i < count; i++ )
825 {
826 wxString title2 = GetLabelTop(i);
827 if ( (title2 == title) ||
828 (wxMenuItem::GetLabelFromText(title2) == label) )
829 {
830 // found
831 return (int)i;
832 }
833 }
834
835 return wxNOT_FOUND;
836
837}
838
839// ----------------------------------------------------------------------------
840// wxMenuBar attaching/detaching to/from the frame
841// ----------------------------------------------------------------------------
842
843void wxMenuBarBase::Attach(wxFrame *frame)
844{
845 wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
846
847 m_menuBarFrame = frame;
848}
849
850void wxMenuBarBase::Detach()
851{
852 wxASSERT_MSG( IsAttached(), wxT("detaching unattached menubar") );
853
854 m_menuBarFrame = NULL;
855}
856
857// ----------------------------------------------------------------------------
858// wxMenuBar searching for items
859// ----------------------------------------------------------------------------
860
861wxMenuItem *wxMenuBarBase::FindItem(int id, wxMenu **menu) const
862{
863 if ( menu )
864 *menu = NULL;
865
866 wxMenuItem *item = NULL;
867 size_t count = GetMenuCount(), i;
868 wxMenuList::const_iterator it;
869 for ( i = 0, it = m_menus.begin(); !item && (i < count); i++, it++ )
870 {
871 item = (*it)->FindItem(id, menu);
872 }
873
874 return item;
875}
876
877int wxMenuBarBase::FindMenuItem(const wxString& menu, const wxString& item) const
878{
879 wxString label = wxMenuItem::GetLabelFromText(menu);
880
881 int i = 0;
882 wxMenuList::compatibility_iterator node;
883 for ( node = m_menus.GetFirst(); node; node = node->GetNext(), i++ )
884 {
885 if ( label == wxMenuItem::GetLabelFromText(GetLabelTop(i)) )
886 return node->GetData()->FindItem(item);
887 }
888
889 return wxNOT_FOUND;
890}
891
892// ---------------------------------------------------------------------------
893// wxMenuBar functions forwarded to wxMenuItem
894// ---------------------------------------------------------------------------
895
896void wxMenuBarBase::Enable(int id, bool enable)
897{
898 wxMenuItem *item = FindItem(id);
899
900 wxCHECK_RET( item, wxT("attempt to enable an item which doesn't exist") );
901
902 item->Enable(enable);
903}
904
905void wxMenuBarBase::Check(int id, bool check)
906{
907 wxMenuItem *item = FindItem(id);
908
909 wxCHECK_RET( item, wxT("attempt to check an item which doesn't exist") );
910 wxCHECK_RET( item->IsCheckable(), wxT("attempt to check an uncheckable item") );
911
912 item->Check(check);
913}
914
915bool wxMenuBarBase::IsChecked(int id) const
916{
917 wxMenuItem *item = FindItem(id);
918
919 wxCHECK_MSG( item, FALSE, wxT("wxMenuBar::IsChecked(): no such item") );
920
921 return item->IsChecked();
922}
923
924bool wxMenuBarBase::IsEnabled(int id) const
925{
926 wxMenuItem *item = FindItem(id);
927
928 wxCHECK_MSG( item, FALSE, wxT("wxMenuBar::IsEnabled(): no such item") );
929
930 return item->IsEnabled();
931}
932
933void wxMenuBarBase::SetLabel(int id, const wxString& label)
934{
935 wxMenuItem *item = FindItem(id);
936
937 wxCHECK_RET( item, wxT("wxMenuBar::SetLabel(): no such item") );
938
939 item->SetText(label);
940}
941
942wxString wxMenuBarBase::GetLabel(int id) const
943{
944 wxMenuItem *item = FindItem(id);
945
946 wxCHECK_MSG( item, wxEmptyString,
947 wxT("wxMenuBar::GetLabel(): no such item") );
948
949 return item->GetText();
950}
951
952void wxMenuBarBase::SetHelpString(int id, const wxString& helpString)
953{
954 wxMenuItem *item = FindItem(id);
955
956 wxCHECK_RET( item, wxT("wxMenuBar::SetHelpString(): no such item") );
957
958 item->SetHelp(helpString);
959}
960
961wxString wxMenuBarBase::GetHelpString(int id) const
962{
963 wxMenuItem *item = FindItem(id);
964
965 wxCHECK_MSG( item, wxEmptyString,
966 wxT("wxMenuBar::GetHelpString(): no such item") );
967
968 return item->GetHelp();
969}
970
971#endif // wxUSE_MENUS