property_metadata.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef UI_BASE_METADATA_PROPERTY_METADATA_H_
  5. #define UI_BASE_METADATA_PROPERTY_METADATA_H_
  6. #include <string>
  7. #include <type_traits>
  8. #include <utility>
  9. #include "base/component_export.h"
  10. #include "ui/base/class_property.h"
  11. #include "ui/base/metadata/base_type_conversion.h"
  12. #include "ui/base/metadata/metadata_cache.h"
  13. #include "ui/base/metadata/metadata_types.h"
  14. namespace ui {
  15. namespace metadata {
  16. namespace internal {
  17. template <typename TSource, typename TTarget, typename = void>
  18. struct DeRefHelper {
  19. static TTarget Get(TSource value) { return value; }
  20. };
  21. template <typename TSource, typename TTarget>
  22. struct DeRefHelper<
  23. TSource,
  24. TTarget,
  25. typename std::enable_if<!std::is_same<TSource, TTarget>::value>::type> {
  26. static TTarget Get(TSource value) { return *value; }
  27. };
  28. template <typename TKey, typename TValue>
  29. struct ClassPropertyMetaDataTypeHelper;
  30. template <typename TKValue_, typename TValue_>
  31. struct ClassPropertyMetaDataTypeHelper<const ui::ClassProperty<TKValue_>* const,
  32. TValue_> {
  33. using TKValue = TKValue_;
  34. using TValue = TValue_;
  35. // Returns |value| when |TKValue| == |TValue|. Otherwise, TKValue must be the
  36. // pointer type to TValue, returns |*value| instead.
  37. // This is useful for owned propertyies like ui::ClassProperty<gfx::Insets*>
  38. // where we want to inspect the actual value, rather than the pointer.
  39. static TValue DeRef(TKValue value) {
  40. return DeRefHelper<TKValue, TValue>::Get(value);
  41. }
  42. };
  43. // Works around static casting issues related to the void*. See the comment on
  44. // the METADATA_ACCESSORS_INTERNAL_BASE macro for more information about why
  45. // this is necessary. NOTE: The reinterpret_cast<> here is merely to bring
  46. // ReinterpretToBaseClass() into scope and make it callable. The body of that
  47. // function does not access |this|, so this call is safe.
  48. template <typename TClass>
  49. TClass* AsClass(void* obj) {
  50. return static_cast<TClass*>(
  51. reinterpret_cast<TClass*>(obj)->ReinterpretToBaseClass(obj));
  52. }
  53. } // namespace internal
  54. // Represents meta data for a specific read-only property member of class
  55. // |TClass|, with underlying type |TValue|, as the type of the actual member.
  56. // Using a separate |TRet| type for the getter function's return type to allow
  57. // it to return a type with qualifier and by reference.
  58. template <typename TClass,
  59. typename TValue,
  60. typename TRet,
  61. TRet (TClass::*Get)() const,
  62. typename TConverter = ui::metadata::TypeConverter<TValue>>
  63. class ObjectPropertyReadOnlyMetaData : public ui::metadata::MemberMetaDataBase {
  64. public:
  65. using MemberMetaDataBase::MemberMetaDataBase;
  66. ObjectPropertyReadOnlyMetaData(const ObjectPropertyReadOnlyMetaData&) =
  67. delete;
  68. ObjectPropertyReadOnlyMetaData& operator=(
  69. const ObjectPropertyReadOnlyMetaData&) = delete;
  70. ~ObjectPropertyReadOnlyMetaData() override = default;
  71. std::u16string GetValueAsString(void* obj) const override {
  72. if (!kTypeIsSerializable && !kTypeIsReadOnly)
  73. return std::u16string();
  74. return TConverter::ToString((internal::AsClass<TClass>(obj)->*Get)());
  75. }
  76. ui::metadata::PropertyFlags GetPropertyFlags() const override {
  77. return kTypeIsSerializable ? (ui::metadata::PropertyFlags::kReadOnly |
  78. ui::metadata::PropertyFlags::kSerializable)
  79. : ui::metadata::PropertyFlags::kReadOnly;
  80. }
  81. const char* GetMemberNamePrefix() const override {
  82. return TConverter::PropertyNamePrefix();
  83. }
  84. private:
  85. static constexpr bool kTypeIsSerializable = TConverter::is_serializable;
  86. static constexpr bool kTypeIsReadOnly = TConverter::is_read_only;
  87. };
  88. // Represents meta data for a specific property member of class |TClass|, with
  89. // underlying type |TValue|, as the type of the actual member.
  90. // Allows for interaction with the property as if it were the underlying data
  91. // type (|TValue|), but still uses the Property's functionality under the hood
  92. // (so it will trigger things like property changed notifications).
  93. template <typename TClass,
  94. typename TValue,
  95. typename TSig,
  96. TSig Set,
  97. typename TRet,
  98. TRet (TClass::*Get)() const,
  99. typename TConverter = ui::metadata::TypeConverter<TValue>>
  100. class ObjectPropertyMetaData
  101. : public ObjectPropertyReadOnlyMetaData<TClass,
  102. TValue,
  103. TRet,
  104. Get,
  105. TConverter> {
  106. public:
  107. using ObjectPropertyReadOnlyMetaData<TClass, TValue, TRet, Get, TConverter>::
  108. ObjectPropertyReadOnlyMetaData;
  109. ObjectPropertyMetaData(const ObjectPropertyMetaData&) = delete;
  110. ObjectPropertyMetaData& operator=(const ObjectPropertyMetaData&) = delete;
  111. ~ObjectPropertyMetaData() override = default;
  112. void SetValueAsString(void* obj, const std::u16string& new_value) override {
  113. if (!kTypeIsSerializable || kTypeIsReadOnly)
  114. return;
  115. if (absl::optional<TValue> result = TConverter::FromString(new_value)) {
  116. (internal::AsClass<TClass>(obj)->*Set)(std::move(result.value()));
  117. }
  118. }
  119. ui::metadata::MemberMetaDataBase::ValueStrings GetValidValues()
  120. const override {
  121. if (!kTypeIsSerializable)
  122. return {};
  123. return TConverter::GetValidStrings();
  124. }
  125. ui::metadata::PropertyFlags GetPropertyFlags() const override {
  126. ui::metadata::PropertyFlags flags = ui::metadata::PropertyFlags::kEmpty;
  127. if (kTypeIsSerializable)
  128. flags = flags | ui::metadata::PropertyFlags::kSerializable;
  129. if (kTypeIsReadOnly)
  130. flags = flags | ui::metadata::PropertyFlags::kReadOnly;
  131. return flags;
  132. }
  133. private:
  134. static constexpr bool kTypeIsSerializable = TConverter::is_serializable;
  135. static constexpr bool kTypeIsReadOnly = TConverter::is_read_only;
  136. };
  137. // Represents metadata for a ui::ClassProperty attached on a class instance.
  138. // Converts property value to |TValue| when possible. This allows inspecting
  139. // the actual value when the property is a pointer of type |TValue*|.
  140. template <typename TClass,
  141. typename TKey,
  142. typename TValue,
  143. typename TConverter = ui::metadata::TypeConverter<TValue>>
  144. class ClassPropertyMetaData : public ui::metadata::MemberMetaDataBase {
  145. public:
  146. using TypeHelper = internal::ClassPropertyMetaDataTypeHelper<TKey, TValue>;
  147. ClassPropertyMetaData(TKey key, const std::string& property_type)
  148. : MemberMetaDataBase(key->name, property_type), key_(key) {}
  149. ClassPropertyMetaData(const ClassPropertyMetaData&) = delete;
  150. ClassPropertyMetaData& operator=(const ClassPropertyMetaData&) = delete;
  151. ~ClassPropertyMetaData() override = default;
  152. // Returns the property value as a string.
  153. // If the property value is an pointer of type |TKValue*| and
  154. // |TKValue| == |TValue|, dereferences the pointer.
  155. std::u16string GetValueAsString(void* obj) const override {
  156. typename TypeHelper::TKValue value =
  157. internal::AsClass<TClass>(obj)->GetProperty(key_);
  158. if (std::is_pointer<typename TypeHelper::TKValue>::value && !value) {
  159. return u"(not assigned)";
  160. } else {
  161. // GetProperty() returns a pointer when this is an owned property.
  162. // If |TValue| is not pointer, DeRef() returns |*value|, otherwise
  163. // it returns |value| as it is.
  164. return TConverter::ToString(TypeHelper::DeRef(value));
  165. }
  166. }
  167. void SetValueAsString(void* obj, const std::u16string& new_value) override {
  168. absl::optional<TValue> value = TConverter::FromString(new_value);
  169. if (value)
  170. internal::AsClass<TClass>(obj)->SetProperty(key_, *value);
  171. }
  172. ui::metadata::PropertyFlags GetPropertyFlags() const override {
  173. ui::metadata::PropertyFlags flags = ui::metadata::PropertyFlags::kEmpty;
  174. if (kTypeIsSerializable)
  175. flags = flags | ui::metadata::PropertyFlags::kSerializable;
  176. if (kTypeIsReadOnly)
  177. flags = flags | ui::metadata::PropertyFlags::kReadOnly;
  178. return flags;
  179. }
  180. private:
  181. TKey key_;
  182. static constexpr bool kTypeIsSerializable = TConverter::is_serializable;
  183. static constexpr bool kTypeIsReadOnly = TConverter::is_read_only;
  184. };
  185. } // namespace metadata
  186. } // namespace ui
  187. #endif // UI_BASE_METADATA_PROPERTY_METADATA_H_