Fix for using of accelerators from menu items.

After TopBar implementation we don't use wxMenuBar anymore.
As a result menu accelerators was unused.
To workaround this issue the accelerator_entries_cache is generated during creating menu items
and than items from this cache are added to the acceleration table for mainframe.
This commit is contained in:
YuSanka 2023-12-15 16:13:08 +01:00 committed by David Kocik
parent 822b862fce
commit ba5e8b87a9
3 changed files with 51 additions and 9 deletions

View File

@ -20,6 +20,7 @@
#include <wx/menu.h>
#include <wx/progdlg.h>
#include <wx/tooltip.h>
#include <wx/accel.h>
//#include <wx/glcanvas.h>
#include <wx/filename.h>
#include <wx/debug.h>
@ -182,19 +183,34 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
else
init_menubar_as_editor();
#ifndef __APPLE__
std::vector<wxAcceleratorEntry*>& entries_cache = accelerator_entries_cache();
assert(entries_cache.size() + 6 < 100);
wxAcceleratorEntry entries[100];
int id = 0;
for (const auto* entry : entries_cache)
entries[id++].Set(entry->GetFlags(), entry->GetKeyCode(), entry->GetMenuItem()->GetId());
#if _WIN32
// This is needed on Windows to fake the CTRL+# of the window menu when using the numpad
wxAcceleratorEntry entries[6];
entries[0].Set(wxACCEL_CTRL, WXK_NUMPAD1, wxID_HIGHEST + 1);
entries[1].Set(wxACCEL_CTRL, WXK_NUMPAD2, wxID_HIGHEST + 2);
entries[2].Set(wxACCEL_CTRL, WXK_NUMPAD3, wxID_HIGHEST + 3);
entries[3].Set(wxACCEL_CTRL, WXK_NUMPAD4, wxID_HIGHEST + 4);
entries[4].Set(wxACCEL_CTRL, WXK_NUMPAD5, wxID_HIGHEST + 5);
entries[5].Set(wxACCEL_CTRL, WXK_NUMPAD6, wxID_HIGHEST + 6);
wxAcceleratorTable accel(6, entries);
SetAcceleratorTable(accel);
entries[id++].Set(wxACCEL_CTRL, WXK_NUMPAD1, wxID_HIGHEST + 1);
entries[id++].Set(wxACCEL_CTRL, WXK_NUMPAD2, wxID_HIGHEST + 2);
entries[id++].Set(wxACCEL_CTRL, WXK_NUMPAD3, wxID_HIGHEST + 3);
entries[id++].Set(wxACCEL_CTRL, WXK_NUMPAD4, wxID_HIGHEST + 4);
entries[id++].Set(wxACCEL_CTRL, WXK_NUMPAD5, wxID_HIGHEST + 5);
entries[id++].Set(wxACCEL_CTRL, WXK_NUMPAD6, wxID_HIGHEST + 6);
#endif // _WIN32
wxAcceleratorTable accel(id, entries);
SetAcceleratorTable(accel);
// clear cache with wxAcceleratorEntry, because it's no need anymore
for (auto entry : entries_cache)
delete entry;
entries_cache.clear();
#endif
// set default tooltip timer in msec
// SetAutoPop supposedly accepts long integers but some bug doesn't allow for larger values
// (SetAutoPop is not available on GTK.)

View File

@ -9,6 +9,7 @@
#include <cmath>
#include <wx/sizer.h>
#include <wx/accel.h>
#include <boost/algorithm/string/replace.hpp>
@ -51,6 +52,14 @@ void sys_color_changed_menu(wxMenu* menu)
}
#endif /* no __linux__ */
#ifndef __APPLE__
std::vector<wxAcceleratorEntry*>& accelerator_entries_cache()
{
static std::vector<wxAcceleratorEntry*> entries;
return entries;
}
#endif
void enable_menu_item(wxUpdateUIEvent& evt, std::function<bool()> const cb_condition, wxMenuItem* item, wxWindow* win)
{
const bool enable = cb_condition();
@ -78,8 +87,20 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
event_handler->Bind(wxEVT_MENU, cb, id);
else
#endif // __WXMSW__
#ifndef __APPLE__
if (parent)
parent->Bind(wxEVT_MENU, cb, id);
else
#endif // n__APPLE__
menu->Bind(wxEVT_MENU, cb, id);
#ifndef __APPLE__
if (wxAcceleratorEntry* entry = wxAcceleratorEntry::Create(string)) {
entry->SetMenuItem(item);
accelerator_entries_cache().push_back(entry);
}
#endif
if (parent) {
parent->Bind(wxEVT_UPDATE_UI, [cb_condition, item, parent](wxUpdateUIEvent& evt) {
enable_menu_item(evt, cb_condition, item, parent); }, id);

View File

@ -26,6 +26,11 @@ void sys_color_changed_menu(wxMenu* menu);
inline void sys_color_changed_menu(wxMenu* /* menu */) {}
#endif // no __linux__
#ifndef __APPLE__
// Caching wxAcceleratorEntries to use them during mainframe creation
std::vector<wxAcceleratorEntry*>& accelerator_entries_cache();
#endif // no __APPLE__
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, wxBitmapBundle* icon, wxEvtHandler* event_handler = nullptr,
std::function<bool()> const cb_condition = []() { return true;}, wxWindow* parent = nullptr, int insert_pos = wxNOT_FOUND);