If initsram/initstate points to LSS file, pull the matching member
[lsnes.git] / src / platform / wxwidgets / settings-common.cpp
blob697e4dee5eeb00dd9eb05af2dbffc3e8751ff17e
1 #include "platform/wxwidgets/settings-common.hpp"
2 #include "core/instance.hpp"
3 #include "core/instance-map.hpp"
4 #include "core/keymapper.hpp"
6 namespace
8 std::map<std::string, settings_tab_factory*>& _factories()
10 static std::map<std::string, settings_tab_factory*> x;
11 return x;
14 class wxeditor_esettings2;
15 instance_map<wxeditor_esettings2> sdialogs;
19 settings_tab_factory::settings_tab_factory(const std::string& tabname,
20 std::function<settings_tab*(wxWindow* parent, emulator_instance& inst)> create_fn)
21 : _tabname(tabname), _create_fn(create_fn)
23 _factories()[_tabname] = this;
26 settings_tab_factory::~settings_tab_factory()
28 _factories().erase(_tabname);
31 std::list<settings_tab_factory*> settings_tab_factory::factories()
33 std::list<settings_tab_factory*> f;
34 for(auto i : _factories())
35 f.push_back(i.second);
36 return f;
39 settings_menu::settings_menu(wxWindow* win, emulator_instance& _inst, int id)
40 : inst(_inst)
42 CHECK_UI_THREAD;
43 parent = win;
44 items[id] = NULL;
45 Append(id, towxstring("All as tabs..."));
46 win->Connect(id++, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(settings_menu::on_selected), NULL,
47 this);
48 AppendSeparator();
49 for(auto i : settings_tab_factory::factories()) {
50 items[id] = i;
51 Append(id, towxstring(i->get_name() + "..."));
52 win->Connect(id++, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(settings_menu::on_selected),
53 NULL, this);
57 void settings_menu::on_selected(wxCommandEvent& e)
59 CHECK_UI_THREAD;
60 int id = e.GetId();
61 if(!items.count(id))
62 return;
63 display_settings_dialog(parent, inst, items[id]);
66 namespace
68 volatile bool keygrab_active = false;
69 std::string pkey;
70 std::function<void(std::string key)> keygrab_callback;
72 class keygrabber : public keyboard::event_listener
74 public:
75 keygrabber()
77 keygrab_active = false;
79 ~keygrabber() throw()
82 void on_key_event(keyboard::modifier_set& mods, keyboard::key& key, keyboard::event& event)
84 if(!keygrab_active)
85 return;
86 uint32_t dev = event.get_change_mask();
87 auto subkeys = key.get_subkeys();
88 for(unsigned i = 0; i < 16 && i < subkeys.size(); i++) {
89 std::string pname = key.get_name() + subkeys[i];
90 if(((dev >> (2 * i)) & 3) == 3)
91 pkey = pname;
92 if(((dev >> (2 * i)) & 3) == 2) {
93 if(pkey == pname) {
94 keygrab_active = false;
95 std::string tmp = pkey;
96 runuifun([this, tmp]() { this->keygrab_callback(tmp); });
97 } else
98 pkey = "";
102 volatile bool keygrab_active;
103 std::string pkey;
104 std::function<void(std::string key)> keygrab_callback;
107 class wxeditor_esettings2 : public wxDialog
109 public:
110 wxeditor_esettings2(emulator_instance& _inst, wxWindow* parent, settings_tab_factory* singletab);
111 ~wxeditor_esettings2();
112 bool ShouldPreventAppExit() const;
113 void on_close(wxCommandEvent& e);
114 void on_notify();
115 private:
116 emulator_instance& inst;
117 wxNotebook* tabset;
118 wxButton* closebutton;
119 std::list<settings_tab*> tabs;
120 std::string get_title(settings_tab_factory* singletab);
121 public:
122 keygrabber keygrab;
125 std::string wxeditor_esettings2::get_title(settings_tab_factory* singletab)
127 if(!singletab)
128 return "lsnes: Configuration";
129 else
130 return "lsnes: Configuration: " + singletab->get_name();
133 wxeditor_esettings2::wxeditor_esettings2(emulator_instance& _inst, wxWindow* parent,
134 settings_tab_factory* singletab)
135 : wxDialog(parent, wxID_ANY, towxstring(get_title(singletab)), wxDefaultPosition, wxSize(-1, -1),
136 wxCAPTION | wxSYSTEM_MENU | wxCLOSE_BOX | wxRESIZE_BORDER), inst(_inst)
138 CHECK_UI_THREAD;
139 //Grab keys to prevent the joystick driver from running who knows what commands.
140 inst.keyboard->set_exclusive(&keygrab);
142 Centre();
143 wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
144 SetSizer(top_s);
146 if(singletab) {
147 //If this throws, let it throw through.
148 settings_tab* t = singletab->create(this, inst);
149 top_s->Add(t, 1, wxGROW);
150 t->set_notify([this]() { this->on_notify(); });
151 tabs.push_back(t);
152 } else {
153 int created = 0;
154 tabset = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP);
155 for(auto i : settings_tab_factory::factories()) {
156 settings_tab* t;
157 try {
158 t = i->create(tabset, inst);
159 } catch(...) {
160 continue;
162 tabset->AddPage(t, towxstring(i->get_name()));
163 t->set_notify([this]() { this->on_notify(); });
164 tabs.push_back(t);
165 created++;
167 top_s->Add(tabset, 1, wxGROW);
168 if(!created)
169 throw std::runtime_error("Nothing to configure here, move along");
172 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
173 pbutton_s->AddStretchSpacer();
174 pbutton_s->Add(closebutton = new wxButton(this, wxID_ANY, wxT("Close")), 0, wxGROW);
175 closebutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
176 wxCommandEventHandler(wxeditor_esettings2::on_close), NULL, this);
177 top_s->Add(pbutton_s, 0, wxGROW);
179 top_s->SetSizeHints(this);
180 Fit();
183 wxeditor_esettings2::~wxeditor_esettings2()
185 CHECK_UI_THREAD;
186 for(auto i : tabs)
187 i->notify_close();
188 inst.keyboard->set_exclusive(NULL);
189 sdialogs.remove(inst);
192 bool wxeditor_esettings2::ShouldPreventAppExit() const
194 return false;
197 void wxeditor_esettings2::on_close(wxCommandEvent& e)
199 CHECK_UI_THREAD;
200 for(auto i : tabs)
201 i->on_close();
202 EndModal(wxID_OK);
205 void wxeditor_esettings2::on_notify()
207 CHECK_UI_THREAD;
208 for(auto i : tabs)
209 i->on_notify();
213 void display_settings_dialog(wxWindow* parent, emulator_instance& inst, settings_tab_factory* singletab)
215 CHECK_UI_THREAD;
216 modal_pause_holder hld;
217 wxDialog* editor;
218 try {
219 try {
220 editor = sdialogs.create(inst, parent, singletab);
221 } catch(std::exception& e) {
222 std::string title = "Configure";
223 if(singletab)
224 title = "Configure " + singletab->get_name();
225 show_message_ok(parent, title, e.what(), wxICON_EXCLAMATION);
226 return;
228 editor->ShowModal();
229 } catch(...) {
230 return;
232 editor->Destroy();
233 do_save_configuration();
236 void settings_activate_keygrab(emulator_instance& inst, std::function<void(std::string key)> callback)
238 auto s = sdialogs.lookup(inst);
239 if(!s) return;
240 s->keygrab.keygrab_callback = callback;
241 s->keygrab.keygrab_active = true;
244 void settings_deactivate_keygrab(emulator_instance& inst)
246 auto s = sdialogs.lookup(inst);
247 if(!s) return;
248 s->keygrab.keygrab_active = false;