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"
36 #include "wx/stockitem.h"
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 #include "wx/listimpl.cpp"
44 WX_DEFINE_LIST(wxMenuList
)
45 WX_DEFINE_LIST(wxMenuItemList
)
47 // ============================================================================
49 // ============================================================================
51 // ----------------------------------------------------------------------------
52 // XTI for wxMenu(Bar)
53 // ----------------------------------------------------------------------------
55 wxDEFINE_FLAGS( wxMenuStyle
)
56 wxBEGIN_FLAGS( wxMenuStyle
)
57 wxFLAGS_MEMBER(wxMENU_TEAROFF
)
58 wxEND_FLAGS( wxMenuStyle
)
60 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxMenu
, wxEvtHandler
, "wx/menu.h")
61 wxCOLLECTION_TYPE_INFO( wxMenuItem
*, wxMenuItemList
) ;
63 template<> void wxCollectionToVariantArray( wxMenuItemList
const &theList
,
66 wxListCollectionToAnyList
<wxMenuItemList
::compatibility_iterator
>( theList
, value
) ;
69 wxBEGIN_PROPERTIES_TABLE(wxMenu
)
70 wxEVENT_PROPERTY( Select
, wxEVT_COMMAND_MENU_SELECTED
, wxCommandEvent
)
72 wxPROPERTY( Title
, wxString
, SetTitle
, GetTitle
, wxString(), \
73 0 /*flags*/, wxT("Helpstring"), wxT("group") )
75 wxREADONLY_PROPERTY_FLAGS( MenuStyle
, wxMenuStyle
, long, GetStyle
, \
76 wxEMPTY_PARAMETER_VALUE
, 0 /*flags*/, wxT("Helpstring"), \
77 wxT("group")) // style
79 wxPROPERTY_COLLECTION( MenuItems
, wxMenuItemList
, wxMenuItem
*, Append
, \
80 GetMenuItems
, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
81 wxEND_PROPERTIES_TABLE()
83 wxEMPTY_HANDLERS_TABLE(wxMenu
)
85 wxDIRECT_CONSTRUCTOR_2( wxMenu
, wxString
, Title
, long, MenuStyle
)
87 wxDEFINE_FLAGS( wxMenuBarStyle
)
89 wxBEGIN_FLAGS( wxMenuBarStyle
)
90 wxFLAGS_MEMBER(wxMB_DOCKABLE
)
91 wxEND_FLAGS( wxMenuBarStyle
)
93 // the negative id would lead the window (its superclass !) to
94 // vetoe streaming out otherwise
95 bool wxMenuBarStreamingCallback( const wxObject
*WXUNUSED(object
), wxObjectWriter
*,
96 wxObjectWriterCallback
*, const wxStringToAnyHashMap
& )
101 wxIMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuBar
, wxWindow
, "wx/menu.h", \
102 wxMenuBarStreamingCallback
)
105 #if wxUSE_EXTENDED_RTTI
106 WX_DEFINE_LIST( wxMenuInfoHelperList
)
108 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxMenuInfoHelper
, wxObject
, "wx/menu.h")
110 wxBEGIN_PROPERTIES_TABLE(wxMenuInfoHelper
)
111 wxREADONLY_PROPERTY( Menu
, wxMenu
*, GetMenu
, wxEMPTY_PARAMETER_VALUE
, \
112 0 /*flags*/, wxT("Helpstring"), wxT("group"))
114 wxREADONLY_PROPERTY( Title
, wxString
, GetTitle
, wxString(), \
115 0 /*flags*/, wxT("Helpstring"), wxT("group"))
116 wxEND_PROPERTIES_TABLE()
118 wxEMPTY_HANDLERS_TABLE(wxMenuInfoHelper
)
120 wxCONSTRUCTOR_2( wxMenuInfoHelper
, wxMenu
*, Menu
, wxString
, Title
)
122 wxCOLLECTION_TYPE_INFO( wxMenuInfoHelper
*, wxMenuInfoHelperList
) ;
124 template<> void wxCollectionToVariantArray( wxMenuInfoHelperList
const &theList
,
127 wxListCollectionToAnyList
<wxMenuInfoHelperList
::compatibility_iterator
>( theList
, value
) ;
132 wxBEGIN_PROPERTIES_TABLE(wxMenuBar
)
133 wxPROPERTY_COLLECTION( MenuInfos
, wxMenuInfoHelperList
, wxMenuInfoHelper
*, AppendMenuInfo
, \
134 GetMenuInfos
, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
135 wxEND_PROPERTIES_TABLE()
137 wxEMPTY_HANDLERS_TABLE(wxMenuBar
)
139 wxCONSTRUCTOR_DUMMY( wxMenuBar
)
141 #if wxUSE_EXTENDED_RTTI
143 const wxMenuInfoHelperList
& wxMenuBarBase
::GetMenuInfos() const
145 wxMenuInfoHelperList
* list
= const_cast< wxMenuInfoHelperList
* > (& m_menuInfos
);
146 WX_CLEAR_LIST( wxMenuInfoHelperList
, *list
);
147 for (size_t i
= 0 ; i
< GetMenuCount(); ++i
)
149 wxMenuInfoHelper
* info
= new wxMenuInfoHelper();
150 info
->Create( GetMenu(i
), GetMenuLabel(i
));
158 wxBEGIN_PROPERTIES_TABLE(wxMenuBar
)
159 wxPROPERTY_COLLECTION( MenuInfos
, wxMenuInfoList
, wxMenuInfo
*, AppendMenuInfo
, \
160 GetMenuInfos
, 0 /*flags*/, wxT("Helpstring"), wxT("group"))
161 wxEND_PROPERTIES_TABLE()
163 wxEMPTY_HANDLERS_TABLE(wxMenuBar
)
165 wxCONSTRUCTOR_DUMMY( wxMenuBar
)
167 // ----------------------------------------------------------------------------
168 // XTI for wxMenuItem
169 // ----------------------------------------------------------------------------
171 #if wxUSE_EXTENDED_RTTI
173 bool wxMenuItemStreamingCallback( const wxObject
*object
, wxObjectWriter
*,
174 wxObjectWriterCallback
*, const wxStringToAnyHashMap
& )
176 const wxMenuItem
* mitem
= wx_dynamic_cast(const wxMenuItem
*, object
);
177 if ( mitem
->GetMenu() && !mitem
->GetMenu()->GetTitle().empty() )
179 // we don't stream out the first two items for menus with a title,
180 // they will be reconstructed
181 if ( mitem
->GetMenu()->FindItemByPosition(0) == mitem
||
182 mitem
->GetMenu()->FindItemByPosition(1) == mitem
)
190 wxBEGIN_ENUM( wxItemKind
)
191 wxENUM_MEMBER( wxITEM_SEPARATOR
)
192 wxENUM_MEMBER( wxITEM_NORMAL
)
193 wxENUM_MEMBER( wxITEM_CHECK
)
194 wxENUM_MEMBER( wxITEM_RADIO
)
195 wxEND_ENUM( wxItemKind
)
197 wxIMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuItem
, wxObject
, "wx/menuitem.h", \
198 wxMenuItemStreamingCallback
)
200 wxBEGIN_PROPERTIES_TABLE(wxMenuItem
)
201 wxPROPERTY( Parent
, wxMenu
*, SetMenu
, GetMenu
, wxEMPTY_PARAMETER_VALUE
, \
202 0 /*flags*/, wxT("Helpstring"), wxT("group") )
203 wxPROPERTY( Id
, int, SetId
, GetId
, wxEMPTY_PARAMETER_VALUE
, \
204 0 /*flags*/, wxT("Helpstring"), wxT("group") )
205 wxPROPERTY( ItemLabel
, wxString
, SetItemLabel
, GetItemLabel
, wxString(), \
206 0 /*flags*/, wxT("Helpstring"), wxT("group") )
207 wxPROPERTY( Help
, wxString
, SetHelp
, GetHelp
, wxString(), \
208 0 /*flags*/, wxT("Helpstring"), wxT("group") )
209 wxREADONLY_PROPERTY( Kind
, wxItemKind
, GetKind
, wxEMPTY_PARAMETER_VALUE
, \
210 0 /*flags*/, wxT("Helpstring"), wxT("group") )
211 wxPROPERTY( SubMenu
, wxMenu
*, SetSubMenu
, GetSubMenu
, wxEMPTY_PARAMETER_VALUE
, \
212 0 /*flags*/, wxT("Helpstring"), wxT("group") )
213 wxPROPERTY( Enabled
, bool, Enable
, IsEnabled
, wxAny((bool)true), \
214 0 /*flags*/, wxT("Helpstring"), wxT("group") )
215 wxPROPERTY( Checked
, bool, Check
, IsChecked
, wxAny((bool)false), \
216 0 /*flags*/, wxT("Helpstring"), wxT("group") )
217 wxPROPERTY( Checkable
, bool, SetCheckable
, IsCheckable
, wxAny((bool)false), \
218 0 /*flags*/, wxT("Helpstring"), wxT("group") )
219 wxEND_PROPERTIES_TABLE()
221 wxEMPTY_HANDLERS_TABLE(wxMenuItem
)
223 wxDIRECT_CONSTRUCTOR_6( wxMenuItem
, wxMenu
*, Parent
, int, Id
, wxString
, \
224 Text
, wxString
, Help
, wxItemKind
, Kind
, wxMenu
*, SubMenu
)
226 // ----------------------------------------------------------------------------
228 // ----------------------------------------------------------------------------
230 wxMenuItemBase
::wxMenuItemBase(wxMenu
*parentMenu
,
232 const wxString
& text
,
233 const wxString
& help
,
240 m_id
= wxWindow
::NewControlId();
244 m_id
= wxID_SEPARATOR
;
246 // there is a lot of existing code just doing Append(wxID_SEPARATOR)
247 // and it makes sense to omit the following optional parameters,
248 // including the kind one which doesn't default to wxITEM_SEPARATOR,
249 // of course, so override it here
250 kind
= wxITEM_SEPARATOR
;
254 // (popup) menu titles in wxMSW use this ID to indicate that
255 // it's not a real menu item, so we don't want the check below to
261 // ids are limited to 16 bits under MSW so portable code shouldn't
262 // use ids outside of this range (negative ids generated by wx are
264 wxASSERT_MSG( (id
>= 0 && id
< SHRT_MAX
) ||
265 (id
>= wxID_AUTO_LOWEST
&& id
<= wxID_AUTO_HIGHEST
),
266 wxS("invalid id value") );
270 // notice that parentMenu can be NULL: the item can be attached to the menu
271 // later with SetMenu()
273 m_parentMenu
= parentMenu
;
283 wxMenuItemBase
::~wxMenuItemBase()
290 wxAcceleratorEntry
*wxMenuItemBase
::GetAccel() const
292 return wxAcceleratorEntry
::Create(GetItemLabel());
295 void wxMenuItemBase
::SetAccel(wxAcceleratorEntry
*accel
)
297 wxString text
= m_text
.BeforeFirst(wxT('\t'));
301 text
+= accel
->ToString();
307 #endif // wxUSE_ACCEL
309 void wxMenuItemBase
::SetItemLabel(const wxString
& str
)
313 if ( m_text
.empty() && !IsSeparator() )
315 wxASSERT_MSG( wxIsStockID(GetId()),
316 wxT("A non-stock menu item with an empty label?") );
317 m_text
= wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR
|
318 wxSTOCK_WITH_MNEMONIC
);
322 void wxMenuItemBase
::SetHelp(const wxString
& str
)
326 if ( m_help
.empty() && !IsSeparator() && wxIsStockID(GetId()) )
328 // get a stock help string
329 m_help
= wxGetStockHelpString(GetId());
334 wxString wxMenuItemBase
::GetLabelText(const wxString
& text
)
336 return wxStripMenuCodes(text
);
340 #if WXWIN_COMPATIBILITY_2_8
341 wxString wxMenuItemBase
::GetLabelFromText(const wxString
& text
)
343 return GetLabelText(text
);
347 bool wxMenuBase
::ms_locked
= true;
349 // ----------------------------------------------------------------------------
350 // wxMenu ctor and dtor
351 // ----------------------------------------------------------------------------
353 void wxMenuBase
::Init(long style
)
358 m_invokingWindow
= NULL
;
361 m_eventHandler
= this;
364 wxMenuBase
::~wxMenuBase()
366 WX_CLEAR_LIST(wxMenuItemList
, m_items
);
369 // ----------------------------------------------------------------------------
370 // wxMenu item adding/removing
371 // ----------------------------------------------------------------------------
373 void wxMenuBase
::AddSubMenu(wxMenu
*submenu
)
375 wxCHECK_RET( submenu
, wxT("can't add a NULL submenu") );
377 submenu
->SetParent((wxMenu
*)this);
380 wxMenuItem
* wxMenuBase
::DoAppend(wxMenuItem
*item
)
382 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Append()") );
384 m_items
.Append(item
);
385 item
->SetMenu((wxMenu
*)this);
386 if ( item
->IsSubMenu() )
388 AddSubMenu(item
->GetSubMenu());
394 wxMenuItem
* wxMenuBase
::Insert(size_t pos
, wxMenuItem
*item
)
396 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Insert") );
398 if ( pos
== GetMenuItemCount() )
400 return DoAppend(item
);
404 wxCHECK_MSG( pos
< GetMenuItemCount(), NULL
,
405 wxT("invalid index in wxMenu::Insert") );
407 return DoInsert(pos
, item
);
411 wxMenuItem
* wxMenuBase
::DoInsert(size_t pos
, wxMenuItem
*item
)
413 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Insert()") );
415 wxMenuItemList
::compatibility_iterator node
= m_items
.Item(pos
);
416 wxCHECK_MSG( node
, NULL
, wxT("invalid index in wxMenu::Insert()") );
418 m_items
.Insert(node
, item
);
419 item
->SetMenu((wxMenu
*)this);
420 if ( item
->IsSubMenu() )
422 AddSubMenu(item
->GetSubMenu());
428 wxMenuItem
*wxMenuBase
::Remove(wxMenuItem
*item
)
430 wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Remove") );
432 return DoRemove(item
);
435 wxMenuItem
*wxMenuBase
::DoRemove(wxMenuItem
*item
)
437 wxMenuItemList
::compatibility_iterator node
= m_items
.Find(item
);
439 // if we get here, the item is valid or one of Remove() functions is broken
440 wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") );
442 // we detach the item, but we do delete the list node (i.e. don't call
443 // DetachNode() here!)
446 // item isn't attached to anything any more
448 wxMenu
*submenu
= item
->GetSubMenu();
451 submenu
->SetParent(NULL
);
452 if ( submenu
->IsAttached() )
459 bool wxMenuBase
::Delete(wxMenuItem
*item
)
461 wxCHECK_MSG( item
, false, wxT("invalid item in wxMenu::Delete") );
463 return DoDelete(item
);
466 bool wxMenuBase
::DoDelete(wxMenuItem
*item
)
468 wxMenuItem
*item2
= DoRemove(item
);
469 wxCHECK_MSG( item2
, false, wxT("failed to delete menu item") );
471 // don't delete the submenu
472 item2
->SetSubMenu(NULL
);
479 bool wxMenuBase
::Destroy(wxMenuItem
*item
)
481 wxCHECK_MSG( item
, false, wxT("invalid item in wxMenu::Destroy") );
483 return DoDestroy(item
);
486 bool wxMenuBase
::DoDestroy(wxMenuItem
*item
)
488 wxMenuItem
*item2
= DoRemove(item
);
489 wxCHECK_MSG( item2
, false, wxT("failed to delete menu item") );
496 // ----------------------------------------------------------------------------
497 // wxMenu searching for items
498 // ----------------------------------------------------------------------------
500 // Finds the item id matching the given string, wxNOT_FOUND if not found.
501 int wxMenuBase
::FindItem(const wxString
& text
) const
503 wxString label
= wxMenuItem
::GetLabelText(text
);
504 for ( wxMenuItemList
::compatibility_iterator node
= m_items
.GetFirst();
506 node
= node
->GetNext() )
508 wxMenuItem
*item
= node
->GetData();
509 if ( item
->IsSubMenu() )
511 int rc
= item
->GetSubMenu()->FindItem(label
);
512 if ( rc
!= wxNOT_FOUND
)
516 // we execute this code for submenus as well to alllow finding them by
517 // name just like the ordinary items
518 if ( !item
->IsSeparator() )
520 if ( item
->GetItemLabelText() == label
)
521 return item
->GetId();
528 // recursive search for item by id
529 wxMenuItem
*wxMenuBase
::FindItem(int itemId
, wxMenu
**itemMenu
) const
534 wxMenuItem
*item
= NULL
;
535 for ( wxMenuItemList
::compatibility_iterator node
= m_items
.GetFirst();
537 node
= node
->GetNext() )
539 item
= node
->GetData();
541 if ( item
->GetId() == itemId
)
544 *itemMenu
= (wxMenu
*)this;
546 else if ( item
->IsSubMenu() )
548 item
= item
->GetSubMenu()->FindItem(itemId
, itemMenu
);
552 // don't exit the loop
560 // non recursive search
561 wxMenuItem
*wxMenuBase
::FindChildItem(int id
, size_t *ppos
) const
563 wxMenuItem
*item
= NULL
;
564 wxMenuItemList
::compatibility_iterator node
= GetMenuItems().GetFirst();
567 for ( pos
= 0; node
; pos
++ )
569 if ( node
->GetData()->GetId() == id
)
571 item
= node
->GetData();
576 node
= node
->GetNext();
581 *ppos
= item ? pos
: (size_t)wxNOT_FOUND
;
588 wxMenuItem
* wxMenuBase
::FindItemByPosition(size_t position
) const
590 wxCHECK_MSG( position
< m_items
.GetCount(), NULL
,
591 wxT("wxMenu::FindItemByPosition(): invalid menu index") );
593 return m_items
.Item( position
)->GetData();
596 // ----------------------------------------------------------------------------
597 // wxMenu helpers used by derived classes
598 // ----------------------------------------------------------------------------
600 // Update a menu and all submenus recursively. source is the object that has
601 // the update event handlers defined for it. If NULL, the menu or associated
602 // window will be used.
603 void wxMenuBase
::UpdateUI(wxEvtHandler
* source
)
605 if (GetInvokingWindow())
607 // Don't update menus if the parent
608 // frame is about to get deleted
609 wxWindow
*tlw
= wxGetTopLevelParent( GetInvokingWindow() );
610 if (tlw
&& wxPendingDelete
.Member(tlw
))
614 if ( !source
&& GetInvokingWindow() )
615 source
= GetInvokingWindow()->GetEventHandler();
617 source
= GetEventHandler();
621 wxMenuItemList
::compatibility_iterator node
= GetMenuItems().GetFirst();
624 wxMenuItem
* item
= node
->GetData();
625 if ( !item
->IsSeparator() )
627 wxWindowID id
= item
->GetId();
628 wxUpdateUIEvent
event(id
);
629 event
.SetEventObject( source
);
631 if ( source
->ProcessEvent(event
) )
633 // if anything changed, update the changed attribute
634 if (event
.GetSetText())
635 SetLabel(id
, event
.GetText());
636 if (event
.GetSetChecked())
637 Check(id
, event
.GetChecked());
638 if (event
.GetSetEnabled())
639 Enable(id
, event
.GetEnabled());
642 // recurse to the submenus
643 if ( item
->GetSubMenu() )
644 item
->GetSubMenu()->UpdateUI(source
);
646 //else: item is a separator (which doesn't process update UI events)
648 node
= node
->GetNext();
652 bool wxMenuBase
::SendEvent(int id
, int checked
)
654 wxCommandEvent
event(wxEVT_COMMAND_MENU_SELECTED
, id
);
655 event
.SetEventObject(this);
656 event
.SetInt(checked
);
658 bool processed
= false;
660 // Try the menu's event handler first
661 wxEvtHandler
*handler
= GetEventHandler();
663 processed
= handler
->SafelyProcessEvent(event
);
665 // Try the window the menu was popped up from or its menu bar belongs to
668 wxWindow
* const win
= GetWindow();
670 processed
= win
->HandleWindowEvent(event
);
676 // ----------------------------------------------------------------------------
677 // wxMenu attaching/detaching to/from menu bar
678 // ----------------------------------------------------------------------------
680 wxMenuBar
* wxMenuBase
::GetMenuBar() const
683 return GetParent()->GetMenuBar();
687 void wxMenuBase
::Attach(wxMenuBarBase
*menubar
)
689 // use Detach() instead!
690 wxASSERT_MSG( menubar
, wxT("menu can't be attached to NULL menubar") );
692 // use IsAttached() to prevent this from happening
693 wxASSERT_MSG( !m_menuBar
, wxT("attaching menu twice?") );
695 m_menuBar
= (wxMenuBar
*)menubar
;
698 void wxMenuBase
::Detach()
700 // use IsAttached() to prevent this from happening
701 wxASSERT_MSG( m_menuBar
, wxT("detaching unattached menu?") );
706 // ----------------------------------------------------------------------------
707 // wxMenu invoking window handling
708 // ----------------------------------------------------------------------------
710 void wxMenuBase
::SetInvokingWindow(wxWindow
*win
)
712 wxASSERT_MSG( !GetParent(),
713 "should only be called for top level popup menus" );
714 wxASSERT_MSG( !IsAttached(),
715 "menus attached to menu bar can't have invoking window" );
717 m_invokingWindow
= win
;
720 wxWindow
*wxMenuBase
::GetWindow() const
722 // only the top level menus have non-NULL invoking window or a pointer to
723 // the menu bar so recurse upwards until we find it
724 const wxMenuBase
*menu
= this;
725 while ( menu
->GetParent() )
727 menu
= menu
->GetParent();
730 return menu
->GetMenuBar() ? menu
->GetMenuBar()->GetFrame()
731 : menu
->GetInvokingWindow();
734 // ----------------------------------------------------------------------------
735 // wxMenu functions forwarded to wxMenuItem
736 // ----------------------------------------------------------------------------
738 void wxMenuBase
::Enable( int id
, bool enable
)
740 wxMenuItem
*item
= FindItem(id
);
742 wxCHECK_RET( item
, wxT("wxMenu::Enable: no such item") );
744 item
->Enable(enable
);
747 bool wxMenuBase
::IsEnabled( int id
) const
749 wxMenuItem
*item
= FindItem(id
);
751 wxCHECK_MSG( item
, false, wxT("wxMenu::IsEnabled: no such item") );
753 return item
->IsEnabled();
756 void wxMenuBase
::Check( int id
, bool enable
)
758 wxMenuItem
*item
= FindItem(id
);
760 wxCHECK_RET( item
, wxT("wxMenu::Check: no such item") );
765 bool wxMenuBase
::IsChecked( int id
) const
767 wxMenuItem
*item
= FindItem(id
);
769 wxCHECK_MSG( item
, false, wxT("wxMenu::IsChecked: no such item") );
771 return item
->IsChecked();
774 void wxMenuBase
::SetLabel( int id
, const wxString
&label
)
776 wxMenuItem
*item
= FindItem(id
);
778 wxCHECK_RET( item
, wxT("wxMenu::SetLabel: no such item") );
780 item
->SetItemLabel(label
);
783 wxString wxMenuBase
::GetLabel( int id
) const
785 wxMenuItem
*item
= FindItem(id
);
787 wxCHECK_MSG( item
, wxEmptyString
, wxT("wxMenu::GetLabel: no such item") );
789 return item
->GetItemLabel();
792 void wxMenuBase
::SetHelpString( int id
, const wxString
& helpString
)
794 wxMenuItem
*item
= FindItem(id
);
796 wxCHECK_RET( item
, wxT("wxMenu::SetHelpString: no such item") );
798 item
->SetHelp( helpString
);
801 wxString wxMenuBase
::GetHelpString( int id
) const
803 wxMenuItem
*item
= FindItem(id
);
805 wxCHECK_MSG( item
, wxEmptyString
, wxT("wxMenu::GetHelpString: no such item") );
807 return item
->GetHelp();
810 // ----------------------------------------------------------------------------
811 // wxMenuBarBase ctor and dtor
812 // ----------------------------------------------------------------------------
814 wxMenuBarBase
::wxMenuBarBase()
817 m_menuBarFrame
= NULL
;
820 wxMenuBarBase
::~wxMenuBarBase()
822 WX_CLEAR_LIST(wxMenuList
, m_menus
);
825 // ----------------------------------------------------------------------------
826 // wxMenuBar item access: the base class versions manage m_menus list, the
827 // derived class should reflect the changes in the real menubar
828 // ----------------------------------------------------------------------------
830 wxMenu
*wxMenuBarBase
::GetMenu(size_t pos
) const
832 wxMenuList
::compatibility_iterator node
= m_menus
.Item(pos
);
833 wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::GetMenu()") );
835 return node
->GetData();
838 bool wxMenuBarBase
::Append(wxMenu
*menu
, const wxString
& title
)
840 wxCHECK_MSG( menu
, false, wxT("can't append NULL menu") );
841 wxCHECK_MSG( !title
.empty(), false, wxT("can't append menu with empty title") );
843 m_menus
.Append(menu
);
849 bool wxMenuBarBase
::Insert(size_t pos
, wxMenu
*menu
,
850 const wxString
& title
)
852 if ( pos
== m_menus
.GetCount() )
854 return wxMenuBarBase
::Append(menu
, title
);
856 else // not at the end
858 wxCHECK_MSG( menu
, false, wxT("can't insert NULL menu") );
860 wxMenuList
::compatibility_iterator node
= m_menus
.Item(pos
);
861 wxCHECK_MSG( node
, false, wxT("bad index in wxMenuBar::Insert()") );
863 m_menus
.Insert(node
, menu
);
870 wxMenu
*wxMenuBarBase
::Replace(size_t pos
, wxMenu
*menu
,
871 const wxString
& WXUNUSED(title
))
873 wxCHECK_MSG( menu
, NULL
, wxT("can't insert NULL menu") );
875 wxMenuList
::compatibility_iterator node
= m_menus
.Item(pos
);
876 wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::Replace()") );
878 wxMenu
*menuOld
= node
->GetData();
887 wxMenu
*wxMenuBarBase
::Remove(size_t pos
)
889 wxMenuList
::compatibility_iterator node
= m_menus
.Item(pos
);
890 wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::Remove()") );
892 wxMenu
*menu
= node
->GetData();
899 int wxMenuBarBase
::FindMenu(const wxString
& title
) const
901 wxString label
= wxMenuItem
::GetLabelText(title
);
903 size_t count
= GetMenuCount();
904 for ( size_t i
= 0; i
< count
; i
++ )
906 wxString title2
= GetMenuLabel(i
);
907 if ( (title2
== title
) ||
908 (wxMenuItem
::GetLabelText(title2
) == label
) )
919 // ----------------------------------------------------------------------------
920 // wxMenuBar attaching/detaching to/from the frame
921 // ----------------------------------------------------------------------------
923 void wxMenuBarBase
::Attach(wxFrame
*frame
)
925 wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
927 m_menuBarFrame
= frame
;
930 void wxMenuBarBase
::Detach()
932 wxASSERT_MSG( IsAttached(), wxT("detaching unattached menubar") );
934 m_menuBarFrame
= NULL
;
937 // ----------------------------------------------------------------------------
938 // wxMenuBar searching for items
939 // ----------------------------------------------------------------------------
941 wxMenuItem
*wxMenuBarBase
::FindItem(int id
, wxMenu
**menu
) const
946 wxMenuItem
*item
= NULL
;
947 size_t count
= GetMenuCount(), i
;
948 wxMenuList
::const_iterator it
;
949 for ( i
= 0, it
= m_menus
.begin(); !item
&& (i
< count
); i
++, it
++ )
951 item
= (*it
)->FindItem(id
, menu
);
957 int wxMenuBarBase
::FindMenuItem(const wxString
& menu
, const wxString
& item
) const
959 wxString label
= wxMenuItem
::GetLabelText(menu
);
962 wxMenuList
::compatibility_iterator node
;
963 for ( node
= m_menus
.GetFirst(); node
; node
= node
->GetNext(), i
++ )
965 if ( label
== wxMenuItem
::GetLabelText(GetMenuLabel(i
)) )
966 return node
->GetData()->FindItem(item
);
972 // ---------------------------------------------------------------------------
973 // wxMenuBar functions forwarded to wxMenuItem
974 // ---------------------------------------------------------------------------
976 void wxMenuBarBase
::Enable(int id
, bool enable
)
978 wxMenuItem
*item
= FindItem(id
);
980 wxCHECK_RET( item
, wxT("attempt to enable an item which doesn't exist") );
982 item
->Enable(enable
);
985 void wxMenuBarBase
::Check(int id
, bool check
)
987 wxMenuItem
*item
= FindItem(id
);
989 wxCHECK_RET( item
, wxT("attempt to check an item which doesn't exist") );
990 wxCHECK_RET( item
->IsCheckable(), wxT("attempt to check an uncheckable item") );
995 bool wxMenuBarBase
::IsChecked(int id
) const
997 wxMenuItem
*item
= FindItem(id
);
999 wxCHECK_MSG( item
, false, wxT("wxMenuBar::IsChecked(): no such item") );
1001 return item
->IsChecked();
1004 bool wxMenuBarBase
::IsEnabled(int id
) const
1006 wxMenuItem
*item
= FindItem(id
);
1008 wxCHECK_MSG( item
, false, wxT("wxMenuBar::IsEnabled(): no such item") );
1010 return item
->IsEnabled();
1013 void wxMenuBarBase
::SetLabel(int id
, const wxString
& label
)
1015 wxMenuItem
*item
= FindItem(id
);
1017 wxCHECK_RET( item
, wxT("wxMenuBar::SetLabel(): no such item") );
1019 item
->SetItemLabel(label
);
1022 wxString wxMenuBarBase
::GetLabel(int id
) const
1024 wxMenuItem
*item
= FindItem(id
);
1026 wxCHECK_MSG( item
, wxEmptyString
,
1027 wxT("wxMenuBar::GetLabel(): no such item") );
1029 return item
->GetItemLabel();
1032 void wxMenuBarBase
::SetHelpString(int id
, const wxString
& helpString
)
1034 wxMenuItem
*item
= FindItem(id
);
1036 wxCHECK_RET( item
, wxT("wxMenuBar::SetHelpString(): no such item") );
1038 item
->SetHelp(helpString
);
1041 wxString wxMenuBarBase
::GetHelpString(int id
) const
1043 wxMenuItem
*item
= FindItem(id
);
1045 wxCHECK_MSG( item
, wxEmptyString
,
1046 wxT("wxMenuBar::GetHelpString(): no such item") );
1048 return item
->GetHelp();
1051 void wxMenuBarBase
::UpdateMenus()
1053 wxEvtHandler
* source
;
1055 int nCount
= GetMenuCount();
1056 for (int n
= 0; n
< nCount
; n
++)
1058 menu
= GetMenu( n
);
1061 source
= menu
->GetEventHandler();
1063 menu
->UpdateUI( source
);
1068 #if WXWIN_COMPATIBILITY_2_8
1069 // get or change the label of the menu at given position
1070 void wxMenuBarBase
::SetLabelTop(size_t pos
, const wxString
& label
)
1072 SetMenuLabel(pos
, label
);
1075 wxString wxMenuBarBase
::GetLabelTop(size_t pos
) const
1077 return GetMenuLabelText(pos
);
1081 #endif // wxUSE_MENUS