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 "ui/properties/dirty_flag.h"
23
24 #include "base/memory/ace_type.h"
25 #include "base/utils/macros.h"
26 #include "base/utils/noncopyable.h"
27 #include "base/utils/utils.h"
28
29 namespace OHOS::Ace::NG {
30
31 using FrameNodeChangeInfoFlag = uint32_t;
32 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_INFO_NONE = 0;
33 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_START_SCROLL = 1 << 1;
34 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_END_SCROLL = 1 << 2;
35 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_START_ANIMATION = 1 << 3;
36 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_GEOMETRY_CHANGE = 1 << 4;
37 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_TRANSFORM_CHANGE = 1 << 5;
38 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_TRANSITION_START = 1 << 6;
39 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CONTENT_CLIP_CHANGE = 1 << 7;
40 inline constexpr FrameNodeChangeInfoFlag FRAME_NODE_CHANGE_ALL =
41 FRAME_NODE_CHANGE_INFO_NONE | FRAME_NODE_CHANGE_START_SCROLL | FRAME_NODE_CHANGE_END_SCROLL |
42 FRAME_NODE_CHANGE_START_ANIMATION | FRAME_NODE_CHANGE_GEOMETRY_CHANGE | FRAME_NODE_CHANGE_TRANSFORM_CHANGE |
43 FRAME_NODE_CHANGE_TRANSITION_START | FRAME_NODE_CONTENT_CLIP_CHANGE;
44
CheckNeedMakePropertyDiff(PropertyChangeFlag flag)45 inline bool CheckNeedMakePropertyDiff(PropertyChangeFlag flag)
46 {
47 return (flag & PROPERTY_UPDATE_DIFF) == PROPERTY_UPDATE_DIFF;
48 }
49
50 bool CheckNeedRender(PropertyChangeFlag propertyChangeFlag);
51
52 bool CheckNeedRequestMeasureAndLayout(PropertyChangeFlag propertyChangeFlag);
53
54 bool CheckNeedRequestParentMeasure(PropertyChangeFlag propertyChangeFlag);
55
56 bool CheckNeedMeasure(PropertyChangeFlag propertyChangeFlag);
57
58 bool CheckNeedLayout(PropertyChangeFlag propertyChangeFlag);
59
60 bool CheckMeasureFlag(PropertyChangeFlag propertyChangeFlag);
61
62 bool CheckForceParentMeasureFlag(PropertyChangeFlag propertyChangeFlag);
63
64 bool CheckLayoutFlag(PropertyChangeFlag propertyChangeFlag);
65
66 bool CheckMeasureSelfFlag(PropertyChangeFlag propertyChangeFlag);
67
68 bool CheckMeasureSelfAndParentFlag(PropertyChangeFlag propertyChangeFlag);
69
70 bool CheckMeasureSelfAndChildFlag(PropertyChangeFlag propertyChangeFlag);
71
72 bool CheckUpdateByChildRequest(PropertyChangeFlag propertyChangeFlag);
73
74 bool CheckNoChanged(PropertyChangeFlag propertyChangeFlag);
75
76 // For XXXProperty Class
77 #define ACE_DEFINE_PROPERTY_GROUP(group, type) \
78 public: \
79 const std::unique_ptr<type>& GetOrCreate##group() \
80 { \
81 if (!prop##group##_) { \
82 prop##group##_ = std::make_unique<type>(); \
83 } \
84 return prop##group##_; \
85 } \
86 const std::unique_ptr<type>& Get##group() const \
87 { \
88 return prop##group##_; \
89 } \
90 std::unique_ptr<type> Clone##group() const \
91 { \
92 if (prop##group##_) { \
93 return std::make_unique<type>(*prop##group##_); \
94 } \
95 return nullptr; \
96 } \
97 void Reset##group() \
98 { \
99 return prop##group##_.reset(); \
100 } \
101 \
102 protected: \
103 std::unique_ptr<type> prop##group##_;
104
105 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
106 public: \
107 std::optional<type> Get##name() const \
108 { \
109 auto& groupProperty = Get##group(); \
110 if (groupProperty) { \
111 return groupProperty->Get##name(); \
112 } \
113 return std::nullopt; \
114 } \
115 bool Has##name() const \
116 { \
117 auto& groupProperty = Get##group(); \
118 if (groupProperty) { \
119 return groupProperty->Has##name(); \
120 } \
121 return false; \
122 } \
123 type Get##name##Value(const type& defaultValue) const \
124 { \
125 auto& groupProperty = Get##group(); \
126 if (groupProperty) { \
127 if (groupProperty->Has##name()) { \
128 return groupProperty->Get##name##Value(); \
129 } \
130 } \
131 return defaultValue; \
132 } \
133 void Reset##name() \
134 { \
135 auto& groupProperty = Get##group(); \
136 if (groupProperty) { \
137 groupProperty->Reset##name(); \
138 } \
139 }
140
141 // For different members of the same type, such as the same foreground and background color types, but the interface
142 // names provided to the outside world need to be different.
143 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM_GET(group, groupItem, name, type) \
144 public: \
145 std::optional<type> Get##name() const \
146 { \
147 auto& groupProperty = Get##group(); \
148 if (groupProperty) { \
149 return groupProperty->Get##groupItem(); \
150 } \
151 return std::nullopt; \
152 } \
153 bool Has##name() const \
154 { \
155 auto& groupProperty = Get##group(); \
156 if (groupProperty) { \
157 return groupProperty->Has##groupItem(); \
158 } \
159 return false; \
160 } \
161 type Get##name##Value(const type& defaultValue) const \
162 { \
163 auto& groupProperty = Get##group(); \
164 if (groupProperty) { \
165 if (groupProperty->Has##groupItem()) { \
166 return groupProperty->Get##groupItem##Value(); \
167 } \
168 } \
169 return defaultValue; \
170 }
171
172 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(group, name, type, changeFlag) \
173 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
174 void Update##name(const type& value) \
175 { \
176 auto& groupProperty = GetOrCreate##group(); \
177 if (groupProperty->Check##name(value)) { \
178 return; \
179 } \
180 groupProperty->Update##name(value); \
181 UpdatePropertyChangeFlag(changeFlag); \
182 }
183
184 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM(group, groupItem, name, type, changeFlag) \
185 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM_GET(group, groupItem, name, type) \
186 void Update##name(const type& value) \
187 { \
188 auto& groupProperty = GetOrCreate##group(); \
189 if (groupProperty->Check##groupItem(value)) { \
190 return; \
191 } \
192 groupProperty->Update##groupItem(value); \
193 UpdatePropertyChangeFlag(changeFlag); \
194 }
195
196 #define ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_AND_CALLBACK(group, name, type, changeFlag) \
197 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
198 void Update##name(const type& value) \
199 { \
200 auto& groupProperty = GetOrCreate##group(); \
201 if (groupProperty->Check##name(value)) { \
202 return; \
203 } \
204 groupProperty->Update##name(value); \
205 UpdatePropertyChangeFlag(changeFlag); \
206 On##name##Update(value); \
207 }
208
209 #define ACE_DEFINE_PROPERTY_FUNC_WITH_GROUP(group, name, type) \
210 ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_GET(group, name, type) \
211 void Update##name(const type& value) \
212 { \
213 auto& groupProperty = GetOrCreate##group(); \
214 if (groupProperty->Check##name(value)) { \
215 return; \
216 } \
217 groupProperty->Update##name(value); \
218 On##name##Update(value); \
219 }
220
221 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
222 public: \
223 const std::optional<type>& Get##name() const \
224 { \
225 return prop##name##_; \
226 } \
227 bool Has##name() const \
228 { \
229 return prop##name##_.has_value(); \
230 } \
231 const type& Get##name##Value() const \
232 { \
233 return prop##name##_.value(); \
234 } \
235 const type& Get##name##Value(const type& defaultValue) const \
236 { \
237 if (!Has##name()) { \
238 return defaultValue; \
239 } \
240 return prop##name##_.value(); \
241 } \
242 std::optional<type> Clone##name() const \
243 { \
244 return prop##name##_; \
245 } \
246 void Reset##name() \
247 { \
248 return prop##name##_.reset(); \
249 } \
250 \
251 protected: \
252 std::optional<type> prop##name##_;
253
254 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(name, type, changeFlag) \
255 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
256 public: \
257 void Update##name(const type& value) \
258 { \
259 if (prop##name##_.has_value()) { \
260 if (NearEqual(prop##name##_.value(), value)) { \
261 return; \
262 } \
263 } \
264 prop##name##_ = value; \
265 UpdatePropertyChangeFlag(changeFlag); \
266 }
267
268 #define ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_AND_USING_CALLBACK(name, type, changeFlag) \
269 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
270 public: \
271 void Update##name(const type& value) \
272 { \
273 if (prop##name##_.has_value()) { \
274 if (NearEqual(prop##name##_.value(), value)) { \
275 return; \
276 } \
277 } \
278 prop##name##_ = value; \
279 UpdatePropertyChangeFlag(changeFlag); \
280 On##name##Update(value); \
281 }
282
283 #define ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP(name, type) \
284 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
285 public: \
286 void Update##name(const type& value) \
287 { \
288 if (prop##name##_.has_value()) { \
289 if (NearEqual(prop##name##_.value(), value)) { \
290 return; \
291 } \
292 } \
293 prop##name##_ = value; \
294 On##name##Update(value); \
295 }
296
297 #define ACE_DEFINE_PROPERTY_ITEM_FUNC_WITHOUT_GROUP_FOR_VIRTUAL_NODE(name, type) \
298 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
299 public: \
300 void Update##name(const type& value, const int64_t accessibilityIdForVirtualNode = -2100000) \
301 { \
302 if (prop##name##_.has_value()) { \
303 if (NearEqual(prop##name##_.value(), value)) { \
304 return; \
305 } \
306 } \
307 prop##name##_ = value; \
308 On##name##Update(value, accessibilityIdForVirtualNode); \
309 }
310
311 // For Property Group Struct
312 #define ACE_DEFINE_PROPERTY_GROUP_ITEM(name, type) \
313 std::optional<type> prop##name; \
314 \
315 const std::optional<type>& Get##name() const \
316 { \
317 return prop##name; \
318 } \
319 bool Has##name() const \
320 { \
321 return prop##name.has_value(); \
322 } \
323 type Get##name##Value() const \
324 { \
325 return prop##name.value(); \
326 } \
327 bool Update##name(const type& value) \
328 { \
329 if (prop##name.has_value()) { \
330 if (NearEqual(prop##name.value(), value)) { \
331 return false; \
332 } \
333 } \
334 prop##name = value; \
335 return true; \
336 } \
337 bool Update##name(const std::optional<type>& value) \
338 { \
339 if (value.has_value()) { \
340 return Update##name(value.value()); \
341 } \
342 return false; \
343 } \
344 bool Check##name(const type& value) const \
345 { \
346 if (!prop##name.has_value()) { \
347 return false; \
348 } \
349 return NearEqual(prop##name.value(), value); \
350 } \
351 void Reset##name() \
352 { \
353 prop##name.reset(); \
354 }
355
356 #define ACE_DEFINE_PROPERTY_GROUP_ITEM_WITH_CALLBACK(name, type) \
357 ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP_GET(name, type) \
358 public: \
359 bool Update##name(const type& value) \
360 { \
361 if (prop##name##_.has_value()) { \
362 if (NearEqual(prop##name##_.value(), value)) { \
363 return false; \
364 } \
365 } \
366 On##name##Update(value); \
367 prop##name##_ = value; \
368 return true; \
369 }
370
371 #define ACE_PROPERTY_TO_JSON_VALUE(target, type) \
372 do { \
373 if (target) { \
374 (target)->ToJsonValue(json, filter); \
375 } else { \
376 type p; \
377 p.ToJsonValue(json, filter); \
378 } \
379 } while (false)
380
381 class ACE_EXPORT Property : public virtual AceType {
382 DECLARE_ACE_TYPE(Property, AceType);
383
384 public:
385 Property() = default;
386
387 ~Property() override = default;
388
GetPropertyChangeFlag()389 PropertyChangeFlag GetPropertyChangeFlag() const
390 {
391 return propertyChangeFlag_;
392 }
393
CleanDirty()394 void CleanDirty()
395 {
396 propertyChangeFlag_ = PROPERTY_UPDATE_NORMAL;
397 }
398
UpdatePropertyChangeFlag(PropertyChangeFlag propertyChangeFlag)399 void UpdatePropertyChangeFlag(PropertyChangeFlag propertyChangeFlag)
400 {
401 propertyChangeFlag_ = propertyChangeFlag_ | propertyChangeFlag;
402 }
403
404 protected:
405 PropertyChangeFlag propertyChangeFlag_ = PROPERTY_UPDATE_NORMAL;
406
407 ACE_DISALLOW_COPY_AND_MOVE(Property);
408 };
409 } // namespace OHOS::Ace::NG
410
411 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PROPERTIES_PROPERTY_H
412