Aegisub/aegisub/libaegisub/include/libaegisub/option_value.h

200 lines
11 KiB
C++

// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
//
// 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.
//
// $Id$
/// @file option_value.h
/// @brief Container for holding an actual option value.
/// @ingroup libaegisub
#ifndef LAGI_PRE
#include <fstream>
#include <stdint.h>
#include "libaegisub/cajun/reader.h"
#include "libaegisub/cajun/writer.h"
#include "libaegisub/cajun/elements.h"
#endif
#include <libaegisub/exception.h>
#include <libaegisub/colour.h>
namespace agi {
DEFINE_BASE_EXCEPTION_NOINNER(OptionValueError, Exception)
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorNotFound, OptionValueError, "options/not_found")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidType, OptionValueError, "options/invalid_type")
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidListType, OptionValueError, "options/array/invalid_type")
class OptionValue;
class ConfigVisitor;
/// @class OptionValueListener
/// Inherit from this class to get the proper type for the notification callback
/// signature.
class OptionValueListener {
public:
// (I might have messed up the syntax here. It's supposed to be a pointer
// to a member function of an OptionValueListener-derived class.)
typedef void (OptionValueListener::*ChangeEvent)(const OptionValue *option);
};
/// @class OptionValue
/// Holds an actual option.
class OptionValue {
std::set<OptionValueListener*> listeners;
protected:
void NotifyChanged();
public:
OptionValue() {};
virtual ~OptionValue() {};
/// Option type
/// No bitsets here.
enum OptionType {
Type_String = 0, ///< String
Type_Int = 1, ///< Integer
Type_Double = 2, ///< Double
Type_Colour = 3, ///< Colour
Type_Bool = 4, ///< Bool
Type_List_String = 100, ///< List of Strings
Type_List_Int = 101, ///< List of Integers
Type_List_Double = 102, ///< List of Doubles
Type_List_Colour = 103, ///< List of Colours
Type_List_Bool = 104 ///< List of Bools
};
virtual OptionType GetType() const = 0;
virtual std::string GetName() const = 0;
virtual bool IsDefault() const = 0;
virtual void Reset() = 0;
virtual std::string GetString() const { throw OptionValueErrorInvalidType("Attempt to retrieve string from non-string value"); }
virtual int64_t GetInt() const { throw OptionValueErrorInvalidType("Attempt to retrieve int from non-int value"); }
virtual double GetDouble() const { throw OptionValueErrorInvalidType("Attempt to retrieve double from non-double value"); }
virtual Colour GetColour() const { throw OptionValueErrorInvalidType("Attempt to retrieve colour from non-colour value"); }
virtual bool GetBool() const { throw OptionValueErrorInvalidType("Attempt to retrieve bool from non-bool value"); }
virtual void SetString(const std::string val) { throw OptionValueErrorInvalidType("Attempt to set string in a non-string value"); }
virtual void SetInt(const int64_t val) { throw OptionValueErrorInvalidType("Attempt to set int in a non-int value"); }
virtual void SetDouble(const double val) { throw OptionValueErrorInvalidType("Attempt to set double in a non-double value"); }
virtual void SetColour(const Colour val) { throw OptionValueErrorInvalidType("Attempt to set colour in a non-colour value"); }
virtual void SetBool(const bool val) { throw OptionValueErrorInvalidType("Attempt to set bool in a non-bool value"); }
virtual std::string GetDefaultString() const { throw OptionValueErrorInvalidType("Attempt to retrieve string from non-string value"); }
virtual int64_t GetDefaultInt() const { throw OptionValueErrorInvalidType("Attempt to retrieve int from non-int value"); }
virtual double GetDefaultDouble() const { throw OptionValueErrorInvalidType("Attempt to retrieve double from non-double value"); }
virtual Colour GetDefaultColour() const { throw OptionValueErrorInvalidType("Attempt to retrieve colour from non-colour value"); }
virtual bool GetDefaultBool() const { throw OptionValueErrorInvalidType("Attempt to retrieve bool from non-bool value"); }
virtual void GetListString(std::vector<std::string> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string list from non-string list"); }
virtual void GetListInt(std::vector<int64_t> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive int list from non-int list"); }
virtual void GetListDouble(std::vector<double> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive double list from non-double list"); }
virtual void GetListColour(std::vector<Colour> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive colour list from non-colour list"); }
virtual void GetListBool(std::vector<bool> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string bool from non-bool list"); }
virtual void SetListString(const std::vector<std::string> val) { throw OptionValueErrorInvalidListType("Attempt to set string list in a non-string list"); }
virtual void SetListInt(const std::vector<int64_t> val) { throw OptionValueErrorInvalidListType("Attempt to set int list in a non-int list"); }
virtual void SetListDouble(const std::vector<double> val) { throw OptionValueErrorInvalidListType("Attempt to set double list in a non-double list"); }
virtual void SetListColour(const std::vector<Colour> val) { throw OptionValueErrorInvalidListType("Attempt to set colour list in a non-colour list"); }
virtual void SetListBool(const std::vector<bool> val) { throw OptionValueErrorInvalidListType("Attempt to set string in a non-bool list"); }
virtual void GetDefaultListString(std::vector<std::string> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string list from non-string list"); }
virtual void GetDefaultListInt(std::vector<int64_t> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive int list from non-int list"); }
virtual void GetDefaultListDouble(std::vector<double> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive double list from non-double list"); }
virtual void GetDefaultListColour(std::vector<Colour> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive colour list from non-colour list"); }
virtual void GetDefaultListBool(std::vector<bool> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string bool from non-bool list"); }
void Subscribe(OptionValueListener*);
void Unsubscribe(OptionValueListener*);
void Subscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent handler);
void Unsubscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent handler);
};
#define CONFIG_OPTIONVALUE(type_name, type) \
class OptionValue##type_name : public OptionValue { \
type value; \
type value_default; \
std::string name; \
public: \
OptionValue##type_name(std::string member_name, type member_value): \
value(member_value), name(member_name) {} \
type Get##type_name() const { return value; } \
void Set##type_name(const type new_val) { value = new_val; } \
type GetDefault##type_name() const { return value_default; } \
OptionType GetType() const { return OptionValue::Type_##type_name; } \
std::string GetName() const { return name; } \
void Reset() { value = value_default; } \
bool IsDefault() const { return (value == value_default) ? 1 : 0; } \
};
CONFIG_OPTIONVALUE(String, std::string)
CONFIG_OPTIONVALUE(Int, int64_t)
CONFIG_OPTIONVALUE(Double, double)
CONFIG_OPTIONVALUE(Colour, Colour)
CONFIG_OPTIONVALUE(Bool, bool)
class OptionValueList: public OptionValue {
friend class ConfigVisitor;
protected:
OptionValueList() {};
virtual ~OptionValueList() {};
virtual void InsertString(const std::string val) { throw OptionValueErrorInvalidListType("Attempt to insert string in a non-string list"); }
virtual void InsertInt(const int64_t val) { throw OptionValueErrorInvalidListType("Attempt to insert int in a non-int list"); }
virtual void InsertDouble(const double val) { throw OptionValueErrorInvalidListType("Attempt to insert double in a non-double list"); }
virtual void InsertColour(const Colour val) { throw OptionValueErrorInvalidListType("Attempt insert set colour in a from non-colour list"); }
virtual void InsertBool(const bool val) { throw OptionValueErrorInvalidListType("Attempt to insert bool in a non-bool list"); }
};
#define CONFIG_OPTIONVALUE_LIST(type_name, type) \
class OptionValueList##type_name : public OptionValueList { \
std::vector<type> array; \
std::vector<type> array_default; \
std::string name; \
void Insert##type_name(const type val) { array.push_back(val); } \
public: \
virtual std::string GetString() const { return "";} \
OptionValueList##type_name(std::string member_name): name(member_name) {} \
void GetList##type_name(std::vector<type> &out) const { out = array; } \
void SetList##type_name(const std::vector<type> val) { array = val;} \
void GetDefaultList##type_name(std::vector<type> &out) const { out = array_default; } \
OptionType GetType() const { return OptionValue::Type_List_##type_name; } \
std::string GetName() const { return name; } \
void Reset() { array = array_default; } \
bool IsDefault() const { return (array == array_default) ? 1 : 0; } \
};
CONFIG_OPTIONVALUE_LIST(String, std::string)
CONFIG_OPTIONVALUE_LIST(Int, int64_t)
CONFIG_OPTIONVALUE_LIST(Double, double)
CONFIG_OPTIONVALUE_LIST(Colour, Colour)
CONFIG_OPTIONVALUE_LIST(Bool, bool)
} // namespace agi