• 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 "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