1 /*
2 * Copyright (c) 2024 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 "customcomponent_measurenode_test.h"
17
18 #include <string>
19
20 #include "../manager/plugin_manager.h"
21 #define ON_CUSTOM_EVENT_1_ID 1011
22 #define ON_CUSTOM_EVENT_6_ID 1013
23 #define ON_CUSTOM_EVENT_7_ID 1014
24 #define MAX_WIDTH 120
25 #define MIN_WIDTH 40
26 #define MAX_HEIGHT 150
27 #define MIN_HEIGHT 30
28 #define PERCENT_WIDTH 500
29 #define PERCENT_HEIGHT 130
30 #define PERCENT 0.9
31 namespace ArkUICapiTest {
32 static ArkUI_IntSize size1_1 = { 0, 0 };
33 static ArkUI_IntSize size1_2 = { 0, 0 };
34 static ArkUI_IntSize size1_3 = { 0, 0 };
35 static ArkUI_IntSize size1_4 = { 0, 0 };
36
37 ArkUI_LayoutConstraint* layoutConstraint = nullptr;
38 static ArkUI_NodeHandle parentColumn = nullptr;
39 std::vector<int32_t> CustomComponentMeasureNodeTest::measureNodeVector = {};
SetArrayNapiDataWithMeasureNode(const std::vector<int32_t> & data,napi_env env)40 static napi_value SetArrayNapiDataWithMeasureNode(const std::vector<int32_t>& data, napi_env env)
41 {
42 napi_value array;
43 napi_create_array(env, &array);
44 for (size_t i = PARAM_0; i < data.size(); i++) {
45 napi_value num;
46 napi_create_int32(env, data[i], &num);
47 napi_set_element(env, array, i, num);
48 }
49 return array;
50 };
PushBackIntToData(std::vector<int32_t> & data,int32_t value)51 static void PushBackIntToData(std::vector<int32_t>& data, int32_t value)
52 {
53 data.push_back(value);
54 }
CreateCustomNode(ArkUI_NativeNodeAPI_1 * nodeAPI,uint32_t color)55 static auto CreateCustomNode(ArkUI_NativeNodeAPI_1* nodeAPI, uint32_t color)
56 {
57 auto customNode = nodeAPI->createNode(ARKUI_NODE_CUSTOM);
58 ArkUI_NumberValue customNodeColor[] = { { .u32 = color } };
59 ArkUI_AttributeItem customNodeColorItem = { customNodeColor, sizeof(customNodeColor) / sizeof(ArkUI_NumberValue) };
60 nodeAPI->setAttribute(customNode, NODE_BACKGROUND_COLOR, &customNodeColorItem);
61 return customNode;
62 }
CreateRowNode(ArkUI_NativeNodeAPI_1 * nodeAPI)63 static auto CreateRowNode(ArkUI_NativeNodeAPI_1* nodeAPI)
64 {
65 auto row = nodeAPI->createNode(ARKUI_NODE_ROW);
66 ArkUI_NumberValue rowPercentWith[] = { { .f32 = 0.8 } };
67 ArkUI_AttributeItem rowPercentWithItem = { rowPercentWith, sizeof(rowPercentWith) / sizeof(ArkUI_NumberValue) };
68 nodeAPI->setAttribute(row, NODE_WIDTH_PERCENT, &rowPercentWithItem);
69 ArkUI_NumberValue rowPercentHeight[] = { { .f32 = 0.15 } };
70 ArkUI_AttributeItem rowPercentHeightItem = { rowPercentHeight,
71 sizeof(rowPercentHeight) / sizeof(ArkUI_NumberValue) };
72 nodeAPI->setAttribute(row, NODE_HEIGHT_PERCENT, &rowPercentHeightItem);
73 ArkUI_NumberValue rowColor[] = { { .u32 = COLOR_GRAY } };
74 ArkUI_AttributeItem rowColorItem = { rowColor, sizeof(rowColor) / sizeof(ArkUI_NumberValue) };
75 nodeAPI->setAttribute(row, NODE_BACKGROUND_COLOR, &rowColorItem);
76 ArkUI_NumberValue rowMargin[] = { { .f32 = 5 } };
77 ArkUI_AttributeItem rowMarginItem = { rowMargin, sizeof(rowMargin) / sizeof(ArkUI_NumberValue) };
78 nodeAPI->setAttribute(row, NODE_MARGIN, &rowMarginItem);
79 return row;
80 }
setLayoutConstraint(ArkUI_LayoutConstraint * layoutConstraint)81 static void setLayoutConstraint(ArkUI_LayoutConstraint* layoutConstraint)
82 {
83 OH_ArkUI_LayoutConstraint_SetMaxWidth(layoutConstraint, MAX_WIDTH);
84 OH_ArkUI_LayoutConstraint_SetMinWidth(layoutConstraint, MIN_WIDTH);
85 OH_ArkUI_LayoutConstraint_SetMaxHeight(layoutConstraint, MAX_HEIGHT);
86 OH_ArkUI_LayoutConstraint_SetMinHeight(layoutConstraint, MIN_HEIGHT);
87 OH_ArkUI_LayoutConstraint_SetPercentReferenceWidth(layoutConstraint, PERCENT_WIDTH);
88 OH_ArkUI_LayoutConstraint_SetPercentReferenceHeight(layoutConstraint, PERCENT_HEIGHT);
89 }
getChildLayoutContraint(ArkUI_NodeCustomEvent * event,int widthOffset,int heightOffset)90 static ArkUI_LayoutConstraint* getChildLayoutContraint(ArkUI_NodeCustomEvent* event, int widthOffset, int heightOffset)
91 {
92 auto layoutConstraint = OH_ArkUI_NodeCustomEvent_GetLayoutConstraintInMeasure(event);
93 auto childLayoutConstraint = OH_ArkUI_LayoutConstraint_Copy(layoutConstraint);
94 auto layoutConstraintMaxWith = OH_ArkUI_LayoutConstraint_GetMaxWidth(layoutConstraint) - widthOffset;
95 auto layoutConstraintMaxHeight = OH_ArkUI_LayoutConstraint_GetMaxHeight(layoutConstraint) - heightOffset;
96 OH_ArkUI_LayoutConstraint_SetMaxWidth(childLayoutConstraint, layoutConstraintMaxWith);
97 OH_ArkUI_LayoutConstraint_SetMaxHeight(childLayoutConstraint, layoutConstraintMaxHeight);
98 return childLayoutConstraint;
99 }
measure(ArkUI_NativeNodeAPI_1 * nodeAPI,ArkUI_NodeHandle nodeHandler,ArkUI_LayoutConstraint * layoutConstraint)100 static void measure(
101 ArkUI_NativeNodeAPI_1* nodeAPI, ArkUI_NodeHandle nodeHandler, ArkUI_LayoutConstraint* layoutConstraint)
102 {
103 auto totalSize = nodeAPI->getTotalChildCount(nodeHandler);
104 for (uint32_t i = 0; i < totalSize; i++) {
105 auto child = nodeAPI->getChildAt(nodeHandler, i);
106 // 调用测算接口测算Native组件。
107 nodeAPI->measureNode(child, layoutConstraint);
108 }
109 }
getChildChildSize(ArkUI_NodeCustomEvent * event)110 static ArkUI_IntSize getChildChildSize(ArkUI_NodeCustomEvent* event)
111 {
112 auto layoutConstraint = OH_ArkUI_NodeCustomEvent_GetLayoutConstraintInMeasure(event);
113 auto layoutConstrainMaxWith = OH_ArkUI_LayoutConstraint_GetMaxWidth(layoutConstraint);
114 auto layoutConstrainMinWith = OH_ArkUI_LayoutConstraint_GetMinWidth(layoutConstraint);
115 auto layoutConstrainMaxHeight = OH_ArkUI_LayoutConstraint_GetMaxHeight(layoutConstraint);
116 auto layoutConstrainMinHeight = OH_ArkUI_LayoutConstraint_GetMinHeight(layoutConstraint);
117 auto layoutConstraintPercentReferenceWidth = OH_ArkUI_LayoutConstraint_GetPercentReferenceWidth(layoutConstraint);
118 auto layoutConstraintPercentReferenceHeight = OH_ArkUI_LayoutConstraint_GetPercentReferenceHeight(layoutConstraint);
119 // 通过用户传入的大小与约束条件进行比较,设置测算大小
120 auto dataIntTemp = OH_ArkUI_NodeCustomEvent_GetUserData(event);
121 ArkUI_IntSize size = *static_cast<ArkUI_IntSize*>(dataIntTemp);
122 if (size.width > layoutConstrainMaxWith || size.width > layoutConstraintPercentReferenceWidth * PERCENT) {
123 size.width = layoutConstrainMaxWith;
124 } else if (size.width < layoutConstrainMinWith) {
125 size.width = layoutConstrainMinWith;
126 }
127 if (size.height > layoutConstrainMaxHeight || size.height > layoutConstraintPercentReferenceHeight * PERCENT) {
128 size.height = layoutConstrainMaxHeight;
129 } else if (size.height < layoutConstrainMinHeight) {
130 size.height = layoutConstrainMinHeight;
131 }
132 return size;
133 }
OnMeasureReceive(ArkUI_NodeCustomEvent * event)134 static void OnMeasureReceive(ArkUI_NodeCustomEvent* event)
135 {
136 if (event == nullptr) {
137 return;
138 }
139 int32_t eventId = OH_ArkUI_NodeCustomEvent_GetEventTargetId(event);
140 ArkUI_NativeNodeAPI_1* nodeAPI = nullptr;
141 OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
142 auto nodeHandler = OH_ArkUI_NodeCustomEvent_GetNodeHandle(event);
143 if (eventId == ON_CUSTOM_EVENT_1_ID) {
144 layoutConstraint = OH_ArkUI_LayoutConstraint_Create();
145 setLayoutConstraint(layoutConstraint);
146 measure(nodeAPI, nodeHandler, layoutConstraint);
147 nodeAPI->setMeasuredSize(nodeHandler, MAX_WIDTH, MAX_HEIGHT);
148 return;
149 } else if (eventId == ON_MEASURE_EVENT_ID) {
150 auto childLayoutConstraint = getChildLayoutContraint(event, 10, 10);
151 auto totalSize = nodeAPI->getTotalChildCount(nodeHandler);
152 int32_t maxWidth = 0;
153 int32_t maxHeight = 0;
154 for (uint32_t i = 0; i < totalSize; i++) {
155 auto child = nodeAPI->getChildAt(nodeHandler, i);
156 nodeAPI->measureNode(child, childLayoutConstraint);
157 auto size = nodeAPI->getMeasuredSize(child);
158 if (size.width > maxWidth) {
159 maxWidth = size.width;
160 }
161 if (size.height > maxHeight) {
162 maxHeight = size.height;
163 }
164 }
165 nodeAPI->setMeasuredSize(nodeHandler, maxWidth, maxHeight);
166 PushBackIntToData(CustomComponentMeasureNodeTest::measureNodeVector, maxWidth);
167 PushBackIntToData(CustomComponentMeasureNodeTest::measureNodeVector, maxHeight);
168 return;
169 } else if (eventId == ON_CUSTOM_EVENT_6_ID) {
170 auto size = getChildChildSize(event);
171 nodeAPI->setMeasuredSize(nodeHandler, size.width, size.height);
172 PushBackIntToData(CustomComponentMeasureNodeTest::measureNodeVector, size.width);
173 PushBackIntToData(CustomComponentMeasureNodeTest::measureNodeVector, size.height);
174 return;
175 } else if (eventId == ON_CUSTOM_EVENT_7_ID) {
176 auto size = getChildChildSize(event);
177 nodeAPI->setMeasuredSize(nodeHandler, size.width, size.height);
178 PushBackIntToData(CustomComponentMeasureNodeTest::measureNodeVector, size.width);
179 PushBackIntToData(CustomComponentMeasureNodeTest::measureNodeVector, size.height);
180 return;
181 }
182 }
OnLayoutReceive(ArkUI_NodeCustomEvent * event)183 static void OnLayoutReceive(ArkUI_NodeCustomEvent* event)
184 {
185 if (event == nullptr) {
186 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "CustomComponentLayoutConstraintTest",
187 "OnLayoutReceive: event is null");
188 return;
189 }
190 int32_t eventId = OH_ArkUI_NodeCustomEvent_GetEventTargetId(event);
191 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "CustomComponentLayoutConstraintTest",
192 "OnLayoutReceive eventId: %{public}d", eventId);
193 ArkUI_NativeNodeAPI_1* nodeAPI = nullptr;
194 OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
195 auto nodeHandler = OH_ArkUI_NodeCustomEvent_GetNodeHandle(event);
196 if (eventId == ON_LAYOUT_EVENT_ID) {
197 // 获取测算大小,将测算大小设置为布局大小
198 auto size = nodeAPI->getMeasuredSize(nodeHandler);
199 ArkUI_NumberValue with[] = { { .f32 = (float)size.width } };
200 ArkUI_AttributeItem withItem = { with, 1 };
201 ArkUI_NumberValue height[] = { { .f32 = (float)size.height } };
202 ArkUI_AttributeItem heightItem = { height, 1 };
203 nodeAPI->setAttribute(nodeHandler, NODE_WIDTH, &withItem);
204 nodeAPI->setAttribute(nodeHandler, NODE_HEIGHT, &heightItem);
205 // 触发子节点的布局
206 auto totalSize = nodeAPI->getTotalChildCount(nodeHandler);
207 for (uint32_t i = 0; i < totalSize; i++) {
208 auto child = nodeAPI->getChildAt(nodeHandler, i);
209 nodeAPI->layoutNode(child, 0, 0);
210 }
211 return;
212 }
213 }
registerEvent(ArkUI_NativeNodeAPI_1 * nodeAPI,ArkUI_NodeHandle customNode1,ArkUI_NodeHandle customNode2,ArkUI_NodeHandle customNode3,ArkUI_NodeHandle customNode4)214 static void registerEvent(ArkUI_NativeNodeAPI_1* nodeAPI, ArkUI_NodeHandle customNode1, ArkUI_NodeHandle customNode2,
215 ArkUI_NodeHandle customNode3, ArkUI_NodeHandle customNode4)
216 {
217 nodeAPI->addNodeCustomEventReceiver(customNode1, &OnMeasureReceive);
218 nodeAPI->registerNodeCustomEvent(customNode1, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, ON_CUSTOM_EVENT_1_ID, nullptr);
219 nodeAPI->addNodeCustomEventReceiver(customNode1, &OnLayoutReceive);
220 nodeAPI->registerNodeCustomEvent(customNode1, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT, ON_LAYOUT_EVENT_ID, nullptr);
221
222 nodeAPI->addNodeCustomEventReceiver(customNode2, &OnMeasureReceive);
223 nodeAPI->registerNodeCustomEvent(customNode2, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, ON_MEASURE_EVENT_ID, nullptr);
224 nodeAPI->addNodeCustomEventReceiver(customNode2, &OnLayoutReceive);
225 nodeAPI->registerNodeCustomEvent(customNode2, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT, ON_LAYOUT_EVENT_ID, nullptr);
226 size1_1 = { 5, 180 };
227 nodeAPI->addNodeCustomEventReceiver(customNode3, &OnMeasureReceive);
228 nodeAPI->registerNodeCustomEvent(customNode3, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, ON_CUSTOM_EVENT_6_ID, &size1_1);
229 nodeAPI->addNodeCustomEventReceiver(customNode3, &OnLayoutReceive);
230 nodeAPI->registerNodeCustomEvent(customNode3, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT, ON_LAYOUT_EVENT_ID, nullptr);
231 size1_2 = { 200, 10 };
232 nodeAPI->addNodeCustomEventReceiver(customNode4, &OnMeasureReceive);
233 nodeAPI->registerNodeCustomEvent(customNode4, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, ON_CUSTOM_EVENT_7_ID, &size1_2);
234 nodeAPI->addNodeCustomEventReceiver(customNode4, &OnLayoutReceive);
235 nodeAPI->registerNodeCustomEvent(customNode4, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT, ON_LAYOUT_EVENT_ID, nullptr);
236 }
addTestNodes(ArkUI_NativeNodeAPI_1 * nodeAPI,ArkUI_NodeHandle parentColumn)237 static auto addTestNodes(ArkUI_NativeNodeAPI_1* nodeAPI, ArkUI_NodeHandle parentColumn)
238 {
239 // 创建1个Row组件
240 auto row = CreateRowNode(nodeAPI);
241 nodeAPI->addChild(parentColumn, row);
242
243 auto customNode1 = CreateCustomNode(nodeAPI, COLOR_RED);
244 nodeAPI->addChild(row, customNode1);
245 ArkUI_NumberValue customNodeWith[] = { { .f32 = 100 } };
246 ArkUI_AttributeItem customNodeWithItem = { customNodeWith, sizeof(customNodeWith) / sizeof(ArkUI_NumberValue) };
247 nodeAPI->setAttribute(customNode1, NODE_WIDTH, &customNodeWithItem);
248 ArkUI_NumberValue customNodeHeight[] = { { .f32 = 100 } };
249 ArkUI_AttributeItem customNodeHeightItem = { customNodeHeight,
250 sizeof(customNodeHeight) / sizeof(ArkUI_NumberValue) };
251 nodeAPI->setAttribute(customNode1, NODE_HEIGHT, &customNodeHeightItem);
252 // custom1_2 是 custom1_1 的孩子
253 auto customNode2 = CreateCustomNode(nodeAPI, COLOR_YELLOW);
254 nodeAPI->addChild(customNode1, customNode2);
255 // custom1_3、custom1_4 是 custom1_2 的孩子
256 auto customNode3 = CreateCustomNode(nodeAPI, COLOR_BLUE);
257 nodeAPI->addChild(customNode2, customNode3);
258 auto customNode4 = CreateCustomNode(nodeAPI, COLOR_PURPLE);
259 nodeAPI->addChild(customNode2, customNode4);
260
261 registerEvent(nodeAPI, customNode1, customNode2, customNode3, customNode4);
262 }
CreateNativeNode(napi_env env,napi_callback_info info)263 napi_value CustomComponentMeasureNodeTest::CreateNativeNode(napi_env env, napi_callback_info info)
264 {
265 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "CustomComponentMeasureNodeTest", "CreateNativeNode");
266
267 size_t argc = PARAM_1;
268 napi_value args[PARAM_1] = { nullptr };
269 napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
270 size_t length = PARAM_64;
271 size_t strLength = PARAM_0;
272 char xComponentID[PARAM_64] = { PARAM_0 };
273 napi_get_value_string_utf8(env, args[PARAM_0], xComponentID, length, &strLength);
274
275 if ((env == nullptr) || (info == nullptr)) {
276 OH_LOG_Print(
277 LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "CustomComponentMeasureNodeTest", "GetContext env or info is null");
278 return nullptr;
279 }
280 ArkUI_NativeNodeAPI_1* nodeAPI = nullptr;
281 OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
282 // set parent node
283 parentColumn = nodeAPI->createNode(ARKUI_NODE_COLUMN);
284 ArkUI_AttributeItem item = {};
285 item.string = "parentColumn";
286 nodeAPI->setAttribute(parentColumn, NODE_ID, &item);
287 addTestNodes(nodeAPI, parentColumn);
288 auto button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
289 nodeAPI->addChild(parentColumn, button);
290
291 std::string id(xComponentID);
292 if (OH_NativeXComponent_AttachNativeRootNode(PluginManager::GetInstance()->GetNativeXComponent(id), parentColumn) ==
293 INVALID_PARAM) {
294 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "ListItemHitTestBehaviorTest",
295 "OH_NativeXComponent_AttachNativeRootNode failed");
296 }
297
298 napi_value exports;
299 if (napi_create_object(env, &exports) != napi_ok) {
300 napi_throw_type_error(env, NULL, "napi_create_object failed");
301 return nullptr;
302 }
303 return exports;
304 }
GetMeasureNodeData(napi_env env,napi_callback_info info)305 napi_value CustomComponentMeasureNodeTest::GetMeasureNodeData(napi_env env, napi_callback_info info)
306 {
307 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "CustomComponentMeasureNodeTest", "GetMeasureNodeData");
308 napi_value result;
309 napi_create_array(env, &result);
310 napi_set_element(
311 env, result, PARAM_0, SetArrayNapiDataWithMeasureNode(CustomComponentMeasureNodeTest::measureNodeVector, env));
312 CustomComponentMeasureNodeTest::measureNodeVector.clear();
313 return result;
314 }
315 } // namespace ArkUICapiTest
316