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