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
|
||||
|
||||
|
||||
@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
|
||||
|
||||
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).}
|
||||
@row3col{accel, @ref overview_xrcformat_type_text_notrans,
|
||||
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,
|
||||
Item's kind is wxITEM_RADIO (default: 0)?}
|
||||
@row3col{checkable, @ref overview_xrcformat_type_bool,
|
||||
@@ -1520,6 +1546,10 @@ Example:
|
||||
<object class="wxMenuItem" name="wxID_FIND">
|
||||
<label>_Find...</label>
|
||||
<accel>Ctrl-F</accel>
|
||||
<extra-accels>
|
||||
<accel>Ctrl-W</accel>
|
||||
<accel>Shift-Ctrl-W</accel>
|
||||
</extra-accels>
|
||||
</object>
|
||||
<object class="separator"/>
|
||||
<object class="wxMenuItem" name="menu_fuzzy">
|
||||
|
||||
@@ -34,11 +34,20 @@ public:
|
||||
virtual void SetBitmap(const wxBitmap& 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
|
||||
void SetMenuItem(GtkWidget *menuItem);
|
||||
GtkWidget *GetMenuItem() const { return m_menuItem; }
|
||||
void SetGtkLabel();
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
void GTKSetExtraAccels();
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
// compatibility only, don't use in new code
|
||||
wxDEPRECATED_CONSTRUCTOR(
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "wx/windowid.h"
|
||||
|
||||
#include "wx/vector.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// forward declarations
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -122,6 +124,14 @@ public:
|
||||
// set the accel for this item - this may also be done indirectly with
|
||||
// SetText()
|
||||
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
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
@@ -163,6 +173,10 @@ protected:
|
||||
bool m_isChecked; // is checked?
|
||||
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
|
||||
wxMenuItemBase(wxMenu *parentMenu = NULL,
|
||||
int itemid = wxID_SEPARATOR,
|
||||
|
||||
@@ -165,6 +165,7 @@ public :
|
||||
virtual void Check( bool check ) = 0;
|
||||
virtual void SetLabel( const wxString& text, wxAcceleratorEntry *entry ) = 0;
|
||||
virtual void Hide( bool hide = true ) = 0;
|
||||
virtual void SetAllowsKeyEquivalentWhenHidden( bool ) {}
|
||||
|
||||
virtual void * GetHMenuItem() = 0;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "wx/defs.h"
|
||||
#include "wx/bitmap.h"
|
||||
#include "wx/vector.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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 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 const wxBitmap& GetBitmap() const { return m_bitmap; }
|
||||
|
||||
@@ -61,6 +68,10 @@ private:
|
||||
|
||||
wxMenuItemImpl* m_peer;
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
wxVector<wxMenuItem*> m_hiddenMenuItems;
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(wxMenuItem);
|
||||
};
|
||||
|
||||
|
||||
@@ -567,6 +567,30 @@ public:
|
||||
*/
|
||||
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_extra_accels = (
|
||||
[xrc:p="o"] element accel {_, t_text }+
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Handlers for non-<object> content:
|
||||
@@ -1193,15 +1197,16 @@ wxMenuItem =
|
||||
element object {
|
||||
attribute class { "wxMenuItem" } &
|
||||
stdObjectNodeAttributes &
|
||||
[xrc:p="o"] element label {_, t_text }* &
|
||||
[xrc:p="o"] element accel {_, t_text }* &
|
||||
[xrc:p="o"] element radio {_, t_bool }* &
|
||||
[xrc:p="o"] element checkable {_, t_bool }* &
|
||||
[xrc:p="o"] element bitmap {_, t_bitmap }* &
|
||||
[xrc:p="o"] element bitmap2 {_, t_bitmap }* &
|
||||
[xrc:p="o"] element help {_, t_text }* &
|
||||
[xrc:p="o"] element enabled {_, t_bool }* &
|
||||
[xrc:p="o"] element checked {_, t_bool }*
|
||||
[xrc:p="o"] element label {_, t_text }* &
|
||||
[xrc:p="o"] element accel {_, t_text }* &
|
||||
[xrc:p="o"] element extra-accels {_, t_extra_accels }* &
|
||||
[xrc:p="o"] element radio {_, t_bool }* &
|
||||
[xrc:p="o"] element checkable {_, t_bool }* &
|
||||
[xrc:p="o"] element bitmap {_, t_bitmap }* &
|
||||
[xrc:p="o"] element bitmap2 {_, t_bitmap }* &
|
||||
[xrc:p="o"] element help {_, t_text }* &
|
||||
[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("controls_tool_or_menuitem"), MyFrame::OnControlsToolOrMenuCommand)
|
||||
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("obj_ref_tool_or_menuitem"), MyFrame::OnObjRefToolOrMenuCommand)
|
||||
EVT_MENU(XRCID("custom_class_tool_or_menuitem"), MyFrame::OnCustomClassToolOrMenuCommand)
|
||||
@@ -285,6 +286,26 @@ void MyFrame::OnUncenteredToolOrMenuCommand(wxCommandEvent& WXUNUSED(event))
|
||||
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))
|
||||
{
|
||||
#if wxUSE_AUI
|
||||
|
||||
@@ -43,6 +43,7 @@ private:
|
||||
void OnDerivedDialogToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnControlsToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnUncenteredToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnMultipleAccels(wxCommandEvent& event);
|
||||
void OnAuiDemoToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnObjRefToolOrMenuCommand(wxCommandEvent& event);
|
||||
void OnCustomClassToolOrMenuCommand(wxCommandEvent& event);
|
||||
|
||||
@@ -45,6 +45,15 @@
|
||||
<bitmap>uncenter.xpm</bitmap>
|
||||
<help>Disable autocentering of a dialog on its parent</help>
|
||||
</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 class="wxMenu" name="advanced_demos_menu">
|
||||
<label>_Advanced</label>
|
||||
|
||||
@@ -296,6 +296,11 @@ void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
|
||||
SetItemLabel(text);
|
||||
}
|
||||
|
||||
void wxMenuItemBase::AddExtraAccel(const wxAcceleratorEntry& accel)
|
||||
{
|
||||
m_extraAccels.push_back(accel);
|
||||
}
|
||||
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
void wxMenuItemBase::SetItemLabel(const wxString& str)
|
||||
|
||||
@@ -704,6 +704,54 @@ void wxMenuItem::SetGtkLabel()
|
||||
#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)
|
||||
{
|
||||
if (m_kind == wxITEM_NORMAL)
|
||||
@@ -987,6 +1035,10 @@ void wxMenu::GtkAppend(wxMenuItem* mitem, int pos)
|
||||
if ( mitem->IsSubMenu() )
|
||||
UpdateSubMenuItemLabels(mitem);
|
||||
|
||||
#if wxUSE_ACCEL
|
||||
mitem->GTKSetExtraAccels();
|
||||
#endif
|
||||
|
||||
g_signal_connect (menuItem, "select",
|
||||
G_CALLBACK(menuitem_select), mitem);
|
||||
g_signal_connect (menuItem, "deselect",
|
||||
|
||||
@@ -225,29 +225,30 @@ void wxMenu::UpdateAccel(wxMenuItem *item)
|
||||
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());
|
||||
if ( accel )
|
||||
{
|
||||
accel->m_command = item->GetId();
|
||||
|
||||
// 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
|
||||
m_accels.Add(accel);
|
||||
}
|
||||
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
|
||||
delete m_accels[n];
|
||||
if ( accel )
|
||||
m_accels[n] = accel;
|
||||
else
|
||||
m_accels.RemoveAt(n);
|
||||
wxAcceleratorEntry *extraAccel = new wxAcceleratorEntry(extraAccelsVector[i]);
|
||||
extraAccel->m_command = item->GetId();
|
||||
m_accels.Add(extraAccel);
|
||||
}
|
||||
|
||||
if ( IsAttached() )
|
||||
@@ -274,19 +275,22 @@ void wxMenu::RemoveAccel(wxMenuItem *item)
|
||||
return;
|
||||
}
|
||||
|
||||
// remove the corresponding accel from the accel table
|
||||
int n = FindAccel(item->GetId());
|
||||
if ( n != wxNOT_FOUND )
|
||||
// remove the corresponding accels from the accel table
|
||||
int n = wxNOT_FOUND;
|
||||
bool accels_found = false;
|
||||
while ( (n = FindAccel(item->GetId())) != wxNOT_FOUND )
|
||||
{
|
||||
delete m_accels[n];
|
||||
|
||||
m_accels.RemoveAt(n);
|
||||
accels_found = true;
|
||||
}
|
||||
|
||||
#if wxUSE_OWNER_DRAWN
|
||||
if ( accels_found )
|
||||
{
|
||||
ResetMaxAccelWidth();
|
||||
#endif
|
||||
}
|
||||
//else: this item doesn't have an accel, nothing to do
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#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
|
||||
// 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");
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
wxCFStringRef cfText(text);
|
||||
|
||||
@@ -211,6 +211,10 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
|
||||
|
||||
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 );
|
||||
// and from internal data structures
|
||||
return wxMenuBase::DoRemove(item);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include "wx/osx/private.h"
|
||||
#include "wx/osx/private/available.h"
|
||||
|
||||
wxIMPLEMENT_ABSTRACT_CLASS(wxMenuItemImpl, wxObject);
|
||||
|
||||
@@ -207,6 +208,45 @@ void wxMenuItem::UpdateItemText()
|
||||
#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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#include <wx/xml/xml.h>
|
||||
|
||||
#if wxUSE_XRC && wxUSE_MENUS
|
||||
|
||||
@@ -79,6 +80,18 @@ wxObject *wxMenuXmlHandler::DoCreateResource()
|
||||
wxString label = GetText(wxT("label"));
|
||||
#if wxUSE_ACCEL
|
||||
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
|
||||
|
||||
wxItemKind kind = wxITEM_NORMAL;
|
||||
@@ -101,11 +114,34 @@ wxObject *wxMenuXmlHandler::DoCreateResource()
|
||||
wxMenuItem *mitem = new wxMenuItem(p_menu, id, label,
|
||||
GetText(wxT("help")), kind);
|
||||
#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())
|
||||
{
|
||||
wxAcceleratorEntry entry;
|
||||
if (entry.FromString(accel))
|
||||
mitem->SetAccel(&entry);
|
||||
else
|
||||
ReportParamError
|
||||
(
|
||||
"accel",
|
||||
wxString::Format("cannot create accel from '%s'", accel)
|
||||
);
|
||||
}
|
||||
#endif // wxUSE_ACCEL
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ enum
|
||||
MenuTestCase_Foo = 10000,
|
||||
MenuTestCase_SelectAll,
|
||||
MenuTestCase_Bar,
|
||||
MenuTestCase_ExtraAccel,
|
||||
MenuTestCase_ExtraAccels,
|
||||
MenuTestCase_First
|
||||
};
|
||||
|
||||
@@ -173,6 +175,34 @@ void MenuTestCase::CreateFrame()
|
||||
"Accelerator conflicting with wxTextCtrl");
|
||||
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);
|
||||
helpMenu->Append(MenuTestCase_Bar, "Bar\tF1");
|
||||
@@ -607,6 +637,42 @@ void MenuTestCase::Events()
|
||||
const wxCommandEvent& ev2 = handler.GetEvent();
|
||||
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
|
||||
// check that when the text control has focus, the accelerator does _not_
|
||||
// work.
|
||||
|
||||
Reference in New Issue
Block a user