1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_PROPERTY_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_PROPERTY_H
18
19 #include <cstdint>
20 #include <optional>
21
22 #include "base/memory/ace_type.h"
23 #include "base/utils/macros.h"
24 #include "base/utils/noncopyable.h"
25
26 namespace OHOS::Ace::NG {
27 using PropertyChangeFlag = uint32_t;
28
29 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_NORMAL = 0;
30 // Mark self, parent, children to remeasure.
31 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE = 1;
32 // Mark self to reLayout.
33 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_LAYOUT = 1 << 1;
34
35 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_DIFF = 1 << 2;
36
37 // Mark self to remeasure.
38 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE_SELF = 1 << 3;
39
40 // Mark self and parent to remeasure.
41 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT = 1 << 4;
42
43 // Mark self remeasure due to child size may change, which may mark parent, self and children to remeasure.
44 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_BY_CHILD_REQUEST = 1 << 5;
45
46 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_RENDER = 1 << 6;
47 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST = 1 << 7;
48
49 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_EVENT = 1 << 8;
50
51 inline constexpr PropertyChangeFlag PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD = 1 << 9;
52
CheckNeedMakePropertyDiff(PropertyChangeFlag flag)53 inline bool CheckNeedMakePropertyDiff(PropertyChangeFlag flag)
54 {
55 return (flag & PROPERTY_UPDATE_DIFF) == PROPERTY_UPDATE_DIFF;
56 }
57
58 bool CheckNeedRender(PropertyChangeFlag propertyChangeFlag);
59
60 bool CheckNeedRequestMeasureAndLayout(PropertyChangeFlag propertyChangeFlag);
61
62 bool CheckNeedRequestParentMeasure(PropertyChangeFlag propertyChangeFlag);
63
64 bool CheckNeedMeasure(PropertyChangeFlag propertyChangeFlag);
65
66 bool CheckNeedLayout(PropertyChangeFlag propertyChangeFlag);
67
68 bool CheckMeasureFlag(PropertyChangeFlag propertyChangeFlag);
69
70 bool CheckForceParentMeasureFlag(PropertyChangeFlag propertyChangeFlag);
71
72 bool CheckLayoutFlag(PropertyChangeFlag propertyChangeFlag);
73
74 bool CheckMeasureSelfFlag(PropertyChangeFlag propertyChangeFlag);
75
76 bool CheckMeasureSelfAndParentFlag(PropertyChangeFlag propertyChangeFlag);
77
78 bool CheckMeasureSelfAndChildFlag(PropertyChangeFlag propertyChangeFlag);
79
80 bool CheckUpdateByChildRequest(PropertyChangeFlag propertyChangeFlag);
81
82 bool CheckNoChanged(PropertyChangeFlag propertyChangeFlag);
83
84 // For XXXProperty Class
85 #define ACE_DEFINE_PROPERTY_GROUP(group, type) \
86 public: \
87 const std::unique_ptr<type>& GetOrCreate##group() \
88 { \
89 if (!prop##group##_) { \
90 prop##group##_ = std::make_unique<type>(); \
91 } \
92 return prop##group##_; \
93 } \
94 const std::unique_ptr<type>& Get##group() const \
95 { \
96 return prop##group##_; \
97 } \
98 std::unique_ptr<type> Clone##group() const \
99 { \
100 if (prop##group##_) { \
101 return std::make_unique<type>(*prop##group##_); \
102 } \
103 return nullptr; \
104 } \
105 void Reset##group() \
106 { \
107 return prop##group##_.reset(); \
108 } \
109 \
110 protected: \
111 std::unique_ptr<type> prop##group##_;
112
113 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
114 public: \
115 std::optional<type> Get##name() const \
116 { \
117 auto& groupProperty = Get##group(); \
118 if (groupProperty) { \
119 return groupProperty->Get##name(); \
120 } \
121 return std::nullopt; \
122 } \
123 bool Has##name() const \
124 { \
125 auto& groupProperty = Get##group(); \
126 if (groupProperty) { \
127 return groupProperty->Has##name(); \
128 } \
129 return false; \
130 } \
131 type Get##name##Value(const type& defaultValue) const \
132 { \
133 auto& groupProperty = Get##group(); \
134 if (groupProperty) { \
135 if (groupProperty->Has##name()) { \
136 return groupProperty->Get##name##Value(); \
137 } \
138 } \
139 return defaultValue; \
140 } \
141 void Reset##name() \
142 { \
143 auto& groupProperty = Get##group(); \
144 if (groupProperty) { \
145 groupProperty->Reset##name(); \
146 } \
147 }
148
149 // For different members of the same type, such as the same foreground and background color types, but the interface
150 // names provided to the outside world need to be different.
151 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM_GET(group, groupItem, name, type) \
152 public: \
153 std::optional<type> Get##name() const \
154 { \
155 auto& groupProperty = Get##group(); \
156 if (groupProperty) { \
157 return groupProperty->Get##groupItem(); \
158 } \
159 return std::nullopt; \
160 } \
161 bool Has##name() const \
162 { \
163 auto& groupProperty = Get##group(); \
164 if (groupProperty) { \
165 return groupProperty->Has##groupItem(); \
166 } \
167 return false; \
168 } \
169 type Get##name##Value(const type& defaultValue) const \
170 { \
171 auto& groupProperty = Get##group(); \
172 if (groupProperty) { \
173 if (groupProperty->Has##groupItem()) { \
174 return groupProperty->Get##groupItem##Value(); \
175 } \
176 } \
177 return defaultValue; \
178 }
179
180 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(group, name, type, changeFlag) \
181 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
182 void Update##name(const type& value) \
183 { \
184 auto& groupProperty = GetOrCreate##group(); \
185 if (groupProperty->Check##name(value)) { \
186 return; \
187 } \
188 groupProperty->Update##name(value); \
189 UpdatePropertyChangeFlag(changeFlag); \
190 }
191
192 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM(group, groupItem, name, type, changeFlag) \
193 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM_GET(group, groupItem, name, type) \
194 void Update##name(const type& value) \
195 { \
196 auto& groupProperty = GetOrCreate##group(); \
197 if (groupProperty->Check##groupItem(value)) { \
198 return; \
199 } \
200 groupProperty->Update##groupItem(value); \
201 UpdatePropertyChangeFlag(changeFlag); \
202 }
203
204 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_AND_CALLBACK(group, name, type, changeFlag) \
205 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
206 void Update##name(const type& value) \
207 { \
208 auto& groupProperty = GetOrCreate##group(); \
209 if (groupProperty->Check##name(value)) { \
210 return; \
211 } \
212 groupProperty->Update##name(value); \
213 UpdatePropertyChangeFlag(changeFlag); \
214 On##name##Update(value); \
215 }
216
217 #define ACE_DEFINE_PROPERTY_FUNC_WITH_GROUP(group, name, type) \
218 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
219 void Update##name(const type& value) \
220 { \
221 auto& groupProperty = GetOrCreate##group(); \
222 if (groupProperty->Check##name(value)) { \
223 return; \
224 } \
225 groupProperty->Update##name(value); \
226 On##name##Update(value); \
227 }
228
229 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
230 public: \
231 const std::optional<type>& Get##name() const \
232 { \
233 return prop##name##_; \
234 } \
235 bool Has##name() const \
236 { \
237 return prop##name##_.has_value(); \
238 } \
239 const type& Get##name##Value() const \
240 { \
241 return prop##name##_.value(); \
242 } \
243 const type& Get##name##Value(const type& defaultValue) const \
244 { \
245 if (!Has##name()) { \
246 return defaultValue; \
247 } \
248 return prop##name##_.value(); \
249 } \
250 std::optional<type> Clone##name() const \
251 { \
252 return prop##name##_; \
253 } \
254 void Reset##name() \
255 { \
256 return prop##name##_.reset(); \
257 } \
258 \
259 protected: \
260 std::optional<type> prop##name##_;
261
262 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(name, type, changeFlag) \
263 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
264 public: \
265 void Update##name(const type& value) \
266 { \
267 if (prop##name##_.has_value()) { \
268 if (NearEqual(prop##name##_.value(), value)) { \
269 return; \
270 } \
271 } \
272 prop##name##_ = value; \
273 UpdatePropertyChangeFlag(changeFlag); \
274 }
275
276 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_AND_USING_CALLBACK(name, type, changeFlag) \
277 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
278 public: \
279 void Update##name(const type& value) \
280 { \
281 if (prop##name##_.has_value()) { \
282 if (NearEqual(prop##name##_.value(), value)) { \
283 return; \
284 } \
285 } \
286 prop##name##_ = value; \
287 UpdatePropertyChangeFlag(changeFlag); \
288 On##name##Update(value); \
289 }
290
291 #define ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP(name, type) \
292 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
293 public: \
294 void Update##name(const type& value) \
295 { \
296 if (prop##name##_.has_value()) { \
297 if (NearEqual(prop##name##_.value(), value)) { \
298 return; \
299 } \
300 } \
301 prop##name##_ = value; \
302 On##name##Update(value); \
303 }
304
305 // For Property Group Struct
306 #define ACE_DEFINE_PROPERTY_GROUP_ITEM(name, type) \
307 std::optional<type> prop##name; \
308 \
309 const std::optional<type>& Get##name() const \
310 { \
311 return prop##name; \
312 } \
313 bool Has##name() const \
314 { \
315 return prop##name.has_value(); \
316 } \
317 type Get##name##Value() const \
318 { \
319 return prop##name.value(); \
320 } \
321 bool Update##name(const type& value) \
322 { \
323 if (prop##name.has_value()) { \
324 if (NearEqual(prop##name.value(), value)) { \
325 return false; \
326 } \
327 } \
328 prop##name = value; \
329 return true; \
330 } \
331 bool Check##name(const type& value) const \
332 { \
333 if (!prop##name.has_value()) { \
334 return false; \
335 } \
336 return NearEqual(prop##name.value(), value); \
337 } \
338 void Reset##name() \
339 { \
340 prop##name.reset(); \
341 }
342
343 #define ACE_PROPERTY_TO_JSON_VALUE(target, type) \
344 do { \
345 if (target) { \
346 (target)->ToJsonValue(json); \
347 } else { \
348 type p; \
349 p.ToJsonValue(json); \
350 } \
351 } while (false)
352
353 class ACE_EXPORT Property : public virtual AceType {
354 DECLARE_ACE_TYPE(Property, AceType);
355
356 public:
357 Property() = default;
358
359 ~Property() override = default;
360
GetPropertyChangeFlag()361 PropertyChangeFlag GetPropertyChangeFlag() const
362 {
363 return propertyChangeFlag_;
364 }
365
CleanDirty()366 void CleanDirty()
367 {
368 propertyChangeFlag_ = PROPERTY_UPDATE_NORMAL;
369 }
370
UpdatePropertyChangeFlag(PropertyChangeFlag propertyChangeFlag)371 void UpdatePropertyChangeFlag(PropertyChangeFlag propertyChangeFlag)
372 {
373 propertyChangeFlag_ = propertyChangeFlag_ | propertyChangeFlag;
374 }
375
376 protected:
377 PropertyChangeFlag propertyChangeFlag_ = PROPERTY_UPDATE_NORMAL;
378
379 ACE_DISALLOW_COPY_AND_MOVE(Property);
380 };
381 } // namespace OHOS::Ace::NG
382
383 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_PROPERTY_H