neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
setting.hpp
Go to the documentation of this file.
1// setting.hpp
2/*
3 * Copyright (c) 2007, 2020 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
42#include <neolib/task/event.hpp>
47
48namespace neolib
49{
50 template <typename T>
51 class setting : public reference_counted<i_setting>
52 {
53 friend class settings;
54 typedef setting<T> self_type;
56 public:
57 typedef T value_type;
59 public:
60 define_declared_event(Changing, changing)
61 define_declared_event(Changed, changed)
62 public:
63 setting(i_settings& aManager, i_string const& aKey, T const& aDefaultValue, i_setting_constraints const& aConstraints = setting_constraints<T>{}, i_string const& aFormat = string{}) :
64 iManager{ aManager },
65 iKey{ aKey },
66 iConstraints{ aConstraints },
67 iFormat{ aFormat },
68 iEnabled{ !aConstraints.initially_disabled() },
69 iDefaultValue{ aDefaultValue },
70 iValue{}
71 {}
72 setting(const self_type& aOther) :
73 base_type{ aOther },
74 iManager{ aOther.iManager },
75 iKey{ aOther.iKey },
76 iConstraints{ aOther.iConstraints },
77 iFormat{ aOther.iFormat },
78 iEnabled{ !aOther.iConstraints.initially_disabled() },
79 iDefaultValue{ aOther.iDefaultValue },
80 iValue{ aOther.iValue }
81 {
82 }
83 setting(const i_setting& aSetting) :
84 iManager{ aSetting.manager() },
85 iKey{ aSetting.key() },
86 iConstraints{ aSetting.constraints() },
87 iFormat{ aSetting.format() },
88 iEnabled{ !aSetting.constraints().initially_disabled() },
89 iDefaultValue{ aSetting.default_value() },
90 iValue{ aSetting.value() }
91 {}
92 public:
93 i_settings& manager() const override
94 {
95 return iManager;
96 }
97 string const& key() const override
98 {
99 return iKey;
100 }
101 setting_constraints<T> const& constraints() const override
102 {
103 return iConstraints;
104 }
105 string const& format() const override
106 {
107 return iFormat;
108 }
109 bool hidden() const override
110 {
111 return iFormat.empty();
112 }
113 bool is_enabled() const override
114 {
115 return iEnabled;
116 }
117 void set_enabled(bool aEnabled) override
118 {
119 if (iEnabled != aEnabled)
120 {
121 iEnabled = aEnabled;
122 Changed.trigger();
123 iManager.changed_setting(*this);
124 }
125 }
126 bool is_default(bool aUnappliedNew = false) const override
127 {
128 if (aUnappliedNew && modified())
129 return !modified_value().is_set();
130 return !iValue.is_set();
131 }
132 bool modified() const override
133 {
134 return iNewValue != std::nullopt;
135 }
136 i_setting_value const& default_value() const override
137 {
138 return iDefaultValue;
139 }
140 using i_setting::value;
141 i_setting_value const& value(bool aUnappliedNew = false) const override
142 {
143 if (aUnappliedNew && modified())
144 {
145 if (modified_value().is_set())
146 return modified_value();
147 return default_value();
148 }
149 if (iValue.is_set())
150 return iValue;
151 return default_value();
152 }
154 i_setting_value const& modified_value() const override
155 {
156 if (!modified())
157 throw setting_not_modified();
158 return *iNewValue;
159 }
161 void value_as_string(i_string& aValue, bool aUnappliedNew = false) const override
162 {
163 aValue = to_string(value(aUnappliedNew).template get<T>());
164 }
166 void set_default_value(i_setting_value const& aDefaultValue) override
167 {
168 if (default_value() != aDefaultValue)
169 {
170 iDefaultValue = aDefaultValue;
171 if (is_default())
172 {
173 Changed.trigger();
174 iManager.changed_setting(*this);
175 }
176 }
177 }
179 void set_value(i_setting_value const& aNewValue) override
180 {
181 if (value() != aNewValue)
182 {
183 if (!modified() || modified_value() != aNewValue)
184 {
185 iNewValue = aNewValue;
186 Changing.trigger();
187 iManager.changing_setting(*this);
188 }
189 }
190 else if (modified())
191 {
192 iNewValue = std::nullopt;
193 Changing.trigger();
194 iManager.changing_setting(*this);
195 }
196 }
197 void set_value_from_string(i_string const& aNewValue) override
198 {
199 set_value(setting_value<T>{ from_string<T>(aNewValue) });
200 }
201 void clear() override
202 {
203 if (!constraints().optional())
204 throw setting_not_optional();
205 if (is_default())
206 {
207 if (modified())
208 iNewValue = std::nullopt;
209 else
210 return;
211 }
212 else
213 iNewValue.emplace();
214 Changing.trigger();
215 iManager.changing_setting(*this);
216 }
217 protected:
219 {
220 // why? type erasure; better than allocating a clone on the heap.
221 thread_local setting_value_type temp;
222 temp = setting_value_type{};
223 return temp;
224 }
225 private:
226 bool apply_change() override
227 {
228 if (modified())
229 {
230 bool changed = (iValue != *iNewValue);
231 iValue = *iNewValue;
232 iNewValue = std::nullopt;
233 if (changed)
234 {
235 Changed.trigger();
236 iManager.changed_setting(*this);
237 }
238 else
239 {
240 Changing.trigger();
241 iManager.changing_setting(*this);
242 }
243 return true;
244 }
245 return false;
246 }
247 bool discard_change() override
248 {
249 if (modified())
250 {
251 iNewValue = std::nullopt;
252 Changing.trigger();
253 iManager.changing_setting(*this);
254 return true;
255 }
256 return false;
257 }
258 private:
259 void clone(i_ref_ptr<i_setting>& aResult) const override
260 {
261 aResult = make_ref<setting<T>>(*this);
262 }
263 private:
264 i_settings& iManager;
265 string iKey;
266 setting_constraints<T> iConstraints;
267 string iFormat;
268 bool iEnabled;
269 setting_value_type iDefaultValue;
270 setting_value_type iValue;
271 std::optional<setting_value_type> iNewValue;
272 };
273}
bool empty() const noexcept
virtual bool is_set() const =0
virtual i_setting_value const & modified_value() const =0
virtual void value_as_string(i_string &aValue, bool aUnappliedNew=false) const =0
virtual void set_value(i_setting_value const &aNewValue)=0
virtual i_setting_value const & value(bool aUnappliedNew=false) const =0
virtual void set_default_value(i_setting_value const &aDefaultValue)=0
virtual void changed_setting(i_setting const &aSetting)=0
virtual void changing_setting(i_setting const &aSetting)=0
bool is_enabled() const override
Definition setting.hpp:113
void set_enabled(bool aEnabled) override
Definition setting.hpp:117
i_setting_value & temp_setting_value() override
Definition setting.hpp:218
void set_value_from_string(i_string const &aNewValue) override
Definition setting.hpp:197
setting_value< T > setting_value_type
Definition setting.hpp:58
string const & key() const override
Definition setting.hpp:97
i_settings & manager() const override
Definition setting.hpp:93
setting_constraints< T > const & constraints() const override
Definition setting.hpp:101
void set_default_value(i_setting_value const &aDefaultValue) override
Definition setting.hpp:166
setting(i_settings &aManager, i_string const &aKey, T const &aDefaultValue, i_setting_constraints const &aConstraints=setting_constraints< T >{}, i_string const &aFormat=string{})
Definition setting.hpp:63
void value_as_string(i_string &aValue, bool aUnappliedNew=false) const override
Definition setting.hpp:161
i_setting_value const & modified_value() const override
Definition setting.hpp:154
setting(const i_setting &aSetting)
Definition setting.hpp:83
define_declared_event(Changing, changing) define_declared_event(Changed
i_setting_value const & default_value() const override
Definition setting.hpp:136
string const & format() const override
Definition setting.hpp:105
bool is_default(bool aUnappliedNew=false) const override
Definition setting.hpp:126
bool hidden() const override
Definition setting.hpp:109
i_setting_value const & value(bool aUnappliedNew=false) const override
Definition setting.hpp:141
void set_value(i_setting_value const &aNewValue) override
Definition setting.hpp:179
void clear() override
Definition setting.hpp:201
setting(const self_type &aOther)
Definition setting.hpp:72
bool modified() const override
Definition setting.hpp:132
#define define_declared_event(name, declName,...)
Definition event.hpp:195