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