OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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 | |
5 #ifndef UI_BASE_CLASS_PROPERTY_H_ | |
6 #define UI_BASE_CLASS_PROPERTY_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include <map> | |
11 #include <memory> | |
12 #include <set> | |
13 | |
14 #include "ui/base/property_data.h" | |
15 #include "ui/base/ui_base_export.h" | |
16 #include "ui/base/ui_base_types.h" | |
17 | |
18 // This header should be included by code that defines ClassProperties. | |
19 // | |
20 // To define a new ClassProperty: | |
21 // | |
22 // #include "foo/foo_export.h" | |
23 // #include "ui/base/class_property.h" | |
24 // | |
25 // DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(FOO_EXPORT, MyType); | |
26 // namespace foo { | |
27 // // Use this to define an exported property that is primitive, | |
28 // // or a pointer you don't want automatically deleted. | |
29 // DEFINE_UI_CLASS_PROPERTY_KEY(MyType, kMyKey, MyDefault); | |
30 // | |
31 // // Use this to define an exported property whose value is a heap | |
32 // // allocated object, and has to be owned and freed by the class. | |
33 // DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Rect, kRestoreBoundsKey, NULL); | |
34 // | |
35 // // Use this to define a non exported property that is primitive, | |
36 // // or a pointer you don't want to automatically deleted, and is used | |
37 // // only in a specific file. This will define the property in an unnamed | |
38 // // namespace which cannot be accessed from another file. | |
39 // DEFINE_LOCAL_UI_CLASS_PROPERTY_KEY(MyType, kMyKey, MyDefault); | |
40 // | |
41 // } // foo namespace | |
42 // | |
43 // To define a new type used for ClassProperty. | |
44 // | |
45 // // outside all namespaces: | |
46 // DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(FOO_EXPORT, MyType) | |
47 // | |
48 // If a property type is not exported, use DECLARE_CLASS_PROPERTY_TYPE(MyType) | |
49 // which is a shorthand for DECLARE_EXPORTED_CLASS_PROPERTY_TYPE(, MyType). | |
50 | |
51 namespace ui { | |
52 | |
53 // Type of a function to delete a property that this window owns. | |
54 using PropertyDeallocator = void(*)(int64_t value); | |
55 | |
56 template<typename T> | |
57 struct ClassProperty { | |
58 T default_value; | |
59 const char* name; | |
60 PropertyDeallocator deallocator; | |
61 }; | |
62 | |
63 namespace subtle { | |
64 | |
65 class PropertyHelper; | |
66 | |
67 } | |
68 | |
69 class UI_BASE_EXPORT PropertyHandler { | |
70 public: | |
71 PropertyHandler(); | |
72 ~PropertyHandler(); | |
73 | |
74 // Sets the |value| of the given class |property|. Setting to the default | |
75 // value (e.g., NULL) removes the property. The caller is responsible for the | |
76 // lifetime of any object set as a property on the class. | |
77 template<typename T> | |
78 void SetProperty(const ClassProperty<T>* property, T value); | |
79 | |
80 // Returns the value of the given class |property|. Returns the | |
81 // property-specific default value if the property was not previously set. | |
82 template<typename T> | |
83 T GetProperty(const ClassProperty<T>* property) const; | |
84 | |
85 // Sets the |property| to its default value. Useful for avoiding a cast when | |
86 // setting to NULL. | |
87 template<typename T> | |
88 void ClearProperty(const ClassProperty<T>* property); | |
89 | |
90 // Returns the value of all properties with a non-default value. | |
91 std::set<const void*> GetAllPropertyKeys() const; | |
sky
2017/02/01 00:54:02
Thanks for fixing the spelling here!
kylix_rd
2017/02/01 18:43:14
Not a problem. It happens.
| |
92 | |
93 protected: | |
94 friend class subtle::PropertyHelper; | |
95 | |
96 virtual void AfterPropertyChange(const void* key, | |
97 int64_t old_value, | |
98 std::unique_ptr<PropertyData> data) {} | |
99 virtual std::unique_ptr<PropertyData> BeforePropertyChange(const void* key); | |
100 void ClearProperties(); | |
101 | |
102 // Called by the public {Set,Get,Clear}Property functions. | |
103 int64_t SetPropertyInternal(const void* key, | |
104 const char* name, | |
105 PropertyDeallocator deallocator, | |
106 int64_t value, | |
107 int64_t default_value); | |
108 int64_t GetPropertyInternal(const void* key, int64_t default_value) const; | |
109 | |
110 private: | |
111 // Value struct to keep the name and deallocator for this property. | |
112 // Key cannot be used for this purpose because it can be char* or | |
113 // ClassProperty<>. | |
114 struct Value { | |
115 const char* name; | |
116 int64_t value; | |
117 PropertyDeallocator deallocator; | |
118 }; | |
119 | |
120 std::map<const void*, Value> prop_map_; | |
121 }; | |
122 | |
123 namespace { | |
124 | |
125 // No single new-style cast works for every conversion to/from int64_t, so we | |
126 // need this helper class. A third specialization is needed for bool because | |
127 // MSVC warning C4800 (forcing value to bool) is not suppressed by an explicit | |
128 // cast (!). | |
129 template<typename T> | |
130 class ClassPropertyCaster { | |
131 public: | |
132 static int64_t ToInt64(T x) { return static_cast<int64_t>(x); } | |
133 static T FromInt64(int64_t x) { return static_cast<T>(x); } | |
134 }; | |
135 template<typename T> | |
136 class ClassPropertyCaster<T*> { | |
137 public: | |
138 static int64_t ToInt64(T* x) { return reinterpret_cast<int64_t>(x); } | |
139 static T* FromInt64(int64_t x) { return reinterpret_cast<T*>(x); } | |
140 }; | |
141 template<> | |
142 class ClassPropertyCaster<bool> { | |
143 public: | |
144 static int64_t ToInt64(bool x) { return static_cast<int64_t>(x); } | |
145 static bool FromInt64(int64_t x) { return x != 0; } | |
146 }; | |
147 | |
148 } // namespace | |
149 | |
150 namespace subtle { | |
151 | |
152 class UI_BASE_EXPORT PropertyHelper { | |
153 public: | |
154 template<typename T> | |
155 static void Set(::ui::PropertyHandler* handler, | |
156 const ::ui::ClassProperty<T>* property, T value) { | |
157 int64_t old = handler->SetPropertyInternal( | |
158 property, property->name, | |
159 value == property->default_value ? nullptr : property->deallocator, | |
160 ClassPropertyCaster<T>::ToInt64(value), | |
161 ClassPropertyCaster<T>::ToInt64(property->default_value)); | |
162 if (property->deallocator && | |
163 old != ClassPropertyCaster<T>::ToInt64(property->default_value)) { | |
164 (*property->deallocator)(old); | |
165 } | |
166 } | |
167 template<typename T> | |
168 static T Get(const ::ui::PropertyHandler* handler, | |
169 const ::ui::ClassProperty<T>* property) { | |
170 return ClassPropertyCaster<T>::FromInt64(handler->GetPropertyInternal( | |
171 property, ClassPropertyCaster<T>::ToInt64(property->default_value))); | |
172 } | |
173 template<typename T> | |
174 static void Clear(::ui::PropertyHandler* handler, | |
175 const ::ui::ClassProperty<T>* property) { | |
176 handler->SetProperty(property, property->default_value); | |
177 } | |
178 }; | |
179 | |
180 } // namespace subtle | |
181 | |
182 } // namespace ui | |
183 | |
184 // Macros to instantiate the property getter/setter template functions. | |
185 #define DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(EXPORT, T) \ | |
186 namespace ui { \ | |
187 template <> \ | |
188 EXPORT void PropertyHandler::SetProperty( \ | |
189 const ClassProperty<T>* property, T value) { \ | |
190 subtle::PropertyHelper::Set<T>(this, property, value); \ | |
191 } \ | |
192 template <> \ | |
193 EXPORT T PropertyHandler::GetProperty( \ | |
194 const ClassProperty<T>* property) const { \ | |
195 return subtle::PropertyHelper::Get<T>(this, property); \ | |
196 } \ | |
197 template <> \ | |
198 EXPORT void PropertyHandler::ClearProperty( \ | |
199 const ClassProperty<T>* property) { \ | |
200 subtle::PropertyHelper::Clear<T>(this, property); \ | |
201 } \ | |
202 } | |
203 | |
204 #define DECLARE_UI_CLASS_PROPERTY_TYPE(T) \ | |
205 DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(, T) | |
206 | |
207 #define DEFINE_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ | |
208 static_assert(sizeof(TYPE) <= sizeof(int64_t), "property type too large"); \ | |
209 namespace { \ | |
210 const ::ui::ClassProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \ | |
211 } \ | |
212 const ::ui::ClassProperty<TYPE>* const NAME = &NAME##_Value; | |
213 | |
214 #define DEFINE_LOCAL_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ | |
215 static_assert(sizeof(TYPE) <= sizeof(int64_t), "property type too large"); \ | |
216 namespace { \ | |
217 const ::ui::ClassProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \ | |
218 const ::ui::ClassProperty<TYPE>* const NAME = &NAME##_Value; \ | |
219 } | |
220 | |
221 #define DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ | |
222 namespace { \ | |
223 void Deallocator##NAME(int64_t p) { \ | |
224 enum { type_must_be_complete = sizeof(TYPE) }; \ | |
225 delete ::ui::ClassPropertyCaster<TYPE*>::FromInt64(p); \ | |
226 } \ | |
227 const ::ui::ClassProperty<TYPE*> NAME##_Value = {DEFAULT, #NAME, \ | |
228 &Deallocator##NAME}; \ | |
229 } \ | |
230 const ::ui::ClassProperty<TYPE*>* const NAME = &NAME##_Value; | |
231 | |
232 #endif // UI_BASE_CLASS_PROPERTY_H_ | |
OLD | NEW |