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