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/pattern/custom/custom_node.h"
17
18 #include "base/json/json_util.h"
19 #include "base/log/ace_performance_monitor.h"
20 #include "base/log/dump_log.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/base/view_stack_processor.h"
23 #include "core/components_ng/pattern/custom/custom_node_pattern.h"
24 #include "core/components_v2/inspector/inspector_constants.h"
25 #include "core/pipeline/base/element_register.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 #include "core/pipeline_ng/ui_task_scheduler.h"
28
29 namespace OHOS::Ace::NG {
CreateCustomNode(int32_t nodeId,const std::string & viewKey)30 RefPtr<CustomNode> CustomNode::CreateCustomNode(int32_t nodeId, const std::string& viewKey)
31 {
32 auto node = MakeRefPtr<CustomNode>(nodeId, viewKey);
33 ElementRegister::GetInstance()->AddUINode(node);
34 return node;
35 }
36
CustomNode(int32_t nodeId,const std::string & viewKey)37 CustomNode::CustomNode(int32_t nodeId, const std::string& viewKey)
38 : UINode(V2::JS_VIEW_ETS_TAG, nodeId, MakeRefPtr<CustomNodePattern>()), viewKey_(viewKey)
39 {}
40
Build(std::shared_ptr<std::list<ExtraInfo>> extraInfos)41 void CustomNode::Build(std::shared_ptr<std::list<ExtraInfo>> extraInfos)
42 {
43 Render();
44 if (extraInfos) {
45 extraInfos_ = *extraInfos;
46 }
47 UINode::Build(extraInfos);
48 }
49
Render()50 void CustomNode::Render()
51 {
52 needMarkParent_ = false;
53 if (renderFunction_) {
54 RenderFunction renderFunction = nullptr;
55 std::swap(renderFunction, renderFunction_);
56 {
57 ACE_SCOPED_TRACE("CustomNode:OnAppear");
58 FireOnAppear();
59 }
60 {
61 COMPONENT_CREATION_DURATION();
62 ACE_SCOPED_TRACE("CustomNode:BuildItem [%s][self:%d][parent:%d]", GetJSViewName().c_str(), GetId(),
63 GetParent() ? GetParent()->GetId() : 0);
64 // first create child node and wrapper.
65 ScopedViewStackProcessor scopedViewStackProcessor;
66 auto parent = GetParent();
67 bool parentNeedExportTexture = parent ? parent->IsNeedExportTexture() : false;
68 ViewStackProcessor::GetInstance()->SetIsExportTexture(parentNeedExportTexture || IsNeedExportTexture());
69 auto child = renderFunction();
70 if (child) {
71 child->MountToParent(Claim(this));
72 }
73 }
74 {
75 ACE_SCOPED_TRACE("CustomNode::DidBuild");
76 FireDidBuild();
77 }
78 }
79 {
80 FireRecycleRenderFunc();
81 }
82 needMarkParent_ = true;
83 }
84
FireCustomDisappear()85 void CustomNode::FireCustomDisappear()
86 {
87 if (!CheckFireOnAppear()) {
88 FireOnAppear();
89 FireDidBuild();
90 }
91 FireOnDisappear();
92 Reset();
93 UINode::FireCustomDisappear();
94 }
95
96 // used in HotReload to update root view @Component
FlushReload()97 void CustomNode::FlushReload()
98 {
99 CHECK_NULL_VOID(completeReloadFunc_);
100 Clean();
101 renderFunction_ = completeReloadFunc_;
102 Build(nullptr);
103 }
104
RenderCustomChild(int64_t deadline)105 bool CustomNode::RenderCustomChild(int64_t deadline)
106 {
107 if (GetSysTimestamp() > deadline) {
108 return false;
109 }
110 Render();
111 return UINode::RenderCustomChild(deadline);
112 }
113
SetJSViewActive(bool active,bool isLazyForEachNode)114 void CustomNode::SetJSViewActive(bool active, bool isLazyForEachNode)
115 {
116 if (GetJsActive() != active) {
117 SetJsActive(active);
118 FireSetActiveFunc(active);
119 }
120 }
121
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)122 void CustomNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
123 {
124 if (parent->GetHostTag() != V2::TAB_CONTENT_ITEM_ETS_TAG) {
125 Render();
126 UINode::AdjustLayoutWrapperTree(parent, forceMeasure, forceLayout);
127 return;
128 }
129
130 if (!renderFunction_ && !HasRecycleRenderFunc()) {
131 UINode::AdjustLayoutWrapperTree(parent, forceMeasure, forceLayout);
132 return;
133 }
134
135 parent->AppendChild(MakeRefPtr<LayoutWrapperNode>(
136 [weak = AceType::WeakClaim(this), forceMeasure, forceLayout](RefPtr<LayoutWrapperNode> layoutWrapper) {
137 auto customNode = weak.Upgrade();
138 CHECK_NULL_VOID(customNode);
139
140 customNode->Render();
141 if (customNode->GetChildren().empty()) {
142 return;
143 }
144 auto child = customNode->GetChildren().front();
145 while (!InstanceOf<FrameNode>(child)) {
146 auto custom = DynamicCast<CustomNode>(child);
147 if (custom) {
148 custom->Render();
149 }
150 auto children = child->GetChildren();
151 if (children.empty()) {
152 return;
153 }
154 child = children.front();
155 }
156 auto frameChild = DynamicCast<FrameNode>(child);
157 CHECK_NULL_VOID(frameChild);
158 frameChild->UpdateLayoutWrapper(layoutWrapper, forceMeasure, forceLayout);
159 }));
160 }
161
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)162 RefPtr<LayoutWrapperNode> CustomNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
163 {
164 Build(nullptr);
165 return UINode::CreateLayoutWrapper(forceMeasure, forceLayout);
166 }
167
MarkNeedSyncRenderTree(bool needRebuild)168 void CustomNode::MarkNeedSyncRenderTree(bool needRebuild)
169 {
170 if (needMarkParent_) {
171 UINode::MarkNeedSyncRenderTree(needRebuild);
172 }
173 }
174
GetFrameChildByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)175 RefPtr<UINode> CustomNode::GetFrameChildByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
176 {
177 if (!isCache) {
178 SetJSViewActive(true);
179 }
180 Render();
181 return UINode::GetFrameChildByIndex(index, needBuild, isCache, addToRenderTree);
182 }
183
DoSetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCache)184 void CustomNode::DoSetActiveChildRange(
185 int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache)
186 {
187 if (showCache) {
188 start -= cacheStart;
189 end += cacheEnd;
190 }
191 if (start <= end) {
192 if (start > 0 || end < 0) {
193 SetActive(false);
194 SetJSViewActive(false);
195 } else {
196 SetJSViewActive(true);
197 }
198 } else {
199 if (end < 0 && start > 0) {
200 SetActive(false);
201 SetJSViewActive(false);
202 } else {
203 SetJSViewActive(true);
204 }
205 }
206 }
207
GetStateInspectorInfo()208 std::unique_ptr<JsonValue> CustomNode::GetStateInspectorInfo()
209 {
210 std::string res = FireOnDumpInspectorFunc();
211 TAG_LOGD(AceLogTag::ACE_STATE_MGMT, "ArkUI State Inspector dump info %{public}s", res.c_str());
212 auto json = JsonUtil::ParseJsonString(res);
213 return json;
214 }
215 } // namespace OHOS::Ace::NG
216