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