From 4eac708596a2067946ebf4996f5891e1a7a47300 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Sun, 8 Apr 2012 13:32:01 +0300 Subject: [PATCH] Wxwidgets: Move the rest of config to main configuration dialog --- src/core/controller.cpp | 4 +- src/core/framerate.cpp | 7 +- src/core/mainloop.cpp | 160 ++--- src/core/window.cpp | 4 +- src/platform/wxwidgets/editor-keyselect.cpp | 430 ------------ src/platform/wxwidgets/mainwindow.cpp | 65 -- src/platform/wxwidgets/settings.cpp | 723 ++++++++++++++++++++ 7 files changed, 810 insertions(+), 583 deletions(-) delete mode 100644 src/platform/wxwidgets/editor-keyselect.cpp diff --git a/src/core/controller.cpp b/src/core/controller.cpp index 5b49754d..7614e50c 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -197,7 +197,7 @@ namespace }; x << (k + 1) << get_logical_button_name(i); y << (k + 1) << get_logical_button_name(i); - expx << "Controller " << (k + 1) << " " << get_logical_button_name(i); + expx << "Controller‣" << (k + 1) << "‣" << get_logical_button_name(i); our_commands.insert(new button_action(x.str(), j, k, y.str())); if(j == 0) our_icommands.insert(new inverse_key(x.str(), expx.str())); @@ -205,7 +205,7 @@ namespace for(unsigned k = 0; k < 8; ++k) { stringfmt x, expx; x << "controller" << (k + 1) << "analog"; - expx << "Controller " << (k + 1) << " analog function"; + expx << "Controller‣" << (k + 1) << "‣Analog function"; our_commands.insert(new analog_action(x.str(), k)); our_icommands.insert(new inverse_key(x.str(), expx.str())); } diff --git a/src/core/framerate.cpp b/src/core/framerate.cpp index bf7a84b0..816f8130 100644 --- a/src/core/framerate.cpp +++ b/src/core/framerate.cpp @@ -12,7 +12,6 @@ #include #include -#define DEFAULT_NOMINAL_RATE 60 #define HISTORY_FRAMES 10 namespace @@ -22,7 +21,7 @@ namespace bool time_frozen = true; uint64_t frame_number = 0; uint64_t frame_start_times[HISTORY_FRAMES]; - double nominal_rate = DEFAULT_NOMINAL_RATE; + double nominal_rate = 100; bool target_nominal = true; double target_fps = 100.0; bool target_infinite = false; @@ -130,8 +129,8 @@ namespace turboed = false; }); - inverse_key turboh("+turbo", "Turbo on hold"); - inverse_key turbot("toggle-turbo", "Toggle turbo"); + inverse_key turboh("+turbo", "Speed‣Turbo hold"); + inverse_key turbot("toggle-turbo", "Speed‣Turbo toggle"); } void freeze_time(uint64_t curtime) diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index e058b415..be107503 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -662,86 +662,86 @@ namespace while(1); }); - inverse_key ipause_emulator("pause-emulator", "(Un)pause"); - inverse_key ijback("cycle-jukebox-backward", "Cycle slot backwards"); - inverse_key ijforward("cycle-jukebox-forward", "Cycle slot forwards"); - inverse_key iloadj("load-jukebox", "load selected slot"); - inverse_key isavej("save-jukebox", "Save selected slot"); - inverse_key iadvframe("+advance-frame", "Advance frame"); - inverse_key iadvsubframe("+advance-poll", "Advance subframe"); - inverse_key iskiplag("advance-skiplag", "Advance to next poll"); - inverse_key ireset("reset", "System reset"); - inverse_key iset_rwmode("set-rwmode", "Switch to read/write"); - inverse_key itoggle_romode("set-romode", "Switch to read-only"); - inverse_key itoggle_rwmode("toggle-rwmode", "Toggle read-only"); - inverse_key irepaint("repaint", "Repaint screen"); - inverse_key itogglepause("toggle-pause-on-end", "Toggle pause-on-end"); - inverse_key irewind_movie("rewind-movie", "Rewind movie"); - inverse_key icancel_saves("cancel-saves", "Cancel pending saves"); - inverse_key iload1("load ${project}1.lsmv", "Load slot 1"); - inverse_key iload2("load ${project}2.lsmv", "Load slot 2"); - inverse_key iload3("load ${project}3.lsmv", "Load slot 3"); - inverse_key iload4("load ${project}4.lsmv", "Load slot 4"); - inverse_key iload5("load ${project}5.lsmv", "Load slot 5"); - inverse_key iload6("load ${project}6.lsmv", "Load slot 6"); - inverse_key iload7("load ${project}7.lsmv", "Load slot 7"); - inverse_key iload8("load ${project}8.lsmv", "Load slot 8"); - inverse_key iload9("load ${project}9.lsmv", "Load slot 9"); - inverse_key iload10("load ${project}10.lsmv", "Load slot 10"); - inverse_key iload11("load ${project}11.lsmv", "Load slot 11"); - inverse_key iload12("load ${project}12.lsmv", "Load slot 12"); - inverse_key iload13("load ${project}13.lsmv", "Load slot 13"); - inverse_key iload14("load ${project}14.lsmv", "Load slot 14"); - inverse_key iload15("load ${project}15.lsmv", "Load slot 15"); - inverse_key iload16("load ${project}16.lsmv", "Load slot 16"); - inverse_key iload17("load ${project}17.lsmv", "Load slot 17"); - inverse_key iload18("load ${project}18.lsmv", "Load slot 18"); - inverse_key iload19("load ${project}19.lsmv", "Load slot 19"); - inverse_key iload20("load ${project}20.lsmv", "Load slot 20"); - inverse_key iload21("load ${project}21.lsmv", "Load slot 21"); - inverse_key iload22("load ${project}22.lsmv", "Load slot 22"); - inverse_key iload23("load ${project}23.lsmv", "Load slot 23"); - inverse_key iload24("load ${project}24.lsmv", "Load slot 24"); - inverse_key iload25("load ${project}25.lsmv", "Load slot 25"); - inverse_key iload26("load ${project}26.lsmv", "Load slot 26"); - inverse_key iload27("load ${project}27.lsmv", "Load slot 27"); - inverse_key iload28("load ${project}28.lsmv", "Load slot 28"); - inverse_key iload29("load ${project}29.lsmv", "Load slot 29"); - inverse_key iload30("load ${project}30.lsmv", "Load slot 30"); - inverse_key iload31("load ${project}31.lsmv", "Load slot 31"); - inverse_key iload32("load ${project}32.lsmv", "Load slot 32"); - inverse_key isave1("save-state ${project}1.lsmv", "Save slot 1"); - inverse_key isave2("save-state ${project}2.lsmv", "Save slot 2"); - inverse_key isave3("save-state ${project}3.lsmv", "Save slot 3"); - inverse_key isave4("save-state ${project}4.lsmv", "Save slot 4"); - inverse_key isave5("save-state ${project}5.lsmv", "Save slot 5"); - inverse_key isave6("save-state ${project}6.lsmv", "Save slot 6"); - inverse_key isave7("save-state ${project}7.lsmv", "Save slot 7"); - inverse_key isave8("save-state ${project}8.lsmv", "Save slot 8"); - inverse_key isave9("save-state ${project}9.lsmv", "Save slot 9"); - inverse_key isave10("save-state ${project}10.lsmv", "Save slot 10"); - inverse_key isave11("save-state ${project}11.lsmv", "Save slot 11"); - inverse_key isave12("save-state ${project}12.lsmv", "Save slot 12"); - inverse_key isave13("save-state ${project}13.lsmv", "Save slot 13"); - inverse_key isave14("save-state ${project}14.lsmv", "Save slot 14"); - inverse_key isave15("save-state ${project}15.lsmv", "Save slot 15"); - inverse_key isave16("save-state ${project}16.lsmv", "Save slot 16"); - inverse_key isave17("save-state ${project}17.lsmv", "Save slot 17"); - inverse_key isave18("save-state ${project}18.lsmv", "Save slot 18"); - inverse_key isave19("save-state ${project}19.lsmv", "Save slot 19"); - inverse_key isave20("save-state ${project}20.lsmv", "Save slot 20"); - inverse_key isave21("save-state ${project}21.lsmv", "Save slot 21"); - inverse_key isave22("save-state ${project}22.lsmv", "Save slot 22"); - inverse_key isave23("save-state ${project}23.lsmv", "Save slot 23"); - inverse_key isave24("save-state ${project}24.lsmv", "Save slot 24"); - inverse_key isave25("save-state ${project}25.lsmv", "Save slot 25"); - inverse_key isave26("save-state ${project}26.lsmv", "Save slot 26"); - inverse_key isave27("save-state ${project}27.lsmv", "Save slot 27"); - inverse_key isave28("save-state ${project}28.lsmv", "Save slot 28"); - inverse_key isave29("save-state ${project}29.lsmv", "Save slot 29"); - inverse_key isave30("save-state ${project}30.lsmv", "Save slot 30"); - inverse_key isave31("save-state ${project}31.lsmv", "Save slot 31"); - inverse_key isave32("save-state ${project}32.lsmv", "Save slot 32"); + inverse_key ipause_emulator("pause-emulator", "Speed‣(Un)pause"); + inverse_key ijback("cycle-jukebox-backward", "Slot select‣Cycle backwards"); + inverse_key ijforward("cycle-jukebox-forward", "Slot select‣Cycle forwards"); + inverse_key iloadj("load-jukebox", "Load‣Selected slot"); + inverse_key isavej("save-jukebox", "Save‣Selected slot"); + inverse_key iadvframe("+advance-frame", "Speed‣Advance frame"); + inverse_key iadvsubframe("+advance-poll", "Speed‣Advance subframe"); + inverse_key iskiplag("advance-skiplag", "Speed‣Advance poll"); + inverse_key ireset("reset", "System‣Reset"); + inverse_key iset_rwmode("set-rwmode", "Movie‣Switch to read/write"); + inverse_key itoggle_romode("set-romode", "Movie‣Switch to read-only"); + inverse_key itoggle_rwmode("toggle-rwmode", "Movie‣Toggle read-only"); + inverse_key irepaint("repaint", "System‣Repaint screen"); + inverse_key itogglepause("toggle-pause-on-end", "Movie‣Toggle pause-on-end"); + inverse_key irewind_movie("rewind-movie", "Movie‣Rewind movie"); + inverse_key icancel_saves("cancel-saves", "Save‣Cancel pending saves"); + inverse_key iload1("load ${project}1.lsmv", "Load‣Slot 1"); + inverse_key iload2("load ${project}2.lsmv", "Load‣Slot 2"); + inverse_key iload3("load ${project}3.lsmv", "Load‣Slot 3"); + inverse_key iload4("load ${project}4.lsmv", "Load‣Slot 4"); + inverse_key iload5("load ${project}5.lsmv", "Load‣Slot 5"); + inverse_key iload6("load ${project}6.lsmv", "Load‣Slot 6"); + inverse_key iload7("load ${project}7.lsmv", "Load‣Slot 7"); + inverse_key iload8("load ${project}8.lsmv", "Load‣Slot 8"); + inverse_key iload9("load ${project}9.lsmv", "Load‣Slot 9"); + inverse_key iload10("load ${project}10.lsmv", "Load‣Slot 10"); + inverse_key iload11("load ${project}11.lsmv", "Load‣Slot 11"); + inverse_key iload12("load ${project}12.lsmv", "Load‣Slot 12"); + inverse_key iload13("load ${project}13.lsmv", "Load‣Slot 13"); + inverse_key iload14("load ${project}14.lsmv", "Load‣Slot 14"); + inverse_key iload15("load ${project}15.lsmv", "Load‣Slot 15"); + inverse_key iload16("load ${project}16.lsmv", "Load‣Slot 16"); + inverse_key iload17("load ${project}17.lsmv", "Load‣Slot 17"); + inverse_key iload18("load ${project}18.lsmv", "Load‣Slot 18"); + inverse_key iload19("load ${project}19.lsmv", "Load‣Slot 19"); + inverse_key iload20("load ${project}20.lsmv", "Load‣Slot 20"); + inverse_key iload21("load ${project}21.lsmv", "Load‣Slot 21"); + inverse_key iload22("load ${project}22.lsmv", "Load‣Slot 22"); + inverse_key iload23("load ${project}23.lsmv", "Load‣Slot 23"); + inverse_key iload24("load ${project}24.lsmv", "Load‣Slot 24"); + inverse_key iload25("load ${project}25.lsmv", "Load‣Slot 25"); + inverse_key iload26("load ${project}26.lsmv", "Load‣Slot 26"); + inverse_key iload27("load ${project}27.lsmv", "Load‣Slot 27"); + inverse_key iload28("load ${project}28.lsmv", "Load‣Slot 28"); + inverse_key iload29("load ${project}29.lsmv", "Load‣Slot 29"); + inverse_key iload30("load ${project}30.lsmv", "Load‣Slot 30"); + inverse_key iload31("load ${project}31.lsmv", "Load‣Slot 31"); + inverse_key iload32("load ${project}32.lsmv", "Load‣Slot 32"); + inverse_key isave1("save-state ${project}1.lsmv", "Save‣Slot 1"); + inverse_key isave2("save-state ${project}2.lsmv", "Save‣Slot 2"); + inverse_key isave3("save-state ${project}3.lsmv", "Save‣Slot 3"); + inverse_key isave4("save-state ${project}4.lsmv", "Save‣Slot 4"); + inverse_key isave5("save-state ${project}5.lsmv", "Save‣Slot 5"); + inverse_key isave6("save-state ${project}6.lsmv", "Save‣Slot 6"); + inverse_key isave7("save-state ${project}7.lsmv", "Save‣Slot 7"); + inverse_key isave8("save-state ${project}8.lsmv", "Save‣Slot 8"); + inverse_key isave9("save-state ${project}9.lsmv", "Save‣Slot 9"); + inverse_key isave10("save-state ${project}10.lsmv", "Save‣Slot 10"); + inverse_key isave11("save-state ${project}11.lsmv", "Save‣Slot 11"); + inverse_key isave12("save-state ${project}12.lsmv", "Save‣Slot 12"); + inverse_key isave13("save-state ${project}13.lsmv", "Save‣Slot 13"); + inverse_key isave14("save-state ${project}14.lsmv", "Save‣Slot 14"); + inverse_key isave15("save-state ${project}15.lsmv", "Save‣Slot 15"); + inverse_key isave16("save-state ${project}16.lsmv", "Save‣Slot 16"); + inverse_key isave17("save-state ${project}17.lsmv", "Save‣Slot 17"); + inverse_key isave18("save-state ${project}18.lsmv", "Save‣Slot 18"); + inverse_key isave19("save-state ${project}19.lsmv", "Save‣Slot 19"); + inverse_key isave20("save-state ${project}20.lsmv", "Save‣Slot 20"); + inverse_key isave21("save-state ${project}21.lsmv", "Save‣Slot 21"); + inverse_key isave22("save-state ${project}22.lsmv", "Save‣Slot 22"); + inverse_key isave23("save-state ${project}23.lsmv", "Save‣Slot 23"); + inverse_key isave24("save-state ${project}24.lsmv", "Save‣Slot 24"); + inverse_key isave25("save-state ${project}25.lsmv", "Save‣Slot 25"); + inverse_key isave26("save-state ${project}26.lsmv", "Save‣Slot 26"); + inverse_key isave27("save-state ${project}27.lsmv", "Save‣Slot 27"); + inverse_key isave28("save-state ${project}28.lsmv", "Save‣Slot 28"); + inverse_key isave29("save-state ${project}29.lsmv", "Save‣Slot 29"); + inverse_key isave30("save-state ${project}30.lsmv", "Save‣Slot 30"); + inverse_key isave31("save-state ${project}31.lsmv", "Save‣Slot 31"); + inverse_key isave32("save-state ${project}32.lsmv", "Save‣Slot 32"); bool on_quit_prompt = false; class mywindowcallbacks : public information_dispatch diff --git a/src/core/window.cpp b/src/core/window.cpp index a9dd01c2..615e66ab 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -148,8 +148,8 @@ namespace } }); - inverse_key ienable_sound("enable-sound on", "Enable sound"); - inverse_key idisable_sound("enable-sound off", "Disable sound"); + inverse_key ienable_sound("enable-sound on", "Sound‣Enable"); + inverse_key idisable_sound("enable-sound off", "Sound‣Disable"); function_ptr_command set_sound_device("set-sound-device", "Set sound device", "Syntax: set-sound-device \nSet sound device to .\n", diff --git a/src/platform/wxwidgets/editor-keyselect.cpp b/src/platform/wxwidgets/editor-keyselect.cpp deleted file mode 100644 index 3baede8f..00000000 --- a/src/platform/wxwidgets/editor-keyselect.cpp +++ /dev/null @@ -1,430 +0,0 @@ -#include "platform/wxwidgets/platform.hpp" -#include "core/keymapper.hpp" - -#include - -namespace -{ - struct keyentry_mod_data - { - wxCheckBox* pressed; - wxCheckBox* unmasked; - unsigned tmpflags; - }; - - class wxdialog_keyentry : public wxDialog - { - public: - wxdialog_keyentry(wxWindow* parent, const std::string& title, const std::string& spec, - bool clearable); - void on_change_setting(wxCommandEvent& e); - void on_ok(wxCommandEvent& e); - void on_cancel(wxCommandEvent& e); - void on_clear(wxCommandEvent& e); - void on_classchange(wxCommandEvent& e); - std::string getkey(); - private: - void set_mask(const std::string& mod); - void set_mod(const std::string& mod); - void set_set(const std::string& mset, - void (wxdialog_keyentry::*fn)(const std::string& mod)); - void load_spec(const std::string& spec); - std::map modifiers; - wxComboBox* mainclass; - wxComboBox* mainkey; - wxButton* ok; - wxButton* cancel; - wxButton* clear; - bool cleared; - }; - - class wxdialog_hotkeys; - - class hotkey - { - public: - hotkey(wxdialog_hotkeys* h, wxWindow* win, wxSizer* s, inverse_key* ikey, unsigned o); - void update(const std::string& primary, const std::string& secondary); - inverse_key* get_associated(); - std::string get_title(); - private: - wxButton* primaryb; - wxButton* secondaryb; - inverse_key* associated; - std::string title; - }; - - class wxdialog_hotkeys : public wxDialog - { - public: - wxdialog_hotkeys(wxWindow* parent); - ~wxdialog_hotkeys(); - void on_close(wxCommandEvent& e); - void on_reconfig(wxCommandEvent& e); - private: - void update(); - wxScrolledWindow* scroll; - wxSizer* scroll_sizer; - std::map hotkeys; - wxButton* close; - }; - - wxdialog_keyentry::wxdialog_keyentry(wxWindow* parent, const std::string& title, const std::string& spec, - bool clearable) - : wxDialog(parent, wxID_ANY, towxstring(title), wxDefaultPosition, wxSize(-1, -1)) - { - std::vector keych; - std::set mods, keys; - - cleared = false; - runemufn([&mods, &keys]() { mods = modifier::get_set(); keys = keygroup::get_keys(); }); - Centre(); - wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0); - SetSizer(top_s); - - wxFlexGridSizer* t_s = new wxFlexGridSizer(mods.size() + 1, 3, 0, 0); - for(auto i : mods) { - t_s->Add(new wxStaticText(this, wxID_ANY, towxstring(i)), 0, wxGROW); - keyentry_mod_data m; - t_s->Add(m.pressed = new wxCheckBox(this, wxID_ANY, wxT("Pressed")), 0, wxGROW); - t_s->Add(m.unmasked = new wxCheckBox(this, wxID_ANY, wxT("Unmasked")), 0, wxGROW); - m.pressed->Disable(); - modifiers[i] = m; - m.pressed->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, - wxCommandEventHandler(wxdialog_keyentry::on_change_setting), NULL, this); - m.unmasked->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, - wxCommandEventHandler(wxdialog_keyentry::on_change_setting), NULL, this); - } - for(auto i : keys) - keych.push_back(towxstring(i)); - t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Key")), 0, wxGROW); - t_s->Add(mainkey = new wxComboBox(this, wxID_ANY, keych[0], wxDefaultPosition, wxDefaultSize, - keych.size(), &keych[0], wxCB_READONLY), 1, wxGROW); - mainkey->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, - wxCommandEventHandler(wxdialog_keyentry::on_change_setting), NULL, this); - top_s->Add(t_s); - - wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL); - if(clearable) - pbutton_s->Add(clear = new wxButton(this, wxID_OK, wxT("Clear")), 0, wxGROW); - pbutton_s->AddStretchSpacer(); - pbutton_s->Add(ok = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW); - pbutton_s->Add(cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW); - ok->Connect(wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxdialog_keyentry::on_ok), NULL, this); - cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxdialog_keyentry::on_cancel), NULL, this); - if(clearable) - clear->Connect(wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxdialog_keyentry::on_clear), NULL, this); - top_s->Add(pbutton_s, 0, wxGROW); - - t_s->SetSizeHints(this); - top_s->SetSizeHints(this); - Fit(); - - if(spec != "") - load_spec(spec); - } - -#define TMPFLAG_UNMASKED 65 -#define TMPFLAG_UNMASKED_LINK_CHILD 2 -#define TMPFLAG_UNMASKED_LINK_PARENT 68 -#define TMPFLAG_PRESSED 8 -#define TMPFLAG_PRESSED_LINK_CHILD 16 -#define TMPFLAG_PRESSED_LINK_PARENT 32 - - void wxdialog_keyentry::set_mask(const std::string& mod) - { - if(!modifiers.count(mod)) - return; - if(modifiers[mod].unmasked->IsEnabled()) { - wxCommandEvent e; - modifiers[mod].unmasked->SetValue(true); - on_change_setting(e); - } - } - - void wxdialog_keyentry::set_mod(const std::string& mod) - { - if(!modifiers.count(mod)) - return; - if(modifiers[mod].pressed->IsEnabled()) { - wxCommandEvent e; - modifiers[mod].pressed->SetValue(true); - on_change_setting(e); - } - } - - void wxdialog_keyentry::set_set(const std::string& mset, - void (wxdialog_keyentry::*fn)(const std::string& mod)) - { - std::string rem = mset; - while(rem != "") { - size_t s = rem.find_first_of(","); - if(s >= rem.length()) { - (this->*fn)(rem); - break; - } else { - (this->*fn)(rem.substr(0, s)); - rem = rem.substr(s + 1); - } - } - } - - void wxdialog_keyentry::load_spec(const std::string& spec) - { - std::string _spec = spec; - size_t s1 = _spec.find_first_of("/"); - size_t s2 = _spec.find_first_of("|"); - if(s1 >= _spec.length() || s2 >= _spec.length()) - return; //Bad. - std::string mod = _spec.substr(0, s1); - std::string mask = _spec.substr(s1 + 1, s2 - s1 - 1); - std::string key = _spec.substr(s2 + 1); - set_set(mask, &wxdialog_keyentry::set_mask); - set_set(mod, &wxdialog_keyentry::set_mod); - mainkey->SetValue(towxstring(key)); - } - - void wxdialog_keyentry::on_change_setting(wxCommandEvent& e) - { - for(auto& i : modifiers) - i.second.tmpflags = 0; - for(auto& i : modifiers) { - modifier* m = NULL; - try { - m = &modifier::lookup(i.first); - } catch(...) { - i.second.pressed->Disable(); - i.second.unmasked->Disable(); - continue; - } - std::string j = m->linked_name(); - if(i.second.unmasked->GetValue()) - i.second.tmpflags |= TMPFLAG_UNMASKED; - if(j != "") { - if(modifiers[j].unmasked->GetValue()) - i.second.tmpflags |= TMPFLAG_UNMASKED_LINK_PARENT; - if(i.second.unmasked->GetValue()) - modifiers[j].tmpflags |= TMPFLAG_UNMASKED_LINK_CHILD; - } - if(i.second.pressed->GetValue()) - i.second.tmpflags |= TMPFLAG_PRESSED; - if(j != "") { - if(modifiers[j].pressed->GetValue()) - i.second.tmpflags |= TMPFLAG_PRESSED_LINK_PARENT; - if(i.second.pressed->GetValue()) - modifiers[j].tmpflags |= TMPFLAG_PRESSED_LINK_CHILD; - } - } - for(auto& i : modifiers) { - //Unmasked is to be enabled if neither unmasked link flag is set. - if(i.second.tmpflags & ((TMPFLAG_UNMASKED_LINK_CHILD | TMPFLAG_UNMASKED_LINK_PARENT) & ~64)) { - i.second.unmasked->SetValue(false); - i.second.unmasked->Disable(); - } else - i.second.unmasked->Enable(); - //Pressed is to be enabled if: - //- This modifier is unmasked or parent is unmasked. - //- Parent nor child is not pressed. - if(((i.second.tmpflags & (TMPFLAG_UNMASKED | TMPFLAG_UNMASKED_LINK_PARENT | - TMPFLAG_PRESSED_LINK_CHILD | TMPFLAG_PRESSED_LINK_PARENT)) & 112) == 64) - i.second.pressed->Enable(); - else { - i.second.pressed->SetValue(false); - i.second.pressed->Disable(); - } - } - } - - void wxdialog_keyentry::on_ok(wxCommandEvent& e) - { - EndModal(wxID_OK); - } - - void wxdialog_keyentry::on_clear(wxCommandEvent& e) - { - cleared = true; - EndModal(wxID_OK); - } - - void wxdialog_keyentry::on_cancel(wxCommandEvent& e) - { - EndModal(wxID_CANCEL); - } - - std::string wxdialog_keyentry::getkey() - { - if(cleared) - return ""; - std::string x; - bool f; - f = true; - for(auto i : modifiers) { - if(i.second.pressed->GetValue()) { - if(!f) - x = x + ","; - f = false; - x = x + i.first; - } - } - x = x + "/"; - f = true; - for(auto i : modifiers) { - if(i.second.unmasked->GetValue()) { - if(!f) - x = x + ","; - f = false; - x = x + i.first; - } - } - x = x + "|" + tostdstring(mainkey->GetValue()); - return x; - } - - wxdialog_hotkeys::wxdialog_hotkeys(wxWindow* parent) - : wxDialog(parent, wxID_ANY, wxT("Hotkeys"), wxDefaultPosition, wxSize(-1, -1)) - { - scroll = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1)); - scroll->SetMinSize(wxSize(-1, 500)); - - Centre(); - wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0); - SetSizer(top_s); - scroll_sizer = new wxFlexGridSizer(0, 3, 0, 0); - scroll->SetSizer(scroll_sizer); - - //Obtain all the inverses. - std::set inverses; - runemufn([&inverses]() { - auto x = inverse_key::get_ikeys(); - for(auto y : x) - inverses.insert(y); - }); - unsigned y = 0; - for(auto x : inverses) { - hotkeys[y] = new hotkey(this, scroll, scroll_sizer, x, y); - y++; - } - update(); - - top_s->Add(scroll); - scroll->SetScrollRate(0, 20); - wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL); - pbutton_s->AddStretchSpacer(); - pbutton_s->Add(close = new wxButton(this, wxID_CANCEL, wxT("Close")), 0, wxGROW); - close->Connect(wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxdialog_hotkeys::on_close), NULL, this); - top_s->Add(pbutton_s, 0, wxGROW); - - scroll_sizer->SetSizeHints(this); - top_s->SetSizeHints(this); - scroll_sizer->Layout(); - top_s->Layout(); - Fit(); - } - - void wxdialog_hotkeys::on_reconfig(wxCommandEvent& e) - { - int id = e.GetId(); - if(id <= wxID_HIGHEST) - return; - unsigned button = (id - wxID_HIGHEST - 1) / 2; - bool primflag = (((id - wxID_HIGHEST - 1) % 2) == 0); - if(!hotkeys.count(button)) - return; - wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + hotkeys[button]-> - get_title(), hotkeys[button]->get_associated()->get(primflag), true); - if(d->ShowModal() == wxID_CANCEL) { - d->Destroy(); - return; - } - std::string key = d->getkey(); - d->Destroy(); - if(key != "") - hotkeys[button]->get_associated()->set(key, primflag); - else - hotkeys[button]->get_associated()->clear(primflag); - update(); - } - - void wxdialog_hotkeys::update() - { - std::map> data; - runemufn([&data]() { - auto x = inverse_key::get_ikeys(); - for(auto y : x) - data[y] = std::make_pair(y->get(true), y->get(false)); - }); - for(auto i : hotkeys) { - inverse_key* j = i.second->get_associated(); - if(!data.count(j)) - continue; - auto y = data[j]; - i.second->update(y.first, y.second); - } - } - - wxdialog_hotkeys::~wxdialog_hotkeys() - { - for(auto i : hotkeys) - delete i.second; - } - - void wxdialog_hotkeys::on_close(wxCommandEvent& e) - { - EndModal(wxID_OK); - } - - hotkey::hotkey(wxdialog_hotkeys* h, wxWindow* win, wxSizer* s, inverse_key* ikey, unsigned o) - { - title = ikey->getname(); - s->Add(new wxStaticText(win, wxID_ANY, towxstring(title)), 0, wxGROW); - s->Add(primaryb = new wxButton(win, wxID_HIGHEST + 1 + 2 * o, wxT("(none)"), wxDefaultPosition, - wxSize(200, -1)), 0, wxGROW); - s->Add(secondaryb = new wxButton(win, wxID_HIGHEST + 2 + 2 * o, wxT("(none)"), wxDefaultPosition, - wxSize(200, -1)), 0, wxGROW); - primaryb->Connect(wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxdialog_hotkeys::on_reconfig), NULL, h); - secondaryb->Connect(wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxdialog_hotkeys::on_reconfig), NULL, h); - associated = ikey; - } - - inverse_key* hotkey::get_associated() - { - return associated; - } - - std::string hotkey::get_title() - { - return title; - } - - void hotkey::update(const std::string& primary, const std::string& secondary) - { - primaryb->SetLabel((primary != "") ? towxstring(primary) : towxstring("(none)")); - secondaryb->SetLabel((secondary != "") ? towxstring(secondary) : towxstring("(none)")); - } -} - -std::string wxeditor_keyselect(wxWindow* parent, bool clearable) -{ - wxdialog_keyentry* d = new wxdialog_keyentry(parent, "Specify key", "", clearable); - if(d->ShowModal() == wxID_CANCEL) { - d->Destroy(); - throw canceled_exception(); - } - std::string key = d->getkey(); - d->Destroy(); - return key; -} - -void wxeditor_hotkeys_display(wxWindow* parent) -{ - modal_pause_holder hld; - wxdialog_hotkeys* d = new wxdialog_hotkeys(parent); - d->ShowModal(); - d->Destroy(); -} diff --git a/src/platform/wxwidgets/mainwindow.cpp b/src/platform/wxwidgets/mainwindow.cpp index fadf3c51..53e8b6b5 100644 --- a/src/platform/wxwidgets/mainwindow.cpp +++ b/src/platform/wxwidgets/mainwindow.cpp @@ -63,8 +63,6 @@ enum wxID_EDIT_AUTHORS, wxID_AUTOHOLD_FIRST, wxID_AUTOHOLD_LAST = wxID_AUTOHOLD_FIRST + 1023, - wxID_EDIT_KEYBINDINGS, - wxID_EDIT_ALIAS, wxID_EDIT_MEMORYWATCH, wxID_SAVE_MEMORYWATCH, wxID_LOAD_MEMORYWATCH, @@ -73,7 +71,6 @@ enum wxID_REWIND_MOVIE, wxID_MEMORY_SEARCH, wxID_CANCEL_SAVES, - wxID_EDIT_HOTKEYS, wxID_SHOW_STATUS, wxID_SET_SPEED, wxID_SET_VOLUME, @@ -764,12 +761,6 @@ wxwin_mainwindow::wxwin_mainwindow() menu_special(wxT("Capture"), reinterpret_cast(dmenu = new dumper_menu(this, wxID_DUMP_FIRST, wxID_DUMP_LAST))); - - menu_start(wxT("Settings")); - menu_entry(wxID_EDIT_KEYBINDINGS, wxT("Configure keybindings...")); - menu_entry(wxID_EDIT_ALIAS, wxT("Configure aliases...")); - menu_separator(); - menu_entry(wxID_EDIT_HOTKEYS, wxT("Configure hotkeys...")); } void wxwin_mainwindow::request_paint() @@ -912,62 +903,6 @@ void wxwin_mainwindow::handle_menu_click_cancelable(wxCommandEvent& e) case wxID_EDIT_AUTHORS: wxeditor_authors_display(this); return; - case wxID_EDIT_HOTKEYS: - wxeditor_hotkeys_display(this); - return; - case wxID_EDIT_KEYBINDINGS: { - modal_pause_holder hld; - std::set bind; - runemufn([&bind]() { bind = keymapper::get_bindings(); }); - std::vector choices; - choices.push_back(NEW_KEYBINDING); - for(auto i : bind) - choices.push_back(i); - std::string key = pick_among(this, "Select binding", "Select keybinding to edit", choices); - if(key == NEW_KEYBINDING) - key = wxeditor_keyselect(this, false); - std::string old_command_value; - runemufn([&old_command_value, key]() { old_command_value = keymapper::get_command_for(key); }); - std::string newcommand = pick_text(this, "Edit binding", "Enter new command for binding:", - old_command_value); - bool fault = false; - std::string faulttext; - runemufn([&fault, &faulttext, key, newcommand]() { - try { - keymapper::bind_for(key, newcommand); - } catch(std::exception& e) { - fault = true; - faulttext = e.what(); - } - }); - if(fault) - show_message_ok(this, "Error", "Can't bind key: " + faulttext, wxICON_EXCLAMATION); - return; - } - case wxID_EDIT_ALIAS: { - modal_pause_holder hld; - std::set bind; - runemufn([&bind]() { bind = command::get_aliases(); }); - std::vector choices; - choices.push_back(NEW_ALIAS); - for(auto i : bind) - choices.push_back(i); - std::string alias = pick_among(this, "Select alias", "Select alias to edit", choices); - if(alias == NEW_ALIAS) { - alias = pick_text(this, "Enter alias name", "Enter name for the new alias:"); - if(!command::valid_alias_name(alias)) { - show_message_ok(this, "Error", "Not a valid alias name: " + alias, - wxICON_EXCLAMATION); - throw canceled_exception(); - } - } - std::string old_alias_value; - runemufn([alias, &old_alias_value]() { old_alias_value = command::get_alias_for(alias); }); - std::string newcmd = pick_text(this, "Edit alias", "Enter new commands for alias:", - old_alias_value, true); - runemufn([alias, newcmd]() { command::set_alias_for(alias, newcmd); }); - return; - } case wxID_EDIT_MEMORYWATCH: { modal_pause_holder hld; std::set bind; diff --git a/src/platform/wxwidgets/settings.cpp b/src/platform/wxwidgets/settings.cpp index 978498aa..09eb8472 100644 --- a/src/platform/wxwidgets/settings.cpp +++ b/src/platform/wxwidgets/settings.cpp @@ -1,10 +1,12 @@ #include "platform/wxwidgets/platform.hpp" +#include "core/command.hpp" #include "core/dispatch.hpp" #include "core/settings.hpp" #include "library/string.hpp" #include #include +#include #include #include #include @@ -42,6 +44,256 @@ extern "C" const char* scalealgo_choices[] = {"Fast Bilinear", "Bilinear", "Bicubic", "Experimential", "Point", "Area", "Bicubic-Linear", "Gauss", "Sinc", "Lanczos", "Spline"}; +namespace +{ + struct keyentry_mod_data + { + wxCheckBox* pressed; + wxCheckBox* unmasked; + unsigned tmpflags; + }; + + class wxdialog_keyentry : public wxDialog + { + public: + wxdialog_keyentry(wxWindow* parent, const std::string& title, const std::string& spec, + bool clearable); + void on_change_setting(wxCommandEvent& e); + void on_ok(wxCommandEvent& e); + void on_cancel(wxCommandEvent& e); + void on_clear(wxCommandEvent& e); + void on_classchange(wxCommandEvent& e); + std::string getkey(); + private: + void set_mask(const std::string& mod); + void set_mod(const std::string& mod); + void set_set(const std::string& mset, + void (wxdialog_keyentry::*fn)(const std::string& mod)); + void load_spec(const std::string& spec); + std::map modifiers; + wxComboBox* mainclass; + wxComboBox* mainkey; + wxButton* ok; + wxButton* cancel; + wxButton* clear; + bool cleared; + }; + + wxdialog_keyentry::wxdialog_keyentry(wxWindow* parent, const std::string& title, const std::string& spec, + bool clearable) + : wxDialog(parent, wxID_ANY, towxstring(title), wxDefaultPosition, wxSize(-1, -1)) + { + std::vector keych; + std::set mods, keys; + + cleared = false; + runemufn([&mods, &keys]() { mods = modifier::get_set(); keys = keygroup::get_keys(); }); + Centre(); + wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0); + SetSizer(top_s); + + wxFlexGridSizer* t_s = new wxFlexGridSizer(mods.size() + 1, 3, 0, 0); + for(auto i : mods) { + t_s->Add(new wxStaticText(this, wxID_ANY, towxstring(i)), 0, wxGROW); + keyentry_mod_data m; + t_s->Add(m.pressed = new wxCheckBox(this, wxID_ANY, wxT("Pressed")), 0, wxGROW); + t_s->Add(m.unmasked = new wxCheckBox(this, wxID_ANY, wxT("Unmasked")), 0, wxGROW); + m.pressed->Disable(); + modifiers[i] = m; + m.pressed->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, + wxCommandEventHandler(wxdialog_keyentry::on_change_setting), NULL, this); + m.unmasked->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, + wxCommandEventHandler(wxdialog_keyentry::on_change_setting), NULL, this); + } + for(auto i : keys) + keych.push_back(towxstring(i)); + t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Key")), 0, wxGROW); + t_s->Add(mainkey = new wxComboBox(this, wxID_ANY, keych[0], wxDefaultPosition, wxDefaultSize, + keych.size(), &keych[0], wxCB_READONLY), 1, wxGROW); + mainkey->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, + wxCommandEventHandler(wxdialog_keyentry::on_change_setting), NULL, this); + top_s->Add(t_s); + + wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL); + if(clearable) + pbutton_s->Add(clear = new wxButton(this, wxID_OK, wxT("Clear")), 0, wxGROW); + pbutton_s->AddStretchSpacer(); + pbutton_s->Add(ok = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW); + pbutton_s->Add(cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW); + ok->Connect(wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxdialog_keyentry::on_ok), NULL, this); + cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxdialog_keyentry::on_cancel), NULL, this); + if(clearable) + clear->Connect(wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxdialog_keyentry::on_clear), NULL, this); + top_s->Add(pbutton_s, 0, wxGROW); + + t_s->SetSizeHints(this); + top_s->SetSizeHints(this); + Fit(); + + if(spec != "") + load_spec(spec); + } + +#define TMPFLAG_UNMASKED 65 +#define TMPFLAG_UNMASKED_LINK_CHILD 2 +#define TMPFLAG_UNMASKED_LINK_PARENT 68 +#define TMPFLAG_PRESSED 8 +#define TMPFLAG_PRESSED_LINK_CHILD 16 +#define TMPFLAG_PRESSED_LINK_PARENT 32 + + void wxdialog_keyentry::set_mask(const std::string& mod) + { + if(!modifiers.count(mod)) + return; + if(modifiers[mod].unmasked->IsEnabled()) { + wxCommandEvent e; + modifiers[mod].unmasked->SetValue(true); + on_change_setting(e); + } + } + + void wxdialog_keyentry::set_mod(const std::string& mod) + { + if(!modifiers.count(mod)) + return; + if(modifiers[mod].pressed->IsEnabled()) { + wxCommandEvent e; + modifiers[mod].pressed->SetValue(true); + on_change_setting(e); + } + } + + void wxdialog_keyentry::set_set(const std::string& mset, + void (wxdialog_keyentry::*fn)(const std::string& mod)) + { + std::string rem = mset; + while(rem != "") { + size_t s = rem.find_first_of(","); + if(s >= rem.length()) { + (this->*fn)(rem); + break; + } else { + (this->*fn)(rem.substr(0, s)); + rem = rem.substr(s + 1); + } + } + } + + void wxdialog_keyentry::load_spec(const std::string& spec) + { + std::string _spec = spec; + size_t s1 = _spec.find_first_of("/"); + size_t s2 = _spec.find_first_of("|"); + if(s1 >= _spec.length() || s2 >= _spec.length()) + return; //Bad. + std::string mod = _spec.substr(0, s1); + std::string mask = _spec.substr(s1 + 1, s2 - s1 - 1); + std::string key = _spec.substr(s2 + 1); + set_set(mask, &wxdialog_keyentry::set_mask); + set_set(mod, &wxdialog_keyentry::set_mod); + mainkey->SetValue(towxstring(key)); + } + + void wxdialog_keyentry::on_change_setting(wxCommandEvent& e) + { + for(auto& i : modifiers) + i.second.tmpflags = 0; + for(auto& i : modifiers) { + modifier* m = NULL; + try { + m = &modifier::lookup(i.first); + } catch(...) { + i.second.pressed->Disable(); + i.second.unmasked->Disable(); + continue; + } + std::string j = m->linked_name(); + if(i.second.unmasked->GetValue()) + i.second.tmpflags |= TMPFLAG_UNMASKED; + if(j != "") { + if(modifiers[j].unmasked->GetValue()) + i.second.tmpflags |= TMPFLAG_UNMASKED_LINK_PARENT; + if(i.second.unmasked->GetValue()) + modifiers[j].tmpflags |= TMPFLAG_UNMASKED_LINK_CHILD; + } + if(i.second.pressed->GetValue()) + i.second.tmpflags |= TMPFLAG_PRESSED; + if(j != "") { + if(modifiers[j].pressed->GetValue()) + i.second.tmpflags |= TMPFLAG_PRESSED_LINK_PARENT; + if(i.second.pressed->GetValue()) + modifiers[j].tmpflags |= TMPFLAG_PRESSED_LINK_CHILD; + } + } + for(auto& i : modifiers) { + //Unmasked is to be enabled if neither unmasked link flag is set. + if(i.second.tmpflags & ((TMPFLAG_UNMASKED_LINK_CHILD | TMPFLAG_UNMASKED_LINK_PARENT) & ~64)) { + i.second.unmasked->SetValue(false); + i.second.unmasked->Disable(); + } else + i.second.unmasked->Enable(); + //Pressed is to be enabled if: + //- This modifier is unmasked or parent is unmasked. + //- Parent nor child is not pressed. + if(((i.second.tmpflags & (TMPFLAG_UNMASKED | TMPFLAG_UNMASKED_LINK_PARENT | + TMPFLAG_PRESSED_LINK_CHILD | TMPFLAG_PRESSED_LINK_PARENT)) & 112) == 64) + i.second.pressed->Enable(); + else { + i.second.pressed->SetValue(false); + i.second.pressed->Disable(); + } + } + } + + void wxdialog_keyentry::on_ok(wxCommandEvent& e) + { + EndModal(wxID_OK); + } + + void wxdialog_keyentry::on_clear(wxCommandEvent& e) + { + cleared = true; + EndModal(wxID_OK); + } + + void wxdialog_keyentry::on_cancel(wxCommandEvent& e) + { + EndModal(wxID_CANCEL); + } + + std::string wxdialog_keyentry::getkey() + { + if(cleared) + return ""; + std::string x; + bool f; + f = true; + for(auto i : modifiers) { + if(i.second.pressed->GetValue()) { + if(!f) + x = x + ","; + f = false; + x = x + i.first; + } + } + x = x + "/"; + f = true; + for(auto i : modifiers) { + if(i.second.unmasked->GetValue()) { + if(!f) + x = x + ","; + f = false; + x = x + i.first; + } + } + x = x + "|" + tostdstring(mainkey->GetValue()); + return x; + } +} + class wxeditor_esettings_joystick_aconfig : public wxDialog { public: @@ -537,6 +789,474 @@ void wxeditor_esettings_screen::refresh() Fit(); } +class wxeditor_esettings_aliases : public wxPanel +{ +public: + wxeditor_esettings_aliases(wxWindow* parent); + ~wxeditor_esettings_aliases(); + void on_add(wxCommandEvent& e); + void on_edit(wxCommandEvent& e); + void on_delete(wxCommandEvent& e); +private: + std::map numbers; + wxListBox* select; + void refresh(); + std::string selected(); +}; + +wxeditor_esettings_aliases::wxeditor_esettings_aliases(wxWindow* parent) + : wxPanel(parent, -1) +{ + wxButton* tmp; + + wxSizer* top_s = new wxBoxSizer(wxVERTICAL); + SetSizer(top_s); + + top_s->Add(select = new wxListBox(this, wxID_ANY), 1, wxGROW); + + wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL); + pbutton_s->AddStretchSpacer(); + pbutton_s->Add(tmp = new wxButton(this, wxID_ANY, wxT("Add")), 0, wxGROW); + tmp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_esettings_aliases::on_add), NULL, + this); + pbutton_s->Add(tmp = new wxButton(this, wxID_ANY, wxT("Edit")), 0, wxGROW); + tmp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_esettings_aliases::on_edit), NULL, + this); + pbutton_s->Add(tmp = new wxButton(this, wxID_ANY, wxT("Delete")), 0, wxGROW); + tmp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_esettings_aliases::on_delete), NULL, + this); + top_s->Add(pbutton_s, 0, wxGROW); + + refresh(); + top_s->SetSizeHints(this); + Fit(); +} + +wxeditor_esettings_aliases::~wxeditor_esettings_aliases() +{ +} + +void wxeditor_esettings_aliases::on_add(wxCommandEvent& e) +{ + try { + std::string name = pick_text(this, "Enter alias name", "Enter name for the new alias:"); + if(!command::valid_alias_name(name)) { + show_message_ok(this, "Error", "Not a valid alias name: " + name, wxICON_EXCLAMATION); + throw canceled_exception(); + } + std::string old_alias_value; + runemufn([name, &old_alias_value]() { old_alias_value = command::get_alias_for(name); }); + std::string newcmd = pick_text(this, "Edit alias", "Enter new commands for '" + name + "':", + old_alias_value, true); + runemufn([name, newcmd]() { command::set_alias_for(name, newcmd); }); + } catch(...) { + } + refresh(); +} + +void wxeditor_esettings_aliases::on_edit(wxCommandEvent& e) +{ + std::string name = selected(); + if(name == "") { + refresh(); + return; + } + try { + std::string old_alias_value; + runemufn([name, &old_alias_value]() { old_alias_value = command::get_alias_for(name); }); + std::string newcmd = pick_text(this, "Edit alias", "Enter new commands for '" + name + "':", + old_alias_value, true); + runemufn([name, newcmd]() { command::set_alias_for(name, newcmd); }); + } catch(...) { + } + refresh(); +} + +void wxeditor_esettings_aliases::on_delete(wxCommandEvent& e) +{ + std::string name = selected(); + if(name == "") { + refresh(); + return; + } + runemufn([name]() { command::set_alias_for(name, ""); }); + refresh(); +} + +void wxeditor_esettings_aliases::refresh() +{ + int n = select->GetSelection(); + std::set bind; + std::vector choices; + runemufn([&bind]() { bind = command::get_aliases(); }); + for(auto i : bind) { + numbers[choices.size()] = i; + choices.push_back(towxstring(i)); + } + select->Set(choices.size(), &choices[0]); + if(n == wxNOT_FOUND && select->GetCount()) + select->SetSelection(0); + else if(n >= select->GetCount()) + select->SetSelection(select->GetCount() ? (select->GetCount() - 1) : wxNOT_FOUND); + else + select->SetSelection(n); +} + +std::string wxeditor_esettings_aliases::selected() +{ + int x = select->GetSelection(); + if(numbers.count(x)) + return numbers[x]; + else + return ""; +} + +class wxeditor_esettings_hotkeys : public wxPanel +{ +public: + wxeditor_esettings_hotkeys(wxWindow* parent); + ~wxeditor_esettings_hotkeys(); + void on_primary(wxCommandEvent& e); + void on_secondary(wxCommandEvent& e); +private: + std::map items; + std::map realitems; + std::map leafname; + wxTreeItemId true_root; + wxTreeCtrl* select; + wxButton* pri_button; + wxButton* sec_button; + void refresh(); + std::string selected(); +}; + +wxeditor_esettings_hotkeys::wxeditor_esettings_hotkeys(wxWindow* parent) + : wxPanel(parent, -1) +{ + wxSizer* top_s = new wxBoxSizer(wxVERTICAL); + SetSizer(top_s); + + top_s->Add(select = new wxTreeCtrl(this, wxID_ANY), 1, wxGROW); + + wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL); + pbutton_s->AddStretchSpacer(); + pbutton_s->Add(pri_button = new wxButton(this, wxID_ANY, wxT("Change primary")), 0, wxGROW); + pri_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxeditor_esettings_hotkeys::on_primary), NULL, this); + pbutton_s->Add(sec_button = new wxButton(this, wxID_ANY, wxT("Change secondary")), 0, wxGROW); + sec_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxeditor_esettings_hotkeys::on_secondary), NULL, this); + top_s->Add(pbutton_s, 0, wxGROW); + + items[""] = select->AddRoot(wxT("")); + + refresh(); + top_s->SetSizeHints(this); + Fit(); +} + +wxeditor_esettings_hotkeys::~wxeditor_esettings_hotkeys() +{ +} + +void wxeditor_esettings_hotkeys::on_primary(wxCommandEvent& e) +{ + std::string name = selected(); + if(name == "") { + refresh(); + return; + } + try { + std::string key; + inverse_key* ik = realitems[name]; + if(!ik) { + refresh(); + return; + } + runemufn([&key, ik]() { key = ik->get(true); }); + wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true); + if(d->ShowModal() == wxID_CANCEL) { + d->Destroy(); + return; + } + key = d->getkey(); + d->Destroy(); + if(key != "") + runemufn([key, ik]() { ik->set(key, true); }); + else + runemufn([key, ik]() { ik->clear(true); }); + refresh(); + } catch(...) { + refresh(); + } +} + +void wxeditor_esettings_hotkeys::on_secondary(wxCommandEvent& e) +{ + std::string name = selected(); + if(name == "") { + refresh(); + return; + } + try { + std::string key; + inverse_key* ik = realitems[name]; + if(!ik) { + refresh(); + return; + } + runemufn([&key, ik]() { key = ik->get(false); }); + wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true); + if(d->ShowModal() == wxID_CANCEL) { + d->Destroy(); + return; + } + key = d->getkey(); + d->Destroy(); + if(key != "") + runemufn([key, ik]() { ik->set(key, false); }); + else + runemufn([key, ik]() { ik->clear(false); }); + refresh(); + } catch(...) { + refresh(); + } +} + +void wxeditor_esettings_hotkeys::refresh() +{ + std::set closure_additional; + std::map keyorder; + std::map> data; + runemufn([&data, &keyorder]() { + auto x = inverse_key::get_ikeys(); + for(auto y : x) { + keyorder[y->getname()] = y; + data[y] = std::make_pair(y->get(true), y->get(false)); + } + }); + //Close keyorder with respect to parents. + for(auto i : keyorder) { + std::string tmp = i.first; + for(size_t itr = 0; itr < tmp.length() - 2 && itr < tmp.length(); itr++) { + unsigned char ch1 = tmp[itr]; + unsigned char ch2 = tmp[itr + 1]; + unsigned char ch3 = tmp[itr + 2]; + if(ch1 == 0xE2 && ch2 == 0x80 && ch3 == 0xA3) { + closure_additional.insert(tmp.substr(0, itr)); + } + } + } + for(auto i : closure_additional) + if(!keyorder.count(i)) { + keyorder[i] = NULL; + } + //Then add the needed entries to the tree. Thanks to the ordering, presence of parent before child is always + //guaranteed. + for(auto i : keyorder) { + if(!items.count(i.first)) { + //Not found, add. + //Find the parent name. + std::string tmp = i.first; + std::string parent = ""; + std::string leaf = i.first; + for(size_t itr = 0; itr < tmp.length() - 2 && itr < tmp.length(); itr++) { + unsigned char ch1 = tmp[itr]; + unsigned char ch2 = tmp[itr + 1]; + unsigned char ch3 = tmp[itr + 2]; + if(ch1 == 0xE2 && ch2 == 0x80 && ch3 == 0xA3) { + parent = tmp.substr(0, itr); + leaf = tmp.substr(itr + 3); + } + } + items[i.first] = select->AppendItem(items[parent], towxstring(leaf)); + leafname[i.first] = leaf; + } + if(i.second) { + //Real, set the keys. + realitems[i.first] = i.second; + std::string text = leafname[i.first]; + if(data[i.second].first == "") + text = text + " (not set)"; + else if(data[i.second].second == "") + text = text + " (" + data[i.second].first + ")"; + else + text = text + " (" + data[i.second].first + " or " + data[i.second].second + ")"; + select->SetItemText(items[i.first], towxstring(text)); + } + } +} + +std::string wxeditor_esettings_hotkeys::selected() +{ + wxTreeItemId sel = select->GetSelection(); + std::string item; + bool found = false; + for(auto i : items) + if(i.second == sel) { + found = true; + item = i.first; + } + if(!found || !realitems.count(item)) + return ""; + return item; +} + +class wxeditor_esettings_bindings : public wxPanel +{ +public: + wxeditor_esettings_bindings(wxWindow* parent); + ~wxeditor_esettings_bindings(); + void on_add(wxCommandEvent& e); + void on_edit(wxCommandEvent& e); + void on_delete(wxCommandEvent& e); +private: + std::map numbers; + wxListBox* select; + void refresh(); + std::set settings; + std::map values; + std::map selections; + std::string selected(); + wxListBox* _settings; +}; + +wxeditor_esettings_bindings::wxeditor_esettings_bindings(wxWindow* parent) + : wxPanel(parent, -1) +{ + wxButton* tmp; + + wxSizer* top_s = new wxBoxSizer(wxVERTICAL); + SetSizer(top_s); + + top_s->Add(select = new wxListBox(this, wxID_ANY), 1, wxGROW); + + wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL); + pbutton_s->AddStretchSpacer(); + pbutton_s->Add(tmp = new wxButton(this, wxID_ANY, wxT("Add")), 0, wxGROW); + tmp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_esettings_bindings::on_add), NULL, + this); + pbutton_s->Add(tmp = new wxButton(this, wxID_ANY, wxT("Edit")), 0, wxGROW); + tmp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_esettings_bindings::on_edit), NULL, + this); + pbutton_s->Add(tmp = new wxButton(this, wxID_ANY, wxT("Delete")), 0, wxGROW); + tmp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxeditor_esettings_bindings::on_delete), NULL, + this); + top_s->Add(pbutton_s, 0, wxGROW); + + refresh(); + top_s->SetSizeHints(this); + Fit(); +} + +wxeditor_esettings_bindings::~wxeditor_esettings_bindings() +{ +} + +void wxeditor_esettings_bindings::on_add(wxCommandEvent& e) +{ + try { + std::string name; + wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify new key", "", false); + if(d->ShowModal() == wxID_CANCEL) { + d->Destroy(); + throw 42; + } + name = d->getkey(); + d->Destroy(); + + std::string newcommand = pick_text(this, "New binding", "Enter command for binding:", ""); + bool fault = false; + std::string faulttext; + runemufn([&fault, &faulttext, name, newcommand]() { + try { + keymapper::bind_for(name, newcommand); + } catch(std::exception& e) { + fault = true; + faulttext = e.what(); + } + }); + if(fault) + wxMessageBox(wxT("Error"), towxstring("Can't bind key: " + faulttext), wxICON_EXCLAMATION); + refresh(); + } catch(...) { + refresh(); + } +} + +void wxeditor_esettings_bindings::on_edit(wxCommandEvent& e) +{ + std::string name = selected(); + if(name == "") { + refresh(); + return; + } + try { + std::string old_command_value; + runemufn([&old_command_value, name]() { old_command_value = keymapper::get_command_for(name); }); + std::string newcommand = pick_text(this, "Edit binding", "Enter new command for binding:", + old_command_value); + bool fault = false; + std::string faulttext; + runemufn([&fault, &faulttext, name, newcommand]() { + try { + keymapper::bind_for(name, newcommand); + } catch(std::exception& e) { + fault = true; + faulttext = e.what(); + } + }); + if(fault) + wxMessageBox(wxT("Error"), towxstring("Can't bind key: " + faulttext), wxICON_EXCLAMATION); + refresh(); + } catch(...) { + refresh(); + } +} + +void wxeditor_esettings_bindings::on_delete(wxCommandEvent& e) +{ + std::string name = selected(); + if(name == "") { + refresh(); + return; + } + runemufn([name]() { try { keymapper::bind_for(name, ""); } catch(...) {} }); + refresh(); +} + +void wxeditor_esettings_bindings::refresh() +{ + int n = select->GetSelection(); + std::map bind; + std::vector choices; + runemufn([&bind]() { + std::set a = keymapper::get_bindings(); + for(auto i : a) + bind[i] = keymapper::get_command_for(i); + }); + for(auto i : bind) { + numbers[choices.size()] = i.first; + choices.push_back(towxstring(i.first + " (" + i.second + ")")); + } + select->Set(choices.size(), &choices[0]); + if(n == wxNOT_FOUND && select->GetCount()) + select->SetSelection(0); + else if(n >= select->GetCount()) + select->SetSelection(select->GetCount() ? (select->GetCount() - 1) : wxNOT_FOUND); + else + select->SetSelection(n); +} + +std::string wxeditor_esettings_bindings::selected() +{ + int x = select->GetSelection(); + if(numbers.count(x)) + return numbers[x]; + else + return ""; +} + class wxeditor_esettings_advanced : public wxPanel, information_dispatch { public: @@ -692,6 +1412,9 @@ wxeditor_esettings::wxeditor_esettings(wxWindow* parent) tabset->AddPage(new wxeditor_esettings_joystick(tabset), wxT("Joysticks")); tabset->AddPage(new wxeditor_esettings_paths(tabset), wxT("Paths")); tabset->AddPage(new wxeditor_esettings_screen(tabset), wxT("Scaling")); + tabset->AddPage(new wxeditor_esettings_hotkeys(tabset), wxT("Hotkeys")); + tabset->AddPage(new wxeditor_esettings_aliases(tabset), wxT("Aliases")); + tabset->AddPage(new wxeditor_esettings_bindings(tabset), wxT("Bindings")); tabset->AddPage(new wxeditor_esettings_advanced(tabset), wxT("Advanced")); top_s->Add(tabset, 1, wxGROW);