• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/components_ng/base/group_node.h"
19 #include "core/components_ng/base/view_stack_model_ng.h"
20 #include "core/components_ng/syntax/for_each_node.h"
21 #include "core/components_ng/syntax/if_else_node.h"
22 
23 namespace OHOS::Ace::NG {
24 namespace {
25 const RefPtr<UINode> INVALID_NODE = nullptr;
26 }
27 thread_local std::unique_ptr<ViewStackProcessor> ViewStackProcessor::instance = nullptr;
28 thread_local std::unique_ptr<ScopedViewStackProcessor> ViewStackModelNG::scopeStack_ = 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 FrameNode* ViewStackProcessor::GetMainFrameNode() const
41 {
42     auto uiNode = GetMainElementNode();
43     if (!uiNode || !uiNode->IsLayoutSeperately()) {
44         return nullptr;
45     }
46     return static_cast<FrameNode*>(Referenced::RawPtr(uiNode));
47 }
48 
GetMainElementNode() const49 const RefPtr<UINode>& ViewStackProcessor::GetMainElementNode() const
50 {
51     if (elementsStack_.empty()) {
52         return INVALID_NODE;
53     }
54     return elementsStack_.top();
55 }
56 
ApplyParentThemeScopeId(const RefPtr<UINode> & element)57 void ViewStackProcessor::ApplyParentThemeScopeId(const RefPtr<UINode>& element)
58 {
59     auto parent = GetMainElementNode();
60     int32_t elementThemeScopeId = element->GetThemeScopeId();
61     if (parent && elementThemeScopeId == 0) {
62         int32_t themeScopeId = parent->GetThemeScopeId();
63         if (elementThemeScopeId != themeScopeId) {
64             element->SetThemeScopeId(themeScopeId);
65         }
66     }
67 }
68 
Push(const RefPtr<UINode> & element,bool)69 void ViewStackProcessor::Push(const RefPtr<UINode>& element, bool /*isCustomView*/)
70 {
71     ApplyParentThemeScopeId(element);
72 
73     if (ShouldPopImmediately()) {
74         Pop();
75     }
76     element->SetRemoveSilently(false);
77     elementsStack_.push(element);
78 }
79 
80 #ifdef ACE_STATIC
PushPtr(int64_t elementPtr)81 void ViewStackProcessor::PushPtr(int64_t elementPtr)
82 {
83     if (elementPtr == 0) {
84         return;
85     }
86     Push(UINode::Claim(reinterpret_cast<UINode*>(elementPtr)), true);
87 }
88 #endif
89 
ShouldPopImmediately()90 bool ViewStackProcessor::ShouldPopImmediately()
91 {
92     if (elementsStack_.size() <= 1) {
93         return false;
94     }
95     // for custom node and atomic node, just pop top node when next node is coming.
96     return GetMainElementNode()->IsAtomicNode();
97 }
98 
ImplicitPopBeforeContinue()99 void ViewStackProcessor::ImplicitPopBeforeContinue()
100 {
101     if ((elementsStack_.size() > 1) && ShouldPopImmediately()) {
102         Pop();
103     }
104 }
105 
FlushImplicitAnimation()106 void ViewStackProcessor::FlushImplicitAnimation()
107 {
108     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
109     CHECK_NULL_VOID(frameNode);
110     if (frameNode->IsOnMainTree()) {
111         frameNode->MarkDirtyNode();
112     }
113 }
114 
FlushRerenderTask()115 void ViewStackProcessor::FlushRerenderTask()
116 {
117     auto node = Finish();
118     CHECK_NULL_VOID(node);
119     node->FlushUpdateAndMarkDirty();
120 }
121 
Pop()122 void ViewStackProcessor::Pop()
123 {
124     if (elementsStack_.empty() || elementsStack_.size() == 1) {
125         return;
126     }
127 
128     auto currentNode = Finish();
129     currentNode->SetBuildByJs(true);
130     auto parent = GetMainElementNode();
131     if (AceType::InstanceOf<GroupNode>(parent)) {
132         auto groupNode = AceType::DynamicCast<GroupNode>(parent);
133         groupNode->AddChildToGroup(currentNode);
134         return;
135     }
136 
137     currentNode->MountToParent(
138         parent, DEFAULT_NODE_SLOT, AceType::InstanceOf<ForEachNode>(parent), AceType::InstanceOf<IfElseNode>(parent));
139     auto currentFrameNode = AceType::DynamicCast<FrameNode>(currentNode);
140     if (currentFrameNode) {
141         currentFrameNode->OnMountToParentDone();
142     }
143 }
144 
PopContainer()145 void ViewStackProcessor::PopContainer()
146 {
147     auto top = GetMainElementNode();
148     // for container node.
149     if (top && !top->IsAtomicNode()) {
150         Pop();
151         return;
152     }
153 
154     while (top && (top->IsAtomicNode())) {
155         if (elementsStack_.size() == 1) {
156             return;
157         }
158         Pop();
159         top = GetMainElementNode();
160     }
161     Pop();
162 }
163 
Finish()164 RefPtr<UINode> ViewStackProcessor::Finish()
165 {
166     if (elementsStack_.empty()) {
167         return nullptr;
168     }
169     auto element = elementsStack_.top();
170     elementsStack_.pop();
171     auto frameNode = AceType::DynamicCast<FrameNode>(element);
172     if (frameNode) {
173         frameNode->MarkBuildDone();
174         frameNode->MarkModifyDone();
175         auto renderContext = frameNode->GetRenderContext();
176         if (renderContext) {
177             renderContext->SetNeedDebugBoundary(true);
178         }
179     }
180     // ForEach Partial Update Path.
181     if (AceType::InstanceOf<ForEachNode>(element)) {
182         auto forEachNode = AceType::DynamicCast<ForEachNode>(element);
183         forEachNode->CompareAndUpdateChildren();
184     }
185     return element;
186 }
187 
SetVisualState(VisualState state)188 void ViewStackProcessor::SetVisualState(VisualState state)
189 {
190     switch (state) {
191         case VisualState::DISABLED:
192             visualState_ = UI_STATE_DISABLED;
193             break;
194         case VisualState::FOCUSED:
195             visualState_ = UI_STATE_FOCUSED;
196             break;
197         case VisualState::PRESSED:
198             visualState_ = UI_STATE_PRESSED;
199             break;
200         case VisualState::SELECTED:
201             visualState_ = UI_STATE_SELECTED;
202             break;
203         case VisualState::NORMAL:
204         default:
205             visualState_ = UI_STATE_NORMAL;
206     }
207     auto eventHub = GetMainFrameNodeEventHub<EventHub>();
208     CHECK_NULL_VOID(eventHub);
209     eventHub->AddSupportedState(visualState_.value());
210 }
211 
IsCurrentVisualStateProcess()212 bool ViewStackProcessor::IsCurrentVisualStateProcess()
213 {
214     if (!visualState_.has_value()) {
215         return true;
216     }
217     auto eventHub = GetMainFrameNodeEventHub<EventHub>();
218     CHECK_NULL_RETURN(eventHub, false);
219     auto result = eventHub->IsCurrentStateOn(visualState_.value());
220     return result;
221 }
222 
PushKey(const std::string & key)223 void ViewStackProcessor::PushKey(const std::string& key)
224 {
225     if (viewKey_.empty()) {
226         // For the root node, the key value is xxx.
227         viewKey_ = key;
228         keyStack_.emplace(key.length());
229     } else {
230         // For descendant nodes, the key value is xxx_xxx
231         viewKey_.append("_").append(key);
232         keyStack_.emplace(key.length() + 1);
233     }
234 }
235 
PopKey()236 void ViewStackProcessor::PopKey()
237 {
238     size_t length = keyStack_.top();
239     keyStack_.pop();
240 
241     if (length > 0) {
242         viewKey_.erase(viewKey_.length() - length);
243     }
244 }
245 
GetKey()246 std::string ViewStackProcessor::GetKey()
247 {
248     return viewKey_.empty() ? "" : viewKey_;
249 }
250 
ProcessViewId(const std::string & viewId)251 std::string ViewStackProcessor::ProcessViewId(const std::string& viewId)
252 {
253     return viewKey_.empty() ? viewId : viewKey_ + "_" + viewId;
254 }
255 
SetImplicitAnimationOption(const AnimationOption & option)256 void ViewStackProcessor::SetImplicitAnimationOption(const AnimationOption& option)
257 {
258     implicitAnimationOption_ = option;
259 }
260 
GetImplicitAnimationOption() const261 const AnimationOption& ViewStackProcessor::GetImplicitAnimationOption() const
262 {
263     return implicitAnimationOption_;
264 }
265 
GetNewUINode()266 RefPtr<UINode> ViewStackProcessor::GetNewUINode()
267 {
268     return Finish();
269 }
270 
Init(int32_t containerId)271 void ScopedViewStackProcessor::Init(int32_t containerId)
272 {
273     std::swap(instance_, ViewStackProcessor::instance);
274     ViewStackProcessor::GetInstance()->SetRebuildContainerId(containerId);
275 }
276 
SwapViewStackProcessor(std::unique_ptr<ViewStackProcessor> & instance)277 void ScopedViewStackProcessor::SwapViewStackProcessor(std::unique_ptr<ViewStackProcessor>& instance)
278 {
279     std::swap(instance, ViewStackProcessor::instance);
280 }
281 
ScopedViewStackProcessor(int32_t containerId)282 ScopedViewStackProcessor::ScopedViewStackProcessor(int32_t containerId)
283 {
284     Init(containerId);
285 }
286 
ScopedViewStackProcessor(std::unique_ptr<ViewStackProcessor> & instance,int32_t containerId)287 ScopedViewStackProcessor::ScopedViewStackProcessor(std::unique_ptr<ViewStackProcessor>& instance, int32_t containerId)
288 {
289     std::swap(instance_, instance);
290     Init(containerId);
291 }
292 
~ScopedViewStackProcessor()293 ScopedViewStackProcessor::~ScopedViewStackProcessor()
294 {
295     ViewStackProcessor::GetInstance()->SetRebuildContainerId(OHOS::Ace::INSTANCE_ID_UNDEFINED);
296     std::swap(instance_, ViewStackProcessor::instance);
297 }
298 } // namespace OHOS::Ace::NG
299