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
16 #include <cstdint>
17 #include <native_drawing/drawing_brush.h>
18 #include <native_drawing/drawing_font.h>
19 #include <native_drawing/drawing_rect.h>
20 #include <native_drawing/drawing_round_rect.h>
21 #include <native_drawing/drawing_text_blob.h>
22 #include <string>
23 #include <cstdio>
24
25 #include <ace/xcomponent/native_interface_xcomponent.h>
26 #include <arkui/native_node.h>
27 #include <arkui/native_node_napi.h>
28 #include <arkui/native_interface.h>
29 #include <hilog/log.h>
30
31 #include "manager.h"
32 #include <native_drawing/drawing_canvas.h>
33 #include <native_drawing/drawing_path.h>
34 #include <native_drawing/drawing_pen.h>
35 #include <native_drawing/drawing_color.h>
36
37
38 namespace NativeXComponentSample {
39 Manager Manager::manager_;
40
~Manager()41 Manager::~Manager()
42 {
43 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "~Manager");
44 for (auto iter = nativeXComponentMap_.begin(); iter != nativeXComponentMap_.end(); ++iter) {
45 if (iter->second != nullptr) {
46 iter->second = nullptr;
47 }
48 }
49 nativeXComponentMap_.clear();
50
51 for (auto iter = containerMap_.begin(); iter != containerMap_.end(); ++iter) {
52 if (iter->second != nullptr) {
53 delete iter->second;
54 iter->second = nullptr;
55 }
56 }
57 containerMap_.clear();
58 }
59
CheckEnv(napi_env env,napi_callback_info info)60 bool CheckEnv(napi_env env, napi_callback_info info)
61 {
62 if ((env == nullptr) || (info == nullptr)) {
63 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode env or info is null");
64 return false;
65 }
66
67 size_t argCnt = 1;
68 napi_value args[1] = {nullptr};
69 if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
70 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed");
71 }
72
73 if (argCnt != 1) {
74 napi_throw_type_error(env, NULL, "Wrong number of arguments");
75 return false;
76 }
77 napi_valuetype valuetype;
78 if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
79 napi_throw_type_error(env, NULL, "napi_typeof failed");
80 return false;
81 }
82
83 if (valuetype != napi_string) {
84 napi_throw_type_error(env, NULL, "Wrong type of arguments");
85 return false;
86 }
87 return true;
88 }
89
CreateNativeNode(napi_env env,napi_callback_info info)90 napi_value Manager::CreateNativeNode(napi_env env, napi_callback_info info)
91 {
92 if (!CheckEnv(env, info)) {
93 return nullptr;
94 }
95 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
96 constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
97 size_t length;
98 if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
99 napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
100 return nullptr;
101 }
102
103 auto manager = Manager::GetInstance();
104 if (manager == nullptr) {
105 return nullptr;
106 }
107
108 OH_NativeXComponent *component = manager->GetNativeXComponent(idStr);
109 if (component == nullptr) {
110 return nullptr;
111 }
112
113 ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
114 OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
115 if (nodeAPI == nullptr) {
116 return nullptr;
117 }
118 if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
119 auto Column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
120 ArkUI_NumberValue ColumnWidthValue[] = {400};
121 ArkUI_AttributeItem ColumnWidthItem = {ColumnWidthValue, 1};
122 nodeAPI->setAttribute(Column, NODE_WIDTH, &ColumnWidthItem);
123 ArkUI_NumberValue ColumnHeightValue[] = {600};
124 ArkUI_AttributeItem ColumnHeightItem = {ColumnHeightValue, 1};
125 nodeAPI->setAttribute(Column, NODE_HEIGHT, &ColumnHeightItem);
126 ArkUI_NumberValue ColumnPaddingValue[] = {5};
127 ArkUI_AttributeItem ColumnPaddingItem = {ColumnPaddingValue, 1};
128 nodeAPI->setAttribute(Column, NODE_PADDING, &ColumnPaddingItem);
129 auto textInput = nodeAPI->createNode(ARKUI_NODE_TEXT_INPUT);
130 nodeAPI->registerNodeEvent(textInput, NODE_TEXT_INPUT_ON_CHANGE_WITH_PREVIEW_TEXT, 0, nullptr);
131 nodeAPI->addChild(Column, textInput);
132 OH_NativeXComponent_AttachNativeRootNode(component, Column);
133 }
134 return nullptr;
135 }
136
137
UpdateNativeNode(napi_env env,napi_callback_info info)138 napi_value Manager::UpdateNativeNode(napi_env env, napi_callback_info info)
139 {
140 if ((env == nullptr) || (info == nullptr)) {
141 return nullptr;
142 }
143
144 size_t argCnt = 1;
145 napi_value args[1] = {nullptr};
146 if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
147 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "UpdateNativeNode napi_get_cb_info failed");
148 }
149
150 if (argCnt != 1) {
151 return nullptr;
152 }
153
154 napi_valuetype valuetype;
155 if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
156 napi_throw_type_error(env, NULL, "napi_typeof failed");
157 return nullptr;
158 }
159
160 if (valuetype != napi_string) {
161 napi_throw_type_error(env, NULL, "Wrong type of arguments");
162 return nullptr;
163 }
164
165 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
166 constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
167 size_t length;
168 if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
169 napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
170 return nullptr;
171 }
172
173 auto manager = Manager::GetInstance();
174 if (manager == nullptr) {
175 return nullptr;
176 }
177
178 OH_NativeXComponent *component = manager->GetNativeXComponent(idStr);
179 if (component == nullptr) {
180 return nullptr;
181 }
182
183 if ((env == nullptr) || (info == nullptr || component == nullptr)) {
184 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext env or info is null");
185 return nullptr;
186 }
187
188 ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
189 OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
190 if (nodeAPI != nullptr) {
191 if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
192 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "UpdateNativeNode");
193 }
194 }
195 return nullptr;
196 }
197
GetContext(napi_env env,napi_callback_info info)198 napi_value Manager::GetContext(napi_env env, napi_callback_info info)
199 {
200 if ((env == nullptr) || (info == nullptr)) {
201 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext env or info is null");
202 return nullptr;
203 }
204
205 size_t argCnt = 1;
206 napi_value args[1] = {nullptr};
207 if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
208 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext napi_get_cb_info failed");
209 }
210
211 if (argCnt != 1) {
212 napi_throw_type_error(env, NULL, "Wrong number of arguments");
213 return nullptr;
214 }
215
216 napi_valuetype valuetype;
217 if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
218 napi_throw_type_error(env, NULL, "napi_typeof failed");
219 return nullptr;
220 }
221
222 if (valuetype != napi_number) {
223 napi_throw_type_error(env, NULL, "Wrong type of arguments");
224 return nullptr;
225 }
226
227 int64_t value;
228 if (napi_get_value_int64(env, args[0], &value) != napi_ok) {
229 napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
230 return nullptr;
231 }
232
233 napi_value exports;
234 if (napi_create_object(env, &exports) != napi_ok) {
235 napi_throw_type_error(env, NULL, "napi_create_object failed");
236 return nullptr;
237 }
238
239 return exports;
240 }
241
Export(napi_env env,napi_value exports)242 void Manager::Export(napi_env env, napi_value exports)
243 {
244 if ((env == nullptr) || (exports == nullptr)) {
245 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: env or exports is null");
246 return;
247 }
248
249 napi_value exportInstance = nullptr;
250 if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
251 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_get_named_property fail");
252 return;
253 }
254
255 OH_NativeXComponent *nativeXComponent = nullptr;
256 if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
257 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_unwrap fail");
258 return;
259 }
260
261 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
262 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
263 if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
264 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
265 "Export: OH_NativeXComponent_GetXComponentId fail");
266 return;
267 }
268
269 std::string id(idStr);
270 auto manager = Manager::GetInstance();
271 if ((manager != nullptr) && (nativeXComponent != nullptr)) {
272 manager->SetNativeXComponent(id, nativeXComponent);
273 auto container = manager->GetContainer(id);
274 if (container != nullptr) {
275 container->RegisterCallback(nativeXComponent);
276 }
277 }
278 }
279
SetNativeXComponent(std::string & id,OH_NativeXComponent * nativeXComponent)280 void Manager::SetNativeXComponent(std::string &id, OH_NativeXComponent *nativeXComponent)
281 {
282 if (nativeXComponent == nullptr) {
283 return;
284 }
285
286 if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {
287 nativeXComponentMap_[id] = nativeXComponent;
288 return;
289 }
290
291 if (nativeXComponentMap_[id] != nativeXComponent) {
292 OH_NativeXComponent *tmp = nativeXComponentMap_[id];
293 delete tmp;
294 tmp = nullptr;
295 nativeXComponentMap_[id] = nativeXComponent;
296 }
297 }
298
GetNativeXComponent(const std::string & id)299 OH_NativeXComponent *Manager::GetNativeXComponent(const std::string &id) { return nativeXComponentMap_[id]; }
300
GetContainer(std::string & id)301 Container *Manager::GetContainer(std::string &id)
302 {
303 if (containerMap_.find(id) == containerMap_.end()) {
304 Container *instance = Container::GetInstance(id);
305 containerMap_[id] = instance;
306 return instance;
307 }
308
309 return containerMap_[id];
310 }
311 } // namespace NativeXComponentSample
312