Port the generic control stuff from wxwidgets work
[lsnes.git] / generic / settings.cpp
blobf12e754f6b85d6803b8c2e13d38d15490110a633
1 #include "settings.hpp"
2 #include "misc.hpp"
3 #include <map>
4 #include <sstream>
5 #include "misc.hpp"
6 #include "command.hpp"
7 #include "globalwrap.hpp"
8 #include "window.hpp"
9 #include <iostream>
11 namespace
13 globalwrap<std::map<std::string, setting*>> settings;
15 function_ptr_command<tokensplitter&> set_setting("set-setting", "set a setting",
16 "Syntax: set-setting <setting> [<value>]\nSet setting to a new value. Omit <value> to set to ''\n",
17 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
18 std::string syntax = "Syntax: set-setting <setting> [<value>]";
19 std::string settingname = t;
20 std::string settingvalue = t.tail();
21 if(settingname == "")
22 throw std::runtime_error("Setting name required.");
23 setting::set(settingname, settingvalue);
24 messages << "Setting '" << settingname << "' set to '" << settingvalue << "'"
25 << std::endl;
26 });
28 function_ptr_command<tokensplitter&> unset_setting("unset-setting", "unset a setting",
29 "Syntax: unset-setting <setting>\nTry to unset a setting. Note that not all settings can be unset\n",
30 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
31 std::string syntax = "Syntax: unset-setting <setting>";
32 std::string settingname = t;
33 if(settingname == "" || t)
34 throw std::runtime_error("Expected setting name and nothing else");
35 setting::blank(settingname);
36 messages << "Setting '" << settingname << "' unset" << std::endl;
37 });
39 function_ptr_command<tokensplitter&> get_command("get-setting", "get value of a setting",
40 "Syntax: get-setting <setting>\nShow value of setting\n",
41 [](tokensplitter& t) throw(std::bad_alloc, std::runtime_error) {
42 std::string settingname = t;
43 if(settingname == "" || t.tail() != "")
44 throw std::runtime_error("Expected setting name and nothing else");
45 if(setting::is_set(settingname))
46 messages << "Setting '" << settingname << "' has value '"
47 << setting::get(settingname) << "'" << std::endl;
48 else
49 messages << "Setting '" << settingname << "' unset" << std::endl;
50 });
52 function_ptr_command<> show_settings("show-settings", "Show values of all settings",
53 "Syntax: show-settings\nShow value of all settings\n",
54 []() throw(std::bad_alloc, std::runtime_error) {
55 setting::print_all();
56 });
59 setting::setting(const std::string& name) throw(std::bad_alloc)
61 settings()[settingname = name] = this;
64 setting::~setting() throw()
66 settings().erase(settingname);
69 void setting::set(const std::string& _setting, const std::string& value) throw(std::bad_alloc, std::runtime_error)
71 if(!settings().count(_setting))
72 throw std::runtime_error("No such setting '" + _setting + "'");
73 try {
74 settings()[_setting]->set(value);
75 window_callback::do_setting_change(_setting, value);
76 } catch(std::bad_alloc& e) {
77 throw;
78 } catch(std::exception& e) {
79 throw std::runtime_error("Can't set setting '" + _setting + "': " + e.what());
83 void setting::blank(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
85 if(!settings().count(_setting))
86 throw std::runtime_error("No such setting '" + _setting + "'");
87 try {
88 settings()[_setting]->blank();
89 window_callback::do_setting_clear(_setting);
91 } catch(std::bad_alloc& e) {
92 throw;
93 } catch(std::exception& e) {
94 throw std::runtime_error("Can't blank setting '" + _setting + "': " + e.what());
98 std::string setting::get(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
100 if(!settings().count(_setting))
101 throw std::runtime_error("No such setting '" + _setting + "'");
102 return settings()[_setting]->get();
105 bool setting::is_set(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
107 if(!settings().count(_setting))
108 throw std::runtime_error("No such setting '" + _setting + "'");
109 return settings()[_setting]->is_set();
112 void setting::print_all() throw(std::bad_alloc)
114 for(auto i : settings()) {
115 if(!i.second->is_set())
116 messages << i.first << ": (unset)" << std::endl;
117 else
118 messages << i.first << ": " << i.second->get() << std::endl;
122 std::set<std::string> setting::get_settings_set() throw(std::bad_alloc)
124 std::set<std::string> r;
125 for(auto i : settings())
126 r.insert(i.first);
127 return r;
131 numeric_setting::numeric_setting(const std::string& sname, int32_t minv, int32_t maxv, int32_t dflt)
132 throw(std::bad_alloc)
133 : setting(sname)
135 minimum = minv;
136 maximum = maxv;
137 value = dflt;
140 void numeric_setting::blank() throw(std::bad_alloc, std::runtime_error)
142 throw std::runtime_error("This setting can't be blanked");
145 bool numeric_setting::is_set() throw()
147 return true;
150 void numeric_setting::set(const std::string& _value) throw(std::bad_alloc, std::runtime_error)
152 int32_t v = parse_value<int32_t>(_value);
153 if(v < minimum || v > maximum) {
154 std::ostringstream x;
155 x << "Value out of range (" << minimum << " - " << maximum << ")";
156 throw std::runtime_error(x.str());
158 value = v;
161 std::string numeric_setting::get() throw(std::bad_alloc)
163 std::ostringstream x;
164 x << value;
165 return x.str();
168 numeric_setting::operator int32_t() throw()
170 return value;
173 boolean_setting::boolean_setting(const std::string& sname, bool dflt) throw(std::bad_alloc)
174 : setting(sname)
176 value = dflt;
178 void boolean_setting::blank() throw(std::bad_alloc, std::runtime_error)
180 throw std::runtime_error("This setting can't be unset");
183 bool boolean_setting::is_set() throw()
185 return true;
188 void boolean_setting::set(const std::string& v) throw(std::bad_alloc, std::runtime_error)
190 if(v == "true" || v == "yes" || v == "on" || v == "1" || v == "enable" || v == "enabled")
191 value = true;
192 else if(v == "false" || v == "no" || v == "off" || v == "0" || v == "disable" || v == "disabled")
193 value = false;
194 else
195 throw std::runtime_error("Invalid value for boolean setting");
197 std::string boolean_setting::get() throw(std::bad_alloc)
199 if(value)
200 return "true";
201 else
202 return "false";
205 boolean_setting::operator bool() throw()
207 return value;