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