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