Force some configuration windows to be larger
[lsnes.git] / src / platform / wxwidgets / settings-common.cpp
blob2db45027743c008ba82bb6582360a29995b13b4f
1 #include "platform/wxwidgets/settings-common.hpp"
2 #include "core/keymapper.hpp"
4 namespace
6 std::map<std::string, settings_tab_factory*>& _factories()
8 static std::map<std::string, settings_tab_factory*> x;
9 return x;
11 class wxeditor_esettings2* dlg;
15 settings_tab_factory::settings_tab_factory(const std::string& tabname,
16 std::function<settings_tab*(wxWindow* parent)> create_fn)
17 : _tabname(tabname), _create_fn(create_fn)
19 _factories()[_tabname] = this;
22 settings_tab_factory::~settings_tab_factory()
24 _factories().erase(_tabname);
27 std::list<settings_tab_factory*> settings_tab_factory::factories()
29 std::list<settings_tab_factory*> f;
30 for(auto i : _factories())
31 f.push_back(i.second);
32 return f;
35 settings_menu::settings_menu(wxWindow* win, int id)
37 parent = win;
38 wxMenuItem* n;
39 items[id] = NULL;
40 n = Append(id, towxstring("All as tabs..."));
41 win->Connect(id++, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(settings_menu::on_selected), NULL,
42 this);
43 AppendSeparator();
44 for(auto i : settings_tab_factory::factories()) {
45 items[id] = i;
46 n = Append(id, towxstring(i->get_name() + "..."));
47 win->Connect(id++, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(settings_menu::on_selected),
48 NULL, this);
52 void settings_menu::on_selected(wxCommandEvent& e)
54 int id = e.GetId();
55 if(!items.count(id))
56 return;
57 display_settings_dialog(parent, items[id]);
60 namespace
62 volatile bool keygrab_active = false;
63 std::string pkey;
64 std::function<void(std::string key)> keygrab_callback;
66 class keygrabber : public keyboard::event_listener
68 public:
69 keygrabber() { keygrab_active = false; }
70 void on_key_event(keyboard::modifier_set& mods, keyboard::key& key, keyboard::event& event)
72 if(!keygrab_active)
73 return;
74 uint32_t dev = event.get_change_mask();
75 auto subkeys = key.get_subkeys();
76 for(unsigned i = 0; i < 16 && i < subkeys.size(); i++) {
77 std::string pname = key.get_name() + subkeys[i];
78 if(((dev >> (2 * i)) & 3) == 3)
79 pkey = pname;
80 if(((dev >> (2 * i)) & 3) == 2) {
81 if(pkey == pname) {
82 keygrab_active = false;
83 std::string tmp = pkey;
84 runuifun([tmp]() { keygrab_callback(tmp); });
85 } else
86 pkey = "";
90 } keygrabber;
92 class wxeditor_esettings2 : public wxDialog
94 public:
95 wxeditor_esettings2(wxWindow* parent, settings_tab_factory* singletab);
96 ~wxeditor_esettings2();
97 bool ShouldPreventAppExit() const;
98 void on_close(wxCommandEvent& e);
99 void on_notify();
100 private:
101 wxNotebook* tabset;
102 wxButton* closebutton;
103 std::list<settings_tab*> tabs;
104 std::string get_title(settings_tab_factory* singletab);
107 std::string wxeditor_esettings2::get_title(settings_tab_factory* singletab)
109 if(!singletab)
110 return "lsnes: Configuration";
111 else
112 return "lsnes: Configuration: " + singletab->get_name();
115 wxeditor_esettings2::wxeditor_esettings2(wxWindow* parent, settings_tab_factory* singletab)
116 : wxDialog(parent, wxID_ANY, towxstring(get_title(singletab)), wxDefaultPosition, wxSize(-1, -1),
117 wxCAPTION | wxSYSTEM_MENU | wxCLOSE_BOX | wxRESIZE_BORDER)
119 //Grab keys to prevent the joystick driver from running who knows what commands.
120 lsnes_kbd.set_exclusive(&keygrabber);
122 Centre();
123 wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
124 SetSizer(top_s);
126 if(singletab) {
127 //If this throws, let it throw through.
128 settings_tab* t = singletab->create(this);
129 top_s->Add(t, 1, wxGROW);
130 t->set_notify([this]() { this->on_notify(); });
131 tabs.push_back(t);
132 } else {
133 int created = 0;
134 tabset = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP);
135 for(auto i : settings_tab_factory::factories()) {
136 settings_tab* t;
137 try {
138 t = i->create(tabset);
139 } catch(...) {
140 continue;
142 tabset->AddPage(t, towxstring(i->get_name()));
143 t->set_notify([this]() { this->on_notify(); });
144 tabs.push_back(t);
145 created++;
147 top_s->Add(tabset, 1, wxGROW);
148 if(!created)
149 throw std::runtime_error("Nothing to configure here, move along");
152 wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
153 pbutton_s->AddStretchSpacer();
154 pbutton_s->Add(closebutton = new wxButton(this, wxID_ANY, wxT("Close")), 0, wxGROW);
155 closebutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
156 wxCommandEventHandler(wxeditor_esettings2::on_close), NULL, this);
157 top_s->Add(pbutton_s, 0, wxGROW);
159 top_s->SetSizeHints(this);
160 Fit();
163 wxeditor_esettings2::~wxeditor_esettings2()
165 for(auto i : tabs)
166 i->notify_close();
167 lsnes_kbd.set_exclusive(NULL);
170 bool wxeditor_esettings2::ShouldPreventAppExit() const
172 return false;
175 void wxeditor_esettings2::on_close(wxCommandEvent& e)
177 for(auto i : tabs)
178 i->on_close();
179 EndModal(wxID_OK);
182 void wxeditor_esettings2::on_notify()
184 for(auto i : tabs)
185 i->on_notify();
189 void settings_tab::call_window_fit()
191 if(dlg) {
192 std::cerr << "Call_window_fit()" << std::endl;
193 dlg->Fit();
197 void display_settings_dialog(wxWindow* parent, settings_tab_factory* singletab)
199 modal_pause_holder hld;
200 wxDialog* editor;
201 try {
202 try {
203 editor = dlg = new wxeditor_esettings2(parent, singletab);
204 } catch(std::exception& e) {
205 std::string title = "Configure";
206 if(singletab)
207 title = "Configure " + singletab->get_name();
208 show_message_ok(parent, title, e.what(), wxICON_EXCLAMATION);
209 return;
211 editor->ShowModal();
212 } catch(...) {
214 dlg = NULL;
215 editor->Destroy();
218 void settings_activate_keygrab(std::function<void(std::string key)> callback)
220 keygrab_callback = callback;
221 keygrab_active = true;
224 void settings_deactivate_keygrab()
226 keygrab_active = false;