#ifndef DATA_SETTING_HPP_ #define DATA_SETTING_HPP_ #include #include #include #include #include "../typedefs.hpp" #include "../delegates.hpp" enum class setting_format { simple, percent }; class Setting { protected: setting_format format; public: Setting(setting_format format) : format(format) { } virtual ~Setting() {} virtual void resetToDefault() = 0; virtual setting_format getFormat() const { return format; } virtual std::string toString() const = 0; }; template class ObservableSetting : public Setting { int nextid = 1; std::unordered_map> observers; protected: T initial; T value; public: ObservableSetting(T value, setting_format format) : Setting(format), initial(value), value(value) {} observer_handler observe(consumer callback, bool callOnStart=false) { const int id = nextid++; observers.emplace(id, callback); if (callOnStart) { callback(value); } return std::shared_ptr(new int(id), [this](int* id) { observers.erase(*id); delete id; }); } const T& get() const { return value; } T& operator*() { return value; } void notify(T value) { for (auto& entry : observers) { entry.second(value); } } void set(T value) { if (value == this->value) { return; } this->value = value; notify(value); } virtual void resetToDefault() override { set(initial); } }; class NumberSetting : public ObservableSetting { protected: number_t min; number_t max; public: NumberSetting( number_t value, number_t min=std::numeric_limits::min(), number_t max=std::numeric_limits::max(), setting_format format=setting_format::simple ) : ObservableSetting(value, format), min(min), max(max) {} number_t& operator*() { return value; } number_t get() const { return value; } number_t getMin() const { return min; } number_t getMax() const { return max; } number_t getT() const { return (value - min) / (max - min); } virtual std::string toString() const override; static inline NumberSetting createPercent(number_t def) { return NumberSetting(def, 0.0, 1.0, setting_format::percent); } }; class IntegerSetting : public ObservableSetting { protected: integer_t min; integer_t max; public: IntegerSetting( integer_t value, integer_t min=std::numeric_limits::min(), integer_t max=std::numeric_limits::max(), setting_format format=setting_format::simple ) : ObservableSetting(value, format), min(min), max(max) {} integer_t getMin() const { return min; } integer_t getMax() const { return max; } integer_t getT() const { return (value - min) / (max - min); } virtual std::string toString() const override; }; class FlagSetting : public ObservableSetting { public: FlagSetting( bool value, setting_format format=setting_format::simple ) : ObservableSetting(value, format) {} void toggle() { set(!get()); } virtual std::string toString() const override; }; class StringSetting : public ObservableSetting { public: StringSetting( std::string value, setting_format format=setting_format::simple ) : ObservableSetting(value, format) {} virtual std::string toString() const override; }; #endif // DATA_SETTING_HPP_