1 #pragma once
2 
3 #ifndef TPROPERTY_INCLUDED
4 #define TPROPERTY_INCLUDED
5 
6 #include "tconvert.h"
7 
8 #include <cstdint>
9 
10 #undef DVAPI
11 #undef DVVAR
12 
13 #ifdef TNZCORE_EXPORTS
14 #define DVAPI DV_EXPORT_API
15 #define DVVAR DV_EXPORT_VAR
16 #else
17 #define DVAPI DV_IMPORT_API
18 #define DVVAR DV_IMPORT_VAR
19 #endif
20 
21 #ifdef _MSC_VER
22 #pragma warning(push)
23 #pragma warning(disable : 4251)
24 #endif
25 
26 template <class T>
27 class TRangeProperty;
28 
29 typedef TRangeProperty<int> TIntProperty;
30 typedef TRangeProperty<double> TDoubleProperty;
31 
32 class DVAPI TBoolProperty;
33 class DVAPI TStringProperty;
34 class DVAPI TEnumProperty;
35 class DVAPI TDoublePairProperty;
36 class DVAPI TIntPairProperty;
37 class DVAPI TStyleIndexProperty;
38 class DVAPI TPointerProperty;
39 
40 class TIStream;
41 class TOStream;
42 
43 //---------------------------------------------------------
44 
45 class DVAPI TProperty {
46 public:
47   class Visitor {
48   public:
49     virtual void visit(TDoubleProperty *p)     = 0;
50     virtual void visit(TIntProperty *p)        = 0;
51     virtual void visit(TBoolProperty *p)       = 0;
52     virtual void visit(TStringProperty *p)     = 0;
53     virtual void visit(TEnumProperty *p)       = 0;
54     virtual void visit(TDoublePairProperty *p) = 0;
55     virtual void visit(TIntPairProperty *p)    = 0;
56     virtual void visit(TStyleIndexProperty *p) = 0;
57     virtual void visit(TPointerProperty *p)    = 0;
~Visitor()58     virtual ~Visitor() {}
59   };
60 
61   class Listener {
62   public:
63     virtual void onPropertyChanged() = 0;
~Listener()64     virtual ~Listener() {}
65   };
66 
67   // eccezioni
68   class TypeError {};
69   class RangeError {};
70 
TProperty(std::string name)71   TProperty(std::string name) : m_name(name) {
72     m_qstringName = QString::fromStdString(name);
73   }
74 
~TProperty()75   virtual ~TProperty() {}
76 
77   virtual TProperty *clone() const = 0;
78 
79   // Used only for translation in Qt
getQStringName()80   QString getQStringName() const { return m_qstringName; }
setQStringName(const QString & str)81   void setQStringName(const QString &str) { m_qstringName = str; }
82   virtual void assignUIName(TProperty *refP);
83 
getName()84   std::string getName() const { return m_name; }
85   virtual std::string getValueAsString() = 0;
86 
87   virtual void accept(Visitor &v) = 0;
88 
89   void addListener(Listener *listener);
90   void removeListener(Listener *listener);
91   void notifyListeners() const;
92 
getId()93   std::string getId() const { return m_id; }
setId(std::string id)94   void setId(std::string id) { m_id = id; }
95 
96 private:
97   std::string m_name;
98   QString m_qstringName;
99   std::string m_id;
100   std::vector<Listener *> m_listeners;
101 };
102 
103 //---------------------------------------------------------
104 
105 template <class T>
106 class TRangeProperty final : public TProperty {
107 public:
108   typedef std::pair<T, T> Range;
109 
110   TRangeProperty(std::string name, T minValue, T maxValue, T value,
111                  bool isMaxRangeLimited = true)
TProperty(name)112       : TProperty(name)
113       , m_range(minValue, maxValue)
114       , m_value(minValue)
115       , m_isMaxRangeLimited(isMaxRangeLimited)
116       , m_isLinearSlider(true) {
117     setValue(value);
118   }
119 
clone()120   TProperty *clone() const override { return new TRangeProperty<T>(*this); }
121 
getRange()122   Range getRange() const { return m_range; }
123 
124   void setValue(T v, bool cropEnabled = false) {
125     if (cropEnabled && m_isMaxRangeLimited)
126       v = tcrop(v, m_range.first, m_range.second);
127     if (cropEnabled && !m_isMaxRangeLimited)
128       v = v < m_range.first ? m_range.first : v;
129     if (v < m_range.first || (v > m_range.second && m_isMaxRangeLimited))
130       throw RangeError();
131     m_value = v;
132   }
133 
getValue()134   T getValue() const { return m_value; }
135 
getValueAsString()136   std::string getValueAsString() override { return std::to_string(m_value); }
137 
accept(Visitor & v)138   void accept(Visitor &v) override { v.visit(this); }
139 
isMaxRangeLimited()140   bool isMaxRangeLimited() const { return m_isMaxRangeLimited; }
141 
setNonLinearSlider()142   void setNonLinearSlider() { m_isLinearSlider = false; }
isLinearSlider()143   bool isLinearSlider() { return m_isLinearSlider; }
144 
145 private:
146   Range m_range;
147   T m_value;
148   bool m_isMaxRangeLimited;
149   bool m_isLinearSlider;
150 };
151 
152 //---------------------------------------------------------
153 #ifdef _WIN32
154 template class DVAPI TRangeProperty<int>;
155 template class DVAPI TRangeProperty<double>;
156 #endif
157 //---------------------------------------------------------
158 
159 class TDoublePairProperty final : public TProperty {
160 public:
161   typedef std::pair<double, double> Range;
162   typedef std::pair<double, double> Value;
163 
164   TDoublePairProperty(std::string name, double minValue, double maxValue,
165                       double v0, double v1, bool isMaxRangeLimited = true)
TProperty(name)166       : TProperty(name)
167       , m_range(Range(minValue, maxValue))
168       , m_isMaxRangeLimited(isMaxRangeLimited)
169       , m_isLinearSlider(true) {
170     setValue(Value(v0, v1));
171   }
172 
clone()173   TProperty *clone() const override { return new TDoublePairProperty(*this); }
174 
getRange()175   Range getRange() const { return m_range; }
176 
isMaxRangeLimited()177   bool isMaxRangeLimited() const { return m_isMaxRangeLimited; }
178 
setValue(const Value & value)179   void setValue(const Value &value) {
180     if (value.first < m_range.first ||
181         (m_isMaxRangeLimited && value.first > m_range.second) ||
182         value.second < m_range.first ||
183         (m_isMaxRangeLimited && value.second > m_range.second))
184       throw RangeError();
185     m_value = value;
186   }
getValue()187   Value getValue() const { return m_value; }
getValueAsString()188   std::string getValueAsString() override {
189     return std::to_string(m_value.first) + "," + std::to_string(m_value.second);
190   }
accept(Visitor & v)191   void accept(Visitor &v) override { v.visit(this); };
192 
setNonLinearSlider()193   void setNonLinearSlider() { m_isLinearSlider = false; }
isLinearSlider()194   bool isLinearSlider() { return m_isLinearSlider; }
195 
196 private:
197   Range m_range;
198   Value m_value;
199   bool m_isMaxRangeLimited;
200   bool m_isLinearSlider;
201 };
202 
203 //---------------------------------------------------------
204 
205 class TIntPairProperty final : public TProperty {
206 public:
207   typedef std::pair<int, int> Range;
208   typedef std::pair<int, int> Value;
209 
210   TIntPairProperty(std::string name, int minValue, int maxValue, int v0, int v1,
211                    bool isMaxRangeLimited = true)
TProperty(name)212       : TProperty(name)
213       , m_range(minValue, maxValue)
214       , m_isMaxRangeLimited(isMaxRangeLimited)
215       , m_isLinearSlider(true) {
216     setValue(Value(v0, v1));
217   }
218 
clone()219   TProperty *clone() const override { return new TIntPairProperty(*this); }
220 
getRange()221   Range getRange() const { return m_range; }
222 
isMaxRangeLimited()223   bool isMaxRangeLimited() const { return m_isMaxRangeLimited; }
224 
setValue(const Value & value)225   void setValue(const Value &value) {
226     if (value.first < m_range.first ||
227         (m_isMaxRangeLimited && value.first > m_range.second) ||
228         value.second < m_range.first ||
229         (m_isMaxRangeLimited && value.second > m_range.second))
230       throw RangeError();
231     m_value = value;
232   }
getValue()233   Value getValue() const { return m_value; }
getValueAsString()234   std::string getValueAsString() override {
235     return std::to_string(m_value.first) + "," + std::to_string(m_value.second);
236   }
accept(Visitor & v)237   void accept(Visitor &v) override { v.visit(this); };
238 
setNonLinearSlider()239   void setNonLinearSlider() { m_isLinearSlider = false; }
isLinearSlider()240   bool isLinearSlider() { return m_isLinearSlider; }
241 
242 private:
243   Range m_range;
244   Value m_value;
245   bool m_isMaxRangeLimited;
246   bool m_isLinearSlider;
247 };
248 
249 //---------------------------------------------------------
250 
251 class DVAPI TBoolProperty final : public TProperty {
252 public:
TBoolProperty(std::string name,bool value)253   TBoolProperty(std::string name, bool value)
254       : TProperty(name), m_value(value) {}
255 
clone()256   TProperty *clone() const override { return new TBoolProperty(*this); }
257 
setValue(bool v)258   void setValue(bool v) { m_value = v; }
getValue()259   bool getValue() const { return m_value; }
getValueAsString()260   std::string getValueAsString() override { return std::to_string(m_value); }
accept(Visitor & v)261   void accept(Visitor &v) override { v.visit(this); };
262 
263 private:
264   bool m_value;
265 };
266 
267 //---------------------------------------------------------
268 
269 class DVAPI TStringProperty final : public TProperty {
270 public:
TStringProperty(std::string name,std::wstring value)271   TStringProperty(std::string name, std::wstring value)
272       : TProperty(name), m_value(value) {}
273 
clone()274   TProperty *clone() const override { return new TStringProperty(*this); }
275 
setValue(std::wstring v)276   void setValue(std::wstring v) { m_value = v; }
getValue()277   std::wstring getValue() const { return m_value; }
getValueAsString()278   std::string getValueAsString() override { return ::to_string(m_value); }
accept(Visitor & v)279   void accept(Visitor &v) override { v.visit(this); };
280 
281 private:
282   std::wstring m_value;
283 };
284 
285 //---------------------------------------------------------
286 
287 class DVAPI TStyleIndexProperty final : public TProperty {
288 public:
TStyleIndexProperty(std::string name,std::wstring value)289   TStyleIndexProperty(std::string name, std::wstring value)
290       : TProperty(name), m_value(value) {}
291 
clone()292   TProperty *clone() const override { return new TStyleIndexProperty(*this); }
293 
setValue(std::wstring v)294   void setValue(std::wstring v) { m_value = v; }
getValue()295   std::wstring getValue() const { return m_value; }
296 
getValueAsString()297   std::string getValueAsString() override { return ::to_string(m_value); }
298 
accept(Visitor & v)299   void accept(Visitor &v) override { v.visit(this); };
300 
301 private:
302   std::wstring m_value;
303 };
304 
305 //------------------------------------------------------------------
306 
307 class DVAPI TPointerProperty final : public TProperty {
308 public:
TPointerProperty(std::string name,void * value)309   TPointerProperty(std::string name, void *value)
310       : TProperty(name), m_value(value) {}
311 
clone()312   TProperty *clone() const override { return new TPointerProperty(*this); }
313 
setValue(void * v)314   void setValue(void *v) { m_value = v; }
getValue()315   void *getValue() const { return m_value; }
316 
getValueAsString()317   std::string getValueAsString() override { return ::to_string(m_value); }
318 
accept(Visitor & v)319   void accept(Visitor &v) override { v.visit(this); };
320 
321 private:
322   void *m_value;
323 };
324 
325 //---------------------------------------------------------
326 
327 class DVAPI TEnumProperty final : public TProperty {
328 public:
329   typedef std::vector<std::wstring> Range;
330   // Used only for translation and styling in Qt
331   struct Item {
332     QString UIName;
333     QString iconName;
334 
335     Item(const QString &name = QString(), const QString &icon = QString())
UINameItem336         : UIName(name), iconName(icon) {}
337   };
338   typedef std::vector<Item> Items;
339 
TEnumProperty(const std::string & name)340   TEnumProperty(const std::string &name) : TProperty(name), m_index(-1) {}
341 
TEnumProperty(const std::string & name,const Range & range,const std::wstring & v)342   TEnumProperty(const std::string &name, const Range &range,
343                 const std::wstring &v)
344       : TProperty(name), m_range(range), m_index(indexOf(v)) {
345     if (m_index < 0) throw RangeError();
346     m_items.resize(m_range.size());
347   }
348 
TEnumProperty(const std::string & name,Range::const_iterator i0,Range::const_iterator i1,const std::wstring & v)349   TEnumProperty(const std::string &name, Range::const_iterator i0,
350                 Range::const_iterator i1, const std::wstring &v)
351       : TProperty(name), m_range(i0, i1), m_index(indexOf(v)) {
352     if (m_index < 0) throw RangeError();
353     m_items.resize(m_range.size());
354   }
355 
clone()356   TProperty *clone() const override { return new TEnumProperty(*this); }
357 
indexOf(const std::wstring & value)358   int indexOf(const std::wstring &value) {
359     Range::const_iterator it = std::find(m_range.begin(), m_range.end(), value);
360     return (it == m_range.end()) ? -1 : it - m_range.begin();
361   }
362 
isValue(const std::wstring & value)363   bool isValue(const std::wstring &value) {
364     bool ret =
365         std::find(m_range.begin(), m_range.end(), value) != m_range.end();
366     return ret;
367   }
368 
369   void addValue(std::wstring value, const QString &iconName = QString()) {
370     if (m_index == -1) m_index = 0;
371     m_range.push_back(value);
372     m_items.push_back(Item(QString::fromStdWString(value), iconName));
373   }
374 
setItemUIName(std::wstring value,const QString & name)375   void setItemUIName(std::wstring value, const QString &name) {
376     int index = indexOf(value);
377     if (index < 0 || index >= (int)m_items.size()) throw RangeError();
378     m_items[index].UIName = name;
379   }
380 
deleteAllValues()381   void deleteAllValues() {
382     m_range.clear();
383     m_items.clear();
384     m_index = -1;
385   }
386 
setIndex(int index)387   void setIndex(int index) {
388     if (index < 0 || index >= (int)m_range.size()) throw RangeError();
389     m_index = index;
390   }
391 
setValue(const std::wstring & value)392   void setValue(const std::wstring &value) {
393     int idx = indexOf(value);
394     if (idx < 0) throw RangeError();
395     m_index = idx;
396   }
397 
getCount()398   int getCount() const { return (int)m_items.size(); }
399 
getRange()400   const Range &getRange() const { return m_range; }
getItems()401   const Items &getItems() const { return m_items; }
402 
getValue()403   std::wstring getValue() const {
404     return (m_index < 0) ? L"" : m_range[m_index];
405   }
getValueAsString()406   std::string getValueAsString() override {
407     return ::to_string(m_range[m_index]);
408   }
409 
getIndex()410   int getIndex() const { return m_index; }
411 
accept(Visitor & v)412   void accept(Visitor &v) override { v.visit(this); }
413 
414   static void enableRangeSaving(bool on);
415   static bool isRangeSavingEnabled();
416 
417   void assignUIName(TProperty *refP) override;
418 
419 private:
420   Range m_range;
421   Items m_items;
422   int m_index;
423 };
424 
425 //---------------------------------------------------------
426 
427 class DVAPI TPropertyGroup {
428 public:
429   typedef std::vector<std::pair<TProperty *, bool>> PropertyVector;
430   typedef std::map<std::string, TProperty *> PropertyTable;
431 
432   // exception
433   class PropertyNotFoundError {};
434 
435   TPropertyGroup();
436   virtual ~TPropertyGroup();
437 
438   virtual TPropertyGroup *clone() const;
439 
440   //! get ownership
441   void add(TProperty *p);
442 
443   //! don't get ownership
444   void bind(TProperty &p);
445 
446   //! returns 0 if the property doesn't exist
447   TProperty *getProperty(std::string name);
getProperty(int i)448   TProperty *getProperty(int i) {
449     return (i >= (int)m_properties.size()) ? 0 : m_properties[i].first;
450   }
451 
452   void setProperties(TPropertyGroup *g);
453 
454   void accept(TProperty::Visitor &v);
455 
getPropertyCount()456   int getPropertyCount() const { return (int)m_properties.size(); }
457 
458   void loadData(TIStream &is);
459   void saveData(TOStream &os) const;
460 
461   void clear();
462 
463   // for adding translation to file writers properties
updateTranslation()464   virtual void updateTranslation(){};
465 
466   void assignUINames(TPropertyGroup *refPg);
467 
468 private:
469   PropertyTable m_table;
470   PropertyVector m_properties;
471 
472 private:
473   // not implemented
474   TPropertyGroup(const TPropertyGroup &);
475   TPropertyGroup &operator=(const TPropertyGroup &);
476 };
477 
478 //---------------------------------------------------------
479 
480 #ifdef _MSC_VER
481 #pragma warning(pop)
482 #endif
483 
484 #endif
485