Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(429)

Side by Side Diff: ui/base/class_property.h

Issue 2632543003: Refactor and push window properties up to class properties. (Closed)
Patch Set: More build fixes Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/base/BUILD.gn ('k') | ui/base/class_property.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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_
OLDNEW
« no previous file with comments | « ui/base/BUILD.gn ('k') | ui/base/class_property.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698