1 /*
2  * Copyright (c) 2022 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 #include "core/components_ng/base/view_stack_processor.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components/common/properties/state_attributes.h"
20 #include "core/components_ng/base/group_node.h"
21 #include "core/components_ng/layout/layout_property.h"
22 #include "core/components_ng/pattern/custom/custom_node.h"
23 #include "core/components_ng/syntax/for_each_node.h"
24 #include "core/components_ng/syntax/if_else_node.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 const RefPtr<UINode> INVALID_NODE = nullptr;
30 }
31 thread_local std::unique_ptr<ViewStackProcessor> ViewStackProcessor::instance = nullptr;
32 
GetInstance()33 ViewStackProcessor* ViewStackProcessor::GetInstance()
34 {
35     if (!instance) {
36         instance.reset(new ViewStackProcessor);
37     }
38     return instance.get();
39 }
40 
41 ViewStackProcessor::ViewStackProcessor() = default;
42 
GetMainFrameNode() const43 FrameNode* ViewStackProcessor::GetMainFrameNode() const
44 {
45     auto uiNode = GetMainElementNode();
46     if (!uiNode || !uiNode->IsLayoutSeperately()) {
47         return nullptr;
48     }
49     return static_cast<FrameNode*>(Referenced::RawPtr(uiNode));
50 }
51 
GetMainElementNode() const52 const RefPtr<UINode>& ViewStackProcessor::GetMainElementNode() const
53 {
54     if (elementsStack_.empty()) {
55         return INVALID_NODE;
56     }
57     return elementsStack_.top();
58 }
59 
Push(const RefPtr<UINode> & element,bool)60 void ViewStackProcessor::Push(const RefPtr<UINode>& element, bool /*isCustomView*/)
61 {
62     if (ShouldPopImmediately()) {
63         Pop();
64     }
65     element->SetRemoveSilently(false);
66     elementsStack_.push(element);
67 }
68 
ShouldPopImmediately()69 bool ViewStackProcessor::ShouldPopImmediately()
70 {
71     if (elementsStack_.size() <= 1) {
72         return false;
73     }
74     // for custom node and atomic node, just pop top node when next node is coming.
75     return GetMainElementNode()->IsAtomicNode();
76 }
77 
ImplicitPopBeforeContinue()78 void ViewStackProcessor::ImplicitPopBeforeContinue()
79 {
80     if ((elementsStack_.size() > 1) && ShouldPopImmediately()) {
81         Pop();
82     }
83 }
84 
FlushImplicitAnimation()85 void ViewStackProcessor::FlushImplicitAnimation()
86 {
87     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
88     CHECK_NULL_VOID(frameNode);
89     if (frameNode->IsOnMainTree()) {
90         frameNode->MarkDirtyNode();
91     }
92 }
93 
FlushRerenderTask()94 void ViewStackProcessor::FlushRerenderTask()
95 {
96     auto node = Finish();
97     CHECK_NULL_VOID(node);
98     node->FlushUpdateAndMarkDirty();
99 }
100 
Pop()101 void ViewStackProcessor::Pop()
102 {
103     if (elementsStack_.empty() || elementsStack_.size() == 1) {
104         return;
105     }
106 
107     auto currentNode = Finish();
108     currentNode->SetBuildByJs(true);
109     auto parent = GetMainElementNode();
110     if (AceType::InstanceOf<GroupNode>(parent)) {
111         auto groupNode = AceType::DynamicCast<GroupNode>(parent);
112         groupNode->AddChildToGroup(currentNode);
113         return;
114     }
115 
116     currentNode->MountToParent(
117         parent, DEFAULT_NODE_SLOT, AceType::InstanceOf<ForEachNode>(parent), AceType::InstanceOf<IfElseNode>(parent));
118     auto currentFrameNode = AceType::DynamicCast<FrameNode>(currentNode);
119     if (currentFrameNode) {
120         currentFrameNode->OnMountToParentDone();
121     }
122 }
123 
PopContainer()124 void ViewStackProcessor::PopContainer()
125 {
126     auto top = GetMainElementNode();
127     // for container node.
128     if (top && !top->IsAtomicNode()) {
129         Pop();
130         return;
131     }
132 
133     while (top && (top->IsAtomicNode())) {
134         if (elementsStack_.size() == 1) {
135             return;
136         }
137         Pop();
138         top = GetMainElementNode();
139     }
140     Pop();
141 }
142 
Finish()143 RefPtr<UINode> ViewStackProcessor::Finish()
144 {
145     if (elementsStack_.empty()) {
146         return nullptr;
147     }
148     auto element = elementsStack_.top();
149     elementsStack_.pop();
150     auto frameNode = AceType::DynamicCast<FrameNode>(element);
151     if (frameNode) {
152         frameNode->MarkBuildDone();
153         frameNode->MarkModifyDone();
154         auto renderContext = frameNode->GetRenderContext();
155         if (renderContext) {
156             renderContext->SetNeedDebugBoundary(true);
157         }
158     }
159     // ForEach Partial Update Path.
160     if (AceType::InstanceOf<ForEachNode>(element)) {
161         auto forEachNode = AceType::DynamicCast<ForEachNode>(element);
162         forEachNode->CompareAndUpdateChildren();
163     }
164     return element;
165 }
166 
SetVisualState(VisualState state)167 void ViewStackProcessor::SetVisualState(VisualState state)
168 {
169     switch (state) {
170         case VisualState::DISABLED:
171             visualState_ = UI_STATE_DISABLED;
172             break;
173         case VisualState::FOCUSED:
174             visualState_ = UI_STATE_FOCUSED;
175             break;
176         case VisualState::PRESSED:
177             visualState_ = UI_STATE_PRESSED;
178             break;
179         case VisualState::SELECTED:
180             visualState_ = UI_STATE_SELECTED;
181             break;
182         case VisualState::NORMAL:
183         default:
184             visualState_ = UI_STATE_NORMAL;
185     }
186     auto eventHub = GetMainFrameNodeEventHub<EventHub>();
187     CHECK_NULL_VOID(eventHub);
188     eventHub->AddSupportedState(visualState_.value());
189 }
190 
IsCurrentVisualStateProcess()191 bool ViewStackProcessor::IsCurrentVisualStateProcess()
192 {
193     if (!visualState_.has_value()) {
194         return true;
195     }
196     auto eventHub = GetMainFrameNodeEventHub<EventHub>();
197     CHECK_NULL_RETURN(eventHub, false);
198     auto result = eventHub->IsCurrentStateOn(visualState_.value());
199     return result;
200 }
201 
PushKey(const std::string & key)202 void ViewStackProcessor::PushKey(const std::string& key)
203 {
204     if (viewKey_.empty()) {
205         // For the root node, the key value is xxx.
206         viewKey_ = key;
207         keyStack_.emplace(key.length());
208     } else {
209         // For descendant nodes, the key value is xxx_xxx
210         viewKey_.append("_").append(key);
211         keyStack_.emplace(key.length() + 1);
212     }
213 }
214 
PopKey()215 void ViewStackProcessor::PopKey()
216 {
217     size_t length = keyStack_.top();
218     keyStack_.pop();
219 
220     if (length > 0) {
221         viewKey_.erase(viewKey_.length() - length);
222     }
223 }
224 
GetKey()225 std::string ViewStackProcessor::GetKey()
226 {
227     return viewKey_.empty() ? "" : viewKey_;
228 }
229 
ProcessViewId(const std::string & viewId)230 std::string ViewStackProcessor::ProcessViewId(const std::string& viewId)
231 {
232     return viewKey_.empty() ? viewId : viewKey_ + "_" + viewId;
233 }
234 
SetImplicitAnimationOption(const AnimationOption & option)235 void ViewStackProcessor::SetImplicitAnimationOption(const AnimationOption& option)
236 {
237     implicitAnimationOption_ = option;
238 }
239 
GetImplicitAnimationOption() const240 const AnimationOption& ViewStackProcessor::GetImplicitAnimationOption() const
241 {
242     return implicitAnimationOption_;
243 }
244 
GetNewUINode()245 RefPtr<UINode> ViewStackProcessor::GetNewUINode()
246 {
247     return Finish();
248 }
249 
ScopedViewStackProcessor(int32_t containerId)250 ScopedViewStackProcessor::ScopedViewStackProcessor(int32_t containerId)
251 {
252     std::swap(instance_, ViewStackProcessor::instance);
253     ViewStackProcessor::GetInstance()->SetRebuildContainerId(containerId);
254 }
255 
~ScopedViewStackProcessor()256 ScopedViewStackProcessor::~ScopedViewStackProcessor()
257 {
258     ViewStackProcessor::GetInstance()->SetRebuildContainerId(OHOS::Ace::INSTANCE_ID_UNDEFINED);
259     std::swap(instance_, ViewStackProcessor::instance);
260 }
261 } // namespace OHOS::Ace::NG
262