#ifndef UI_BASE_METADATA_PROPERTY_METADATA_H_
#define UI_BASE_METADATA_PROPERTY_METADATA_H_
#include <string>
#include <type_traits>
#include <utility>
#include "base/component_export.h"
#include "ui/base/class_property.h"
#include "ui/base/metadata/base_type_conversion.h"
#include "ui/base/metadata/metadata_cache.h"
#include "ui/base/metadata/metadata_types.h"
namespace ui {
namespace metadata {
namespace internal {
template <typename TSource, typename TTarget, typename = void>
struct DeRefHelper {
static TTarget Get(TSource value) { return value; }
};
template <typename TSource, typename TTarget>
struct DeRefHelper<
TSource,
TTarget,
typename std::enable_if<!std::is_same<TSource, TTarget>::value>::type> {
static TTarget Get(TSource value) { return *value; }
};
template <typename TKey, typename TValue>
struct ClassPropertyMetaDataTypeHelper;
template <typename TKValue_, typename TValue_>
struct ClassPropertyMetaDataTypeHelper<const ui::ClassProperty<TKValue_>* const,
TValue_> {
using TKValue = TKValue_;
using TValue = TValue_;
static TValue DeRef(TKValue value) {
return DeRefHelper<TKValue, TValue>::Get(value);
}
};
template <typename TClass>
TClass* AsClass(void* obj) {
return static_cast<TClass*>(
reinterpret_cast<TClass*>(obj)->ReinterpretToBaseClass(obj));
}
}
template <typename TClass,
typename TValue,
typename TRet,
TRet (TClass::*Get)() const,
typename TConverter = ui::metadata::TypeConverter<TValue>>
class ObjectPropertyReadOnlyMetaData : public ui::metadata::MemberMetaDataBase {
public:
using MemberMetaDataBase::MemberMetaDataBase;
ObjectPropertyReadOnlyMetaData(const ObjectPropertyReadOnlyMetaData&) =
delete;
ObjectPropertyReadOnlyMetaData& operator=(
const ObjectPropertyReadOnlyMetaData&) = delete;
~ObjectPropertyReadOnlyMetaData() override = default;
std::u16string GetValueAsString(void* obj) const override {
if (!kTypeIsSerializable && !kTypeIsReadOnly)
return std::u16string();
return TConverter::ToString((internal::AsClass<TClass>(obj)->*Get)());
}
ui::metadata::PropertyFlags GetPropertyFlags() const override {
return kTypeIsSerializable ? (ui::metadata::PropertyFlags::kReadOnly |
ui::metadata::PropertyFlags::kSerializable)
: ui::metadata::PropertyFlags::kReadOnly;
}
const char* GetMemberNamePrefix() const override {
return TConverter::PropertyNamePrefix();
}
private:
static constexpr bool kTypeIsSerializable = TConverter::is_serializable;
static constexpr bool kTypeIsReadOnly = TConverter::is_read_only;
};
template <typename TClass,
typename TValue,
typename TSig,
TSig Set,
typename TRet,
TRet (TClass::*Get)() const,
typename TConverter = ui::metadata::TypeConverter<TValue>>
class ObjectPropertyMetaData
: public ObjectPropertyReadOnlyMetaData<TClass,
TValue,
TRet,
Get,
TConverter> {
public:
using ObjectPropertyReadOnlyMetaData<TClass, TValue, TRet, Get, TConverter>::
ObjectPropertyReadOnlyMetaData;
ObjectPropertyMetaData(const ObjectPropertyMetaData&) = delete;
ObjectPropertyMetaData& operator=(const ObjectPropertyMetaData&) = delete;
~ObjectPropertyMetaData() override = default;
void SetValueAsString(void* obj, const std::u16string& new_value) override {
if (!kTypeIsSerializable || kTypeIsReadOnly)
return;
if (absl::optional<TValue> result = TConverter::FromString(new_value)) {
(internal::AsClass<TClass>(obj)->*Set)(std::move(result.value()));
}
}
ui::metadata::MemberMetaDataBase::ValueStrings GetValidValues()
const override {
if (!kTypeIsSerializable)
return {};
return TConverter::GetValidStrings();
}
ui::metadata::PropertyFlags GetPropertyFlags() const override {
ui::metadata::PropertyFlags flags = ui::metadata::PropertyFlags::kEmpty;
if (kTypeIsSerializable)
flags = flags | ui::metadata::PropertyFlags::kSerializable;
if (kTypeIsReadOnly)
flags = flags | ui::metadata::PropertyFlags::kReadOnly;
return flags;
}
private:
static constexpr bool kTypeIsSerializable = TConverter::is_serializable;
static constexpr bool kTypeIsReadOnly = TConverter::is_read_only;
};
template <typename TClass,
typename TKey,
typename TValue,
typename TConverter = ui::metadata::TypeConverter<TValue>>
class ClassPropertyMetaData : public ui::metadata::MemberMetaDataBase {
public:
using TypeHelper = internal::ClassPropertyMetaDataTypeHelper<TKey, TValue>;
ClassPropertyMetaData(TKey key, const std::string& property_type)
: MemberMetaDataBase(key->name, property_type), key_(key) {}
ClassPropertyMetaData(const ClassPropertyMetaData&) = delete;
ClassPropertyMetaData& operator=(const ClassPropertyMetaData&) = delete;
~ClassPropertyMetaData() override = default;
std::u16string GetValueAsString(void* obj) const override {
typename TypeHelper::TKValue value =
internal::AsClass<TClass>(obj)->GetProperty(key_);
if (std::is_pointer<typename TypeHelper::TKValue>::value && !value) {
return u"(not assigned)";
} else {
return TConverter::ToString(TypeHelper::DeRef(value));
}
}
void SetValueAsString(void* obj, const std::u16string& new_value) override {
absl::optional<TValue> value = TConverter::FromString(new_value);
if (value)
internal::AsClass<TClass>(obj)->SetProperty(key_, *value);
}
ui::metadata::PropertyFlags GetPropertyFlags() const override {
ui::metadata::PropertyFlags flags = ui::metadata::PropertyFlags::kEmpty;
if (kTypeIsSerializable)
flags = flags | ui::metadata::PropertyFlags::kSerializable;
if (kTypeIsReadOnly)
flags = flags | ui::metadata::PropertyFlags::kReadOnly;
return flags;
}
private:
TKey key_;
static constexpr bool kTypeIsSerializable = TConverter::is_serializable;
static constexpr bool kTypeIsReadOnly = TConverter::is_read_only;
};
}
}
#endif