Constructs a wxMenuItem object.
-The preferred way to create standard menu items is to use default value of
-\arg{text}. If no text is supplied and \arg{id} is one of standard IDs from
-\helpref{this list}{stockitems}, a standard label and a standard accelerator
-will be used. In addition to that, the button will be decorated with stock
-icons under GTK+ 2.
+Menu items can be standard, or ``stock menu items'', or custom. For the
+standard menu items (such as commands to open a file, exit the program and so
+on, see \helpref{stock items}{stockitems} for the full list) it is enough to
+specify just the stock ID and leave \arg{text} and \arg{helpString} empty. In
+fact, leaving at least \arg{text} empty for the stock menu items is strongly
+recommended as they will have appearance and keyboard interface (including
+standard accelerators) familiar to the user.
+
+For the custom (non-stock) menu items, \arg{text} must be specified and while
+\arg{helpString} may be left empty, it's recommended to pass the item
+description (which is automatically shown by the library in the status bar when
+the menu item is selected) in this parameter.
+
+Finally note that you can e.g. use a stock menu label without using its stock
+help string:
+
+\begin{verbatim}
+// use all stock properties:
+helpMenu->Append(wxID_ABOUT);
+
+// use the stock label and the stock accelerator but not the stock help string:
+helpMenu->Append(wxID_ABOUT, wxEmptyString, wxT("My custom help string"));
+
+// use all stock properties except for the bitmap:
+wxMenuItem *mymenu = new wxMenuItem(helpMenu, wxID_ABOUT);
+mymenu->SetBitmap(wxArtProvider::GetBitmap(wxART_WARNING));
+helpMenu->Append(mymenu);
+\end{verbatim}
+
+that is, stock properties are set independently one from the other.
\wxheading{Parameters}
\section{Stock items}\label{stockitems}
-Window IDs for which stock buttons are created
-(see \helpref{wxButton constructor}{wxbuttonctor}):
+Window IDs for which stock buttons and menu items are created
+(see \helpref{wxButton constructor}{wxbuttonctor} and
+\helpref{wxMenuItem constructor}{wxmenuitemctor}):
\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf Stock ID}}{{\bf Stock label}}
\twocolitem{wxID\_ABOUT}{"\&About"}
\twocolitem{wxID\_ADD}{"Add"}
\twocolitem{wxID\_APPLY}{"\&Apply"}
\twocolitem{wxID\_ZOOM\_FIT}{"Zoom to \&Fit"}
\twocolitem{wxID\_ZOOM\_IN}{"Zoom \&In"}
\twocolitem{wxID\_ZOOM\_OUT}{"Zoom \&Out"}
-\end{twocollist}\itemsep=0pt
+\end{twocollist}
+
+
+Note that some of the IDs listed above have also a stock accelerator
+and an help string associated.
// any), i.e. it may contain '&' or '_' or "\t..." and thus is
// different from the item's label which only contains the text shown
// in the menu
- virtual void SetText(const wxString& str) { m_text = str; }
+ virtual void SetText(const wxString& str);
wxString GetLabel() const { return GetLabelFromText(m_text); }
const wxString& GetText() const { return m_text; }
void Toggle() { Check(!m_isChecked); }
// help string (displayed in the status bar by default)
- void SetHelp(const wxString& str) { m_help = str; }
+ void SetHelp(const wxString& str);
const wxString& GetHelp() const { return m_help; }
#if wxUSE_ACCEL
#endif
+// wxStockHelpStringClient conceptually works like wxArtClient: it gives a hint to
+// wxGetStockHelpString() about the context where the help string is to be used
+enum wxStockHelpStringClient
+{
+ wxSTOCK_MENU // help string to use for menu items
+};
+
+// Returns an help string for the given stock UI element and for the given "context".
+WXDLLEXPORT wxString wxGetStockHelpString(wxWindowID id,
+ wxStockHelpStringClient client = wxSTOCK_MENU);
+
+
#ifdef __WXGTK20__
#include <gdk/gdktypes.h>
#include "wx/menu.h"
#endif
+#include "wx/stockitem.h"
+
// ----------------------------------------------------------------------------
// template lists
// ----------------------------------------------------------------------------
bool
wxAcceleratorEntry::ParseAccel(const wxString& text, int *flagsOut, int *keyOut)
{
- // the parser won't like leading/trailing spaces
- wxString label = text.Strip(wxString::both);
+ // the parser won't like trailing spaces
+ wxString label = text;
+ label.Trim(true); // the initial \t must be preserved so don't strip leading whitespaces
// check for accelerators: they are given after '\t'
int posTab = label.Find(wxT('\t'));
if ( posTab == wxNOT_FOUND )
+ {
+ wxLogDebug(wxT("Invalid menu label: no accelerators"));
return false;
+ }
// parse the accelerator string
int accelFlags = wxACCEL_NORMAL;
const wxString& help,
wxItemKind kind,
wxMenu *subMenu)
- : m_text(text),
- m_help(help)
{
wxASSERT_MSG( parentMenu != NULL, wxT("menuitem should have a menu") );
m_id = wxNewId();
if (m_id == wxID_SEPARATOR)
m_kind = wxITEM_SEPARATOR;
+
+ SetText(text);
+ SetHelp(help);
}
wxMenuItemBase::~wxMenuItemBase()
#endif // wxUSE_ACCEL
+void wxMenuItemBase::SetText(const wxString& str)
+{
+ m_text = str;
+
+ if ( m_text.empty() && !IsSeparator() )
+ {
+ wxASSERT_MSG( wxIsStockID(GetId()),
+ wxT("A non-stock menu item with an empty label?") );
+ m_text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR |
+ wxSTOCK_WITH_MNEMONIC);
+ }
+}
+
+void wxMenuItemBase::SetHelp(const wxString& str)
+{
+ m_help = str;
+
+ if ( m_help.empty() && !IsSeparator() && wxIsStockID(GetId()) )
+ {
+ // get a stock help string
+ m_help = wxGetStockHelpString(GetId());
+ }
+}
+
bool wxMenuBase::ms_locked = true;
// ----------------------------------------------------------------------------
return stockLabel;
}
+wxString wxGetStockHelpString(wxWindowID id, wxStockHelpStringClient client)
+{
+ wxString stockHelp;
+
+ #define STOCKITEM(stockid, ctx, helpstr) \
+ case stockid: \
+ if (client==ctx) stockHelp = helpstr; \
+ break;
+
+ switch (id)
+ {
+ // NB: these help string should be not too specific as they could be used
+ // in completely different programs!
+ STOCKITEM(wxID_ABOUT, wxSTOCK_MENU, _("Show about dialog"))
+ STOCKITEM(wxID_COPY, wxSTOCK_MENU, _("Copy selection"))
+ STOCKITEM(wxID_CUT, wxSTOCK_MENU, _("Cut selection"))
+ STOCKITEM(wxID_DELETE, wxSTOCK_MENU, _("Delete selection"))
+ STOCKITEM(wxID_REPLACE, wxSTOCK_MENU, _("Replace selection"))
+ STOCKITEM(wxID_PASTE, wxSTOCK_MENU, _("Paste selection"))
+ STOCKITEM(wxID_EXIT, wxSTOCK_MENU, _("Quit this program"))
+ STOCKITEM(wxID_REDO, wxSTOCK_MENU, _("Redo last action"))
+ STOCKITEM(wxID_UNDO, wxSTOCK_MENU, _("Undo last action"))
+ STOCKITEM(wxID_CLOSE, wxSTOCK_MENU, _("Close current document"))
+ STOCKITEM(wxID_SAVE, wxSTOCK_MENU, _("Save current document"))
+ STOCKITEM(wxID_SAVEAS, wxSTOCK_MENU, _("Save current document with a different filename"))
+
+ default:
+ // there's no stock help string for this ID / client
+ return wxEmptyString;
+ }
+
+ #undef STOCKITEM
+
+ return stockHelp;
+}
+
#if wxUSE_ACCEL
wxAcceleratorEntry wxGetStockAccelerator(wxWindowID id)
void wxMenuItem::SetText( const wxString& string )
{
wxString str = string;
- if (str.IsEmpty())
+ if ( str.empty() && !IsSeparator() )
{
wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
- str = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+ str = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR |
+ wxSTOCK_WITH_MNEMONIC);
}
// Some optimization to avoid flicker
void wxMenuItem::Init()
{
- if (m_text.IsEmpty())
- {
- wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
- m_text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
- }
-
m_radioGroup.start = -1;
m_isRadioGroupStart = false;
if ( m_text == txt )
return;
- if (text.IsEmpty())
- {
- wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
- text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
- }
-
+ // wxMenuItemBase will do stock ID checks
wxMenuItemBase::SetText(text);
- OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
+
+ // m_text could now be different from 'text' if we are a stock menu item,
+ // so use only m_text below
+
+ OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(m_text) );
#if wxUSE_OWNER_DRAWN
// tell the owner drawing code to to show the accel string as well
- SetAccelString(text.AfterFirst(_T('\t')));
+ SetAccelString(m_text.AfterFirst(_T('\t')));
#endif
HMENU hMenu = GetHMenuOf(m_parentMenu);
#endif //owner drawn
{
flagsOld |= MF_STRING;
- data = (wxChar*) text.c_str();
+ data = (wxChar*) m_text.c_str();
}
#ifdef __WXWINCE__
info.cbSize = sizeof(info);
info.fMask = MIIM_TYPE;
info.fType = MFT_STRING;
- info.cch = text.length();
+ info.cch = m_text.length();
info.dwTypeData = (LPTSTR) data ;
if ( !::SetMenuItemInfo(hMenu, id, FALSE, & info) )
{
if (m_text == sText)
return;
- if (sText.IsEmpty())
- {
- wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
- sText = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
- }
-
+ // wxMenuItemBase will do stock ID checks
wxMenuItemBase::SetText(sText);
- OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText));
+
+ // m_text could now be different from 'text' if we are a stock menu item,
+ // so use only m_text below
+
+ OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(m_text));
#if wxUSE_OWNER_DRAWN
if (rText.IsEmpty())
- SetAccelString(sText.AfterFirst(_T('\t')));
+ SetAccelString(m_text.AfterFirst(_T('\t')));
else
SetAccelString(rText.AfterFirst(_T('\t')));
#endif // wxUSE_OWNER_DRAWN
#endif //owner drawn
{
uFlagsOld |= MIS_TEXT;
- pData = (BYTE*)sText.c_str();
+ pData = (BYTE*)m_text.c_str();
}
//
m_strAccel = m_text.AfterFirst(_T('\t'));
}
-void wxMenuItem::SetText(const wxString& txt)
+void wxMenuItem::SetText(const wxString& text)
{
- if ( txt != m_text )
+ if ( text != m_text )
{
- wxString text = txt;
- if (text.IsEmpty())
- {
- wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
- text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
- }
-
// first call the base class version to change m_text
+ // (and also check if we don't have a stock menu item)
wxMenuItemBase::SetText(text);
UpdateAccelInfo();