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 "MSXException.hh"
9 #include "checked_cast.hh"
10 
11 namespace openmsx {
12 
13 // class BaseSetting
14 
15 BaseSetting::BaseSetting(std::string_view name)
16  : fullName(name)
17  , baseName(fullName)
18 {
19 }
20 
22  : fullName(std::move(name))
23  , baseName(fullName)
24 {
25 }
26 
27 void BaseSetting::info(TclObject& result) const
28 {
30  additionalInfo(result);
31 }
32 
33 
34 // class Setting
35 
36 Setting::Setting(CommandController& commandController_,
37  std::string_view name, static_string_view description_,
38  const TclObject& initialValue, SaveSetting save_)
39  : BaseSetting(name)
40  , commandController(commandController_)
41  , description(description_)
42  , value(initialValue)
43  , defaultValue(initialValue)
44  , restoreValue(initialValue)
45  , save(save_)
46 {
47  checkFunc = [](TclObject&) { /* nothing */ };
48 }
49 
51 {
52  if (needLoadSave()) {
53  if (const auto* savedValue =
54  getGlobalCommandController().getSettingsConfig()
55  .getValueForSetting(getBaseName())) {
56  try {
57  setValueDirect(TclObject(*savedValue));
58  } catch (MSXException&) {
59  // saved value no longer valid, just keep default
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 
77 std::string_view Setting::getDescription() const
78 {
79  return description;
80 }
81 
82 void Setting::setValue(const TclObject& newValue)
83 {
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  auto base = getBaseName();
99  TclObject val = getValue();
100  commandController.getCliComm().update(
101  CliComm::SETTING, base, val.getString());
102 
103  // Always keep SettingsConfig in sync.
104  auto& config = getGlobalCommandController().getSettingsConfig();
105  if (!needLoadSave() || (val == getDefaultValue())) {
106  config.removeValueForSetting(base);
107  } else {
108  // check for non-saveable value
109  // (mechanism can be generalize later when needed)
110  if (val == dontSaveValue) val = getRestoreValue();
111  config.setValueForSetting(base, val.getString());
112  }
113 }
114 
116 {
117  TclObject result;
118  info(result);
119  commandController.getCliComm().update(
121 }
122 
124 {
125  return save == SAVE;
126 }
128 {
129  return save != DONT_TRANSFER;
130 }
131 
132 void Setting::setDontSaveValue(const TclObject& dontSaveValue_)
133 {
134  dontSaveValue = dontSaveValue_;
135 }
136 
137 GlobalCommandController& Setting::getGlobalCommandController() const
138 {
139  if (auto* globalCommandController =
140  dynamic_cast<GlobalCommandController*>(&commandController)) {
141  return *globalCommandController;
142  } else {
143  return checked_cast<MSXCommandController*>(&commandController)
144  ->getGlobalCommandController();
145  }
146 }
147 
149 {
150  return commandController.getInterpreter();
151 }
152 
153 void Setting::tabCompletion(std::vector<std::string>& /*tokens*/) const
154 {
155  // nothing
156 }
157 
158 void Setting::additionalInfo(TclObject& /*result*/) const
159 {
160  // nothing
161 }
162 
163 
164 void Setting::setValueDirect(const TclObject& newValue_)
165 {
166  TclObject newValue = newValue_;
167  checkFunc(newValue);
168  if (newValue != value) {
169  value = newValue;
170  notify();
171  }
172 
173  // synchronize proxy
174  auto* controller = dynamic_cast<MSXCommandController*>(
176  if (!controller) {
177  // This is not a machine specific setting.
178  return;
179  }
180  if (!controller->isActive()) {
181  // This setting does not belong to the active machine.
182  return;
183  }
184 
185  // Tcl already makes sure this doesn't result in an endless loop.
186  try {
188  } catch (MSXException&) {
189  // ignore
190  }
191 }
192 
193 } // namespace openmsx
virtual void additionalInfo(TclObject &result) const =0
Helper method for info().
BaseSetting(std::string_view name)
Definition: Setting.cc:15
void info(TclObject &result) const
For SettingInfo.
Definition: Setting.cc:27
const TclObject & getBaseNameObj() const
Definition: Setting.hh:36
virtual std::string_view getTypeString() const =0
Returns a string describing the setting type (integer, string, ..) Could be used in a GUI to pick an ...
virtual TclObject getDefaultValue() const =0
Get the default value of this setting.
const TclObject & getFullNameObj() const
Get the name of this setting.
Definition: Setting.hh:35
std::string_view getBaseName() const
Definition: Setting.hh:38
virtual void update(UpdateType type, std::string_view name, std::string_view value)=0
virtual void registerSetting(Setting &setting)=0
TODO.
virtual void unregisterSetting(Setting &setting)=0
virtual CliComm & getCliComm()=0
virtual Interpreter & getInterpreter()=0
void setVariable(const TclObject &name, const TclObject &value)
Definition: Interpreter.cc:249
virtual ~Setting()
Definition: Setting.cc:71
std::string_view getDescription() const final
pure virtual methods ///
Definition: Setting.cc:77
void tabCompletion(std::vector< std::string > &tokens) const override
Complete a partly typed value.
Definition: Setting.cc:153
const TclObject & getValue() const final
Gets the current value of this setting as a TclObject.
Definition: Setting.hh:142
bool needLoadSave() const final
Does this setting need to be loaded or saved (settings.xml).
Definition: Setting.cc:123
void setDontSaveValue(const TclObject &dontSaveValue) final
This value will never end up in the settings.xml file.
Definition: Setting.cc:132
bool needTransfer() const final
Does this setting need to be transfered on reverse.
Definition: Setting.cc:127
Interpreter & getInterpreter() const
Definition: Setting.cc:148
TclObject getRestoreValue() const final
Get the value that will be set after a Tcl 'unset' command.
Definition: Setting.hh:168
TclObject getDefaultValue() const final
Get the default value of this setting.
Definition: Setting.hh:167
CommandController & getCommandController() const
Definition: Setting.hh:177
void setValue(const TclObject &newValue) final
Change the value of this setting to the given value.
Definition: Setting.cc:82
void notifyPropertyChange() const
Definition: Setting.cc:115
void additionalInfo(TclObject &result) const override
Helper method for info().
Definition: Setting.cc:158
Setting(const Setting &)=delete
void setValueDirect(const TclObject &newValue) final
Similar to setValue(), but doesn't trigger Tcl traces.
Definition: Setting.cc:164
void removeValueForSetting(std::string_view setting)
void notify() const
Definition: Subject.hh:67
void addListElement(const T &t)
Definition: TclObject.hh:129
zstring_view getString() const
Definition: TclObject.cc:111
static_string_view
This file implemented 3 utility functions:
Definition: Autofire.cc:9