openMSX
Setting.cc
Go to the documentation of this file.
1 #include "Setting.hh"
2 #include "CommandController.hh"
5 #include "SettingsConfig.hh"
6 #include "TclObject.hh"
7 #include "CliComm.hh"
8 #include "XMLElement.hh"
9 #include "MSXException.hh"
10 #include "checked_cast.hh"
11 
12 using std::string;
13 
14 namespace openmsx {
15 
16 // class BaseSetting
17 
19  : name(name_.str())
20 {
21 }
22 
23 void BaseSetting::info(TclObject& result) const
24 {
25  result.addListElement(getTypeString());
27  additionalInfo(result);
28 }
29 
30 
31 // class Setting
32 
33 Setting::Setting(CommandController& commandController_,
34  string_ref name_, string_ref desc_,
35  const string& initialValue, SaveSetting save_)
36  : BaseSetting(name_)
37  , commandController(commandController_)
38  , description(desc_.str())
39  , value(initialValue)
40  , defaultValue(initialValue)
41  , restoreValue(initialValue)
42  , save(save_)
43 {
44  checkFunc = [](TclObject&) { /* nothing */ };
45 }
46 
48 {
49  if (needLoadSave()) {
50  auto& settingsConfig = getGlobalCommandController()
52  if (auto* config = settingsConfig.findChild("settings")) {
53  if (auto* elem = config->findChildWithAttribute(
54  "setting", "id", getName())) {
55  try {
56  setStringDirect(elem->getData());
57  } catch (MSXException&) {
58  // saved value no longer valid, just keep default
59  }
60  }
61  }
62  }
64 
65  // This is needed to for example inform catapult of the new setting
66  // value when a setting was destroyed/recreated (by a machine switch
67  // for example).
68  notify();
69 }
70 
72 {
74 }
75 
76 
78 {
79  return description;
80 }
81 
82 void Setting::setString(const string& value)
83 {
84  getCommandController().changeSetting(*this, value);
85 }
86 
87 void Setting::notify() const
88 {
89  // Notify all subsystems of a change in the setting value. There
90  // are actually quite a few subsystems involved with the settings:
91  // - the setting classes themselves
92  // - the Tcl variables (and possibly traces on those variables)
93  // - Subject/Observers
94  // - CliComm setting-change events (for external GUIs)
95  // - SettingsConfig (keeps values, also of not yet created settings)
96  // This method takes care of the last 3 in this list.
98  commandController.getCliComm().update(
100 
101  // Always keep SettingsConfig in sync.
102  auto& config = getGlobalCommandController().getSettingsConfig().getXMLElement();
103  auto& settings = config.getCreateChild("settings");
104  string value = getString();
105  if (!needLoadSave() || (value == getDefaultValue())) {
106  // remove setting
107  if (auto* elem = settings.findChildWithAttribute(
108  "setting", "id", getName())) {
109  settings.removeChild(*elem);
110  }
111  } else {
112  // add (or overwrite) setting
113  auto& elem = settings.getCreateChildWithAttribute(
114  "setting", "id", getName());
115  // check for non-saveable value
116  // (mechanism can be generalize later when needed)
117  if (value == dontSaveValue) value = getRestoreValue();
118  elem.setData(value);
119  }
120 }
121 
123 {
124  TclObject result;
125  info(result);
126  commandController.getCliComm().update(
127  CliComm::SETTINGINFO, getName(), result.getString());
128 }
129 
131 {
132  return save == SAVE;
133 }
135 {
136  return save != DONT_TRANSFER;
137 }
138 
139 void Setting::setDontSaveValue(const std::string& dontSaveValue_)
140 {
141  dontSaveValue = dontSaveValue_;
142 }
143 
144 GlobalCommandController& Setting::getGlobalCommandController() const
145 {
146  if (auto* globalCommandController =
147  dynamic_cast<GlobalCommandController*>(&commandController)) {
148  return *globalCommandController;
149  } else {
150  return checked_cast<MSXCommandController*>(&commandController)
151  ->getGlobalCommandController();
152  }
153 }
154 
156 {
157  return commandController.getInterpreter();
158 }
159 
160 void Setting::tabCompletion(std::vector<string>& /*tokens*/) const
161 {
162  // nothing
163 }
164 
165 void Setting::additionalInfo(TclObject& /*result*/) const
166 {
167  // nothing
168 }
169 
170 void Setting::setRestoreValue(const string& value)
171 {
172  restoreValue = value;
173 }
174 
175 
176 string Setting::getString() const
177 {
178  return value.getString().str();
179 }
180 
182 {
183  return defaultValue;
184 }
185 
187 {
188  return restoreValue;
189 }
190 
191 void Setting::setStringDirect(const string& str)
192 {
193  TclObject newValue(str);
194  checkFunc(newValue);
195  if (newValue != value) {
196  value = newValue;
197  notify();
198  }
199 
200  // synchronize proxy
201  auto* controller = dynamic_cast<MSXCommandController*>(
203  if (!controller) {
204  // This is not a machine specific setting.
205  return;
206  }
207  if (!controller->isActive()) {
208  // This setting does not belong to the active machine.
209  return;
210  }
211 
212  auto& globalController = controller->getGlobalCommandController();
213  // Tcl already makes sure this doesn't result in an endless loop.
214  try {
215  globalController.changeSetting(getName(), getString());
216  } catch (MSXException&) {
217  // ignore
218  }
219 }
220 
221 } // namespace openmsx
virtual std::string getDescription() const
pure virtual methods ///
Definition: Setting.cc:77
virtual void unregisterSetting(Setting &setting)=0
virtual bool needTransfer() const
Does this setting need to be transfered on reverse.
Definition: Setting.cc:134
void notify() const
Definition: Subject.hh:64
string_ref getString() const
Definition: TclObject.cc:180
virtual void setString(const std::string &value)
Change the value of this setting to the given value.
Definition: Setting.cc:82
XMLElement & getCreateChild(string_ref name, string_ref defaultValue="")
Definition: XMLElement.cc:187
GlobalCommandController & getGlobalCommandController()
This class implements a subset of the proposal for std::string_ref (proposed for the next c++ standar...
Definition: string_ref.hh:18
virtual std::string getDefaultValue() const =0
Get the default value of this setting.
virtual std::string getRestoreValue() const
Get the value that will be set after a Tcl 'unset' command.
Definition: Setting.cc:186
BaseSetting(string_ref name)
Definition: Setting.cc:18
virtual void update(UpdateType type, string_ref name, string_ref value)=0
virtual std::string getDefaultValue() const
Get the default value of this setting.
Definition: Setting.cc:181
void save(SDL_Surface *surface, const std::string &filename)
Definition: PNG.cc:369
void notifyPropertyChange() const
Definition: Setting.cc:122
void info(TclObject &result) const
For SettingInfo.
Definition: Setting.cc:23
virtual string_ref getTypeString() const =0
Returns a string describing the setting type (integer, string, ..) Could be used in a GUI to pick an ...
virtual void changeSetting(Setting &setting, const std::string &value)=0
virtual void tabCompletion(std::vector< std::string > &tokens) const
Complete a partly typed value.
Definition: Setting.cc:160
Setting(CommandController &commandController, string_ref name, string_ref description, const std::string &initialValue, SaveSetting save=SAVE)
Definition: Setting.cc:33
virtual Interpreter & getInterpreter()=0
virtual void setDontSaveValue(const std::string &dontSaveValue)
This value will never end up in the settings.xml file.
Definition: Setting.cc:139
virtual bool needLoadSave() const
Does this setting need to be loaded or saved (settings.xml).
Definition: Setting.cc:130
virtual void setStringDirect(const std::string &value)
Similar to setString(), but doesn't trigger Tcl traces.
Definition: Setting.cc:191
Interpreter & getInterpreter() const
Definition: Setting.cc:155
virtual SettingsConfig & getSettingsConfig()
virtual std::string getString() const
Get the current value of this setting in a string format that can be presented to the user...
Definition: Setting.cc:176
virtual void registerSetting(Setting &setting)=0
TODO.
const std::string & getName() const
Get the name of this setting.
Definition: Setting.hh:26
void addListElement(string_ref element)
Definition: TclObject.cc:110
virtual ~Setting()
Definition: Setting.cc:71
virtual CliComm & getCliComm()=0
CommandController & getCommandController() const
Definition: Setting.hh:149
virtual void additionalInfo(TclObject &result) const
Helper method for info().
Definition: Setting.cc:165
virtual void additionalInfo(TclObject &result) const =0
Helper method for info().
void setRestoreValue(const std::string &value)
Set restore value.
Definition: Setting.cc:170
XMLElement & getXMLElement()
void changeSetting(const std::string &name, const std::string &value)