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