Make various instance stuff to take references to other instance objs
[lsnes.git] / src / platform / wxwidgets / settings-advanced.cpp
blobd1d58674a627dec95f65917a2ebaa70c35240cd2
1 #include "platform/wxwidgets/settings-common.hpp"
2 #include "core/instance.hpp"
3 #include "core/settings.hpp"
5 namespace
7 enum
9 wxID_CHANGE = wxID_HIGHEST + 1
12 class wxeditor_esettings_advanced : public settings_tab
14 public:
15 wxeditor_esettings_advanced(wxWindow* parent);
16 ~wxeditor_esettings_advanced();
17 void on_change(wxCommandEvent& e);
18 void on_change2(wxMouseEvent& e);
19 void on_selchange(wxCommandEvent& e);
20 void on_setting_change(const settingvar::base& val);
21 void on_mouse(wxMouseEvent& e);
22 void on_popup_menu(wxCommandEvent& e);
23 void _refresh();
24 struct listener : public settingvar::listener
26 listener(settingvar::group& group, wxeditor_esettings_advanced& _obj)
27 : obj(_obj), grp(group)
29 group.add_listener(*this);
31 ~listener() throw()
33 grp.remove_listener(*this);
35 void on_setting_change(settingvar::group& grp, const settingvar::base& val)
37 obj.on_setting_change(val);
39 wxeditor_esettings_advanced& obj;
40 settingvar::group& grp;
42 private:
43 listener _listener;
44 void refresh();
45 std::set<std::string> settings;
46 std::map<std::string, std::string> values;
47 std::map<std::string, std::string> names;
48 std::map<int, std::string> selections;
49 std::string selected();
50 wxButton* changebutton;
51 wxListBox* _settings;
54 wxeditor_esettings_advanced::wxeditor_esettings_advanced(wxWindow* parent)
55 : settings_tab(parent), _listener(lsnes_instance.settings, *this)
57 wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
58 SetSizer(top_s);
60 top_s->Add(_settings = new wxListBox(this, wxID_ANY), 1, wxGROW);
61 _settings->SetMinSize(wxSize(300, 400));
62 _settings->Connect(wxEVT_COMMAND_LISTBOX_SELECTED,
63 wxCommandEventHandler(wxeditor_esettings_advanced::on_selchange), NULL, this);
64 _settings->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(wxeditor_esettings_advanced::on_mouse), NULL,
65 this);
66 _settings->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxeditor_esettings_advanced::on_mouse), NULL,
67 this);
69 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
70 pbutton_s->AddStretchSpacer();
71 pbutton_s->Add(changebutton = new wxButton(this, wxID_ANY, wxT("Change")), 0, wxGROW);
72 _settings->Connect(wxEVT_LEFT_DCLICK,
73 wxMouseEventHandler(wxeditor_esettings_advanced::on_change2), NULL, this);
74 changebutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
75 wxCommandEventHandler(wxeditor_esettings_advanced::on_change), NULL, this);
76 top_s->Add(pbutton_s, 0, wxGROW);
78 refresh();
79 wxCommandEvent e;
80 on_selchange(e);
81 top_s->SetSizeHints(this);
82 Fit();
85 wxeditor_esettings_advanced::~wxeditor_esettings_advanced()
89 std::string change_value_of_boolean(const std::string& name, const settingvar::description& desc,
90 const std::string& current)
92 return string_to_bool(current) ? "0" : "1";
95 std::string change_value_of_enumeration(wxWindow* parent, const std::string& name,
96 const settingvar::description& desc, const std::string& current)
98 std::vector<std::string> valset;
99 unsigned dflt = 0;
100 for(unsigned i = 0; i <= desc._enumeration->max_val(); i++) {
101 valset.push_back(desc._enumeration->get(i));
102 if(desc._enumeration->get(i) == current)
103 dflt = i;
105 return pick_among(parent, "Set value to", "Set " + name + " to value:", valset, dflt);
108 std::string change_value_of_string(wxWindow* parent, const std::string& name,
109 const settingvar::description& desc, const std::string& current)
111 return pick_text(parent, "Set value to", "Set " + name + " to value:", current);
114 class numeric_inputbox : public wxDialog
116 public:
117 numeric_inputbox(wxWindow* parent, const std::string& name, int64_t minval, int64_t maxval,
118 const std::string& val)
119 : wxDialog(parent, wxID_ANY, wxT("Set value to"))
121 wxSizer* s1 = new wxBoxSizer(wxVERTICAL);
122 SetSizer(s1);
123 s1->Add(new wxStaticText(this, wxID_ANY, towxstring("Set " + name + " to value:")), 0,
124 wxGROW);
126 s1->Add(sp = new wxSpinCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize,
127 wxSP_ARROW_KEYS, minval, maxval, parse_value<int64_t>(val)), 1, wxGROW);
129 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
130 pbutton_s->AddStretchSpacer();
131 wxButton* t;
132 pbutton_s->Add(t = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
133 t->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
134 wxCommandEventHandler(numeric_inputbox::on_button), NULL, this);
135 pbutton_s->Add(t = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
136 t->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
137 wxCommandEventHandler(numeric_inputbox::on_button), NULL, this);
138 s1->Add(pbutton_s, 0, wxGROW);
140 s1->SetSizeHints(this);
142 std::string get_value() { return (stringfmt() << sp->GetValue()).str(); }
143 void on_button(wxCommandEvent& e) { EndModal(e.GetId()); }
144 private:
145 wxSpinCtrl* sp;
148 class path_inputbox : public wxDialog
150 public:
151 path_inputbox(wxWindow* parent, const std::string& name, const std::string& val)
152 : wxDialog(parent, wxID_ANY, wxT("Set path to"))
154 wxButton* t;
155 wxSizer* s1 = new wxBoxSizer(wxVERTICAL);
156 SetSizer(s1);
157 s1->Add(new wxStaticText(this, wxID_ANY, towxstring("Set " + name + " to value:")), 0,
158 wxGROW);
159 wxSizer* s2 = new wxBoxSizer(wxHORIZONTAL);
160 s2->Add(pth = new wxTextCtrl(this, wxID_ANY, towxstring(val), wxDefaultPosition,
161 wxSize(400, -1)), 1, wxGROW);
162 s2->Add(t = new wxButton(this, wxID_HIGHEST + 1, wxT("...")), 0, wxGROW);
163 t->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
164 wxCommandEventHandler(path_inputbox::on_pbutton), NULL, this);
165 s1->Add(s2, 1, wxGROW);
167 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
168 pbutton_s->AddStretchSpacer();
169 pbutton_s->Add(t = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
170 t->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
171 wxCommandEventHandler(path_inputbox::on_button), NULL, this);
172 pbutton_s->Add(t = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
173 t->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
174 wxCommandEventHandler(path_inputbox::on_button), NULL, this);
175 s1->Add(pbutton_s, 0, wxGROW);
177 s1->SetSizeHints(this);
179 std::string get_value() { return tostdstring(pth->GetValue()); }
180 void on_pbutton(wxCommandEvent& e) {
181 wxDirDialog* d;
182 d = new wxDirDialog(this, wxT("Select project directory"),
183 pth->GetValue(), wxDD_DIR_MUST_EXIST);
184 if(d->ShowModal() == wxID_CANCEL) {
185 d->Destroy();
186 return;
188 pth->SetValue(d->GetPath());
189 d->Destroy();
191 void on_button(wxCommandEvent& e) {
192 switch(e.GetId()) {
193 case wxID_OK:
194 case wxID_CANCEL:
195 EndModal(e.GetId());
196 break;
199 private:
200 wxTextCtrl* pth;
203 std::string change_value_of_numeric(wxWindow* parent, const std::string& name,
204 const settingvar::description& desc, const std::string& current)
206 auto d = new numeric_inputbox(parent, name, desc.min_val, desc.max_val, current);
207 int x = d->ShowModal();
208 if(x == wxID_CANCEL) {
209 d->Destroy();
210 throw canceled_exception();
212 std::string v = d->get_value();
213 d->Destroy();
214 return v;
217 std::string change_value_of_path(wxWindow* parent, const std::string& name,
218 const settingvar::description& desc, const std::string& current)
220 auto d = new path_inputbox(parent, name, current);
221 int x = d->ShowModal();
222 if(x == wxID_CANCEL) {
223 d->Destroy();
224 throw canceled_exception();
226 std::string v = d->get_value();
227 d->Destroy();
228 return v;
231 void wxeditor_esettings_advanced::on_popup_menu(wxCommandEvent& e)
233 if(closing())
234 return;
235 if(e.GetId() == wxID_EDIT)
236 on_change(e);
239 void wxeditor_esettings_advanced::on_mouse(wxMouseEvent& e)
241 if(!e.RightUp() && !(e.LeftUp() && e.ControlDown()))
242 return;
243 if(selected() == "")
244 return;
245 wxMenu menu;
246 menu.Connect(wxEVT_COMMAND_MENU_SELECTED,
247 wxCommandEventHandler(wxeditor_esettings_advanced::on_popup_menu), NULL, this);
248 menu.Append(wxID_EDIT, towxstring("Change"));
249 PopupMenu(&menu);
252 void wxeditor_esettings_advanced::on_change2(wxMouseEvent& e)
254 wxCommandEvent e2;
255 on_change(e2);
258 void wxeditor_esettings_advanced::on_change(wxCommandEvent& e)
260 if(closing())
261 return;
262 std::string name = selected();
263 if(name == "")
264 return;
265 std::string value;
266 std::string err;
267 value = lsnes_instance.setcache.get(name);
268 auto model = lsnes_instance.setcache.get_description(name);
269 try {
270 switch(model.type) {
271 case settingvar::description::T_BOOLEAN:
272 value = change_value_of_boolean(name, model, value); break;
273 case settingvar::description::T_NUMERIC:
274 value = change_value_of_numeric(this, name, model, value); break;
275 case settingvar::description::T_STRING:
276 value = change_value_of_string(this, name, model, value); break;
277 case settingvar::description::T_PATH:
278 value = change_value_of_path(this, name, model, value); break;
279 case settingvar::description::T_ENUMERATION:
280 value = change_value_of_enumeration(this, name, model, value); break;
281 default:
282 value = change_value_of_string(this, name, model, value); break;
284 } catch(...) {
285 return;
287 lsnes_instance.iqueue.run([this, name, value]() {
288 run_show_error(this, "Error setting value", "", [name, value]() {
289 lsnes_instance.setcache.set(name, value);
294 void wxeditor_esettings_advanced::on_selchange(wxCommandEvent& e)
296 if(closing())
297 return;
298 std::string sel = selected();
299 bool enable = (sel != "");
300 changebutton->Enable(enable);
303 void wxeditor_esettings_advanced::on_setting_change(const settingvar::base& val)
305 if(closing())
306 return;
307 runuifun([this, &val]() {
308 std::string setting = val.get_iname();
309 std::string value = val.str();
310 this->settings.insert(setting);
311 this->values[setting] = value;
312 this->_refresh();
316 void wxeditor_esettings_advanced::refresh()
318 if(closing())
319 return;
320 settings = lsnes_instance.setcache.get_keys();
321 for(auto i : settings) {
322 values[i] = lsnes_instance.setcache.get(i);
323 names[i] = lsnes_instance.setcache.get_hname(i);
325 _refresh();
328 std::string wxeditor_esettings_advanced::selected()
330 if(closing())
331 return "";
332 int x = _settings->GetSelection();
333 if(selections.count(x))
334 return selections[x];
335 else
336 return "";
339 void wxeditor_esettings_advanced::_refresh()
341 if(closing())
342 return;
343 std::vector<wxString> strings;
344 std::multimap<std::string, std::string> sort;
345 int k = 0;
346 for(auto i : settings)
347 sort.insert(std::make_pair(names[i], i));
348 for(auto i : sort) {
349 //FIXME: Do something with this?
350 //auto description = lsnes_instance.setcache.get_description(i.second);
351 strings.push_back(towxstring(names[i.second] + " (Value: " + values[i.second] + ")"));
352 selections[k++] = i.second;
354 _settings->Set(strings.size(), &strings[0]);
357 settings_tab_factory advanced_tab("Advanced", [](wxWindow* parent) -> settings_tab* {
358 return new wxeditor_esettings_advanced(parent);