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