Allow to add extra accelerators to wxMenuItem
These accelerators are not shown in wxMenuItem label, but still will work. Implement support for them in all major ports and XRC. Co-Authored-By: Vadim Zeitlin <vadim@wxwidgets.org>
This commit is contained in:
committed by
Vadim Zeitlin
parent
e729791222
commit
0cd898975c
@@ -518,6 +518,28 @@ Example:
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
|
|
||||||
|
@subsection overview_xrcformat_type_extra_accels Accelerators List
|
||||||
|
|
||||||
|
Defines a list of wxMenuItem's extra accelerators.
|
||||||
|
|
||||||
|
The extra-accels property element is a "composite" element:
|
||||||
|
it contains one or more @c \<accel\> "sub-properties":
|
||||||
|
|
||||||
|
@beginTable
|
||||||
|
@hdr3col{property, type, description}
|
||||||
|
@row3col{accel, @ref overview_xrcformat_type_text_notrans,
|
||||||
|
wxMenuItem's accelerator (default: none).}
|
||||||
|
@endTable
|
||||||
|
|
||||||
|
Example:
|
||||||
|
@code
|
||||||
|
<extra-accels>
|
||||||
|
<accel>Ctrl-W</accel>
|
||||||
|
<accel>Shift-Ctrl-W</accel>
|
||||||
|
</extra-accels>
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
|
||||||
@section overview_xrcformat_windows Controls and Windows
|
@section overview_xrcformat_windows Controls and Windows
|
||||||
|
|
||||||
This section describes support wxWindow-derived classes in XRC format.
|
This section describes support wxWindow-derived classes in XRC format.
|
||||||
@@ -1496,6 +1518,10 @@ wxMenuItem objects support the following properties:
|
|||||||
Item's label (may be omitted if stock ID is used).}
|
Item's label (may be omitted if stock ID is used).}
|
||||||
@row3col{accel, @ref overview_xrcformat_type_text_notrans,
|
@row3col{accel, @ref overview_xrcformat_type_text_notrans,
|
||||||
Item's accelerator (default: none).}
|
Item's accelerator (default: none).}
|
||||||
|
@row3col{extra-accels, @ref overview_xrcformat_type_extra_accels,
|
||||||
|
List of item's extra accelerators. Such accelerators will not be shown
|
||||||
|
in item's label, but still will work. (default: none).
|
||||||
|
This property is only supported since wxWidgets 3.1.6.}
|
||||||
@row3col{radio, @ref overview_xrcformat_type_bool,
|
@row3col{radio, @ref overview_xrcformat_type_bool,
|
||||||
Item's kind is wxITEM_RADIO (default: 0)?}
|
Item's kind is wxITEM_RADIO (default: 0)?}
|
||||||
@row3col{checkable, @ref overview_xrcformat_type_bool,
|
@row3col{checkable, @ref overview_xrcformat_type_bool,
|
||||||
@@ -1520,6 +1546,10 @@ Example:
|
|||||||
<object class="wxMenuItem" name="wxID_FIND">
|
<object class="wxMenuItem" name="wxID_FIND">
|
||||||
<label>_Find...</label>
|
<label>_Find...</label>
|
||||||
<accel>Ctrl-F</accel>
|
<accel>Ctrl-F</accel>
|
||||||
|
<extra-accels>
|
||||||
|
<accel>Ctrl-W</accel>
|
||||||
|
<accel>Shift-Ctrl-W</accel>
|
||||||
|
</extra-accels>
|
||||||
</object>
|
</object>
|
||||||
<object class="separator"/>
|
<object class="separator"/>
|
||||||
<object class="wxMenuItem" name="menu_fuzzy">
|
<object class="wxMenuItem" name="menu_fuzzy">
|
||||||
|
|||||||
@@ -34,11 +34,20 @@ public:
|
|||||||
virtual void SetBitmap(const wxBitmap& bitmap);
|
virtual void SetBitmap(const wxBitmap& bitmap);
|
||||||
virtual const wxBitmap& GetBitmap() const { return m_bitmap; }
|
virtual const wxBitmap& GetBitmap() const { return m_bitmap; }
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
virtual void AddExtraAccel(const wxAcceleratorEntry& accel) wxOVERRIDE;
|
||||||
|
virtual void ClearExtraAccels() wxOVERRIDE;
|
||||||
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
void SetMenuItem(GtkWidget *menuItem);
|
void SetMenuItem(GtkWidget *menuItem);
|
||||||
GtkWidget *GetMenuItem() const { return m_menuItem; }
|
GtkWidget *GetMenuItem() const { return m_menuItem; }
|
||||||
void SetGtkLabel();
|
void SetGtkLabel();
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
void GTKSetExtraAccels();
|
||||||
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
#if WXWIN_COMPATIBILITY_2_8
|
#if WXWIN_COMPATIBILITY_2_8
|
||||||
// compatibility only, don't use in new code
|
// compatibility only, don't use in new code
|
||||||
wxDEPRECATED_CONSTRUCTOR(
|
wxDEPRECATED_CONSTRUCTOR(
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include "wx/windowid.h"
|
#include "wx/windowid.h"
|
||||||
|
|
||||||
|
#include "wx/vector.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// forward declarations
|
// forward declarations
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -122,6 +124,14 @@ public:
|
|||||||
// set the accel for this item - this may also be done indirectly with
|
// set the accel for this item - this may also be done indirectly with
|
||||||
// SetText()
|
// SetText()
|
||||||
virtual void SetAccel(wxAcceleratorEntry *accel);
|
virtual void SetAccel(wxAcceleratorEntry *accel);
|
||||||
|
|
||||||
|
// add the accel to extra accels list
|
||||||
|
virtual void AddExtraAccel(const wxAcceleratorEntry& accel);
|
||||||
|
|
||||||
|
// return vector of extra accels. Implementation only.
|
||||||
|
const wxVector<wxAcceleratorEntry>& GetExtraAccels() const { return m_extraAccels; }
|
||||||
|
|
||||||
|
virtual void ClearExtraAccels() { m_extraAccels.clear(); }
|
||||||
#endif // wxUSE_ACCEL
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
#if WXWIN_COMPATIBILITY_2_8
|
#if WXWIN_COMPATIBILITY_2_8
|
||||||
@@ -163,6 +173,10 @@ protected:
|
|||||||
bool m_isChecked; // is checked?
|
bool m_isChecked; // is checked?
|
||||||
bool m_isEnabled; // is enabled?
|
bool m_isEnabled; // is enabled?
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
wxVector<wxAcceleratorEntry> m_extraAccels; // extra accels will work, but won't be shown in wxMenuItem title
|
||||||
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
// this ctor is for the derived classes only, we're never created directly
|
// this ctor is for the derived classes only, we're never created directly
|
||||||
wxMenuItemBase(wxMenu *parentMenu = NULL,
|
wxMenuItemBase(wxMenu *parentMenu = NULL,
|
||||||
int itemid = wxID_SEPARATOR,
|
int itemid = wxID_SEPARATOR,
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ public :
|
|||||||
virtual void Check( bool check ) = 0;
|
virtual void Check( bool check ) = 0;
|
||||||
virtual void SetLabel( const wxString& text, wxAcceleratorEntry *entry ) = 0;
|
virtual void SetLabel( const wxString& text, wxAcceleratorEntry *entry ) = 0;
|
||||||
virtual void Hide( bool hide = true ) = 0;
|
virtual void Hide( bool hide = true ) = 0;
|
||||||
|
virtual void SetAllowsKeyEquivalentWhenHidden( bool ) {}
|
||||||
|
|
||||||
virtual void * GetHMenuItem() = 0;
|
virtual void * GetHMenuItem() = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "wx/defs.h"
|
#include "wx/defs.h"
|
||||||
#include "wx/bitmap.h"
|
#include "wx/bitmap.h"
|
||||||
|
#include "wx/vector.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxMenuItem: an item in the menu, optionally implements owner-drawn behaviour
|
// wxMenuItem: an item in the menu, optionally implements owner-drawn behaviour
|
||||||
@@ -42,6 +43,12 @@ public:
|
|||||||
virtual void Enable(bool bDoEnable = true) wxOVERRIDE;
|
virtual void Enable(bool bDoEnable = true) wxOVERRIDE;
|
||||||
virtual void Check(bool bDoCheck = true) wxOVERRIDE;
|
virtual void Check(bool bDoCheck = true) wxOVERRIDE;
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
virtual void AddExtraAccel(const wxAcceleratorEntry& accel) wxOVERRIDE;
|
||||||
|
virtual void ClearExtraAccels() wxOVERRIDE;
|
||||||
|
void RemoveHiddenItems();
|
||||||
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
virtual void SetBitmap(const wxBitmap& bitmap) ;
|
virtual void SetBitmap(const wxBitmap& bitmap) ;
|
||||||
virtual const wxBitmap& GetBitmap() const { return m_bitmap; }
|
virtual const wxBitmap& GetBitmap() const { return m_bitmap; }
|
||||||
|
|
||||||
@@ -61,6 +68,10 @@ private:
|
|||||||
|
|
||||||
wxMenuItemImpl* m_peer;
|
wxMenuItemImpl* m_peer;
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
wxVector<wxMenuItem*> m_hiddenMenuItems;
|
||||||
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
wxDECLARE_DYNAMIC_CLASS(wxMenuItem);
|
wxDECLARE_DYNAMIC_CLASS(wxMenuItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -567,6 +567,30 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void SetAccel(wxAcceleratorEntry *accel);
|
virtual void SetAccel(wxAcceleratorEntry *accel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add an extra accelerator for this menu item.
|
||||||
|
|
||||||
|
Additional accelerators are not shown in the item's label,
|
||||||
|
but still will trigger the menu command when pressed.
|
||||||
|
|
||||||
|
They can be useful to let multiple keys be used as accelerators
|
||||||
|
for the same command, e.g. @c WXK_ADD and @c WXK_NUMPAD_ADD.
|
||||||
|
|
||||||
|
@onlyfor{wxmsw,wxgtk}
|
||||||
|
|
||||||
|
@since 3.1.6
|
||||||
|
*/
|
||||||
|
void AddExtraAccel(wxAcceleratorEntry *accel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clear the extra accelerators list.
|
||||||
|
|
||||||
|
This doesn't affect the main item accelerator (if any).
|
||||||
|
|
||||||
|
@since 3.1.6
|
||||||
|
*/
|
||||||
|
void ClearExtraAccels();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -501,6 +501,10 @@ t_list_of_numbers = xsd:string { pattern = "\d+(,\d+)*" }
|
|||||||
|
|
||||||
t_list_of_numbers_with_weights = xsd:string { pattern = "\d+(:\d+)?(,\d+(:\d+)?)*" }
|
t_list_of_numbers_with_weights = xsd:string { pattern = "\d+(:\d+)?(,\d+(:\d+)?)*" }
|
||||||
|
|
||||||
|
t_extra_accels = (
|
||||||
|
[xrc:p="o"] element accel {_, t_text }+
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Handlers for non-<object> content:
|
# Handlers for non-<object> content:
|
||||||
@@ -1193,15 +1197,16 @@ wxMenuItem =
|
|||||||
element object {
|
element object {
|
||||||
attribute class { "wxMenuItem" } &
|
attribute class { "wxMenuItem" } &
|
||||||
stdObjectNodeAttributes &
|
stdObjectNodeAttributes &
|
||||||
[xrc:p="o"] element label {_, t_text }* &
|
[xrc:p="o"] element label {_, t_text }* &
|
||||||
[xrc:p="o"] element accel {_, t_text }* &
|
[xrc:p="o"] element accel {_, t_text }* &
|
||||||
[xrc:p="o"] element radio {_, t_bool }* &
|
[xrc:p="o"] element extra-accels {_, t_extra_accels }* &
|
||||||
[xrc:p="o"] element checkable {_, t_bool }* &
|
[xrc:p="o"] element radio {_, t_bool }* &
|
||||||
[xrc:p="o"] element bitmap {_, t_bitmap }* &
|
[xrc:p="o"] element checkable {_, t_bool }* &
|
||||||
[xrc:p="o"] element bitmap2 {_, t_bitmap }* &
|
[xrc:p="o"] element bitmap {_, t_bitmap }* &
|
||||||
[xrc:p="o"] element help {_, t_text }* &
|
[xrc:p="o"] element bitmap2 {_, t_bitmap }* &
|
||||||
[xrc:p="o"] element enabled {_, t_bool }* &
|
[xrc:p="o"] element help {_, t_text }* &
|
||||||
[xrc:p="o"] element checked {_, t_bool }*
|
[xrc:p="o"] element enabled {_, t_bool }* &
|
||||||
|
[xrc:p="o"] element checked {_, t_bool }*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
EVT_MENU(XRCID("derived_tool_or_menuitem"), MyFrame::OnDerivedDialogToolOrMenuCommand)
|
EVT_MENU(XRCID("derived_tool_or_menuitem"), MyFrame::OnDerivedDialogToolOrMenuCommand)
|
||||||
EVT_MENU(XRCID("controls_tool_or_menuitem"), MyFrame::OnControlsToolOrMenuCommand)
|
EVT_MENU(XRCID("controls_tool_or_menuitem"), MyFrame::OnControlsToolOrMenuCommand)
|
||||||
EVT_MENU(XRCID("uncentered_tool_or_menuitem"), MyFrame::OnUncenteredToolOrMenuCommand)
|
EVT_MENU(XRCID("uncentered_tool_or_menuitem"), MyFrame::OnUncenteredToolOrMenuCommand)
|
||||||
|
EVT_MENU(XRCID("multiple_accels"), MyFrame::OnMultipleAccels)
|
||||||
EVT_MENU(XRCID("aui_demo_tool_or_menuitem"), MyFrame::OnAuiDemoToolOrMenuCommand)
|
EVT_MENU(XRCID("aui_demo_tool_or_menuitem"), MyFrame::OnAuiDemoToolOrMenuCommand)
|
||||||
EVT_MENU(XRCID("obj_ref_tool_or_menuitem"), MyFrame::OnObjRefToolOrMenuCommand)
|
EVT_MENU(XRCID("obj_ref_tool_or_menuitem"), MyFrame::OnObjRefToolOrMenuCommand)
|
||||||
EVT_MENU(XRCID("custom_class_tool_or_menuitem"), MyFrame::OnCustomClassToolOrMenuCommand)
|
EVT_MENU(XRCID("custom_class_tool_or_menuitem"), MyFrame::OnCustomClassToolOrMenuCommand)
|
||||||
@@ -285,6 +286,26 @@ void MyFrame::OnUncenteredToolOrMenuCommand(wxCommandEvent& WXUNUSED(event))
|
|||||||
dlg.ShowModal();
|
dlg.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnMultipleAccels(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
#if defined(__WXOSX_COCOA__)
|
||||||
|
wxString main = "Cmd-W";
|
||||||
|
wxString extra1 = "Cmd-T";
|
||||||
|
wxString extra2 = "Shift-Cmd-W";
|
||||||
|
#else
|
||||||
|
wxString main = "Ctrl-W";
|
||||||
|
wxString extra1 = "Ctrl-T";
|
||||||
|
wxString extra2 = "Shift-Ctrl-W";
|
||||||
|
#endif
|
||||||
|
msg.Printf(
|
||||||
|
"You can open this dialog with any of '%s' (main), '%s' or '%s' (extra) accelerators.",
|
||||||
|
main, extra1, extra2
|
||||||
|
);
|
||||||
|
|
||||||
|
wxMessageBox(msg, _("Multiple accelerators demo"), wxOK | wxICON_INFORMATION, this);
|
||||||
|
}
|
||||||
|
|
||||||
void MyFrame::OnAuiDemoToolOrMenuCommand(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnAuiDemoToolOrMenuCommand(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
#if wxUSE_AUI
|
#if wxUSE_AUI
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ private:
|
|||||||
void OnDerivedDialogToolOrMenuCommand(wxCommandEvent& event);
|
void OnDerivedDialogToolOrMenuCommand(wxCommandEvent& event);
|
||||||
void OnControlsToolOrMenuCommand(wxCommandEvent& event);
|
void OnControlsToolOrMenuCommand(wxCommandEvent& event);
|
||||||
void OnUncenteredToolOrMenuCommand(wxCommandEvent& event);
|
void OnUncenteredToolOrMenuCommand(wxCommandEvent& event);
|
||||||
|
void OnMultipleAccels(wxCommandEvent& event);
|
||||||
void OnAuiDemoToolOrMenuCommand(wxCommandEvent& event);
|
void OnAuiDemoToolOrMenuCommand(wxCommandEvent& event);
|
||||||
void OnObjRefToolOrMenuCommand(wxCommandEvent& event);
|
void OnObjRefToolOrMenuCommand(wxCommandEvent& event);
|
||||||
void OnCustomClassToolOrMenuCommand(wxCommandEvent& event);
|
void OnCustomClassToolOrMenuCommand(wxCommandEvent& event);
|
||||||
|
|||||||
@@ -45,6 +45,15 @@
|
|||||||
<bitmap>uncenter.xpm</bitmap>
|
<bitmap>uncenter.xpm</bitmap>
|
||||||
<help>Disable autocentering of a dialog on its parent</help>
|
<help>Disable autocentering of a dialog on its parent</help>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="wxMenuItem" name="multiple_accels">
|
||||||
|
<label>_Multiple accelerators</label>
|
||||||
|
<help>You can open the dialog with multiple accelerators</help>
|
||||||
|
<accel>Ctrl-W</accel>
|
||||||
|
<extra-accels>
|
||||||
|
<accel>Ctrl-T</accel>
|
||||||
|
<accel>Shift-Ctrl-W</accel>
|
||||||
|
</extra-accels>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="wxMenu" name="advanced_demos_menu">
|
<object class="wxMenu" name="advanced_demos_menu">
|
||||||
<label>_Advanced</label>
|
<label>_Advanced</label>
|
||||||
|
|||||||
@@ -296,6 +296,11 @@ void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
|
|||||||
SetItemLabel(text);
|
SetItemLabel(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxMenuItemBase::AddExtraAccel(const wxAcceleratorEntry& accel)
|
||||||
|
{
|
||||||
|
m_extraAccels.push_back(accel);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_ACCEL
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
void wxMenuItemBase::SetItemLabel(const wxString& str)
|
void wxMenuItemBase::SetItemLabel(const wxString& str)
|
||||||
|
|||||||
@@ -704,6 +704,54 @@ void wxMenuItem::SetGtkLabel()
|
|||||||
#endif // wxUSE_ACCEL
|
#endif // wxUSE_ACCEL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
void wxMenuItem::GTKSetExtraAccels()
|
||||||
|
{
|
||||||
|
GtkAccelGroup* const accelGroup = GetRootParentMenu(m_parentMenu)->m_accel;
|
||||||
|
|
||||||
|
const size_t extraAccelsSize = m_extraAccels.size();
|
||||||
|
for (size_t i = 0; i < extraAccelsSize; ++i)
|
||||||
|
{
|
||||||
|
GtkAccel(m_extraAccels[i]).Add(m_menuItem, accelGroup, GTK_ACCEL_MASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMenuItem::AddExtraAccel(const wxAcceleratorEntry& accel)
|
||||||
|
{
|
||||||
|
wxMenuItemBase::AddExtraAccel(accel);
|
||||||
|
|
||||||
|
// If the item is not yet part of the menu, all its extra accelerators will
|
||||||
|
// be registered with GTK in GTKSetExtraAccels() once it is added to the
|
||||||
|
// menu, but if it had already been added to it, we need to let GTK know
|
||||||
|
// about the new extra accelerator.
|
||||||
|
if (m_menuItem)
|
||||||
|
{
|
||||||
|
GtkAccelGroup* const accelGroup = GetRootParentMenu(m_parentMenu)->m_accel;
|
||||||
|
|
||||||
|
GtkAccel(accel).Add(m_menuItem, accelGroup, GTK_ACCEL_MASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMenuItem::ClearExtraAccels()
|
||||||
|
{
|
||||||
|
// Tell GTK not to use the existing accelerators any longer if they're
|
||||||
|
// already in use.
|
||||||
|
if (m_menuItem)
|
||||||
|
{
|
||||||
|
GtkAccelGroup* const accelGroup = GetRootParentMenu(m_parentMenu)->m_accel;
|
||||||
|
|
||||||
|
const size_t extraAccelsSize = m_extraAccels.size();
|
||||||
|
for (size_t i = 0; i < extraAccelsSize; ++i)
|
||||||
|
{
|
||||||
|
GtkAccel(m_extraAccels[i]).Remove(m_menuItem, accelGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxMenuItemBase::ClearExtraAccels();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
void wxMenuItem::SetBitmap(const wxBitmap& bitmap)
|
void wxMenuItem::SetBitmap(const wxBitmap& bitmap)
|
||||||
{
|
{
|
||||||
if (m_kind == wxITEM_NORMAL)
|
if (m_kind == wxITEM_NORMAL)
|
||||||
@@ -987,6 +1035,10 @@ void wxMenu::GtkAppend(wxMenuItem* mitem, int pos)
|
|||||||
if ( mitem->IsSubMenu() )
|
if ( mitem->IsSubMenu() )
|
||||||
UpdateSubMenuItemLabels(mitem);
|
UpdateSubMenuItemLabels(mitem);
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
mitem->GTKSetExtraAccels();
|
||||||
|
#endif
|
||||||
|
|
||||||
g_signal_connect (menuItem, "select",
|
g_signal_connect (menuItem, "select",
|
||||||
G_CALLBACK(menuitem_select), mitem);
|
G_CALLBACK(menuitem_select), mitem);
|
||||||
g_signal_connect (menuItem, "deselect",
|
g_signal_connect (menuItem, "deselect",
|
||||||
|
|||||||
@@ -225,29 +225,30 @@ void wxMenu::UpdateAccel(wxMenuItem *item)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the (new) accel for this item
|
// remove old accels
|
||||||
|
int n = wxNOT_FOUND;
|
||||||
|
while ( (n = FindAccel(item->GetId())) != wxNOT_FOUND )
|
||||||
|
{
|
||||||
|
delete m_accels[n];
|
||||||
|
m_accels.RemoveAt(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the (new) accel for this item and add it if any
|
||||||
wxAcceleratorEntry *accel = wxAcceleratorEntry::Create(item->GetItemLabel());
|
wxAcceleratorEntry *accel = wxAcceleratorEntry::Create(item->GetItemLabel());
|
||||||
if ( accel )
|
if ( accel )
|
||||||
|
{
|
||||||
accel->m_command = item->GetId();
|
accel->m_command = item->GetId();
|
||||||
|
m_accels.Add(accel);
|
||||||
// find the old one
|
|
||||||
int n = FindAccel(item->GetId());
|
|
||||||
if ( n == wxNOT_FOUND )
|
|
||||||
{
|
|
||||||
// no old, add new if any
|
|
||||||
if ( accel )
|
|
||||||
m_accels.Add(accel);
|
|
||||||
else
|
|
||||||
return; // skipping RebuildAccelTable() below
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// add extra accels
|
||||||
|
const wxVector<wxAcceleratorEntry>& extraAccelsVector = item->GetExtraAccels();
|
||||||
|
const int extraAccelsSize = extraAccelsVector.size();
|
||||||
|
for (int i = 0; i < extraAccelsSize; ++i)
|
||||||
{
|
{
|
||||||
// replace old with new or just remove the old one if no new
|
wxAcceleratorEntry *extraAccel = new wxAcceleratorEntry(extraAccelsVector[i]);
|
||||||
delete m_accels[n];
|
extraAccel->m_command = item->GetId();
|
||||||
if ( accel )
|
m_accels.Add(extraAccel);
|
||||||
m_accels[n] = accel;
|
|
||||||
else
|
|
||||||
m_accels.RemoveAt(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( IsAttached() )
|
if ( IsAttached() )
|
||||||
@@ -274,19 +275,22 @@ void wxMenu::RemoveAccel(wxMenuItem *item)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the corresponding accel from the accel table
|
// remove the corresponding accels from the accel table
|
||||||
int n = FindAccel(item->GetId());
|
int n = wxNOT_FOUND;
|
||||||
if ( n != wxNOT_FOUND )
|
bool accels_found = false;
|
||||||
|
while ( (n = FindAccel(item->GetId())) != wxNOT_FOUND )
|
||||||
{
|
{
|
||||||
delete m_accels[n];
|
delete m_accels[n];
|
||||||
|
|
||||||
m_accels.RemoveAt(n);
|
m_accels.RemoveAt(n);
|
||||||
|
accels_found = true;
|
||||||
|
}
|
||||||
|
|
||||||
#if wxUSE_OWNER_DRAWN
|
#if wxUSE_OWNER_DRAWN
|
||||||
|
if ( accels_found )
|
||||||
|
{
|
||||||
ResetMaxAccelWidth();
|
ResetMaxAccelWidth();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
//else: this item doesn't have an accel, nothing to do
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_ACCEL
|
#endif // wxUSE_ACCEL
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
|
|
||||||
#include "wx/osx/private.h"
|
#include "wx/osx/private.h"
|
||||||
|
#include "wx/osx/private/available.h"
|
||||||
|
|
||||||
// a mapping from wx ids to standard osx actions in order to support the native menu item handling
|
// a mapping from wx ids to standard osx actions in order to support the native menu item handling
|
||||||
// if a new mapping is added, make sure the wxNonOwnedWindowController has a handler for this action as well
|
// if a new mapping is added, make sure the wxNonOwnedWindowController has a handler for this action as well
|
||||||
@@ -270,6 +271,15 @@ public :
|
|||||||
wxLogDebug("wxMenuItemCocoaImpl::Hide not yet supported under OS X < 10.5");
|
wxLogDebug("wxMenuItemCocoaImpl::Hide not yet supported under OS X < 10.5");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetAllowsKeyEquivalentWhenHidden( bool allow ) wxOVERRIDE
|
||||||
|
{
|
||||||
|
// setAllowsKeyEquivalentWhenHidden is available since macOS 10.13
|
||||||
|
if (WX_IS_MACOS_AVAILABLE(10, 13))
|
||||||
|
[m_osxMenuItem setAllowsKeyEquivalentWhenHidden:allow ];
|
||||||
|
else
|
||||||
|
wxLogDebug("wxMenuItemCocoaImpl::setAllowsKeyEquivalentWhenHidden not supported under OS X < 10.13");
|
||||||
|
}
|
||||||
|
|
||||||
void SetLabel( const wxString& text, wxAcceleratorEntry *entry ) wxOVERRIDE
|
void SetLabel( const wxString& text, wxAcceleratorEntry *entry ) wxOVERRIDE
|
||||||
{
|
{
|
||||||
wxCFStringRef cfText(text);
|
wxCFStringRef cfText(text);
|
||||||
|
|||||||
@@ -211,6 +211,10 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
|
|||||||
|
|
||||||
wxOSXMenuRemoveItem(m_hMenu , pos );
|
wxOSXMenuRemoveItem(m_hMenu , pos );
|
||||||
*/
|
*/
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
// we need to remove all hidden menu items related to this one
|
||||||
|
item->RemoveHiddenItems();
|
||||||
|
#endif
|
||||||
GetPeer()->Remove( item );
|
GetPeer()->Remove( item );
|
||||||
// and from internal data structures
|
// and from internal data structures
|
||||||
return wxMenuBase::DoRemove(item);
|
return wxMenuBase::DoRemove(item);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
|
|
||||||
#include "wx/osx/private.h"
|
#include "wx/osx/private.h"
|
||||||
|
#include "wx/osx/private/available.h"
|
||||||
|
|
||||||
wxIMPLEMENT_ABSTRACT_CLASS(wxMenuItemImpl, wxObject);
|
wxIMPLEMENT_ABSTRACT_CLASS(wxMenuItemImpl, wxObject);
|
||||||
|
|
||||||
@@ -207,6 +208,45 @@ void wxMenuItem::UpdateItemText()
|
|||||||
#endif // wxUSE_ACCEL/!wxUSE_ACCEL
|
#endif // wxUSE_ACCEL/!wxUSE_ACCEL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if wxUSE_ACCEL
|
||||||
|
|
||||||
|
void wxMenuItem::AddExtraAccel(const wxAcceleratorEntry& accel)
|
||||||
|
{
|
||||||
|
if (WX_IS_MACOS_AVAILABLE(10, 13))
|
||||||
|
{
|
||||||
|
wxMenuItemBase::AddExtraAccel(accel);
|
||||||
|
|
||||||
|
// create the same wxMenuItem but hidden and with different accelerator.
|
||||||
|
wxMenuItem* hiddenMenuItem = new wxMenuItem(m_parentMenu, GetId(), m_text, m_help, GetKind(), m_subMenu);
|
||||||
|
hiddenMenuItem->SetAccel(&(m_extraAccels.back()));
|
||||||
|
hiddenMenuItem->GetPeer()->Hide(true);
|
||||||
|
hiddenMenuItem->GetPeer()->SetAllowsKeyEquivalentWhenHidden(true);
|
||||||
|
m_parentMenu->GetPeer()->InsertOrAppend( hiddenMenuItem, -1 );
|
||||||
|
hiddenMenuItem->SetMenu(m_parentMenu);
|
||||||
|
m_hiddenMenuItems.push_back(hiddenMenuItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLogDebug("Extra accelerators not being supported under macOS < 10.13");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMenuItem::ClearExtraAccels()
|
||||||
|
{
|
||||||
|
wxMenuItemBase::ClearExtraAccels();
|
||||||
|
RemoveHiddenItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMenuItem::RemoveHiddenItems()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_hiddenMenuItems.size(); ++i)
|
||||||
|
{
|
||||||
|
m_parentMenu->GetPeer()->Remove( m_hiddenMenuItems[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxMenuItemBase
|
// wxMenuItemBase
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
// For compilers that support precompilation, includes "wx.h".
|
// For compilers that support precompilation, includes "wx.h".
|
||||||
#include "wx/wxprec.h"
|
#include "wx/wxprec.h"
|
||||||
|
|
||||||
|
#include <wx/xml/xml.h>
|
||||||
|
|
||||||
#if wxUSE_XRC && wxUSE_MENUS
|
#if wxUSE_XRC && wxUSE_MENUS
|
||||||
|
|
||||||
@@ -79,6 +80,18 @@ wxObject *wxMenuXmlHandler::DoCreateResource()
|
|||||||
wxString label = GetText(wxT("label"));
|
wxString label = GetText(wxT("label"));
|
||||||
#if wxUSE_ACCEL
|
#if wxUSE_ACCEL
|
||||||
wxString accel = GetText(wxT("accel"), false);
|
wxString accel = GetText(wxT("accel"), false);
|
||||||
|
wxVector<wxString> extraAccels;
|
||||||
|
if (HasParam(wxT("extra-accels")))
|
||||||
|
{
|
||||||
|
wxXmlNode* const extraAccelsNode = GetParamNode(wxT("extra-accels"));
|
||||||
|
wxXmlNode* node = extraAccelsNode->GetChildren();
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
if (node->GetName() == wxT("accel"))
|
||||||
|
extraAccels.push_back(node->GetChildren()->GetContent());
|
||||||
|
node = node->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // wxUSE_ACCEL
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
wxItemKind kind = wxITEM_NORMAL;
|
wxItemKind kind = wxITEM_NORMAL;
|
||||||
@@ -101,11 +114,34 @@ wxObject *wxMenuXmlHandler::DoCreateResource()
|
|||||||
wxMenuItem *mitem = new wxMenuItem(p_menu, id, label,
|
wxMenuItem *mitem = new wxMenuItem(p_menu, id, label,
|
||||||
GetText(wxT("help")), kind);
|
GetText(wxT("help")), kind);
|
||||||
#if wxUSE_ACCEL
|
#if wxUSE_ACCEL
|
||||||
|
if (!extraAccels.empty())
|
||||||
|
{
|
||||||
|
const int entriesSize = extraAccels.size();
|
||||||
|
for (int i = 0; i < entriesSize; ++i)
|
||||||
|
{
|
||||||
|
wxAcceleratorEntry entry;
|
||||||
|
if (entry.FromString(extraAccels[i]))
|
||||||
|
mitem->AddExtraAccel(entry);
|
||||||
|
else
|
||||||
|
ReportParamError
|
||||||
|
(
|
||||||
|
"extra-accels",
|
||||||
|
wxString::Format("cannot create accel from '%s\'", extraAccels[i])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!accel.empty())
|
if (!accel.empty())
|
||||||
{
|
{
|
||||||
wxAcceleratorEntry entry;
|
wxAcceleratorEntry entry;
|
||||||
if (entry.FromString(accel))
|
if (entry.FromString(accel))
|
||||||
mitem->SetAccel(&entry);
|
mitem->SetAccel(&entry);
|
||||||
|
else
|
||||||
|
ReportParamError
|
||||||
|
(
|
||||||
|
"accel",
|
||||||
|
wxString::Format("cannot create accel from '%s'", accel)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#endif // wxUSE_ACCEL
|
#endif // wxUSE_ACCEL
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ enum
|
|||||||
MenuTestCase_Foo = 10000,
|
MenuTestCase_Foo = 10000,
|
||||||
MenuTestCase_SelectAll,
|
MenuTestCase_SelectAll,
|
||||||
MenuTestCase_Bar,
|
MenuTestCase_Bar,
|
||||||
|
MenuTestCase_ExtraAccel,
|
||||||
|
MenuTestCase_ExtraAccels,
|
||||||
MenuTestCase_First
|
MenuTestCase_First
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,6 +175,34 @@ void MenuTestCase::CreateFrame()
|
|||||||
"Accelerator conflicting with wxTextCtrl");
|
"Accelerator conflicting with wxTextCtrl");
|
||||||
m_itemCount++;
|
m_itemCount++;
|
||||||
|
|
||||||
|
// Test adding an extra accelerator to the item before adding it to the menu.
|
||||||
|
wxAcceleratorEntry entry;
|
||||||
|
|
||||||
|
wxMenuItem* const
|
||||||
|
extraAccel = new wxMenuItem(fileMenu, MenuTestCase_ExtraAccel, "Extra accels");
|
||||||
|
|
||||||
|
CHECK( entry.FromString("Ctrl-U") );
|
||||||
|
extraAccel->SetAccel(&entry);
|
||||||
|
|
||||||
|
CHECK( entry.FromString("Ctrl-V") );
|
||||||
|
extraAccel->AddExtraAccel(entry);
|
||||||
|
|
||||||
|
fileMenu->Append(extraAccel);
|
||||||
|
m_itemCount++;
|
||||||
|
|
||||||
|
// And now also test adding 2 of them after creating the initial menu item.
|
||||||
|
wxMenuItem* const
|
||||||
|
extraAccels = fileMenu->Append(MenuTestCase_ExtraAccels, "Extra accels 2");
|
||||||
|
m_itemCount++;
|
||||||
|
|
||||||
|
CHECK( entry.FromString("Ctrl-T") );
|
||||||
|
extraAccels->AddExtraAccel(entry);
|
||||||
|
|
||||||
|
CHECK(entry.FromString("Shift-Ctrl-W"));
|
||||||
|
extraAccels->AddExtraAccel(entry);
|
||||||
|
|
||||||
|
CHECK(entry.FromString("Ctrl-W"));
|
||||||
|
extraAccels->SetAccel(&entry);
|
||||||
|
|
||||||
PopulateMenu(helpMenu, "Helpmenu item ", m_itemCount);
|
PopulateMenu(helpMenu, "Helpmenu item ", m_itemCount);
|
||||||
helpMenu->Append(MenuTestCase_Bar, "Bar\tF1");
|
helpMenu->Append(MenuTestCase_Bar, "Bar\tF1");
|
||||||
@@ -607,6 +637,42 @@ void MenuTestCase::Events()
|
|||||||
const wxCommandEvent& ev2 = handler.GetEvent();
|
const wxCommandEvent& ev2 = handler.GetEvent();
|
||||||
CHECK( ev2.GetId() == static_cast<int>(MenuTestCase_SelectAll) );
|
CHECK( ev2.GetId() == static_cast<int>(MenuTestCase_SelectAll) );
|
||||||
|
|
||||||
|
// Invoke accelerator and extra accelerators, all of them should work.
|
||||||
|
sim.Char('U', wxMOD_CONTROL);
|
||||||
|
wxYield();
|
||||||
|
if ( handler.GotEvent() )
|
||||||
|
CHECK( handler.GetEvent().GetId() == MenuTestCase_ExtraAccel );
|
||||||
|
else
|
||||||
|
FAIL("No expected event for Ctrl-U");
|
||||||
|
|
||||||
|
sim.Char('V', wxMOD_CONTROL);
|
||||||
|
wxYield();
|
||||||
|
if ( handler.GotEvent() )
|
||||||
|
CHECK( handler.GetEvent().GetId() == MenuTestCase_ExtraAccel );
|
||||||
|
else
|
||||||
|
FAIL("No expected event for Ctrl-V");
|
||||||
|
|
||||||
|
sim.Char('W', wxMOD_CONTROL);
|
||||||
|
wxYield();
|
||||||
|
if ( handler.GotEvent() )
|
||||||
|
CHECK( handler.GetEvent().GetId() == MenuTestCase_ExtraAccels );
|
||||||
|
else
|
||||||
|
FAIL("No expected event for Ctrl-W");
|
||||||
|
|
||||||
|
sim.Char('T', wxMOD_CONTROL);
|
||||||
|
wxYield();
|
||||||
|
if ( handler.GotEvent() )
|
||||||
|
CHECK( handler.GetEvent().GetId() == MenuTestCase_ExtraAccels );
|
||||||
|
else
|
||||||
|
FAIL("No expected event for Ctrl-T");
|
||||||
|
|
||||||
|
sim.Char('W', wxMOD_CONTROL | wxMOD_SHIFT);
|
||||||
|
wxYield();
|
||||||
|
if ( handler.GotEvent() )
|
||||||
|
CHECK( handler.GetEvent().GetId() == MenuTestCase_ExtraAccels );
|
||||||
|
else
|
||||||
|
FAIL("No expected event for Ctrl-Shift-W");
|
||||||
|
|
||||||
// Now create a text control which uses the same accelerator for itself and
|
// Now create a text control which uses the same accelerator for itself and
|
||||||
// check that when the text control has focus, the accelerator does _not_
|
// check that when the text control has focus, the accelerator does _not_
|
||||||
// work.
|
// work.
|
||||||
|
|||||||
Reference in New Issue
Block a user