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