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