1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/menucmn.cpp
3 // Purpose: wxMenu and wxMenuBar methods common to all ports
4 // Author: Vadim Zeitlin
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 #include "wx/listimpl.cpp"
43 WX_DEFINE_LIST(wxMenuList
)
44 WX_DEFINE_LIST(wxMenuItemList
)
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 wxMenuItemBase::wxMenuItemBase(wxMenu
*parentMenu
,
63 wxASSERT_MSG( parentMenu
!= NULL
, wxT("menuitem should have a menu") );
65 m_parentMenu
= parentMenu
;
73 if (m_id
== wxID_SEPARATOR
)
74 m_kind
= wxITEM_SEPARATOR
;
77 wxMenuItemBase::~wxMenuItemBase()
84 static inline bool CompareAccelString(const wxString
& str
, const wxChar
*accel
)
87 return str
== accel
|| str
== wxGetTranslation(accel
);
93 // return wxAcceleratorEntry for the given menu string or NULL if none
95 wxAcceleratorEntry
*wxGetAccelFromString(const wxString
& label
)
97 // wxPrintf( wxT("label %s\n"), label.c_str() );
99 // check for accelerators: they are given after '\t'
100 int posTab
= label
.Find(wxT('\t'));
101 if ( posTab
!= wxNOT_FOUND
) {
102 // parse the accelerator string
104 int accelFlags
= wxACCEL_NORMAL
;
106 for ( size_t n
= (size_t)posTab
+ 1; n
< label
.Len(); n
++ ) {
107 if ( (label
[n
] == '+') || (label
[n
] == '-') ) {
108 if ( CompareAccelString(current
, wxTRANSLATE("ctrl")) )
109 accelFlags
|= wxACCEL_CTRL
;
110 else if ( CompareAccelString(current
, wxTRANSLATE("alt")) )
111 accelFlags
|= wxACCEL_ALT
;
112 else if ( CompareAccelString(current
, wxTRANSLATE("shift")) )
113 accelFlags
|= wxACCEL_SHIFT
;
115 // we may have "Ctrl-+", for example, but we still want to
116 // catch typos like "Crtl-A" so only give the warning if we
117 // have something before the current '+' or '-', else take
118 // it as a literal symbol
119 if ( current
.empty() )
123 // skip clearing it below
128 wxLogDebug(wxT("Unknown accel modifier: '%s'"),
136 current
+= (wxChar
) wxTolower(label
[n
]);
140 if ( current
.empty() ) {
141 wxLogDebug(wxT("No accel key found, accel string ignored."));
144 if ( current
.Len() == 1 ) {
146 keyCode
= current
[0U];
148 // Only call wxToupper if control, alt, or shift is held down,
149 // otherwise lower case accelerators won't work.
150 if (accelFlags
!= wxACCEL_NORMAL
) {
151 keyCode
= wxToupper(keyCode
);
155 // is it a function key?
156 if ( current
[0U] == 'f' && wxIsdigit(current
[1U]) &&
157 (current
.Len() == 2 ||
158 (current
.Len() == 3 && wxIsdigit(current
[2U]))) ) {
159 keyCode
= WXK_F1
+ wxAtoi(current
.c_str() + 1) - 1;
162 // several special cases
164 if ( current
== wxT("DEL") )
165 keyCode
= WXK_DELETE
;
166 else if ( current
== wxT("DELETE") )
167 keyCode
= WXK_DELETE
;
168 else if ( current
== wxT("BACK") )
170 else if ( current
== wxT("INS") )
171 keyCode
= WXK_INSERT
;
172 else if ( current
== wxT("INSERT") )
173 keyCode
= WXK_INSERT
;
174 else if ( current
== wxT("ENTER") || current
== wxT("RETURN") )
175 keyCode
= WXK_RETURN
;
176 else if ( current
== wxT("PGUP") )
178 else if ( current
== wxT("PGDN") )
180 else if ( current
== wxT("LEFT") )
182 else if ( current
== wxT("RIGHT") )
184 else if ( current
== wxT("UP") )
186 else if ( current
== wxT("DOWN") )
188 else if ( current
== wxT("HOME") )
190 else if ( current
== wxT("END") )
192 else if ( current
== wxT("SPACE") || current
== _("SPACE") )
194 else if ( current
== wxT("TAB") )
196 else if ( current
== wxT("ESC") || current
== wxT("ESCAPE") )
197 keyCode
= WXK_ESCAPE
;
198 else if ( current
== wxT("CANCEL") )
199 keyCode
= WXK_CANCEL
;
200 else if ( current
== wxT("CLEAR") )
202 else if ( current
== wxT("MENU") )
204 else if ( current
== wxT("PAUSE") )
206 else if ( current
== wxT("CAPITAL") )
207 keyCode
= WXK_CAPITAL
;
208 else if ( current
== wxT("SELECT") )
209 keyCode
= WXK_SELECT
;
210 else if ( current
== wxT("PRINT") )
212 else if ( current
== wxT("EXECUTE") )
213 keyCode
= WXK_EXECUTE
;
214 else if ( current
== wxT("SNAPSHOT") )
215 keyCode
= WXK_SNAPSHOT
;
216 else if ( current
== wxT("HELP") )
218 else if ( current
== wxT("ADD") )
220 else if ( current
== wxT("SEPARATOR") )
221 keyCode
= WXK_SEPARATOR
;
222 else if ( current
== wxT("SUBTRACT") )
223 keyCode
= WXK_SUBTRACT
;
224 else if ( current
== wxT("DECIMAL") )
225 keyCode
= WXK_DECIMAL
;
226 else if ( current
== wxT("DIVIDE") )
227 keyCode
= WXK_DIVIDE
;
228 else if ( current
== wxT("NUM_LOCK") )
229 keyCode
= WXK_NUMLOCK
;
230 else if ( current
== wxT("SCROLL_LOCK") )
231 keyCode
= WXK_SCROLL
;
232 else if ( current
== wxT("PAGEUP") )
233 keyCode
= WXK_PAGEUP
;
234 else if ( current
== wxT("PAGEDOWN") )
235 keyCode
= WXK_PAGEDOWN
;
236 else if ( current
== wxT("KP_SPACE") )
237 keyCode
= WXK_NUMPAD_SPACE
;
238 else if ( current
== wxT("KP_TAB") )
239 keyCode
= WXK_NUMPAD_TAB
;
240 else if ( current
== wxT("KP_ENTER") )
241 keyCode
= WXK_NUMPAD_ENTER
;
242 else if ( current
== wxT("KP_HOME") )
243 keyCode
= WXK_NUMPAD_HOME
;
244 else if ( current
== wxT("KP_LEFT") )
245 keyCode
= WXK_NUMPAD_LEFT
;
246 else if ( current
== wxT("KP_UP") )
247 keyCode
= WXK_NUMPAD_UP
;
248 else if ( current
== wxT("KP_RIGHT") )
249 keyCode
= WXK_NUMPAD_RIGHT
;
250 else if ( current
== wxT("KP_DOWN") )
251 keyCode
= WXK_NUMPAD_DOWN
;
252 else if ( current
== wxT("KP_PRIOR") )
253 keyCode
= WXK_NUMPAD_PRIOR
;
254 else if ( current
== wxT("KP_PAGEUP") )
255 keyCode
= WXK_NUMPAD_PAGEUP
;
256 else if ( current
== wxT("KP_NEXT;") )
257 keyCode
= WXK_NUMPAD_NEXT
;
258 else if ( current
== wxT("KP_PAGEDOWN") )
259 keyCode
= WXK_NUMPAD_PAGEDOWN
;
260 else if ( current
== wxT("KP_END") )
261 keyCode
= WXK_NUMPAD_END
;
262 else if ( current
== wxT("KP_BEGIN") )
263 keyCode
= WXK_NUMPAD_BEGIN
;
264 else if ( current
== wxT("KP_INSERT") )
265 keyCode
= WXK_NUMPAD_INSERT
;
266 else if ( current
== wxT("KP_DELETE") )
267 keyCode
= WXK_NUMPAD_DELETE
;
268 else if ( current
== wxT("KP_EQUAL") )
269 keyCode
= WXK_NUMPAD_EQUAL
;
270 else if ( current
== wxT("KP_MULTIPLY") )
271 keyCode
= WXK_NUMPAD_MULTIPLY
;
272 else if ( current
== wxT("KP_ADD") )
273 keyCode
= WXK_NUMPAD_ADD
;
274 else if ( current
== wxT("KP_SEPARATOR") )
275 keyCode
= WXK_NUMPAD_SEPARATOR
;
276 else if ( current
== wxT("KP_SUBTRACT") )
277 keyCode
= WXK_NUMPAD_SUBTRACT
;
278 else if ( current
== wxT("KP_DECIMAL") )
279 keyCode
= WXK_NUMPAD_DECIMAL
;
280 else if ( current
== wxT("KP_DIVIDE") )
281 keyCode
= WXK_NUMPAD_DIVIDE
;
282 else if ( current
== wxT("WINDOWS_LEFT") )
283 keyCode
= WXK_WINDOWS_LEFT
;
284 else if ( current
== wxT("WINDOWS_RIGHT") )
285 keyCode
= WXK_WINDOWS_RIGHT
;
286 else if ( current
== wxT("WINDOWS_MENU") )
287 keyCode
= WXK_WINDOWS_MENU
;
288 else if ( current
== wxT("COMMAND") )
289 keyCode
= WXK_COMMAND
;
290 else if ( current
.Left(3) == wxT("KP_") && wxIsdigit(current
[3U]) )
291 keyCode
= WXK_NUMPAD0
+ wxAtoi(current
.c_str() + 3);
292 else if ( current
.Left(7) == wxT("SPECIAL") && wxIsdigit(current
[7U]) )
293 keyCode
= WXK_SPECIAL1
+ wxAtoi(current
.c_str() + 7) - 1;
296 wxLogDebug(wxT("Unrecognized accel key '%s', accel string ignored."),
305 // we do have something
306 return new wxAcceleratorEntry(accelFlags
, keyCode
);
310 return (wxAcceleratorEntry
*)NULL
;
313 wxAcceleratorEntry
*wxMenuItemBase::GetAccel() const
315 return wxGetAccelFromString(GetText());
318 void wxMenuItemBase::SetAccel(wxAcceleratorEntry
*accel
)
320 wxString text
= m_text
.BeforeFirst(wxT('\t'));
325 int flags
= accel
->GetFlags();
326 if ( flags
& wxACCEL_ALT
)
328 if ( flags
& wxACCEL_CTRL
)
329 text
+= wxT("Ctrl-");
330 if ( flags
& wxACCEL_SHIFT
)
331 text
+= wxT("Shift-");
333 int code
= accel
->GetKeyCode();
348 text
<< wxT('F') << code
- WXK_F1
+ 1;
351 // if there are any other keys wxGetAccelFromString() may return,
352 // we should process them here
355 if ( wxIsalnum(code
) )
357 text
<< (wxChar
)code
;
362 wxFAIL_MSG( wxT("unknown keyboard accel") );
369 #endif // wxUSE_ACCEL
371 bool wxMenuBase::ms_locked
= true;
373 // ----------------------------------------------------------------------------
374 // wxMenu ctor and dtor
375 // ----------------------------------------------------------------------------
377 void wxMenuBase::Init(long style
)
379 m_menuBar
= (wxMenuBar
*)NULL
;
380 m_menuParent
= (wxMenu
*)NULL
;
382 m_invokingWindow
= (wxWindow
*)NULL
;
384 m_clientData
= (void *)NULL
;
385 m_eventHandler
= this;
388 wxMenuBase::~wxMenuBase()
390 WX_CLEAR_LIST(wxMenuItemList
, m_items
);
392 // Actually, in GTK, the submenus have to get deleted first.
395 // ----------------------------------------------------------------------------
396 // wxMenu item adding/removing
397 // ----------------------------------------------------------------------------
399 void wxMenuBase::AddSubMenu(wxMenu
*submenu
)
401 wxCHECK_RET( submenu
, _T("can't add a NULL submenu") );
403 submenu
->SetParent((wxMenu
*)this);
406 wxMenuItem
* wxMenuBase::DoAppend(wxMenuItem
*item
)
408 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Append()") );
410 m_items
.Append(item
);
411 item
->SetMenu((wxMenu
*)this);
412 if ( item
->IsSubMenu() )
414 AddSubMenu(item
->GetSubMenu());
420 wxMenuItem
* wxMenuBase::Insert(size_t pos
, wxMenuItem
*item
)
422 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Insert") );
424 if ( pos
== GetMenuItemCount() )
426 return DoAppend(item
);
430 wxCHECK_MSG( pos
< GetMenuItemCount(), NULL
,
431 wxT("invalid index in wxMenu::Insert") );
433 return DoInsert(pos
, item
);
437 wxMenuItem
* wxMenuBase::DoInsert(size_t pos
, wxMenuItem
*item
)
439 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Insert()") );
441 wxMenuItemList::compatibility_iterator node
= m_items
.Item(pos
);
442 wxCHECK_MSG( node
, NULL
, wxT("invalid index in wxMenu::Insert()") );
444 m_items
.Insert(node
, item
);
445 item
->SetMenu((wxMenu
*)this);
446 if ( item
->IsSubMenu() )
448 AddSubMenu(item
->GetSubMenu());
454 wxMenuItem
*wxMenuBase::Remove(wxMenuItem
*item
)
456 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Remove") );
458 return DoRemove(item
);
461 wxMenuItem
*wxMenuBase::DoRemove(wxMenuItem
*item
)
463 wxMenuItemList::compatibility_iterator node
= m_items
.Find(item
);
465 // if we get here, the item is valid or one of Remove() functions is broken
466 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
468 // we detach the item, but we do delete the list node (i.e. don't call
469 // DetachNode() here!)
472 // item isn't attached to anything any more
473 item
->SetMenu((wxMenu
*)NULL
);
474 wxMenu
*submenu
= item
->GetSubMenu();
477 submenu
->SetParent((wxMenu
*)NULL
);
478 if ( submenu
->IsAttached() )
485 bool wxMenuBase::Delete(wxMenuItem
*item
)
487 wxCHECK_MSG( item
, false, wxT("invalid item in wxMenu::Delete") );
489 return DoDelete(item
);
492 bool wxMenuBase::DoDelete(wxMenuItem
*item
)
494 wxMenuItem
*item2
= DoRemove(item
);
495 wxCHECK_MSG( item2
, false, wxT("failed to delete menu item") );
497 // don't delete the submenu
498 item2
->SetSubMenu((wxMenu
*)NULL
);
505 bool wxMenuBase::Destroy(wxMenuItem
*item
)
507 wxCHECK_MSG( item
, false, wxT("invalid item in wxMenu::Destroy") );
509 return DoDestroy(item
);
512 bool wxMenuBase::DoDestroy(wxMenuItem
*item
)
514 wxMenuItem
*item2
= DoRemove(item
);
515 wxCHECK_MSG( item2
, false, wxT("failed to delete menu item") );
522 // ----------------------------------------------------------------------------
523 // wxMenu searching for items
524 // ----------------------------------------------------------------------------
526 // Finds the item id matching the given string, wxNOT_FOUND if not found.
527 int wxMenuBase::FindItem(const wxString
& text
) const
529 wxString label
= wxMenuItem::GetLabelFromText(text
);
530 for ( wxMenuItemList::compatibility_iterator node
= m_items
.GetFirst();
532 node
= node
->GetNext() )
534 wxMenuItem
*item
= node
->GetData();
535 if ( item
->IsSubMenu() )
537 int rc
= item
->GetSubMenu()->FindItem(label
);
538 if ( rc
!= wxNOT_FOUND
)
542 // we execute this code for submenus as well to alllow finding them by
543 // name just like the ordinary items
544 if ( !item
->IsSeparator() )
546 if ( item
->GetLabel() == label
)
547 return item
->GetId();
554 // recursive search for item by id
555 wxMenuItem
*wxMenuBase::FindItem(int itemId
, wxMenu
**itemMenu
) const
560 wxMenuItem
*item
= NULL
;
561 for ( wxMenuItemList::compatibility_iterator node
= m_items
.GetFirst();
563 node
= node
->GetNext() )
565 item
= node
->GetData();
567 if ( item
->GetId() == itemId
)
570 *itemMenu
= (wxMenu
*)this;
572 else if ( item
->IsSubMenu() )
574 item
= item
->GetSubMenu()->FindItem(itemId
, itemMenu
);
578 // don't exit the loop
586 // non recursive search
587 wxMenuItem
*wxMenuBase::FindChildItem(int id
, size_t *ppos
) const
589 wxMenuItem
*item
= (wxMenuItem
*)NULL
;
590 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
593 for ( pos
= 0; node
; pos
++ )
595 if ( node
->GetData()->GetId() == id
)
597 item
= node
->GetData();
602 node
= node
->GetNext();
607 *ppos
= item
? pos
: (size_t)wxNOT_FOUND
;
614 wxMenuItem
* wxMenuBase::FindItemByPosition(size_t position
) const
616 wxCHECK_MSG( position
< m_items
.GetCount(), NULL
,
617 _T("wxMenu::FindItemByPosition(): invalid menu index") );
619 return m_items
.Item( position
)->GetData();
622 // ----------------------------------------------------------------------------
623 // wxMenu helpers used by derived classes
624 // ----------------------------------------------------------------------------
626 // Update a menu and all submenus recursively. source is the object that has
627 // the update event handlers defined for it. If NULL, the menu or associated
628 // window will be used.
629 void wxMenuBase::UpdateUI(wxEvtHandler
* source
)
631 if (GetInvokingWindow())
633 // Don't update menus if the parent
634 // frame is about to get deleted
635 wxWindow
*tlw
= wxGetTopLevelParent( GetInvokingWindow() );
636 if (tlw
&& wxPendingDelete
.Member(tlw
))
640 if ( !source
&& GetInvokingWindow() )
641 source
= GetInvokingWindow()->GetEventHandler();
643 source
= GetEventHandler();
647 wxMenuItemList::compatibility_iterator node
= GetMenuItems().GetFirst();
650 wxMenuItem
* item
= node
->GetData();
651 if ( !item
->IsSeparator() )
653 wxWindowID id
= item
->GetId();
654 wxUpdateUIEvent
event(id
);
655 event
.SetEventObject( source
);
657 if ( source
->ProcessEvent(event
) )
659 // if anything changed, update the changed attribute
660 if (event
.GetSetText())
661 SetLabel(id
, event
.GetText());
662 if (event
.GetSetChecked())
663 Check(id
, event
.GetChecked());
664 if (event
.GetSetEnabled())
665 Enable(id
, event
.GetEnabled());
668 // recurse to the submenus
669 if ( item
->GetSubMenu() )
670 item
->GetSubMenu()->UpdateUI(source
);
672 //else: item is a separator (which doesn't process update UI events)
674 node
= node
->GetNext();
678 bool wxMenuBase::SendEvent(int id
, int checked
)
680 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, id
);
681 event
.SetEventObject(this);
682 event
.SetInt(checked
);
684 bool processed
= false;
686 // Try the menu's event handler
689 wxEvtHandler
*handler
= GetEventHandler();
691 processed
= handler
->ProcessEvent(event
);
694 // Try the window the menu was popped up from (and up through the
698 const wxMenuBase
*menu
= this;
701 wxWindow
*win
= menu
->GetInvokingWindow();
704 processed
= win
->GetEventHandler()->ProcessEvent(event
);
708 menu
= menu
->GetParent();
715 // ----------------------------------------------------------------------------
716 // wxMenu attaching/detaching to/from menu bar
717 // ----------------------------------------------------------------------------
719 wxMenuBar
* wxMenuBase::GetMenuBar() const
722 return GetParent()->GetMenuBar();
726 void wxMenuBase::Attach(wxMenuBarBase
*menubar
)
728 // use Detach() instead!
729 wxASSERT_MSG( menubar
, _T("menu can't be attached to NULL menubar") );
731 // use IsAttached() to prevent this from happening
732 wxASSERT_MSG( !m_menuBar
, _T("attaching menu twice?") );
734 m_menuBar
= (wxMenuBar
*)menubar
;
737 void wxMenuBase::Detach()
739 // use IsAttached() to prevent this from happening
740 wxASSERT_MSG( m_menuBar
, _T("detaching unattached menu?") );
745 // ----------------------------------------------------------------------------
746 // wxMenu functions forwarded to wxMenuItem
747 // ----------------------------------------------------------------------------
749 void wxMenuBase::Enable( int id
, bool enable
)
751 wxMenuItem
*item
= FindItem(id
);
753 wxCHECK_RET( item
, wxT("wxMenu::Enable: no such item") );
755 item
->Enable(enable
);
758 bool wxMenuBase::IsEnabled( int id
) const
760 wxMenuItem
*item
= FindItem(id
);
762 wxCHECK_MSG( item
, false, wxT("wxMenu::IsEnabled: no such item") );
764 return item
->IsEnabled();
767 void wxMenuBase::Check( int id
, bool enable
)
769 wxMenuItem
*item
= FindItem(id
);
771 wxCHECK_RET( item
, wxT("wxMenu::Check: no such item") );
776 bool wxMenuBase::IsChecked( int id
) const
778 wxMenuItem
*item
= FindItem(id
);
780 wxCHECK_MSG( item
, false, wxT("wxMenu::IsChecked: no such item") );
782 return item
->IsChecked();
785 void wxMenuBase::SetLabel( int id
, const wxString
&label
)
787 wxMenuItem
*item
= FindItem(id
);
789 wxCHECK_RET( item
, wxT("wxMenu::SetLabel: no such item") );
791 item
->SetText(label
);
794 wxString
wxMenuBase::GetLabel( int id
) const
796 wxMenuItem
*item
= FindItem(id
);
798 wxCHECK_MSG( item
, wxEmptyString
, wxT("wxMenu::GetLabel: no such item") );
800 return item
->GetText();
803 void wxMenuBase::SetHelpString( int id
, const wxString
& helpString
)
805 wxMenuItem
*item
= FindItem(id
);
807 wxCHECK_RET( item
, wxT("wxMenu::SetHelpString: no such item") );
809 item
->SetHelp( helpString
);
812 wxString
wxMenuBase::GetHelpString( int id
) const
814 wxMenuItem
*item
= FindItem(id
);
816 wxCHECK_MSG( item
, wxEmptyString
, wxT("wxMenu::GetHelpString: no such item") );
818 return item
->GetHelp();
821 // ----------------------------------------------------------------------------
822 // wxMenuBarBase ctor and dtor
823 // ----------------------------------------------------------------------------
825 wxMenuBarBase::wxMenuBarBase()
828 m_menuBarFrame
= NULL
;
831 wxMenuBarBase::~wxMenuBarBase()
833 WX_CLEAR_LIST(wxMenuList
, m_menus
);
836 // ----------------------------------------------------------------------------
837 // wxMenuBar item access: the base class versions manage m_menus list, the
838 // derived class should reflect the changes in the real menubar
839 // ----------------------------------------------------------------------------
841 wxMenu
*wxMenuBarBase::GetMenu(size_t pos
) const
843 wxMenuList::compatibility_iterator node
= m_menus
.Item(pos
);
844 wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::GetMenu()") );
846 return node
->GetData();
849 bool wxMenuBarBase::Append(wxMenu
*menu
, const wxString
& WXUNUSED(title
))
851 wxCHECK_MSG( menu
, false, wxT("can't append NULL menu") );
853 m_menus
.Append(menu
);
859 bool wxMenuBarBase::Insert(size_t pos
, wxMenu
*menu
,
860 const wxString
& title
)
862 if ( pos
== m_menus
.GetCount() )
864 return wxMenuBarBase::Append(menu
, title
);
866 else // not at the end
868 wxCHECK_MSG( menu
, false, wxT("can't insert NULL menu") );
870 wxMenuList::compatibility_iterator node
= m_menus
.Item(pos
);
871 wxCHECK_MSG( node
, false, wxT("bad index in wxMenuBar::Insert()") );
873 m_menus
.Insert(node
, menu
);
880 wxMenu
*wxMenuBarBase::Replace(size_t pos
, wxMenu
*menu
,
881 const wxString
& WXUNUSED(title
))
883 wxCHECK_MSG( menu
, NULL
, wxT("can't insert NULL menu") );
885 wxMenuList::compatibility_iterator node
= m_menus
.Item(pos
);
886 wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::Replace()") );
888 wxMenu
*menuOld
= node
->GetData();
897 wxMenu
*wxMenuBarBase::Remove(size_t pos
)
899 wxMenuList::compatibility_iterator node
= m_menus
.Item(pos
);
900 wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::Remove()") );
902 wxMenu
*menu
= node
->GetData();
909 int wxMenuBarBase::FindMenu(const wxString
& title
) const
911 wxString label
= wxMenuItem::GetLabelFromText(title
);
913 size_t count
= GetMenuCount();
914 for ( size_t i
= 0; i
< count
; i
++ )
916 wxString title2
= GetLabelTop(i
);
917 if ( (title2
== title
) ||
918 (wxMenuItem::GetLabelFromText(title2
) == label
) )
929 // ----------------------------------------------------------------------------
930 // wxMenuBar attaching/detaching to/from the frame
931 // ----------------------------------------------------------------------------
933 void wxMenuBarBase::Attach(wxFrame
*frame
)
935 wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
937 m_menuBarFrame
= frame
;
940 void wxMenuBarBase::Detach()
942 wxASSERT_MSG( IsAttached(), wxT("detaching unattached menubar") );
944 m_menuBarFrame
= NULL
;
947 // ----------------------------------------------------------------------------
948 // wxMenuBar searching for items
949 // ----------------------------------------------------------------------------
951 wxMenuItem
*wxMenuBarBase::FindItem(int id
, wxMenu
**menu
) const
956 wxMenuItem
*item
= NULL
;
957 size_t count
= GetMenuCount(), i
;
958 wxMenuList::const_iterator it
;
959 for ( i
= 0, it
= m_menus
.begin(); !item
&& (i
< count
); i
++, it
++ )
961 item
= (*it
)->FindItem(id
, menu
);
967 int wxMenuBarBase::FindMenuItem(const wxString
& menu
, const wxString
& item
) const
969 wxString label
= wxMenuItem::GetLabelFromText(menu
);
972 wxMenuList::compatibility_iterator node
;
973 for ( node
= m_menus
.GetFirst(); node
; node
= node
->GetNext(), i
++ )
975 if ( label
== wxMenuItem::GetLabelFromText(GetLabelTop(i
)) )
976 return node
->GetData()->FindItem(item
);
982 // ---------------------------------------------------------------------------
983 // wxMenuBar functions forwarded to wxMenuItem
984 // ---------------------------------------------------------------------------
986 void wxMenuBarBase::Enable(int id
, bool enable
)
988 wxMenuItem
*item
= FindItem(id
);
990 wxCHECK_RET( item
, wxT("attempt to enable an item which doesn't exist") );
992 item
->Enable(enable
);
995 void wxMenuBarBase::Check(int id
, bool check
)
997 wxMenuItem
*item
= FindItem(id
);
999 wxCHECK_RET( item
, wxT("attempt to check an item which doesn't exist") );
1000 wxCHECK_RET( item
->IsCheckable(), wxT("attempt to check an uncheckable item") );
1005 bool wxMenuBarBase::IsChecked(int id
) const
1007 wxMenuItem
*item
= FindItem(id
);
1009 wxCHECK_MSG( item
, false, wxT("wxMenuBar::IsChecked(): no such item") );
1011 return item
->IsChecked();
1014 bool wxMenuBarBase::IsEnabled(int id
) const
1016 wxMenuItem
*item
= FindItem(id
);
1018 wxCHECK_MSG( item
, false, wxT("wxMenuBar::IsEnabled(): no such item") );
1020 return item
->IsEnabled();
1023 void wxMenuBarBase::SetLabel(int id
, const wxString
& label
)
1025 wxMenuItem
*item
= FindItem(id
);
1027 wxCHECK_RET( item
, wxT("wxMenuBar::SetLabel(): no such item") );
1029 item
->SetText(label
);
1032 wxString
wxMenuBarBase::GetLabel(int id
) const
1034 wxMenuItem
*item
= FindItem(id
);
1036 wxCHECK_MSG( item
, wxEmptyString
,
1037 wxT("wxMenuBar::GetLabel(): no such item") );
1039 return item
->GetText();
1042 void wxMenuBarBase::SetHelpString(int id
, const wxString
& helpString
)
1044 wxMenuItem
*item
= FindItem(id
);
1046 wxCHECK_RET( item
, wxT("wxMenuBar::SetHelpString(): no such item") );
1048 item
->SetHelp(helpString
);
1051 wxString
wxMenuBarBase::GetHelpString(int id
) const
1053 wxMenuItem
*item
= FindItem(id
);
1055 wxCHECK_MSG( item
, wxEmptyString
,
1056 wxT("wxMenuBar::GetHelpString(): no such item") );
1058 return item
->GetHelp();
1061 void wxMenuBarBase::UpdateMenus( void )
1063 wxEvtHandler
* source
;
1065 int nCount
= GetMenuCount();
1066 for (int n
= 0; n
< nCount
; n
++)
1068 menu
= GetMenu( n
);
1071 source
= menu
->GetEventHandler();
1073 menu
->UpdateUI( source
);
1078 #endif // wxUSE_MENUS