diff --git a/docs/doxygen/overviews/xrc_format.h b/docs/doxygen/overviews/xrc_format.h index 015c8a182c..0c676c36fe 100644 --- a/docs/doxygen/overviews/xrc_format.h +++ b/docs/doxygen/overviews/xrc_format.h @@ -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 \ "sub-properties": + +@beginTable +@hdr3col{property, type, description} +@row3col{accel, @ref overview_xrcformat_type_text_notrans, + wxMenuItem's accelerator (default: none).} +@endTable + +Example: +@code + + Ctrl-W + Shift-Ctrl-W + +@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: Ctrl-F + + Ctrl-W + Shift-Ctrl-W + diff --git a/include/wx/gtk/menuitem.h b/include/wx/gtk/menuitem.h index 376959b32e..0156cbc727 100644 --- a/include/wx/gtk/menuitem.h +++ b/include/wx/gtk/menuitem.h @@ -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( diff --git a/include/wx/menuitem.h b/include/wx/menuitem.h index 8c1d2c68e2..93a739d595 100644 --- a/include/wx/menuitem.h +++ b/include/wx/menuitem.h @@ -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& 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 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, diff --git a/include/wx/osx/core/private.h b/include/wx/osx/core/private.h index 3be6ab906f..ffbcb1312f 100644 --- a/include/wx/osx/core/private.h +++ b/include/wx/osx/core/private.h @@ -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; diff --git a/include/wx/osx/menuitem.h b/include/wx/osx/menuitem.h index 803739b647..44f22ff15e 100644 --- a/include/wx/osx/menuitem.h +++ b/include/wx/osx/menuitem.h @@ -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 m_hiddenMenuItems; +#endif // wxUSE_ACCEL + wxDECLARE_DYNAMIC_CLASS(wxMenuItem); }; diff --git a/interface/wx/menuitem.h b/interface/wx/menuitem.h index f421836c65..fc5de12019 100644 --- a/interface/wx/menuitem.h +++ b/interface/wx/menuitem.h @@ -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(); + //@} }; diff --git a/misc/schema/xrc_schema.rnc b/misc/schema/xrc_schema.rnc index b601d54e36..742190bc0c 100644 --- a/misc/schema/xrc_schema.rnc +++ b/misc/schema/xrc_schema.rnc @@ -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- 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 }* } diff --git a/samples/xrc/myframe.cpp b/samples/xrc/myframe.cpp index e897500454..6ec36104aa 100644 --- a/samples/xrc/myframe.cpp +++ b/samples/xrc/myframe.cpp @@ -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 diff --git a/samples/xrc/myframe.h b/samples/xrc/myframe.h index 5315e0bd0d..17ab0f43c1 100644 --- a/samples/xrc/myframe.h +++ b/samples/xrc/myframe.h @@ -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); diff --git a/samples/xrc/rc/menu.xrc b/samples/xrc/rc/menu.xrc index e154d358f0..0d568f2bbc 100644 --- a/samples/xrc/rc/menu.xrc +++ b/samples/xrc/rc/menu.xrc @@ -45,6 +45,15 @@ uncenter.xpm Disable autocentering of a dialog on its parent + + + You can open the dialog with multiple accelerators + Ctrl-W + + Ctrl-T + Shift-Ctrl-W + + diff --git a/src/common/menucmn.cpp b/src/common/menucmn.cpp index fb6a04b6d2..03dbe8fd02 100644 --- a/src/common/menucmn.cpp +++ b/src/common/menucmn.cpp @@ -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) diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index d27e1a4685..77e64cb1be 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -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", diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index 52deb6ce88..4ac1468572 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -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& 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 diff --git a/src/osx/cocoa/menuitem.mm b/src/osx/cocoa/menuitem.mm index 85e9abe3e1..9aa2f4d5a1 100644 --- a/src/osx/cocoa/menuitem.mm +++ b/src/osx/cocoa/menuitem.mm @@ -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); diff --git a/src/osx/menu_osx.cpp b/src/osx/menu_osx.cpp index e70899b881..8ff64ee79d 100644 --- a/src/osx/menu_osx.cpp +++ b/src/osx/menu_osx.cpp @@ -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); diff --git a/src/osx/menuitem_osx.cpp b/src/osx/menuitem_osx.cpp index 80dc0a8f9a..2d6487d358 100644 --- a/src/osx/menuitem_osx.cpp +++ b/src/osx/menuitem_osx.cpp @@ -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 // ---------------------------------------------------------------------------- diff --git a/src/xrc/xh_menu.cpp b/src/xrc/xh_menu.cpp index 9e073cb2b4..14ff78317b 100644 --- a/src/xrc/xh_menu.cpp +++ b/src/xrc/xh_menu.cpp @@ -10,6 +10,7 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" +#include #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 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 diff --git a/tests/menu/menu.cpp b/tests/menu/menu.cpp index 6ce4a58664..1bf5a53942 100644 --- a/tests/menu/menu.cpp +++ b/tests/menu/menu.cpp @@ -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(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.