#ifndef _GLIBMM_VALUE_H #define _GLIBMM_VALUE_H /* Copyright 2002 The gtkmm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include #include #include #include #include namespace Glib { class ObjectBase; class Object; /** @defgroup glibmmValue Generic Values * * Glib::Value<> is specialized for almost any type used within * the glibmm and gtkmm libraries. * * - Basic types like int, char, bool, etc., also void*. * - Glib::ustring and std::string. * - Pointers to classes derived from Glib::Object. * - Glib::RefPtr<> pointer types, which are assumed to be Glib::Object pointers. * - All flags and enum types used within the gtkmm libraries. * * If a type doesn't fit into any of these categories, then a generic * implementation for custom types will be used. The requirements imposed * on custom types are described in the Glib::Value class documentation. */ /** * @ingroup glibmmValue */ class GLIBMM_API ValueBase { public: /** Initializes the GValue, but without a type. You have to * call init() before using the set(), get(), or reset() methods. */ ValueBase(); ValueBase(const ValueBase& other); ValueBase& operator=(const ValueBase& other); ~ValueBase() noexcept; /** Setup the GValue for storing the specified @a type. * The contents will be initialized to the default value for this type. * Note that init() should never be called twice. * * init() is not implemented as constructor, to avoid the necessity * to implement a forward constructor in each derived class. * * @param type The type that the Value should hold. */ void init(GType type); /** Setup the GValue storing the type and value of the specified @a value. * Note that init() should never be called twice. * * init() is not implemented as constructor, to avoid the necessity * to implement a forward constructor in each derived class. * * @param value The existing GValue. */ void init(const GValue* value); /** Reset contents to the default value of its type. */ void reset(); GValue* gobj() { return &gobject_; } const GValue* gobj() const { return &gobject_; } protected: GValue gobject_; }; /** * @ingroup glibmmValue */ class GLIBMM_API ValueBase_Boxed : public ValueBase { public: static GType value_type() G_GNUC_CONST; #ifndef DOXYGEN_SHOULD_SKIP_THIS GParamSpec* create_param_spec(const Glib::ustring& name, const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const; #endif protected: void set_boxed(const void* data); void* get_boxed() const; // doesn't copy }; /** * @ingroup glibmmValue */ class GLIBMM_API ValueBase_Object : public ValueBase { public: static GType value_type() G_GNUC_CONST; #ifndef DOXYGEN_SHOULD_SKIP_THIS GParamSpec* create_param_spec(const Glib::ustring& name, const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const; #endif protected: void set_object(Glib::ObjectBase* data); Glib::ObjectBase* get_object() const; Glib::RefPtr get_object_copy() const; }; /** * @ingroup glibmmValue */ class GLIBMM_API ValueBase_Enum : public ValueBase { public: static GType value_type() G_GNUC_CONST; #ifndef DOXYGEN_SHOULD_SKIP_THIS GParamSpec* create_param_spec(const Glib::ustring& name, const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const; #endif protected: void set_enum(int data); int get_enum() const; }; /** * @ingroup glibmmValue */ class GLIBMM_API ValueBase_Flags : public ValueBase { public: static GType value_type() G_GNUC_CONST; #ifndef DOXYGEN_SHOULD_SKIP_THIS GParamSpec* create_param_spec(const Glib::ustring& name, const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const; #endif protected: void set_flags(unsigned int data); unsigned int get_flags() const; }; /** * @ingroup glibmmValue */ class GLIBMM_API ValueBase_String : public ValueBase { public: static GType value_type() G_GNUC_CONST; #ifndef DOXYGEN_SHOULD_SKIP_THIS GParamSpec* create_param_spec(const Glib::ustring& name, const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const; #endif protected: void set_cstring(const char* data); const char* get_cstring() const; // never returns nullptr }; /** * @ingroup glibmmValue */ class GLIBMM_API ValueBase_Variant : public ValueBase { public: static GType value_type() G_GNUC_CONST; #ifndef DOXYGEN_SHOULD_SKIP_THIS GParamSpec* create_param_spec(const Glib::ustring& name, const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const; #endif protected: void set_variant(GVariant* data); GVariant* get_variant() const; // doesn't copy, may return nullptr }; } // namespace Glib /* Include primary Glib::Value<> template, before any specializations: */ #define _GLIBMM_VALUE_H_INCLUDE_VALUE_CUSTOM_H #include #undef _GLIBMM_VALUE_H_INCLUDE_VALUE_CUSTOM_H namespace Glib { /** * @ingroup glibmmValue */ template class Value_Boxed : public ValueBase_Boxed { // Used by _CLASS_BOXEDTYPE and _CLASS_BOXEDTYPE_STATIC public: using CppType = T; static GType value_type() { return T::get_type(); } void set(const CppType& data) { set_boxed(data.gobj()); } CppType get() const { return CppType(static_cast(get_boxed())); } }; /** * @ingroup glibmmValue */ template class Value_RefPtrBoxed : public ValueBase_Boxed { // Used by _CLASS_OPAQUE_REFCOUNTED with _IS_REFCOUNTED_BOXEDTYPE public: using CppType = Glib::RefPtr; static GType value_type() { return T::get_type(); } // Equivalent to set_boxed(Glib::unwrap(data)) without including wrap.h. void set(const CppType& data) { set_boxed(data ? data->gobj() : nullptr); } // get() is defined in the Value<> specializations. It requires the declaration // of Glib::wrap(T::BaseObjectType*, bool) to be visible. // CppType get() const { return Glib::wrap(static_cast(get_boxed()), true); } }; // More spec-compliant compilers (such as Tru64) need this to be near Glib::Object instead. #ifdef GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION namespace Traits { template struct HasGetBaseType; template struct HasGetBaseType { template struct Check; template static std::true_type Test(Check*); template static std::false_type Test(...); static const bool value = decltype(Test(0))::value; //using type = decltype(Test(0)); }; } // namespace Traits /** Partial specialization for RefPtr<> to Glib::Object. * @ingroup glibmmValue */ template class Value, typename std::enable_if::value>::type> : public ValueBase_Object { public: using CppType = Glib::RefPtr; static GType value_type() { return T::get_base_type(); } void set(const CppType& data) { set_object(const_cast*>(data.get())); } CppType get() const { return std::dynamic_pointer_cast(get_object_copy()); } }; // The SUN Forte Compiler has a problem with this: #ifdef GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS /** Partial specialization for RefPtr<> to const Glib::Object. * @ingroup glibmmValue */ /* template class Value, typename std::enable_if::value>::type> : public ValueBase_Object { public: using CppType = Glib::RefPtr; static GType value_type() { return T::get_base_type(); } void set(const CppType& data) { set_object(const_cast(data.get())); } CppType get() const { return std::dynamic_pointer_cast(get_object_copy()); } }; */ #endif // GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS #endif // GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION } // namespace Glib /* Include generated specializations of Glib::Value<> for fundamental types: */ #define _GLIBMM_VALUE_H_INCLUDE_VALUE_BASICTYPES_H #include #undef _GLIBMM_VALUE_H_INCLUDE_VALUE_BASICTYPES_H namespace Glib { /** Specialization for strings. * @ingroup glibmmValue */ template <> class GLIBMM_API Value : public ValueBase_String { public: using CppType = std::string; void set(const std::string& data); std::string get() const { return get_cstring(); } }; /** Specialization for UTF-8 strings. * @ingroup glibmmValue */ template <> class GLIBMM_API Value : public ValueBase_String { public: using CppType = Glib::ustring; void set(const Glib::ustring& data); Glib::ustring get() const { return get_cstring(); } }; /** Specialization for vectors of strings. * @ingroup glibmmValue */ template <> class GLIBMM_API Value> : public ValueBase_Boxed { public: using CppType = std::vector; static GType value_type(); void set(const CppType& data); CppType get() const; }; /** Specialization for vectors of UTF-8 strings. * @ingroup glibmmValue */ template <> class GLIBMM_API Value> : public ValueBase_Boxed { public: using CppType = std::vector; static GType value_type(); void set(const CppType& data); CppType get() const; }; /** Base class of Glib::Value specializations for enum types. * @ingroup glibmmValue */ template class Value_Enum : public ValueBase_Enum { public: using CppType = T; void set(CppType data) { set_enum(static_cast(data)); } CppType get() const { return CppType(get_enum()); } }; /** Base class of Glib::Value specializations for flags types. * @ingroup glibmmValue */ template class Value_Flags : public ValueBase_Flags { public: using CppType = T; void set(CppType data) { set_flags(static_cast(data)); } CppType get() const { return CppType(get_flags()); } }; } // namespace Glib #endif /* _GLIBMM_VALUE_H */