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_BASE_VIEW_STACK_PROCESSOR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_BASE_VIEW_STACK_PROCESSOR_H
18 
19 #include <memory>
20 #include <stack>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "base/memory/referenced.h"
25 #include "core/common/container.h"
26 #include "core/common/container_scope.h"
27 #include "core/components/common/properties/animation_option.h"
28 #include "core/components_ng/base/frame_node.h"
29 #include "core/components_ng/base/ui_node.h"
30 #include "core/components_ng/event/state_style_manager.h"
31 #include "core/components_ng/layout/layout_property.h"
32 #include "core/gestures/gesture_processor.h"
33 #include "core/pipeline/base/render_context.h"
34 
35 #define ACE_UPDATE_LAYOUT_PROPERTY(target, name, value)                         \
36     do {                                                                        \
37         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \
38         ACE_UPDATE_NODE_LAYOUT_PROPERTY(target, name, value, frameNode);        \
39     } while (false)
40 #define ACE_UPDATE_NODE_LAYOUT_PROPERTY(target, name, value, frameNode)         \
41     do {                                                                        \
42         CHECK_NULL_VOID(frameNode);                                             \
43         auto cast##target = (frameNode)->GetLayoutPropertyPtr<target>();        \
44         if (cast##target) {                                                     \
45             cast##target->Update##name(value);                                  \
46         }                                                                       \
47     } while (false)
48 
49 #define ACE_GET_NODE_LAYOUT_PROPERTY(target, name, value, frameNode)            \
50     do {                                                                        \
51         auto cast##target = frameNode->GetLayoutPropertyPtr<target>();          \
52         if (cast##target) {                                                     \
53             value = cast##target->Get##name##Value();                           \
54         }                                                                       \
55     } while (false)
56 
57 #define ACE_GET_NODE_LAYOUT_PROPERTY_WITH_DEFAULT_VALUE(target, name, value, frameNode, defaultValue)   \
58     do {                                                                                                \
59         auto cast##target = frameNode->GetLayoutPropertyPtr<target>();                                  \
60         if (cast##target) {                                                                             \
61             value = cast##target->Get##name##Value(defaultValue);                                       \
62         }                                                                                               \
63     } while (false)
64 
65 #define ACE_UPDATE_PAINT_PROPERTY(target, name, value)                          \
66     do {                                                                        \
67         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \
68         ACE_UPDATE_NODE_PAINT_PROPERTY(target, name, value, frameNode);         \
69     } while (false)
70 #define ACE_UPDATE_NODE_PAINT_PROPERTY(target, name, value, frameNode)          \
71     do {                                                                        \
72         CHECK_NULL_VOID(frameNode);                                             \
73         auto cast##target = (frameNode)->GetPaintPropertyPtr<target>();         \
74         if (cast##target) {                                                     \
75             cast##target->Update##name(value);                                  \
76         }                                                                       \
77     } while (false)
78 
79 #define ACE_GET_NODE_PAINT_PROPERTY(target, name, value, frameNode)             \
80     do {                                                                        \
81         auto cast##target = frameNode->GetPaintPropertyPtr<target>();           \
82         if (cast##target) {                                                     \
83             value = cast##target->Get##name##Value();                           \
84         }                                                                       \
85     } while (false)
86 
87 #define ACE_GET_NODE_PAINT_PROPERTY_WITH_DEFAULT_VALUE(target, name, value, frameNode, defaultValue) \
88     do {                                                                                             \
89         auto cast##target = frameNode->GetPaintPropertyPtr<target>();                                \
90         if (cast##target) {                                                                          \
91             value = cast##target->Get##name##Value(defaultValue);                                    \
92         }                                                                                            \
93     } while (false)
94 
95 #define ACE_UPDATE_RENDER_CONTEXT(name, value)                                  \
96     do {                                                                        \
97         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \
98         ACE_UPDATE_NODE_RENDER_CONTEXT(name, value, frameNode);                 \
99     } while (false)
100 #define ACE_UPDATE_NODE_RENDER_CONTEXT(name, value, frameNode)                  \
101     do {                                                                        \
102         CHECK_NULL_VOID(frameNode);                                             \
103         const auto& target = (frameNode)->GetRenderContext();                   \
104         if (target) {                                                           \
105             target->Update##name(value);                                        \
106         }                                                                       \
107     } while (false)
108 
109 #define ACE_RESET_LAYOUT_PROPERTY(target, name)                                 \
110     do {                                                                        \
111         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \
112         ACE_RESET_NODE_LAYOUT_PROPERTY(target, name, frameNode);                \
113     } while (false)
114 #define ACE_RESET_NODE_LAYOUT_PROPERTY(target, name, frameNode)                 \
115     do {                                                                        \
116         CHECK_NULL_VOID(frameNode);                                             \
117         auto cast##target = frameNode->GetLayoutPropertyPtr<target>();          \
118         CHECK_NULL_VOID(cast##target);                                          \
119         cast##target->Reset##name();                                            \
120     } while (false)
121 
122 #define ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(target, name, changeFlag)                      \
123     do {                                                                                   \
124         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();            \
125         ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode);     \
126     } while (false)
127 #define ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode)      \
128     do {                                                                                   \
129         CHECK_NULL_VOID(frameNode);                                                        \
130         auto cast##target = frameNode->GetLayoutPropertyPtr<target>();                     \
131         CHECK_NULL_VOID(cast##target);                                                     \
132         if (cast##target->Has##name()) {                                                   \
133             cast##target->Reset##name();                                                   \
134             cast##target->UpdatePropertyChangeFlag(changeFlag);                            \
135         }                                                                                  \
136     } while (false)
137 
138 #define ACE_RESET_PAINT_PROPERTY(target, name)                                  \
139     do {                                                                        \
140         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \
141         ACE_RESET_NODE_PAINT_PROPERTY(target, name, frameNode);                 \
142     } while (false)
143 #define ACE_RESET_NODE_PAINT_PROPERTY(target, name, frameNode)                  \
144     do {                                                                        \
145         CHECK_NULL_VOID(frameNode);                                             \
146         auto cast##target = frameNode->GetPaintPropertyPtr<target>();           \
147         CHECK_NULL_VOID(cast##target);                                          \
148         cast##target->Reset##name();                                            \
149     } while (false)
150 
151 #define ACE_RESET_PAINT_PROPERTY_WITH_FLAG(target, name, changeFlag)                      \
152     do {                                                                                  \
153         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();           \
154         ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode);     \
155     } while (false)
156 #define ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode)      \
157     do {                                                                                  \
158         CHECK_NULL_VOID(frameNode);                                                       \
159         auto cast##target = frameNode->GetPaintPropertyPtr<target>();                     \
160         CHECK_NULL_VOID(cast##target);                                                    \
161         cast##target->Reset##name();                                                      \
162         cast##target->UpdatePropertyChangeFlag(changeFlag);                               \
163     } while (false)
164 
165 #define ACE_RESET_RENDER_CONTEXT(target, name)                                  \
166     do {                                                                        \
167         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \
168         ACE_RESET_NODE_RENDER_CONTEXT(target, name, frameNode);                 \
169     } while (false)
170 #define ACE_RESET_NODE_RENDER_CONTEXT(target, name, frameNode)                  \
171     do {                                                                        \
172         CHECK_NULL_VOID(frameNode);                                             \
173         const auto& cast##target = (frameNode)->GetRenderContext();             \
174         CHECK_NULL_VOID(cast##target);                                          \
175         cast##target->Reset##name();                                            \
176     } while (false)
177 
178 namespace OHOS::Ace::NG {
179 class ACE_EXPORT ViewStackProcessor final {
180 public:
181     friend class ScopedViewStackProcessor;
182 
183     ACE_FORCE_EXPORT static ViewStackProcessor* GetInstance();
184     ~ViewStackProcessor() = default;
185 
186     template<typename Pattern>
GetMainFrameNodePattern()187     RefPtr<Pattern> GetMainFrameNodePattern() const
188     {
189         auto frameNode = GetMainFrameNode();
190         if (!frameNode) {
191             return nullptr;
192         }
193         return AceType::DynamicCast<Pattern>(frameNode->GetPattern());
194     }
195 
196     template<typename Pattern>
GetMainFrameNodePattern(FrameNode * frameNode)197     RefPtr<Pattern> GetMainFrameNodePattern(FrameNode* frameNode) const
198     {
199         if (!frameNode) {
200             return nullptr;
201         }
202         return AceType::DynamicCast<Pattern>(frameNode->GetPattern());
203     }
204 
205     template<typename EventHubType>
GetMainFrameNodeEventHub()206     RefPtr<EventHubType> GetMainFrameNodeEventHub() const
207     {
208         auto frameNode = GetMainFrameNode();
209         if (!frameNode) {
210             return nullptr;
211         }
212         return frameNode->GetEventHub<EventHubType>();
213     }
214 
GetMainFrameNodeGestureEventHub()215     RefPtr<GestureEventHub> GetMainFrameNodeGestureEventHub() const
216     {
217         auto frameNode = GetMainFrameNode();
218         if (!frameNode) {
219             return nullptr;
220         }
221         return frameNode->GetOrCreateGestureEventHub();
222     }
223 
GetMainFrameNodeInputEventHub()224     RefPtr<InputEventHub> GetMainFrameNodeInputEventHub() const
225     {
226         auto frameNode = GetMainFrameNode();
227         if (!frameNode) {
228             return nullptr;
229         }
230         return frameNode->GetOrCreateInputEventHub();
231     }
232 
GetOrCreateMainFrameNodeFocusHub()233     RefPtr<FocusHub> GetOrCreateMainFrameNodeFocusHub() const
234     {
235         auto frameNode = GetMainFrameNode();
236         if (!frameNode) {
237             return nullptr;
238         }
239         return frameNode->GetOrCreateFocusHub();
240     }
241 
GetMainFrameNodeFocusHub()242     RefPtr<FocusHub> GetMainFrameNodeFocusHub() const
243     {
244         auto frameNode = GetMainFrameNode();
245         if (!frameNode) {
246             return nullptr;
247         }
248         return frameNode->GetFocusHub();
249     }
250 
251     ACE_FORCE_EXPORT FrameNode* GetMainFrameNode() const;
252 
253    // Get main component include composed component created by js view.
254     const RefPtr<UINode>& GetMainElementNode() const;
255 
256     // create wrappingComponentsMap and the component to map and then Push
257     // the map to the render component stack.
258     ACE_FORCE_EXPORT void Push(const RefPtr<UINode>& element, bool isCustomView = false);
259 
260     // Wrap the components map for the stack top and then pop the stack.
261     // Add the wrapped component has child of the new stack top's main component.
262     void Pop();
263 
264     // pop the last container
265     ACE_FORCE_EXPORT void PopContainer();
266 
267     // End of Render function, create component tree and flush modify task.
268     ACE_FORCE_EXPORT RefPtr<UINode> Finish();
269 
270     // Set key to be used for next node on the stack
271     void PushKey(const std::string& key);
272 
273     // Returns a key for the node if it has been pushed to the stack. Default is ""
274     std::string GetKey();
275 
276     // Takes care of the viewId wrt to foreach
277     std::string ProcessViewId(const std::string& viewId);
278 
279     // Clear the key pushed to the stack
280     void PopKey();
281 
282     // Check whether the current node is in the corresponding polymorphic style state.
283     // When the polymorphic style is not set on the front end, it returns true regardless of the current node state;
284     // When the polymorphic style is set on the front end, true is returned only if the current node state is the same
285     // as the polymorphic style.
286     bool IsCurrentVisualStateProcess();
287 
288     void SetVisualState(VisualState state);
289 
GetVisualState()290     std::optional<UIState> GetVisualState() const
291     {
292         return visualState_;
293     }
294 
IsVisualStateSet()295     bool IsVisualStateSet()
296     {
297         return visualState_.has_value();
298     }
299 
ClearVisualState()300     void ClearVisualState()
301     {
302         visualState_.reset();
303     }
304 
ClearStack()305     void ClearStack()
306     {
307         auto emptyStack = std::stack<RefPtr<UINode>>();
308         elementsStack_.swap(emptyStack);
309     }
310 
GetOrCreateGestureProcessor()311     RefPtr<GestureProcessor> GetOrCreateGestureProcessor()
312     {
313         if (!gestureStack_) {
314             gestureStack_ = AceType::MakeRefPtr<GestureProcessor>();
315         }
316         return gestureStack_;
317     }
318 
ResetGestureProcessor()319     void ResetGestureProcessor()
320     {
321         return gestureStack_.Reset();
322     }
323 
324     /**
325      * when nesting observeComponentCreation functions, such as in the case of
326      * If, and the if branch creates a Text etc that requires an implicit pop
327      * this function is needed after executing the inner observeComponentCreation
328      * and before read ViewStackProcessor.GetTopMostElementId(); on the outer one
329      */
330     void ImplicitPopBeforeContinue();
331 
332     // End of Rerender function, flush modifier task.
333     ACE_FORCE_EXPORT void FlushRerenderTask();
334 
335     /**
336      * start 'get' access recording
337      * account all get access to given node id
338      * next node creation will claim the given node id
339      * see ClaimNodeId()
340      */
StartGetAccessRecordingFor(int32_t elmtId)341     void StartGetAccessRecordingFor(int32_t elmtId)
342     {
343         accountGetAccessToNodeId_ = elmtId;
344         reservedNodeId_ = elmtId;
345         if (containerId_ != OHOS::Ace::INSTANCE_ID_UNDEFINED) {
346             restoreInstanceId_ = Container::CurrentId();
347             ContainerScope::UpdateCurrent(containerId_);
348         }
349     }
350 
ClaimNodeId()351     int32_t ClaimNodeId()
352     {
353         const auto result = reservedNodeId_;
354         reservedNodeId_ = ElementRegister::UndefinedElementId;
355         return result;
356     }
357 
SetRecycleNodeId(int32_t recycleNodeId)358     void SetRecycleNodeId(int32_t recycleNodeId)
359     {
360         recycleNodeId_ = recycleNodeId;
361     }
362 
GetRecycleNodeId()363     int32_t GetRecycleNodeId()
364     {
365         const auto result = recycleNodeId_;
366         recycleNodeId_ = ElementRegister::UndefinedElementId;
367         return result;
368     }
369 
370     /**
371      * get the elmtId to which all get access should be accounted
372      * ElementRegister::UndefinedElementId; means no get access recording enabled
373      */
GetNodeIdToAccountFor()374     ElementIdType GetNodeIdToAccountFor() const
375     {
376         return accountGetAccessToNodeId_;
377     }
SetNodeIdToAccountFor(ElementIdType elmtId)378     void SetNodeIdToAccountFor(ElementIdType elmtId)
379     {
380         accountGetAccessToNodeId_ = elmtId;
381     }
382 
383     /**
384      * inverse of StartGetAccessRecordingFor
385      */
StopGetAccessRecording()386     void StopGetAccessRecording()
387     {
388         if (restoreInstanceId_ != OHOS::Ace::INSTANCE_ID_UNDEFINED) {
389             ContainerScope::UpdateCurrent(restoreInstanceId_);
390             restoreInstanceId_ = OHOS::Ace::INSTANCE_ID_UNDEFINED;
391         }
392         accountGetAccessToNodeId_ = ElementRegister::UndefinedElementId;
393         reservedNodeId_ = ElementRegister::UndefinedElementId;
394     }
395 
396     void FlushImplicitAnimation();
397 
398     // used for knowing which page node to execute the pageTransitionFunc
SetPageNode(const RefPtr<FrameNode> & pageNode)399     void SetPageNode(const RefPtr<FrameNode>& pageNode)
400     {
401         currentPage_ = pageNode;
402     }
403 
GetPageNode()404     const RefPtr<FrameNode>& GetPageNode() const
405     {
406         return currentPage_;
407     }
408 
409     // Sets the implicit animation option. This is needed for 3D Model View.
410     void SetImplicitAnimationOption(const AnimationOption& option);
411 
412     // Returns implicit animation option.
413     const AnimationOption& GetImplicitAnimationOption() const;
414 
415     RefPtr<UINode> GetNewUINode();
416 
GetAndPushFrameNode(const std::string & tag,int32_t elmtId)417     void GetAndPushFrameNode(const std::string& tag, int32_t elmtId)
418     {
419         auto frameNode = FrameNode::GetFrameNode(tag, elmtId);
420         if (!frameNode) {
421             return;
422         }
423         Push(frameNode);
424     }
425 
CheckTopNodeFirstBuilding()426     bool CheckTopNodeFirstBuilding() const
427     {
428         auto node = GetMainFrameNode();
429         CHECK_NULL_RETURN(node, false);
430         return node->IsFirstBuilding();
431     }
432 
SetCustomTitleNode(const RefPtr<UINode> & customTitleNode)433     void SetCustomTitleNode(const RefPtr<UINode>& customTitleNode)
434     {
435         customTitleNode_ = customTitleNode;
436     }
437 
GetCustomTitleNode()438     const RefPtr<UINode> GetCustomTitleNode() const
439     {
440         return customTitleNode_;
441     }
442 
SetIsBuilderNode(bool isBuilderNode)443     void SetIsBuilderNode(bool isBuilderNode)
444     {
445         isBuilderNode_ = isBuilderNode;
446     }
447 
IsBuilderNode()448     bool IsBuilderNode() const
449     {
450         return isBuilderNode_;
451     }
452 
SetIsExportTexture(bool isExportTexture)453     void SetIsExportTexture(bool isExportTexture)
454     {
455         isExportTexture_ = isExportTexture;
456     }
457 
IsExportTexture()458     bool IsExportTexture() const
459     {
460         return isExportTexture_;
461     }
462 
SetRebuildContainerId(int32_t containerId)463     void SetRebuildContainerId(int32_t containerId)
464     {
465         containerId_ = containerId;
466     }
467 
IsEmpty()468     bool IsEmpty() const
469     {
470         return elementsStack_.empty();
471     }
472 private:
473     ViewStackProcessor();
474 
475     bool ShouldPopImmediately();
476 
477     // Singleton instance
478     static thread_local std::unique_ptr<ViewStackProcessor> instance;
479 
480     // render component stack
481     std::stack<RefPtr<UINode>> elementsStack_;
482 
483     RefPtr<FrameNode> currentPage_;
484 
485     RefPtr<UINode> customTitleNode_;
486 
487     RefPtr<GestureProcessor> gestureStack_;
488 
489     std::string viewKey_;
490     std::stack<size_t> keyStack_;
491 
492     std::stack<int32_t> parentIdStack_;
493 
494     std::optional<UIState> visualState_ = std::nullopt;
495     bool isBuilderNode_ = false;
496     bool isExportTexture_ = false;
497     int32_t containerId_ = OHOS::Ace::INSTANCE_ID_UNDEFINED;
498     int32_t restoreInstanceId_ = OHOS::Ace::INSTANCE_ID_UNDEFINED;
499 
500     ElementIdType recycleNodeId_ = ElementRegister::UndefinedElementId;
501     // elmtId reserved for next component creation
502     ElementIdType reservedNodeId_ = ElementRegister::UndefinedElementId;
503 
504     // elmtId to account get access to
505     ElementIdType accountGetAccessToNodeId_ = ElementRegister::UndefinedElementId;
506 
507     AnimationOption implicitAnimationOption_;
508 
509     ACE_DISALLOW_COPY_AND_MOVE(ViewStackProcessor);
510 };
511 
512 class ACE_FORCE_EXPORT ScopedViewStackProcessor final {
513 public:
514     ScopedViewStackProcessor(int32_t containerId = OHOS::Ace::INSTANCE_ID_UNDEFINED);
515     ~ScopedViewStackProcessor();
516 
517 private:
518     std::unique_ptr<ViewStackProcessor> instance_;
519 
520     ACE_DISALLOW_COPY_AND_MOVE(ScopedViewStackProcessor);
521 };
522 } // namespace OHOS::Ace::NG
523 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_BASE_VIEW_STACK_PROCESSOR_H
524