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