Force some configuration windows to be larger
[lsnes.git] / src / platform / wxwidgets / settings-controllers.cpp
blobf0ea807500e117ab8096b072935d93dacb4af8c4
1 #include "platform/wxwidgets/settings-common.hpp"
2 #include "platform/wxwidgets/settings-keyentry.hpp"
3 #include "core/keymapper.hpp"
4 #include "library/string.hpp"
6 namespace
8 enum
10 wxID_ADDKEY = wxID_HIGHEST + 1,
11 wxID_DROPKEY
14 class wxeditor_esettings_controllers : public settings_tab
16 public:
17 wxeditor_esettings_controllers(wxWindow* parent);
18 ~wxeditor_esettings_controllers();
19 void on_setkey(wxCommandEvent& e);
20 void on_clearkey(wxCommandEvent& e);
21 void on_change(wxCommandEvent& e);
22 void on_mouse(wxMouseEvent& e);
23 void on_popup_menu(wxCommandEvent& e);
24 private:
25 wxTreeCtrl* controls;
26 std::map<string_list<char>, wxTreeItemId> items;
27 std::map<string_list<char>, std::string> names;
28 std::map<string_list<char>, keyboard::ctrlrkey*> realitems;
29 wxButton* set_button;
30 wxButton* clear_button;
31 void refresh();
32 string_list<char> get_selection();
33 wxTreeItemId get_item(const string_list<char>& i);
36 wxeditor_esettings_controllers::wxeditor_esettings_controllers(wxWindow* parent)
37 : settings_tab(parent)
39 wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
40 SetSizer(top_s);
41 wxString empty[1];
43 top_s->Add(controls = new wxTreeCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
44 wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT), 1, wxGROW);
45 controls->SetMinSize(wxSize(300, 400));
46 controls->Connect(wxEVT_COMMAND_TREE_SEL_CHANGED,
47 wxCommandEventHandler(wxeditor_esettings_controllers::on_change), NULL, this);
48 controls->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(wxeditor_esettings_controllers::on_mouse), NULL,
49 this);
50 controls->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxeditor_esettings_controllers::on_mouse), NULL,
51 this);
52 controls->SetMinSize(wxSize(400, 300));
54 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
55 pbutton_s->AddStretchSpacer();
56 pbutton_s->Add(set_button = new wxButton(this, wxID_ANY, wxT("Add")), 0, wxGROW);
57 set_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
58 wxCommandEventHandler(wxeditor_esettings_controllers::on_setkey), NULL, this);
59 set_button->Enable(false);
60 pbutton_s->Add(clear_button = new wxButton(this, wxID_ANY, wxT("Drop")), 0, wxGROW);
61 clear_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
62 wxCommandEventHandler(wxeditor_esettings_controllers::on_clearkey), NULL, this);
63 clear_button->Enable(false);
64 top_s->Add(pbutton_s, 0, wxGROW);
66 items[string_list<char>()] = controls->AddRoot(wxT(""));
68 refresh();
69 top_s->SetSizeHints(this);
70 Fit();
73 wxTreeItemId wxeditor_esettings_controllers::get_item(const string_list<char>& i)
75 if(i.size() == 1)
76 return items[string_list<char>()];
77 if(items.count(i) && items[i].IsOk())
78 return items[i];
79 return items[i] = controls->AppendItem(get_item(i.strip_one()), towxstring(i[i.size() - 1]));
82 string_list<char> wxeditor_esettings_controllers::get_selection()
84 if(closing())
85 return string_list<char>();
86 string_list<char> sel;
87 wxTreeItemId id = controls->GetSelection();
88 for(auto i : items)
89 if(i.second == id)
90 sel = i.first;
91 return sel;
94 void wxeditor_esettings_controllers::on_change(wxCommandEvent& e)
96 if(closing())
97 return;
98 string_list<char> sel = get_selection();
99 set_button->Enable(realitems.count(sel));
100 clear_button->Enable(realitems.count(sel));
103 wxeditor_esettings_controllers::~wxeditor_esettings_controllers()
107 void wxeditor_esettings_controllers::on_setkey(wxCommandEvent& e)
109 if(closing())
110 return;
111 string_list<char> sel = get_selection();
112 std::string name = names.count(sel) ? names[sel] : "";
113 if(name == "") {
114 refresh();
115 return;
117 try {
118 keyboard::ctrlrkey* ik = realitems[sel];
119 if(!ik) {
120 refresh();
121 return;
123 bool axis = ik->is_axis();
124 std::string wtitle = (axis ? "Specify axis for " : "Specify key for ") + name;
125 press_button_dialog* p = new press_button_dialog(this, wtitle, axis);
126 p->ShowModal();
127 std::string key = p->getkey();
128 p->Destroy();
129 if(key != "")
130 ik->append(key);
131 } catch(...) {
133 refresh();
136 void wxeditor_esettings_controllers::on_clearkey(wxCommandEvent& e)
138 if(closing())
139 return;
140 string_list<char> sel = get_selection();
141 std::string name = names.count(sel) ? names[sel] : "";
142 if(name == "") {
143 refresh();
144 return;
146 try {
147 keyboard::ctrlrkey* ik = realitems[sel];
148 if(!ik) {
149 refresh();
150 return;
152 std::vector<wxString> dropchoices;
153 std::string tmp;
154 unsigned idx = 0;
155 while((tmp = ik->get_string(idx++)) != "")
156 dropchoices.push_back(towxstring(tmp));
157 idx = 0;
158 if(dropchoices.size() == 0) {
159 refresh();
160 return;
162 if(dropchoices.size() > 1) {
163 wxSingleChoiceDialog* d2 = new wxSingleChoiceDialog(this,
164 towxstring("Select key to remove from set"), towxstring("Pick key to drop"),
165 dropchoices.size(), &dropchoices[0]);
166 if(d2->ShowModal() == wxID_CANCEL) {
167 d2->Destroy();
168 refresh();
169 return;
171 idx = d2->GetSelection();
172 d2->Destroy();
174 auto g = ik->get(idx);
175 ik->remove(g.first, g.second);
176 } catch(...) {
178 refresh();
181 void wxeditor_esettings_controllers::on_popup_menu(wxCommandEvent& e)
183 if(closing())
184 return;
185 if(e.GetId() == wxID_ADDKEY)
186 on_setkey(e);
187 else if(e.GetId() >= wxID_DROPKEY) {
188 string_list<char> sel = get_selection();
189 if(!realitems.count(sel))
190 return;
191 keyboard::ctrlrkey* ik = realitems[sel];
192 if(!ik)
193 return;
194 auto g = ik->get(e.GetId() - wxID_DROPKEY);
195 ik->remove(g.first, g.second);
197 refresh();
200 void wxeditor_esettings_controllers::on_mouse(wxMouseEvent& e)
202 if(!e.RightUp() && !(e.LeftUp() && e.ControlDown()))
203 return;
204 string_list<char> sel = get_selection();
205 if(!realitems.count(sel))
206 return;
207 keyboard::ctrlrkey* ik = realitems[sel];
208 if(!ik)
209 return;
211 wxMenu menu;
212 menu.Connect(wxEVT_COMMAND_MENU_SELECTED,
213 wxCommandEventHandler(wxeditor_esettings_controllers::on_popup_menu), NULL, this);
214 menu.Append(wxID_ADDKEY, towxstring("Add new key"));
215 bool first = true;
216 unsigned idx = 0;
217 std::string tmp;
218 while((tmp = ik->get_string(idx++)) != "") {
219 if(first)
220 menu.AppendSeparator();
221 first = false;
222 menu.Append(wxID_DROPKEY + idx - 1, towxstring("Drop " + tmp));
224 PopupMenu(&menu);
227 void wxeditor_esettings_controllers::refresh()
229 if(closing())
230 return;
231 std::map<keyboard::ctrlrkey*, std::string> data;
232 auto x = lsnes_mapper.get_controller_keys();
233 realitems.clear();
234 for(auto y : x) {
235 string_list<char> key = split_on_codepoint(y->get_name(), U'\u2023');
236 names[key] = y->get_name();
237 realitems[key] = y;
238 std::string tmp;
239 unsigned idx = 0;
240 while((tmp = y->get_string(idx++)) != "")
241 data[y] += ((data[y] != "") ? ", " : "") + tmp;
244 //Delete no longer present stuff.
245 for(auto i = items.rbegin(); i != items.rend(); i++) {
246 auto j = realitems.lower_bound(i->first);
247 if(j == realitems.end() || !i->first.prefix_of(j->first)) {
248 //Delete this item.
249 if(i->second.IsOk())
250 controls->Delete(i->second);
251 items[i->first] = wxTreeItemId();
254 for(auto i : realitems) {
255 string_list<char> key = i.first;
256 std::string text = key[key.size() - 1];
257 if(data[i.second] == "")
258 text = text + " (not set)";
259 else
260 text = text + " (" + clean_keystring(data[i.second]) + ")";
261 wxTreeItemId id = get_item(key);
262 controls->SetItemText(id, towxstring(text));
265 wxCommandEvent e;
266 on_change(e);
269 settings_tab_factory controllers("Controllers", [](wxWindow* parent) -> settings_tab* {
270 return new wxeditor_esettings_controllers(parent);