Fix zero luma corner case
[lsnes.git] / src / plat-wxwidgets / axeseditor.cpp
blob4aea69d4f26708d7ab736bfff5770ab224625255
1 #include "core/keymapper.hpp"
3 #include "plat-wxwidgets/axeseditor.hpp"
4 #include "plat-wxwidgets/common.hpp"
6 #include <boost/lexical_cast.hpp>
7 #include <sstream>
9 #define AMODE_DISABLED "Disabled"
10 #define AMODE_AXIS_PAIR "Axis"
11 #define AMODE_AXIS_PAIR_INVERSE "Axis (inverted)"
12 #define AMODE_PRESSURE_M0 "Pressure - to 0"
13 #define AMODE_PRESSURE_MP "Pressure - to +"
14 #define AMODE_PRESSURE_0M "Pressure 0 to -"
15 #define AMODE_PRESSURE_0P "Pressure 0 to +"
16 #define AMODE_PRESSURE_PM "Pressure + to -"
17 #define AMODE_PRESSURE_P0 "Pressure + to 0"
19 wx_axes_editor_axis::wx_axes_editor_axis(wxSizer* sizer, wxWindow* window, const std::string& name)
21 wxString choices[9];
22 choices[0] = wxT(AMODE_DISABLED);
23 choices[1] = wxT(AMODE_AXIS_PAIR);
24 choices[2] = wxT(AMODE_AXIS_PAIR_INVERSE);
25 choices[3] = wxT(AMODE_PRESSURE_M0);
26 choices[4] = wxT(AMODE_PRESSURE_MP);
27 choices[5] = wxT(AMODE_PRESSURE_0M);
28 choices[6] = wxT(AMODE_PRESSURE_0P);
29 choices[7] = wxT(AMODE_PRESSURE_PM);
30 choices[8] = wxT(AMODE_PRESSURE_P0);
31 size_t defaultidx = 0;
32 std::string low;
33 std::string mid;
34 std::string high;
35 std::string tolerance;
36 keygroup* k = keygroup::lookup_by_name(name);
37 if(!k)
38 return;
39 struct keygroup::parameters p = k->get_parameters();
41 switch(p.ktype) {
42 case keygroup::KT_DISABLED: defaultidx = 0; break;
43 case keygroup::KT_AXIS_PAIR: defaultidx = 1; break;
44 case keygroup::KT_AXIS_PAIR_INVERSE: defaultidx = 2; break;
45 case keygroup::KT_PRESSURE_M0: defaultidx = 3; break;
46 case keygroup::KT_PRESSURE_MP: defaultidx = 4; break;
47 case keygroup::KT_PRESSURE_0M: defaultidx = 5; break;
48 case keygroup::KT_PRESSURE_0P: defaultidx = 6; break;
49 case keygroup::KT_PRESSURE_PM: defaultidx = 7; break;
50 case keygroup::KT_PRESSURE_P0: defaultidx = 8; break;
52 std::ostringstream x1;
53 std::ostringstream x2;
54 std::ostringstream x3;
55 std::ostringstream x4;
56 x1 << p.cal_left;
57 x2 << p.cal_center;
58 x3 << p.cal_right;
59 x4 << p.cal_tolerance;
60 low = x1.str();
61 mid = x2.str();
62 high = x3.str();
63 tolerance = x4.str();
66 a_name = name;
67 sizer->Add(new wxStaticText(window, wxID_ANY, towxstring(name)), 0, wxGROW);
68 sizer->Add(a_type = new wxComboBox(window, wxID_ANY, choices[defaultidx], wxDefaultPosition, wxDefaultSize,
69 9, choices, wxCB_READONLY), 0, wxGROW);
70 sizer->Add(a_low = new wxTextCtrl(window, wxID_ANY, towxstring(low)), 0, wxGROW);
71 sizer->Add(a_mid = new wxTextCtrl(window, wxID_ANY, towxstring(mid)), 0, wxGROW);
72 sizer->Add(a_high = new wxTextCtrl(window, wxID_ANY, towxstring(high)), 0, wxGROW);
73 sizer->Add(a_tolerance = new wxTextCtrl(window, wxID_ANY, towxstring(tolerance)), 0, wxGROW);
74 a_low->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
75 window);
76 a_mid->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
77 window);
78 a_high->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
79 window);
80 a_tolerance->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(wx_axes_editor::on_value_change), NULL,
81 window);
84 bool wx_axes_editor_axis::is_ok()
86 int32_t low, mid, high;
87 double tolerance;
89 try {
90 low = boost::lexical_cast<int32_t>(tostdstring(a_low->GetValue()));
91 mid = boost::lexical_cast<int32_t>(tostdstring(a_mid->GetValue()));
92 high = boost::lexical_cast<int32_t>(tostdstring(a_high->GetValue()));
93 tolerance = boost::lexical_cast<double>(tostdstring(a_tolerance->GetValue()));
94 } catch(...) {
95 return false;
98 if(low < -32768 || low > 32767 || low > mid)
99 return false;
100 if(mid < -32768 || mid > 32767 || mid > high)
101 return false;
102 if(high < -32768 || high > 32767)
103 return false;
104 if(tolerance <= 0 || tolerance >= 1)
105 return false;
106 return true;
109 void wx_axes_editor_axis::apply()
111 keygroup* k = keygroup::lookup_by_name(a_name);
112 if(!k)
113 return;
115 int32_t low, mid, high;
116 double tolerance;
117 enum keygroup::type ntype;
118 enum keygroup::type ctype = k->get_parameters().ktype;;
120 std::string amode = tostdstring(a_type->GetValue());
121 if(amode == AMODE_AXIS_PAIR)
122 ntype = keygroup::KT_AXIS_PAIR;
123 if(amode == AMODE_AXIS_PAIR_INVERSE)
124 ntype = keygroup::KT_AXIS_PAIR_INVERSE;
125 if(amode == AMODE_DISABLED)
126 ntype = keygroup::KT_DISABLED;
127 if(amode == AMODE_PRESSURE_0M)
128 ntype = keygroup::KT_PRESSURE_0M;
129 if(amode == AMODE_PRESSURE_0P)
130 ntype = keygroup::KT_PRESSURE_0P;
131 if(amode == AMODE_PRESSURE_M0)
132 ntype = keygroup::KT_PRESSURE_M0;
133 if(amode == AMODE_PRESSURE_MP)
134 ntype = keygroup::KT_PRESSURE_MP;
135 if(amode == AMODE_PRESSURE_PM)
136 ntype = keygroup::KT_PRESSURE_PM;
137 if(amode == AMODE_PRESSURE_P0)
138 ntype = keygroup::KT_PRESSURE_P0;
139 try {
140 low = boost::lexical_cast<int32_t>(tostdstring(a_low->GetValue()));
141 mid = boost::lexical_cast<int32_t>(tostdstring(a_mid->GetValue()));
142 high = boost::lexical_cast<int32_t>(tostdstring(a_high->GetValue()));
143 tolerance = boost::lexical_cast<double>(tostdstring(a_tolerance->GetValue()));
144 } catch(...) {
145 return;
147 if(low < -32768 || low > 32767 || low > mid)
148 return;
149 if(mid < -32768 || mid > 32767 || mid > high)
150 return;
151 if(high < -32768 || high > 32767)
152 return;
153 if(tolerance <= 0 || tolerance >= 1)
154 return;
155 if(ctype != ntype)
156 k->change_type(ntype);
157 k->change_calibration(low, mid, high, tolerance);
160 wx_axes_editor::wx_axes_editor(wxWindow* parent)
161 : wxDialog(parent, wxID_ANY, wxT("lsnes: Edit axes"), wxDefaultPosition, wxSize(-1, -1))
163 std::set<std::string> axisnames = keygroup::get_axis_set();
165 Centre();
166 wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0);
167 SetSizer(top_s);
169 wxFlexGridSizer* t_s = new wxFlexGridSizer(axisnames.size() + 1, 6, 0, 0);
170 t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Name")), 0, wxGROW);
171 t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Type")), 0, wxGROW);
172 t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Low")), 0, wxGROW);
173 t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Mid")), 0, wxGROW);
174 t_s->Add(new wxStaticText(this, wxID_ANY, wxT("High")), 0, wxGROW);
175 t_s->Add(new wxStaticText(this, wxID_ANY, wxT("Tolerance")), 0, wxGROW);
176 for(auto i : axisnames)
177 axes.push_back(new wx_axes_editor_axis(t_s, this, i));
178 top_s->Add(t_s);
180 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
181 pbutton_s->AddStretchSpacer();
182 pbutton_s->Add(okbutton = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
183 pbutton_s->Add(cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel")), 0, wxGROW);
184 okbutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
185 wxCommandEventHandler(wx_axes_editor::on_ok), NULL, this);
186 cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
187 wxCommandEventHandler(wx_axes_editor::on_cancel), NULL, this);
188 top_s->Add(pbutton_s, 0, wxGROW);
190 t_s->SetSizeHints(this);
191 top_s->SetSizeHints(this);
192 Fit();
195 wx_axes_editor::~wx_axes_editor()
197 for(auto i : axes)
198 delete i;
201 bool wx_axes_editor::ShouldPreventAppExit() const
203 return false;
206 void wx_axes_editor::on_value_change(wxCommandEvent& e)
208 bool all_ok = true;
209 for(auto i : axes)
210 all_ok = all_ok && i->is_ok();
211 okbutton->Enable(all_ok);
214 void wx_axes_editor::on_cancel(wxCommandEvent& e)
216 EndModal(wxID_CANCEL);
219 void wx_axes_editor::on_ok(wxCommandEvent& e)
221 for(auto i : axes)
222 i->apply();
223 EndModal(wxID_OK);