+#if wxUSE_EXTENDED_RTTI
+
+bool wxMenuItemStreamingCallback( const wxObject *object, wxObjectWriter *,
+ wxObjectWriterCallback *, const wxStringToAnyHashMap & )
+{
+ const wxMenuItem * mitem = wx_dynamic_cast(const wxMenuItem*, object);
+ if ( mitem->GetMenu() && !mitem->GetMenu()->GetTitle().empty() )
+ {
+ // we don't stream out the first two items for menus with a title,
+ // they will be reconstructed
+ if ( mitem->GetMenu()->FindItemByPosition(0) == mitem ||
+ mitem->GetMenu()->FindItemByPosition(1) == mitem )
+ return false;
+ }
+ return true;
+}
+
+#endif
+
+wxBEGIN_ENUM( wxItemKind )
+wxENUM_MEMBER( wxITEM_SEPARATOR )
+wxENUM_MEMBER( wxITEM_NORMAL )
+wxENUM_MEMBER( wxITEM_CHECK )
+wxENUM_MEMBER( wxITEM_RADIO )
+wxEND_ENUM( wxItemKind )
+
+wxIMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxMenuItem, wxObject, "wx/menuitem.h", \
+ wxMenuItemStreamingCallback)
+
+wxBEGIN_PROPERTIES_TABLE(wxMenuItem)
+wxPROPERTY( Parent, wxMenu*, SetMenu, GetMenu, wxEMPTY_PARAMETER_VALUE, \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxPROPERTY( Id, int, SetId, GetId, wxEMPTY_PARAMETER_VALUE, \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxPROPERTY( ItemLabel, wxString, SetItemLabel, GetItemLabel, wxString(), \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxPROPERTY( Help, wxString, SetHelp, GetHelp, wxString(), \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxREADONLY_PROPERTY( Kind, wxItemKind, GetKind, wxEMPTY_PARAMETER_VALUE, \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxPROPERTY( SubMenu, wxMenu*, SetSubMenu, GetSubMenu, wxEMPTY_PARAMETER_VALUE, \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxPROPERTY( Enabled, bool, Enable, IsEnabled, wxAny((bool)true), \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxPROPERTY( Checked, bool, Check, IsChecked, wxAny((bool)false), \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxPROPERTY( Checkable, bool, SetCheckable, IsCheckable, wxAny((bool)false), \
+ 0 /*flags*/, wxT("Helpstring"), wxT("group") )
+wxEND_PROPERTIES_TABLE()
+
+wxEMPTY_HANDLERS_TABLE(wxMenuItem)
+
+wxDIRECT_CONSTRUCTOR_6( wxMenuItem, wxMenu*, Parent, int, Id, wxString, \
+ Text, wxString, Help, wxItemKind, Kind, wxMenu*, SubMenu )
+
+// ----------------------------------------------------------------------------
+// wxMenuItemBase
+// ----------------------------------------------------------------------------
+
+wxMenuItemBase::wxMenuItemBase(wxMenu *parentMenu,
+ int itemid,
+ const wxString& text,
+ const wxString& help,
+ wxItemKind kind,
+ wxMenu *subMenu)
+{
+ switch ( itemid )
+ {
+ case wxID_ANY:
+ m_id = wxWindow::NewControlId();
+ break;
+
+ case wxID_SEPARATOR:
+ m_id = wxID_SEPARATOR;
+
+ // there is a lot of existing code just doing Append(wxID_SEPARATOR)
+ // and it makes sense to omit the following optional parameters,
+ // including the kind one which doesn't default to wxITEM_SEPARATOR,
+ // of course, so override it here
+ kind = wxITEM_SEPARATOR;
+ break;
+
+ case wxID_NONE:
+ // (popup) menu titles in wxMSW use this ID to indicate that
+ // it's not a real menu item, so we don't want the check below to
+ // apply to it
+ m_id = itemid;
+ break;
+
+ default:
+ // ids are limited to 16 bits under MSW so portable code shouldn't
+ // use ids outside of this range (negative ids generated by wx are
+ // fine though)
+ wxASSERT_MSG( (itemid >= 0 && itemid < SHRT_MAX) ||
+ (itemid >= wxID_AUTO_LOWEST && itemid <= wxID_AUTO_HIGHEST),
+ wxS("invalid itemid value") );
+ m_id = itemid;
+ }
+
+ // notice that parentMenu can be NULL: the item can be attached to the menu
+ // later with SetMenu()
+
+ m_parentMenu = parentMenu;
+ m_subMenu = subMenu;
+ m_isEnabled = true;
+ m_isChecked = false;
+ m_kind = kind;
+
+ SetItemLabel(text);
+ SetHelp(help);
+}
+
+wxMenuItemBase::~wxMenuItemBase()
+{
+ delete m_subMenu;