1 /*
2 * Copyright (c) 2025 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 #include "core/common/builder_util.h"
16
17 #include "core/components_ng/base/view_stack_processor.h"
18 #include "core/pipeline_ng/pipeline_context.h"
19
20 namespace OHOS::Ace::BuilderUtils {
21
IsBuilderRootNode(const RefPtr<NG::UINode> & node)22 bool IsBuilderRootNode(const RefPtr<NG::UINode>& node)
23 {
24 return node ? node->GetJsBuilderNodeId() != -1 : false;
25 }
26
GetBuilderNodes(const RefPtr<NG::UINode> & node,std::list<RefPtr<NG::UINode>> & nodes)27 void GetBuilderNodes(const RefPtr<NG::UINode>& node, std::list<RefPtr<NG::UINode>>& nodes)
28 {
29 CHECK_NULL_VOID(node && !node->IsCNode());
30 if (IsBuilderRootNode(node)) {
31 nodes.push_back(node);
32 } else {
33 GetFirstBuilderNode(node, nodes);
34 }
35 }
36
IsBuilderContainer(const RefPtr<NG::UINode> & node)37 bool IsBuilderContainer(const RefPtr<NG::UINode>& node)
38 {
39 CHECK_NULL_RETURN(node, false);
40 return node->GetTag() == V2::NODE_CONTAINER_ETS_TAG || node->GetTag() == V2::JS_NODE_SLOT_ETS_TAG;
41 }
42
AddBuilderToContainer(const RefPtr<NG::UINode> & node,const std::list<RefPtr<NG::UINode>> & nodes)43 void AddBuilderToContainer(const RefPtr<NG::UINode>& node, const std::list<RefPtr<NG::UINode>>& nodes)
44 {
45 NG::ScopedViewStackProcessor builder;
46 CHECK_NULL_VOID(node);
47 auto context = node->GetContext();
48 CHECK_NULL_VOID(context);
49 auto frontend = context->GetFrontend();
50 CHECK_NULL_VOID(frontend);
51 std::vector<int32_t> argv = { node->GetId() };
52 for (const auto& child : nodes) {
53 argv.push_back(child->GetJsBuilderNodeId());
54 }
55 frontend->BuilderNodeFunc("__addBuilderNode__", argv);
56 }
57
AddBuilderToBuilder(const RefPtr<NG::UINode> & node,const std::list<RefPtr<NG::UINode>> & nodes)58 void AddBuilderToBuilder(const RefPtr<NG::UINode>& node, const std::list<RefPtr<NG::UINode>>& nodes)
59 {
60 NG::ScopedViewStackProcessor builder;
61 CHECK_NULL_VOID(node);
62 auto context = node->GetContext();
63 CHECK_NULL_VOID(context);
64 auto frontend = context->GetFrontend();
65 CHECK_NULL_VOID(frontend);
66 std::vector<int32_t> argv = { node->GetJsBuilderNodeId() };
67 for (const auto& child : nodes) {
68 argv.push_back(child->GetJsBuilderNodeId());
69 }
70 frontend->BuilderNodeFunc("__addBuilderNodeToBuilder__", argv);
71 }
72
RemoveBuilderFromContainer(const RefPtr<NG::UINode> & node,const std::list<RefPtr<NG::UINode>> & nodes)73 void RemoveBuilderFromContainer(const RefPtr<NG::UINode>& node, const std::list<RefPtr<NG::UINode>>& nodes)
74 {
75 NG::ScopedViewStackProcessor builder;
76 CHECK_NULL_VOID(node);
77 auto context = node->GetContext();
78 CHECK_NULL_VOID(context);
79 auto frontend = context->GetFrontend();
80 CHECK_NULL_VOID(frontend);
81 std::vector<int32_t> argv = { node->GetId() };
82 for (const auto& child : nodes) {
83 argv.push_back(child->GetJsBuilderNodeId());
84 }
85 frontend->BuilderNodeFunc("__deleteBuilderNode__", argv);
86 }
87
ClearChildInBuilderContainer(int32_t nodeId,std::list<RefPtr<NG::UINode>> & nodes)88 void ClearChildInBuilderContainer(int32_t nodeId, std::list<RefPtr<NG::UINode>>& nodes)
89 {
90 NG::ScopedViewStackProcessor builder;
91 CHECK_NULL_VOID(!nodes.empty());
92 auto node = nodes.front();
93 CHECK_NULL_VOID(node);
94 auto context = node->GetContext();
95 CHECK_NULL_VOID(context);
96 auto frontend = context->GetFrontend();
97 CHECK_NULL_VOID(frontend);
98 std::vector<int32_t> argv = { nodeId };
99 for (const auto& child : nodes) {
100 argv.push_back(child->GetJsBuilderNodeId());
101 }
102 frontend->BuilderNodeFunc("__deleteBuilderNode__", argv);
103 }
104
RemoveBuilderFromBuilder(const RefPtr<NG::UINode> & node,const std::list<RefPtr<NG::UINode>> & nodes)105 void RemoveBuilderFromBuilder(const RefPtr<NG::UINode>& node, const std::list<RefPtr<NG::UINode>>& nodes)
106 {
107 NG::ScopedViewStackProcessor builder;
108 CHECK_NULL_VOID(node);
109 auto context = node->GetContext();
110 CHECK_NULL_VOID(context);
111 auto frontend = context->GetFrontend();
112 CHECK_NULL_VOID(frontend);
113 std::vector<int32_t> argv = { node->GetJsBuilderNodeId() };
114 for (const auto& child : nodes) {
115 argv.push_back(child->GetJsBuilderNodeId());
116 }
117 frontend->BuilderNodeFunc("__deleteBuilderNodeFromBuilder__", argv);
118 }
119
AddBuilderToParent(const RefPtr<NG::UINode> & node,std::list<RefPtr<NG::UINode>> nodes)120 void AddBuilderToParent(const RefPtr<NG::UINode>& node, std::list<RefPtr<NG::UINode>> nodes)
121 {
122 auto parent = node;
123 CHECK_NULL_VOID(parent && !nodes.empty());
124 while (parent && !parent->IsCNode()) {
125 if (IsBuilderContainer(parent)) {
126 AddBuilderToContainer(parent, nodes);
127 return;
128 }
129 if (IsBuilderRootNode(parent)) {
130 AddBuilderToBuilder(parent, nodes);
131 return;
132 }
133 parent = parent->GetParent();
134 }
135 }
136
AddBuilderToParent(const RefPtr<NG::UINode> & parentNode,const RefPtr<NG::UINode> & childNode)137 void AddBuilderToParent(const RefPtr<NG::UINode>& parentNode, const RefPtr<NG::UINode>& childNode)
138 {
139 CHECK_NULL_VOID(childNode && parentNode);
140 std::list<RefPtr<NG::UINode>> nodes;
141 BuilderUtils::GetBuilderNodes(childNode, nodes);
142 BuilderUtils::AddBuilderToParent(parentNode, nodes);
143 }
144
RemoveBuilderFromParent(const RefPtr<NG::UINode> & node,std::list<RefPtr<NG::UINode>> nodes)145 void RemoveBuilderFromParent(const RefPtr<NG::UINode>& node, std::list<RefPtr<NG::UINode>> nodes)
146 {
147 auto parent = node;
148 CHECK_NULL_VOID(parent && !nodes.empty());
149 while (parent && !parent->IsCNode()) {
150 if (IsBuilderContainer(parent)) {
151 RemoveBuilderFromContainer(parent, nodes);
152 return;
153 }
154 if (IsBuilderRootNode(parent)) {
155 RemoveBuilderFromBuilder(parent, nodes);
156 return;
157 }
158 parent = parent->GetParent();
159 }
160 }
161
RemoveBuilderFromParent(const RefPtr<NG::UINode> & parentNode,const RefPtr<NG::UINode> & childNode)162 void RemoveBuilderFromParent(const RefPtr<NG::UINode>& parentNode, const RefPtr<NG::UINode>& childNode)
163 {
164 CHECK_NULL_VOID(childNode && parentNode);
165 std::list<RefPtr<NG::UINode>> nodes;
166 BuilderUtils::GetBuilderNodes(childNode, nodes);
167 BuilderUtils::RemoveBuilderFromParent(parentNode, nodes);
168 }
169
GetFirstBuilderNode(const RefPtr<NG::UINode> & node,std::list<RefPtr<NG::UINode>> & nodes)170 void GetFirstBuilderNode(const RefPtr<NG::UINode>& node, std::list<RefPtr<NG::UINode>>& nodes)
171 {
172 CHECK_NULL_VOID(node);
173 std::stack<RefPtr<NG::UINode>> nodeStack;
174 auto children = node->GetChildren();
175 for (auto it = children.rbegin(); it != children.rend(); ++it) {
176 nodeStack.push(*it);
177 }
178 while (!nodeStack.empty()) {
179 auto currentNode = nodeStack.top();
180 nodeStack.pop();
181 if (IsBuilderRootNode(currentNode)) {
182 nodes.push_back(currentNode);
183 continue;
184 }
185 if (IsBuilderContainer(currentNode) || currentNode->IsCNode()) {
186 continue;
187 }
188 auto currentChildren = currentNode->GetChildren();
189 for (auto it = currentChildren.rbegin(); it != currentChildren.rend(); ++it) {
190 nodeStack.push(*it);
191 }
192 }
193 }
194
195 } // namespace OHOS::Ace::BuilderUtils
196