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