// Copyright (c) 2010, Amar Takhar // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /// @file option_value.h /// @brief Container for holding an actual option value. /// @ingroup libaegisub #include #include #include #include #include // X11 is awesome and defines Bool to int #undef Bool namespace agi { /// Option type /// No bitsets here. enum class OptionType { String = 0, ///< String Int = 1, ///< Integer Double = 2, ///< Double Color = 3, ///< Color Bool = 4, ///< Bool ListString = 100, ///< List of Strings ListInt = 101, ///< List of Integers ListDouble = 102, ///< List of Doubles ListColor = 103, ///< List of Colors ListBool = 104 ///< List of Bools }; /// @class OptionValue /// Holds an actual option. class OptionValue { agi::signal::Signal ValueChanged; std::string name; std::string TypeToString(OptionType type) const; InternalError TypeError(OptionType type) const; template T *As(OptionType type) { if (GetType() == type) return static_cast(this); throw TypeError(type); } template const T *As(OptionType type) const { if (GetType() == type) return static_cast(this); throw TypeError(type); } protected: void NotifyChanged() { ValueChanged(*this); } OptionValue(std::string name) BOOST_NOEXCEPT : name(std::move(name)) { } public: virtual ~OptionValue() = default; std::string const& GetName() const { return name; } virtual OptionType GetType() const = 0; virtual bool IsDefault() const = 0; virtual void Reset() = 0; std::string const& GetString() const; int64_t const& GetInt() const; double const& GetDouble() const; Color const& GetColor() const; bool const& GetBool() const; std::string const& GetDefaultString() const; int64_t const& GetDefaultInt() const; double const& GetDefaultDouble() const; Color const& GetDefaultColor() const; bool const& GetDefaultBool() const; void SetString(const std::string); void SetInt(const int64_t); void SetDouble(const double); void SetColor(const Color); void SetBool(const bool); std::vector const& GetListString() const; std::vector const& GetListInt() const; std::vector const& GetListDouble() const; std::vector const& GetListColor() const; std::vector const& GetListBool() const; std::vector const& GetDefaultListString() const; std::vector const& GetDefaultListInt() const; std::vector const& GetDefaultListDouble() const; std::vector const& GetDefaultListColor() const; std::vector const& GetDefaultListBool() const; void SetListString(std::vector); void SetListInt(std::vector); void SetListDouble(std::vector); void SetListColor(std::vector); void SetListBool(std::vector); virtual void Set(const OptionValue *new_value)=0; DEFINE_SIGNAL_ADDERS(ValueChanged, Subscribe) }; #define CONFIG_OPTIONVALUE(type_name, type) \ class OptionValue##type_name final : public OptionValue { \ type value; \ type value_default; \ public: \ typedef type value_type; \ OptionValue##type_name(std::string member_name, type member_value) \ : OptionValue(std::move(member_name)) \ , value(member_value), value_default(member_value) { } \ type const& GetValue() const { return value; } \ type const& GetDefault() const { return value_default; } \ void SetValue(type new_val) { value = std::move(new_val); NotifyChanged(); } \ OptionType GetType() const { return OptionType::type_name; } \ void Reset() { value = value_default; NotifyChanged(); } \ bool IsDefault() const { return value == value_default; } \ void Set(const OptionValue *nv); \ }; CONFIG_OPTIONVALUE(String, std::string) CONFIG_OPTIONVALUE(Int, int64_t) CONFIG_OPTIONVALUE(Double, double) CONFIG_OPTIONVALUE(Color, Color) CONFIG_OPTIONVALUE(Bool, bool) #define CONFIG_OPTIONVALUE_LIST(type_name, type) \ class OptionValueList##type_name final : public OptionValue { \ std::vector array; \ std::vector array_default; \ std::string name; \ public: \ typedef std::vector value_type; \ OptionValueList##type_name(std::string name, std::vector const& value = std::vector()) \ : OptionValue(std::move(name)) \ , array(value), array_default(value) { } \ std::vector const& GetValue() const { return array; } \ std::vector const& GetDefault() const { return array_default; } \ void SetValue(std::vector val) { array = std::move(val); NotifyChanged(); } \ OptionType GetType() const { return OptionType::List##type_name; } \ void Reset() { array = array_default; NotifyChanged(); } \ bool IsDefault() const { return array == array_default; } \ void Set(const OptionValue *nv); \ }; CONFIG_OPTIONVALUE_LIST(String, std::string) CONFIG_OPTIONVALUE_LIST(Int, int64_t) CONFIG_OPTIONVALUE_LIST(Double, double) CONFIG_OPTIONVALUE_LIST(Color, Color) CONFIG_OPTIONVALUE_LIST(Bool, bool) #define CONFIG_OPTIONVALUE_ACCESSORS(ReturnType, Type) \ inline ReturnType const& OptionValue::Get##Type() const { return As(OptionType::Type)->GetValue(); } \ inline ReturnType const& OptionValue::GetDefault##Type() const { return As(OptionType::Type)->GetDefault(); } \ inline void OptionValue::Set##Type(ReturnType v) { As(OptionType::Type)->SetValue(std::move(v)); } CONFIG_OPTIONVALUE_ACCESSORS(std::string, String) CONFIG_OPTIONVALUE_ACCESSORS(int64_t, Int) CONFIG_OPTIONVALUE_ACCESSORS(double, Double) CONFIG_OPTIONVALUE_ACCESSORS(Color, Color) CONFIG_OPTIONVALUE_ACCESSORS(bool, Bool) CONFIG_OPTIONVALUE_ACCESSORS(std::vector, ListString) CONFIG_OPTIONVALUE_ACCESSORS(std::vector, ListInt) CONFIG_OPTIONVALUE_ACCESSORS(std::vector, ListDouble) CONFIG_OPTIONVALUE_ACCESSORS(std::vector, ListColor) CONFIG_OPTIONVALUE_ACCESSORS(std::vector, ListBool) #undef CONFIG_OPTIONVALUE #undef CONFIG_OPTIONVALUE_LIST #undef CONFIG_OPTIONVALUE_ACCESSORS } // namespace agi