• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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