diff --git a/examples/Picker/jscontext/AppScope/app.json5 b/examples/Picker/jscontext/AppScope/app.json5 index c5e8fbd7b9c82e3580e794b44c4313c41601bb54..37c0274fde553b6e2c2ff52d9c049ce38ac261c1 100644 --- a/examples/Picker/jscontext/AppScope/app.json5 +++ b/examples/Picker/jscontext/AppScope/app.json5 @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "app": { - "bundleName": "com.example.jscontext", - "vendor": "example", - "versionCode": 1000000, - "versionName": "1.0.0", - "icon": "$media:layered_image", - "label": "$string:app_name" - } -} +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.example.jscontext", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/examples/Picker/jscontext/AppScope/resources/base/element/string.json b/examples/Picker/jscontext/AppScope/resources/base/element/string.json index 3ff48a288d3ce0181a48484ca1f066d499c22dfc..4be0a52562e92e4cdcbe1d404c291de891b3601f 100644 --- a/examples/Picker/jscontext/AppScope/resources/base/element/string.json +++ b/examples/Picker/jscontext/AppScope/resources/base/element/string.json @@ -1,8 +1,8 @@ -{ - "string": [ - { - "name": "app_name", - "value": "jscontext" - } - ] -} +{ + "string": [ + { + "name": "app_name", + "value": "jscontext" + } + ] +} diff --git a/examples/Picker/jscontext/AppScope/resources/base/media/hello.svg b/examples/Picker/jscontext/AppScope/resources/base/media/hello.svg index 693b14dc81c2dda69fe1049d2c4639b7ea4a8775..601d34fbb54938fc2b3c22564fea9d6aa75c239f 100644 --- a/examples/Picker/jscontext/AppScope/resources/base/media/hello.svg +++ b/examples/Picker/jscontext/AppScope/resources/base/media/hello.svg @@ -1,32 +1,32 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/Picker/jscontext/build-profile.json5 b/examples/Picker/jscontext/build-profile.json5 index 65e82c9c33cfcaf5de211339a1fa7e6091d26d2c..d1be996ef85e8fe20fd91c859e471d2c55584fb9 100644 --- a/examples/Picker/jscontext/build-profile.json5 +++ b/examples/Picker/jscontext/build-profile.json5 @@ -1,82 +1,82 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "app": { - "signingConfigs": [ - { - "name": "default", - "type": "HarmonyOS", - "material": { - "certpath": "C:\\Users\\royce\\.ohos\\config\\default_jscontext_tAJTFbrb2XukQoHs4mGDxqrz-c3cvgPxyu-1n8cOvZQ=.cer", - "keyAlias": "debugKey", - "keyPassword": "0000001BB65F7D513F612151B92EE510743747080A481C12B09F5E8F50367BEF7383467AF5CED61C83FCD6", - "profile": "C:\\Users\\royce\\.ohos\\config\\default_jscontext_tAJTFbrb2XukQoHs4mGDxqrz-c3cvgPxyu-1n8cOvZQ=.p7b", - "signAlg": "SHA256withECDSA", - "storeFile": "C:\\Users\\royce\\.ohos\\config\\default_jscontext_tAJTFbrb2XukQoHs4mGDxqrz-c3cvgPxyu-1n8cOvZQ=.p12", - "storePassword": "0000001B130AAFD7688AC1756FA468BDBB57453725D9B6673F5B9CAECBC04F32F0A2B596D4823B9B2D2CFC" - } - } - ], - "products": [ - { - "name": "default", - "signingConfig": "default", - "compileSdkVersion": 20, - "compatibleSdkVersion": 20, - "runtimeOS": "OpenHarmony", - "buildOption": { - "strictMode": { - "caseSensitiveCheck": true, - "useNormalizedOHMUrl": true - } - } - } - ], - "buildModeSet": [ - { - "name": "debug", - }, - { - "name": "release" - } - ] - }, - "modules": [ - { - "name": "entry", - "srcPath": "./entry", - "targets": [ - { - "name": "default", - "applyToProducts": [ - "default" - ] - } - ] - }, - { - "name": "car", - "srcPath": "./car", - "targets": [ - { - "name": "default", - "applyToProducts": [ - "default" - ] - } - ] - } - ] +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "signingConfigs": [ + { + "name": "default", + "type": "HarmonyOS", + "material": { + "certpath": "C:\\Users\\royce\\.ohos\\config\\default_jscontext_tAJTFbrb2XukQoHs4mGDxqrz-c3cvgPxyu-1n8cOvZQ=.cer", + "keyAlias": "debugKey", + "keyPassword": "0000001BB65F7D513F612151B92EE510743747080A481C12B09F5E8F50367BEF7383467AF5CED61C83FCD6", + "profile": "C:\\Users\\royce\\.ohos\\config\\default_jscontext_tAJTFbrb2XukQoHs4mGDxqrz-c3cvgPxyu-1n8cOvZQ=.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "C:\\Users\\royce\\.ohos\\config\\default_jscontext_tAJTFbrb2XukQoHs4mGDxqrz-c3cvgPxyu-1n8cOvZQ=.p12", + "storePassword": "0000001B130AAFD7688AC1756FA468BDBB57453725D9B6673F5B9CAECBC04F32F0A2B596D4823B9B2D2CFC" + } + } + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 20, + "compatibleSdkVersion": 20, + "runtimeOS": "OpenHarmony", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "car", + "srcPath": "./car", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/build-profile.json5 b/examples/Picker/jscontext/entry/build-profile.json5 index 1f28520fc48e32a1440b8c3ed958205edb0f123e..fba020fc65d3688db00310abd41bcbffda7dd814 100644 --- a/examples/Picker/jscontext/entry/build-profile.json5 +++ b/examples/Picker/jscontext/entry/build-profile.json5 @@ -1,54 +1,54 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "apiType": "stageMode", - "buildOption": { - "externalNativeOptions": { - "path": "./src/main/cpp/CMakeLists.txt", - "arguments": "", - "cppFlags": "", - "abiFilters": ["armeabi-v7a","arm64-v8a","x86_64"] - } - }, - "buildOptionSet": [ - { - "name": "release", - "arkOptions": { - "obfuscation": { - "ruleOptions": { - "enable": false, - "files": [ - "./obfuscation-rules.txt" - ] - } - } - }, - "nativeLib": { - "debugSymbol": { - "strip": true, - "exclude": [] - } - } - }, - ], - "targets": [ - { - "name": "default" - }, - { - "name": "ohosTest", - } - ] +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "apiType": "stageMode", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": ["armeabi-v7a","arm64-v8a","x86_64"] + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/oh-package-lock.json5 b/examples/Picker/jscontext/entry/oh-package-lock.json5 index e76a9588d75c64a099d8baa57b0077db3020b546..7bb726592058156328774f82fed982bed8feb1a1 100644 --- a/examples/Picker/jscontext/entry/oh-package-lock.json5 +++ b/examples/Picker/jscontext/entry/oh-package-lock.json5 @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "meta": { - "stableOrder": true - }, - "lockfileVersion": 3, - "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", - "specifiers": { - "car@../car": "car@../car", - "libentry.so@src/main/cpp/types/libentry": "libentry.so@src/main/cpp/types/libentry" - }, - "packages": { - "car@../car": { - "name": "car", - "version": "1.0.0", - "resolved": "../car", - "registryType": "local", - "packageType": "InterfaceHar" - }, - "libentry.so@src/main/cpp/types/libentry": { - "name": "libentry.so", - "version": "1.0.0", - "resolved": "src/main/cpp/types/libentry", - "registryType": "local" - } - } +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "car@../car": "car@../car", + "libentry.so@src/main/cpp/types/libentry": "libentry.so@src/main/cpp/types/libentry" + }, + "packages": { + "car@../car": { + "name": "car", + "version": "1.0.0", + "resolved": "../car", + "registryType": "local", + "packageType": "InterfaceHar" + }, + "libentry.so@src/main/cpp/types/libentry": { + "name": "libentry.so", + "version": "1.0.0", + "resolved": "src/main/cpp/types/libentry", + "registryType": "local" + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/oh-package.json5 b/examples/Picker/jscontext/entry/oh-package.json5 index 59a54466473016b7f1bdff145b32aa827558a473..7999d40b83d4e3fe71e63c95246c1fb2854a64f5 100644 --- a/examples/Picker/jscontext/entry/oh-package.json5 +++ b/examples/Picker/jscontext/entry/oh-package.json5 @@ -1,26 +1,26 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "name": "entry", - "version": "1.0.0", - "description": "Please describe the basic information.", - "main": "", - "author": "", - "license": "", - "dependencies": { - "libentry.so": "file:./src/main/cpp/types/libentry", - "car": "file:../car" - } +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry", + "car": "file:../car" + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/cpp/napi_init.cpp b/examples/Picker/jscontext/entry/src/main/cpp/napi_init.cpp index 3d02b6561c78705829e8f6f8dfa295888f8c07ee..816065313ba4f8ea293dc4adabd419545fc1191b 100644 --- a/examples/Picker/jscontext/entry/src/main/cpp/napi_init.cpp +++ b/examples/Picker/jscontext/entry/src/main/cpp/napi_init.cpp @@ -1,389 +1,389 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "hilog/log.h" -#include "napi/native_api.h" -#include -#include -#include - -extern "C" napi_status napi_create_ark_context(napi_env env, napi_env *newEnv); -extern "C" napi_status napi_switch_ark_context(napi_env env); -extern "C" napi_status napi_destroy_ark_context(napi_env env); - -static std::map envMaps_; - -const int ATTR_INDEX_0 = 0; -const int ATTR_INDEX_1 = 1; -const int ATTR_INDEX_2 = 2; -const int ATTR_INDEX_3 = 3; -const int ATTR_INDEX_4 = 4; -const int BUFFER_SIZE = 4096; - -std::string GetString(const napi_env &env, const napi_value &value) -{ - std::unique_ptr buffer = std::make_unique(BUFFER_SIZE); - size_t length = 0; - napi_get_value_string_utf8(env, value, buffer.get(), BUFFER_SIZE, &length); - return std::string(buffer.get(), length); -} - - -// Helper functions for NAPI_Global_callFunctionInContext1 -static napi_value LoadAndGetProperty(napi_env env, const char* path, const char* propertyName) -{ - napi_value plugin = nullptr; - napi_status status = napi_load_module_with_info(env, path, "com.example.jscontext/entry", &plugin); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] load module info of env failed"); - return nullptr; - } - - napi_value property = nullptr; - status = napi_get_named_property(env, plugin, propertyName, &property); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] get name property of env failed"); - return nullptr; - } - return property; -} - -static void CallFunctionAndLogResult(napi_env env, napi_value func, napi_value arg, const char* logPrefix) -{ - napi_value result = nullptr; - napi_value args[1] = {arg}; - napi_status status = napi_call_function(env, nullptr, func, 1, args, &result); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] call function of env failed"); - return; - } - - int32_t ret = 0; - status = napi_get_value_int32(env, result, &ret); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_get_value_int32 of env failed"); - } else { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] %s ret is %{public}d", logPrefix, ret); - } -} - -// context1 -static napi_value NAPI_Global_callFunctionInContext1(napi_env env, napi_callback_info info) -{ - OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext1 called"); - napi_status status = napi_ok; - - size_t argc = 1; - napi_value args[ATTR_INDEX_1] = {nullptr}; - if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { - return nullptr; - } - - napi_value getLocation1 = LoadAndGetProperty(env, "entry/src/main/ets/pages/plugin1", "GetLocation"); - napi_value getLocation2 = LoadAndGetProperty(env, "entry/src/main/ets/pages/plugin2", "GetLocation"); - - if (getLocation1 != nullptr) { - CallFunctionAndLogResult(env, args[ATTR_INDEX_0], getLocation1, "plugin1"); - } - if (getLocation2 != nullptr) { - CallFunctionAndLogResult(env, args[ATTR_INDEX_0], getLocation2, "plugin2"); - } - - OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext1 finished"); - return nullptr; -} - -// Helper functions for NAPI_Global_callFunctionInContext2 -static napi_env CreateAndSwitchContext(napi_env env) -{ - napi_env newEnv = nullptr; - napi_status status = napi_create_ark_context(env, &newEnv); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context failed"); - return nullptr; - } - napi_switch_ark_context(newEnv); - return newEnv; -} - -// context2 -static napi_value NAPI_Global_callFunctionInContext2(napi_env env, napi_callback_info info) -{ - OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext2 called"); - - size_t argc = 1; - napi_value args[ATTR_INDEX_1] = {nullptr}; - if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { - return nullptr; - } - - napi_value getLocation1 = LoadAndGetProperty(env, "entry/src/main/ets/pages/plugin1", "GetLocation"); - napi_env newEnv2 = CreateAndSwitchContext(env); - if (newEnv2 == nullptr) { - return nullptr; - } - - napi_value getLocation2 = LoadAndGetProperty(newEnv2, "entry/src/main/ets/pages/plugin2", "GetLocation"); - if (getLocation2 != nullptr) { - CallFunctionAndLogResult(newEnv2, args[ATTR_INDEX_0], getLocation2, "plugin2 in new context"); - } - - napi_switch_ark_context(env); - if (getLocation1 != nullptr) { - CallFunctionAndLogResult(env, args[ATTR_INDEX_0], getLocation1, "plugin1 in original context"); - } - - OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext2 finished"); - napi_destroy_ark_context(newEnv2); - return nullptr; -} - -// Helper functions for NAPI_Global_RequirePlugin -static napi_value SetupPluginEnv(napi_env env, napi_env pluginEnv, napi_value hmsValue) -{ - napi_status status = napi_switch_ark_context(pluginEnv); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] switch context status failed. %{public}d", status); - return nullptr; - } - - napi_value plugin_global; - status = napi_get_global(pluginEnv, &plugin_global); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_get_global failed. %{public}d", status); - return nullptr; - } - - status = napi_set_named_property(pluginEnv, plugin_global, "hms", hmsValue); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_set_named_property failed. %{public}d", status); - } - return plugin_global; -} - -static napi_value NAPI_Global_RequirePlugin(napi_env env, napi_callback_info info) -{ - size_t argc = 2; - napi_value args[ATTR_INDEX_2]; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - std::string id = GetString(env, args[ATTR_INDEX_0]); - OH_LOG_INFO(LOG_APP, "[jsMultiContext] native require plugin id is %{public}s", id.c_str()); - - napi_env pluginEnv = nullptr; - napi_status status = napi_create_ark_context(env, &pluginEnv); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context failed. %{public}d", status); - return nullptr; - } - - SetupPluginEnv(env, pluginEnv, args[ATTR_INDEX_1]); - - napi_value pluginObj = nullptr; - status = napi_load_module_with_info(pluginEnv, id.c_str(), "com.example.jscontext/entry", &pluginObj); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] native napi_load_module_with_info failed"); - } - - napi_value car = nullptr; - status = napi_get_named_property(pluginEnv, pluginObj, "car", &car); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] get car failed"); - } - - napi_switch_ark_context(env); - return car; -} - -// Helper functions for NAPI_Global_nativeRequirePluginComponent -static bool InitializeArkUIEnv(napi_env env) -{ - auto ret = OH_ArkUI_InitModuleForArkTSEnv(env); - if (ret != ARKUI_ERROR_CODE_NO_ERROR) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] OH_ArkUI_InitModuleForArkTSEnv failed"); - return false; - } - return true; -} - -static napi_value NAPI_Global_nativeRequirePluginComponent(napi_env env, napi_callback_info info) -{ - size_t argc = 3; - napi_value args[ATTR_INDEX_3] = {}; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - OH_LOG_INFO(LOG_APP, "[jsMultiContext] id = %{public}s", GetString(env, args[ATTR_INDEX_0]).c_str()); - - ArkUI_NodeContentHandle nodeHandle = nullptr; - int32_t code = OH_ArkUI_GetNodeContentFromNapiValue(env, args[ATTR_INDEX_1], &nodeHandle); - if (code != ARKUI_ERROR_CODE_NO_ERROR) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] getNodeContent failed"); - } - - napi_env newEnv2 = nullptr; - napi_status status = napi_create_ark_context(env, &newEnv2); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context failed"); - } - - OH_LOG_INFO(LOG_APP, "[jsMultiContext] create NAPI_Global_nativeRequirePluginComponent p = %{public}p", newEnv2); - envMaps_["envArkui"] = newEnv2; - - status = napi_switch_ark_context(newEnv2); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] switch component context failed"); - } - - InitializeArkUIEnv(newEnv2); - - std::string car = "car"; - napi_value pluginObj; - napi_status status1 = napi_load_module_with_info(newEnv2, car.c_str(), "com.example.jscontext/entry", &pluginObj); - if (status1 != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_load_module_with_info failed"); - } - - napi_value carComponent = nullptr; - status = napi_get_named_property(newEnv2, pluginObj, "InitBuilder", &carComponent); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] native fetch carContent failed"); - } - - napi_value result2 = nullptr; - status = napi_call_function(newEnv2, pluginObj, carComponent, 1, &args[ATTR_INDEX_2], &result2); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_call_function failed"); - } - - napi_switch_ark_context(env); - return result2; -} - -static napi_value NAPI_Global_nativeDestroyPluginComponent(napi_env env, napi_callback_info info) -{ - size_t argc = 1; - napi_value args[ATTR_INDEX_1] = {}; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - auto pluginName = GetString(env, args[ATTR_INDEX_0]); - OH_LOG_INFO(LOG_APP, "[jsMultiContext] DestroyPlugin %{public}s", pluginName.c_str()); - - if (envMaps_.find(pluginName) != envMaps_.end()) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] DestroyPlugin success! p = %{public}p", envMaps_[pluginName]); - - OH_ArkUI_NotifyArkTSEnvDestroy(envMaps_[pluginName]); - auto ret = napi_destroy_ark_context(envMaps_[pluginName]); - if (ret != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] DestroyPlugin failed!"); - return nullptr; - } - envMaps_.erase(pluginName); - } - return nullptr; -} - -// Helper functions for NAPI_Global_nativeRequirePlugins -static bool SetupPluginEnvironment(napi_env env, const std::string& pluginName) -{ - if (envMaps_.find(pluginName) != envMaps_.end()) { - return true; - } - - napi_env newEnv = nullptr; - napi_status status = napi_create_ark_context(env, &newEnv); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context of %{public}s failed", pluginName.c_str()); - return false; - } - - envMaps_[pluginName] = newEnv; - OH_LOG_INFO(LOG_APP, "[jsMultiContext] create envMaps_[%{public}s] p = %{public}p", pluginName.c_str(), newEnv); - - status = napi_switch_ark_context(newEnv); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] switch %{public}s failed", pluginName.c_str()); - return false; - } - - if (!InitializeArkUIEnv(newEnv)) { - return false; - } - - return true; -} - -static napi_value NAPI_Global_nativeRequirePlugins(napi_env env, napi_callback_info info) -{ - size_t argc = 4; - napi_value args[ATTR_INDEX_4] = {}; - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - auto moduleName = GetString(env, args[ATTR_INDEX_0]); - auto builderFunc = GetString(env, args[ATTR_INDEX_1]); - auto pluginName = GetString(env, args[ATTR_INDEX_3]); - if (!SetupPluginEnvironment(env, pluginName)) { - return nullptr; - } - - napi_value pluginObj; - napi_status status = napi_load_module_with_info( - envMaps_[pluginName], moduleName.c_str(), "com.example.jscontext/entry", &pluginObj); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] load module %{public}s failed", moduleName.c_str()); - } - - napi_value component = nullptr; - status = napi_get_named_property(envMaps_[pluginName], pluginObj, builderFunc.c_str(), &component); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] fetch %{public}s failed", builderFunc.c_str()); - } - - napi_value result = nullptr; - napi_value para[1] = {args[ATTR_INDEX_2]}; - status = napi_call_function(envMaps_[pluginName], pluginObj, component, 1, para, &result); - if (status != napi_ok) { - OH_LOG_INFO(LOG_APP, "[jsMultiContext] call %{public}s failed", builderFunc.c_str()); - } - - napi_switch_ark_context(env); - return result; -} - -EXTERN_C_START -static napi_value Init(napi_env env, napi_value exports) -{ - napi_property_descriptor desc[] = { - {"callFunctionInContext1", nullptr, NAPI_Global_callFunctionInContext1, nullptr, nullptr, nullptr, napi_default, - nullptr}, - {"callFunctionInContext2", nullptr, NAPI_Global_callFunctionInContext2, nullptr, nullptr, nullptr, napi_default, - nullptr}, - {"nativeRequirePlugin", nullptr, NAPI_Global_RequirePlugin, nullptr, nullptr, nullptr, napi_default, nullptr}, - {"nativeRequirePluginComponent", nullptr, NAPI_Global_nativeRequirePluginComponent, nullptr, nullptr, nullptr, - napi_default, nullptr}, - {"nativeDestroyPluginComponent", nullptr, NAPI_Global_nativeDestroyPluginComponent, nullptr, nullptr, nullptr, - napi_default, nullptr}, - {"nativeRequirePlugins", nullptr, NAPI_Global_nativeRequirePlugins, nullptr, nullptr, nullptr, napi_default, - nullptr}}; - napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[ATTR_INDEX_0]), desc); - return exports; -} -EXTERN_C_END - -static napi_module demoModule = { - .nm_version = 1, - .nm_flags = 0, - .nm_filename = nullptr, - .nm_register_func = Init, - .nm_modname = "entry", - .nm_priv = ((void *)0), - .reserved = {0}, -}; - +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hilog/log.h" +#include "napi/native_api.h" +#include +#include +#include + +extern "C" napi_status napi_create_ark_context(napi_env env, napi_env *newEnv); +extern "C" napi_status napi_switch_ark_context(napi_env env); +extern "C" napi_status napi_destroy_ark_context(napi_env env); + +static std::map envMaps_; + +const int ATTR_INDEX_0 = 0; +const int ATTR_INDEX_1 = 1; +const int ATTR_INDEX_2 = 2; +const int ATTR_INDEX_3 = 3; +const int ATTR_INDEX_4 = 4; +const int BUFFER_SIZE = 4096; + +std::string GetString(const napi_env &env, const napi_value &value) +{ + std::unique_ptr buffer = std::make_unique(BUFFER_SIZE); + size_t length = 0; + napi_get_value_string_utf8(env, value, buffer.get(), BUFFER_SIZE, &length); + return std::string(buffer.get(), length); +} + + +// Helper functions for NAPI_Global_callFunctionInContext1 +static napi_value LoadAndGetProperty(napi_env env, const char* path, const char* propertyName) +{ + napi_value plugin = nullptr; + napi_status status = napi_load_module_with_info(env, path, "com.example.jscontext/entry", &plugin); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] load module info of env failed"); + return nullptr; + } + + napi_value property = nullptr; + status = napi_get_named_property(env, plugin, propertyName, &property); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] get name property of env failed"); + return nullptr; + } + return property; +} + +static void CallFunctionAndLogResult(napi_env env, napi_value func, napi_value arg, const char* logPrefix) +{ + napi_value result = nullptr; + napi_value args[1] = {arg}; + napi_status status = napi_call_function(env, nullptr, func, 1, args, &result); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] call function of env failed"); + return; + } + + int32_t ret = 0; + status = napi_get_value_int32(env, result, &ret); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_get_value_int32 of env failed"); + } else { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] %s ret is %{public}d", logPrefix, ret); + } +} + +// context1 +static napi_value NAPI_Global_callFunctionInContext1(napi_env env, napi_callback_info info) +{ + OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext1 called"); + napi_status status = napi_ok; + + size_t argc = 1; + napi_value args[ATTR_INDEX_1] = {nullptr}; + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { + return nullptr; + } + + napi_value getLocation1 = LoadAndGetProperty(env, "entry/src/main/ets/pages/plugin1", "GetLocation"); + napi_value getLocation2 = LoadAndGetProperty(env, "entry/src/main/ets/pages/plugin2", "GetLocation"); + + if (getLocation1 != nullptr) { + CallFunctionAndLogResult(env, args[ATTR_INDEX_0], getLocation1, "plugin1"); + } + if (getLocation2 != nullptr) { + CallFunctionAndLogResult(env, args[ATTR_INDEX_0], getLocation2, "plugin2"); + } + + OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext1 finished"); + return nullptr; +} + +// Helper functions for NAPI_Global_callFunctionInContext2 +static napi_env CreateAndSwitchContext(napi_env env) +{ + napi_env newEnv = nullptr; + napi_status status = napi_create_ark_context(env, &newEnv); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context failed"); + return nullptr; + } + napi_switch_ark_context(newEnv); + return newEnv; +} + +// context2 +static napi_value NAPI_Global_callFunctionInContext2(napi_env env, napi_callback_info info) +{ + OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext2 called"); + + size_t argc = 1; + napi_value args[ATTR_INDEX_1] = {nullptr}; + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { + return nullptr; + } + + napi_value getLocation1 = LoadAndGetProperty(env, "entry/src/main/ets/pages/plugin1", "GetLocation"); + napi_env newEnv2 = CreateAndSwitchContext(env); + if (newEnv2 == nullptr) { + return nullptr; + } + + napi_value getLocation2 = LoadAndGetProperty(newEnv2, "entry/src/main/ets/pages/plugin2", "GetLocation"); + if (getLocation2 != nullptr) { + CallFunctionAndLogResult(newEnv2, args[ATTR_INDEX_0], getLocation2, "plugin2 in new context"); + } + + napi_switch_ark_context(env); + if (getLocation1 != nullptr) { + CallFunctionAndLogResult(env, args[ATTR_INDEX_0], getLocation1, "plugin1 in original context"); + } + + OH_LOG_INFO(LOG_APP, "[jsMultiContext] NAPI_Global_callFunctionInContext2 finished"); + napi_destroy_ark_context(newEnv2); + return nullptr; +} + +// Helper functions for NAPI_Global_RequirePlugin +static napi_value SetupPluginEnv(napi_env env, napi_env pluginEnv, napi_value hmsValue) +{ + napi_status status = napi_switch_ark_context(pluginEnv); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] switch context status failed. %{public}d", status); + return nullptr; + } + + napi_value plugin_global; + status = napi_get_global(pluginEnv, &plugin_global); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_get_global failed. %{public}d", status); + return nullptr; + } + + status = napi_set_named_property(pluginEnv, plugin_global, "hms", hmsValue); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_set_named_property failed. %{public}d", status); + } + return plugin_global; +} + +static napi_value NAPI_Global_RequirePlugin(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[ATTR_INDEX_2]; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + std::string id = GetString(env, args[ATTR_INDEX_0]); + OH_LOG_INFO(LOG_APP, "[jsMultiContext] native require plugin id is %{public}s", id.c_str()); + + napi_env pluginEnv = nullptr; + napi_status status = napi_create_ark_context(env, &pluginEnv); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context failed. %{public}d", status); + return nullptr; + } + + SetupPluginEnv(env, pluginEnv, args[ATTR_INDEX_1]); + + napi_value pluginObj = nullptr; + status = napi_load_module_with_info(pluginEnv, id.c_str(), "com.example.jscontext/entry", &pluginObj); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] native napi_load_module_with_info failed"); + } + + napi_value car = nullptr; + status = napi_get_named_property(pluginEnv, pluginObj, "car", &car); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] get car failed"); + } + + napi_switch_ark_context(env); + return car; +} + +// Helper functions for NAPI_Global_nativeRequirePluginComponent +static bool InitializeArkUIEnv(napi_env env) +{ + auto ret = OH_ArkUI_InitModuleForArkTSEnv(env); + if (ret != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] OH_ArkUI_InitModuleForArkTSEnv failed"); + return false; + } + return true; +} + +static napi_value NAPI_Global_nativeRequirePluginComponent(napi_env env, napi_callback_info info) +{ + size_t argc = 3; + napi_value args[ATTR_INDEX_3] = {}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + OH_LOG_INFO(LOG_APP, "[jsMultiContext] id = %{public}s", GetString(env, args[ATTR_INDEX_0]).c_str()); + + ArkUI_NodeContentHandle nodeHandle = nullptr; + int32_t code = OH_ArkUI_GetNodeContentFromNapiValue(env, args[ATTR_INDEX_1], &nodeHandle); + if (code != ARKUI_ERROR_CODE_NO_ERROR) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] getNodeContent failed"); + } + + napi_env newEnv2 = nullptr; + napi_status status = napi_create_ark_context(env, &newEnv2); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context failed"); + } + + OH_LOG_INFO(LOG_APP, "[jsMultiContext] create NAPI_Global_nativeRequirePluginComponent p = %{public}p", newEnv2); + envMaps_["envArkui"] = newEnv2; + + status = napi_switch_ark_context(newEnv2); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] switch component context failed"); + } + + InitializeArkUIEnv(newEnv2); + + std::string car = "car"; + napi_value pluginObj; + napi_status status1 = napi_load_module_with_info(newEnv2, car.c_str(), "com.example.jscontext/entry", &pluginObj); + if (status1 != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_load_module_with_info failed"); + } + + napi_value carComponent = nullptr; + status = napi_get_named_property(newEnv2, pluginObj, "InitBuilder", &carComponent); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] native fetch carContent failed"); + } + + napi_value result2 = nullptr; + status = napi_call_function(newEnv2, pluginObj, carComponent, 1, &args[ATTR_INDEX_2], &result2); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] napi_call_function failed"); + } + + napi_switch_ark_context(env); + return result2; +} + +static napi_value NAPI_Global_nativeDestroyPluginComponent(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[ATTR_INDEX_1] = {}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + auto pluginName = GetString(env, args[ATTR_INDEX_0]); + OH_LOG_INFO(LOG_APP, "[jsMultiContext] DestroyPlugin %{public}s", pluginName.c_str()); + + if (envMaps_.find(pluginName) != envMaps_.end()) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] DestroyPlugin success! p = %{public}p", envMaps_[pluginName]); + + OH_ArkUI_NotifyArkTSEnvDestroy(envMaps_[pluginName]); + auto ret = napi_destroy_ark_context(envMaps_[pluginName]); + if (ret != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] DestroyPlugin failed!"); + return nullptr; + } + envMaps_.erase(pluginName); + } + return nullptr; +} + +// Helper functions for NAPI_Global_nativeRequirePlugins +static bool SetupPluginEnvironment(napi_env env, const std::string& pluginName) +{ + if (envMaps_.find(pluginName) != envMaps_.end()) { + return true; + } + + napi_env newEnv = nullptr; + napi_status status = napi_create_ark_context(env, &newEnv); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] create ark context of %{public}s failed", pluginName.c_str()); + return false; + } + + envMaps_[pluginName] = newEnv; + OH_LOG_INFO(LOG_APP, "[jsMultiContext] create envMaps_[%{public}s] p = %{public}p", pluginName.c_str(), newEnv); + + status = napi_switch_ark_context(newEnv); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] switch %{public}s failed", pluginName.c_str()); + return false; + } + + if (!InitializeArkUIEnv(newEnv)) { + return false; + } + + return true; +} + +static napi_value NAPI_Global_nativeRequirePlugins(napi_env env, napi_callback_info info) +{ + size_t argc = 4; + napi_value args[ATTR_INDEX_4] = {}; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + auto moduleName = GetString(env, args[ATTR_INDEX_0]); + auto builderFunc = GetString(env, args[ATTR_INDEX_1]); + auto pluginName = GetString(env, args[ATTR_INDEX_3]); + if (!SetupPluginEnvironment(env, pluginName)) { + return nullptr; + } + + napi_value pluginObj; + napi_status status = napi_load_module_with_info( + envMaps_[pluginName], moduleName.c_str(), "com.example.jscontext/entry", &pluginObj); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] load module %{public}s failed", moduleName.c_str()); + } + + napi_value component = nullptr; + status = napi_get_named_property(envMaps_[pluginName], pluginObj, builderFunc.c_str(), &component); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] fetch %{public}s failed", builderFunc.c_str()); + } + + napi_value result = nullptr; + napi_value para[1] = {args[ATTR_INDEX_2]}; + status = napi_call_function(envMaps_[pluginName], pluginObj, component, 1, para, &result); + if (status != napi_ok) { + OH_LOG_INFO(LOG_APP, "[jsMultiContext] call %{public}s failed", builderFunc.c_str()); + } + + napi_switch_ark_context(env); + return result; +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + {"callFunctionInContext1", nullptr, NAPI_Global_callFunctionInContext1, nullptr, nullptr, nullptr, napi_default, + nullptr}, + {"callFunctionInContext2", nullptr, NAPI_Global_callFunctionInContext2, nullptr, nullptr, nullptr, napi_default, + nullptr}, + {"nativeRequirePlugin", nullptr, NAPI_Global_RequirePlugin, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"nativeRequirePluginComponent", nullptr, NAPI_Global_nativeRequirePluginComponent, nullptr, nullptr, nullptr, + napi_default, nullptr}, + {"nativeDestroyPluginComponent", nullptr, NAPI_Global_nativeDestroyPluginComponent, nullptr, nullptr, nullptr, + napi_default, nullptr}, + {"nativeRequirePlugins", nullptr, NAPI_Global_nativeRequirePlugins, nullptr, nullptr, nullptr, napi_default, + nullptr}}; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[ATTR_INDEX_0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/Index.d.ts b/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/Index.d.ts index 4ec36a628bed18b99725b009341b7e61e29426a8..0f0fb5c566cc667c10aeabc032a00afc88c854f5 100644 --- a/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/Index.d.ts +++ b/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/Index.d.ts @@ -1,20 +1,20 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export const callFunctionInContext1: (func: (func: () => number) => {}) => number; -export const callFunctionInContext2: (func: (func: () => number) => {}) => number; -export const nativeRequirePlugin: (id, hms) => object; -export const nativeRequirePluginComponent: (id, object, context) => object; -export const nativeDestroyPluginComponent: (pluginName)=>{}; +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export const callFunctionInContext1: (func: (func: () => number) => {}) => number; +export const callFunctionInContext2: (func: (func: () => number) => {}) => number; +export const nativeRequirePlugin: (id, hms) => object; +export const nativeRequirePluginComponent: (id, object, context) => object; +export const nativeDestroyPluginComponent: (pluginName)=>{}; export const nativeRequirePlugins: (moduleName, builderFunc, context, pluginName) => object; \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/oh-package.json5 b/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/oh-package.json5 index c69ca2198f11d3288b2ac61227a583604b647c78..77052c679533e45a066030a9fc21cdbf9cbcf995 100644 --- a/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/oh-package.json5 +++ b/examples/Picker/jscontext/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -1,20 +1,20 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "name": "libentry.so", - "types": "./Index.d.ts", - "version": "1.0.0", - "description": "Please describe the basic information." +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/entryability/EntryAbility.ets b/examples/Picker/jscontext/entry/src/main/ets/entryability/EntryAbility.ets index b12b706076bc833e0f1c073e99881ef3b3a84004..508880af8c33aa838016d1cd4b2c68be2f447540 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/entryability/EntryAbility.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/entryability/EntryAbility.ets @@ -1,44 +1,44 @@ -import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; -import { hilog } from '@kit.PerformanceAnalysisKit'; -import { window } from '@kit.ArkUI'; - -const DOMAIN = 0x0000; - -export default class EntryAbility extends UIAbility { - onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { - this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); - } - - onDestroy(): void { - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); - } - - onWindowStageCreate(windowStage: window.WindowStage): void { - // Main window is created, set main page for this ability - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); - - windowStage.loadContent('pages/Index', (err) => { - if (err.code) { - hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); - return; - } - hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); - }); - } - - onWindowStageDestroy(): void { - // Main window is destroyed, release UI related resources - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); - } - - onForeground(): void { - // Ability has brought to foreground - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); - } - - onBackground(): void { - // Ability has back to background - hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); - } +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/examples/Picker/jscontext/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets index fae19f9dd53d2857e2843539cbedf5bee4a34b5a..8e4de99282050bad799ac892eb85ac5449364a51 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -1,16 +1,16 @@ -import { hilog } from '@kit.PerformanceAnalysisKit'; -import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; - -const DOMAIN = 0x0000; - -export default class EntryBackupAbility extends BackupExtensionAbility { - async onBackup() { - hilog.info(DOMAIN, 'testTag', 'onBackup ok'); - await Promise.resolve(); - } - - async onRestore(bundleVersion: BundleVersion) { - hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); - await Promise.resolve(); - } +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/Index.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/Index.ets index 65fdeecfb32cdb5d52c41a15ece04557b2017690..c6dec491c76c971fea4a960672de4fb6875bf13d 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/Index.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/Index.ets @@ -1,31 +1,31 @@ -import router from '@ohos.router'; - -interface ListCategories { - title: string, - url: string -} - -@Entry -@Component -struct Index { - @State message: string = 'Search' - private items: ListCategories[] = [ - { title: '普通模式', url: 'pages/normal/normalIndex' }, - { title: '沙箱上下文模式', url: 'pages/sandbox/plugins' }, - { title: '普通+沙箱上下文模式', url: 'pages/mixed/plugins' }, - ] - - build() { - Column() { - List({ space: '10vp' }) { - ForEach(this.items, (item: ListCategories) => { - ListItem() { - Text(item.title).fontSize(16).fontWeight(FontWeight.Bold).onClick(() => { - router.pushUrl({ url: item.url }); - }) - }.width('90%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) - }) - }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') - }.width('100%').height('100%') - } +import router from '@ohos.router'; + +interface ListCategories { + title: string, + url: string +} + +@Entry +@Component +struct Index { + @State message: string = 'Search' + private items: ListCategories[] = [ + { title: '普通模式', url: 'pages/normal/normalIndex' }, + { title: '沙箱上下文模式', url: 'pages/sandbox/plugins' }, + { title: '普通+沙箱上下文模式', url: 'pages/mixed/plugins' }, + ] + + build() { + Column() { + List({ space: '10vp' }) { + ForEach(this.items, (item: ListCategories) => { + ListItem() { + Text(item.title).fontSize(16).fontWeight(FontWeight.Bold).onClick(() => { + router.pushUrl({ url: item.url }); + }) + }.width('90%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) + }) + }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') + }.width('100%').height('100%') + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed100.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed100.ets index 5de9009daa8d247a966231a64a80462eef9a69fb..56edde769611b0821c862b9604b2e6a8560014f6 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed100.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed100.ets @@ -1,32 +1,32 @@ -import { MultiComponent100 } from '../../framework/PComponent' -import * as comps from '../../framework/normalComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - Text('普通模式').fontSize(40).backgroundColor(Color.Gray) - comps.DatePickerComponent() - comps.CalendarPickerComponent() - comps.TimePickerComponent() - comps.TextPickerComponent() - comps.DatePickerDialogComponent() - comps.CalendarPickerDialogComponent() - comps.TimePickerDialogComponent() - comps.TextPickerDialogComponent() - comps.ImageComponent() - comps.ImageAnimatorComponent() - comps.CounterComponent() - comps.PatternLockComponent() - comps.TextClockComponent() - comps.TextTimerComponent() - Text('沙箱模式随机').fontSize(40).backgroundColor(Color.Gray) - MultiComponent100() - } - } - } +import { MultiComponent100 } from '../../framework/PComponent' +import * as comps from '../../framework/normalComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + Text('普通模式').fontSize(40).backgroundColor(Color.Gray) + comps.DatePickerComponent() + comps.CalendarPickerComponent() + comps.TimePickerComponent() + comps.TextPickerComponent() + comps.DatePickerDialogComponent() + comps.CalendarPickerDialogComponent() + comps.TimePickerDialogComponent() + comps.TextPickerDialogComponent() + comps.ImageComponent() + comps.ImageAnimatorComponent() + comps.CounterComponent() + comps.PatternLockComponent() + comps.TextClockComponent() + comps.TextTimerComponent() + Text('沙箱模式随机').fontSize(40).backgroundColor(Color.Gray) + MultiComponent100() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed20.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed20.ets index 77e42887b9e98a06eee3cdda08d6e3da4a7075de..589093603b20c0c3b7734d37dd7785b56cce2c44 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed20.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed20.ets @@ -1,32 +1,32 @@ -import { MultiComponent20 } from '../../framework/PComponent' -import * as comps from '../../framework/normalComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - Text('普通模式').fontSize(40).backgroundColor(Color.Gray) - comps.DatePickerComponent() - comps.CalendarPickerComponent() - comps.TimePickerComponent() - comps.TextPickerComponent() - comps.DatePickerDialogComponent() - comps.CalendarPickerDialogComponent() - comps.TimePickerDialogComponent() - comps.TextPickerDialogComponent() - comps.ImageComponent() - comps.ImageAnimatorComponent() - comps.CounterComponent() - comps.PatternLockComponent() - comps.TextClockComponent() - comps.TextTimerComponent() - Text('沙箱模式随机').fontSize(40).backgroundColor(Color.Gray) - MultiComponent20() - } - } - } +import { MultiComponent20 } from '../../framework/PComponent' +import * as comps from '../../framework/normalComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + Text('普通模式').fontSize(40).backgroundColor(Color.Gray) + comps.DatePickerComponent() + comps.CalendarPickerComponent() + comps.TimePickerComponent() + comps.TextPickerComponent() + comps.DatePickerDialogComponent() + comps.CalendarPickerDialogComponent() + comps.TimePickerDialogComponent() + comps.TextPickerDialogComponent() + comps.ImageComponent() + comps.ImageAnimatorComponent() + comps.CounterComponent() + comps.PatternLockComponent() + comps.TextClockComponent() + comps.TextTimerComponent() + Text('沙箱模式随机').fontSize(40).backgroundColor(Color.Gray) + MultiComponent20() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed50.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed50.ets index 5029d8cef8a23cacefaf40203d0c98a77365ebcf..b113de01d4c3f6ebc9cc79f3246e9bc743cd7217 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed50.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixed50.ets @@ -1,32 +1,32 @@ -import { MultiComponent50 } from '../../framework/PComponent' -import * as comps from '../../framework/normalComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - Text('普通模式').fontSize(40).backgroundColor(Color.Gray) - comps.DatePickerComponent() - comps.CalendarPickerComponent() - comps.TimePickerComponent() - comps.TextPickerComponent() - comps.DatePickerDialogComponent() - comps.CalendarPickerDialogComponent() - comps.TimePickerDialogComponent() - comps.TextPickerDialogComponent() - comps.ImageComponent() - comps.ImageAnimatorComponent() - comps.CounterComponent() - comps.PatternLockComponent() - comps.TextClockComponent() - comps.TextTimerComponent() - Text('沙箱模式随机').fontSize(40).backgroundColor(Color.Gray) - MultiComponent50() - } - } - } +import { MultiComponent50 } from '../../framework/PComponent' +import * as comps from '../../framework/normalComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + Text('普通模式').fontSize(40).backgroundColor(Color.Gray) + comps.DatePickerComponent() + comps.CalendarPickerComponent() + comps.TimePickerComponent() + comps.TextPickerComponent() + comps.DatePickerDialogComponent() + comps.CalendarPickerDialogComponent() + comps.TimePickerDialogComponent() + comps.TextPickerDialogComponent() + comps.ImageComponent() + comps.ImageAnimatorComponent() + comps.CounterComponent() + comps.PatternLockComponent() + comps.TextClockComponent() + comps.TextTimerComponent() + Text('沙箱模式随机').fontSize(40).backgroundColor(Color.Gray) + MultiComponent50() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixedAll.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixedAll.ets index e628c6d0dedd9ee1f854c57122f802b97d29f048..fef3e15ec9e1c4111cc70bd78f31b86712bff8df 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixedAll.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/mixedAll.ets @@ -1,33 +1,33 @@ -import { LoadAll } from '../../framework/PComponent' -import * as comps from '../../framework/normalComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - Text('普通模式').fontSize(40).backgroundColor(Color.Gray) - comps.DatePickerComponent() - comps.CalendarPickerComponent() - comps.TimePickerComponent() - comps.TextPickerComponent() - comps.DatePickerDialogComponent() - comps.CalendarPickerDialogComponent() - comps.TimePickerDialogComponent() - comps.TextPickerDialogComponent() - comps.ImageComponent() - comps.ImageAnimatorComponent() - comps.CounterComponent() - comps.PatternLockComponent() - comps.TextClockComponent() - comps.TextTimerComponent() - Divider() - Text('沙箱模式').fontSize(40).backgroundColor(Color.Gray) - LoadAll() - } - } - } +import { LoadAll } from '../../framework/PComponent' +import * as comps from '../../framework/normalComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + Text('普通模式').fontSize(40).backgroundColor(Color.Gray) + comps.DatePickerComponent() + comps.CalendarPickerComponent() + comps.TimePickerComponent() + comps.TextPickerComponent() + comps.DatePickerDialogComponent() + comps.CalendarPickerDialogComponent() + comps.TimePickerDialogComponent() + comps.TextPickerDialogComponent() + comps.ImageComponent() + comps.ImageAnimatorComponent() + comps.CounterComponent() + comps.PatternLockComponent() + comps.TextClockComponent() + comps.TextTimerComponent() + Divider() + Text('沙箱模式').fontSize(40).backgroundColor(Color.Gray) + LoadAll() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/plugins.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/plugins.ets index 51abff20f2546b11bf13db326847b0063538a81b..a951031d65b5fa7a5de888fc2734a253f4503219 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/plugins.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/mixed/plugins.ets @@ -1,109 +1,109 @@ -// main context environment -import { UIContext, CommonModifier } from '@kit.ArkUI'; -import router from '@ohos.router'; - -class MyCheckboxStyle implements ContentModifier { - public selectedColor: Color = Color.White; - - constructor(selectedColor: Color) { - this.selectedColor = selectedColor; - } - - applyContent(): WrappedBuilder<[CheckBoxConfiguration]> { - return wrapBuilder(buildCheckbox); - } -} - -@Builder -function buildCheckbox(config: CheckBoxConfiguration) { - Column({ space: 10 }) { - Text(config.name + (config.selected ? '(选中)' : '(非选中)')) - Shape() { - // 五边形复选框样式 - Path() - .width(200) - .height(60) - .commands('M100 0 L0 100 L50 200 L150 200 L200 100 Z') - .fillOpacity(0) - .strokeWidth(3) - // 红色三角图案样式 - Path() - .width(10) - .height(10) - .commands('M50 0 L100 100 L0 100 Z') - .visibility(config.selected ? Visibility.Visible : Visibility.Hidden) - .fill(config.selected ? (config.contentModifier as MyCheckboxStyle).selectedColor : Color.Black) - .stroke((config.contentModifier as MyCheckboxStyle).selectedColor) - .margin({ left: 11, top: 10 }) - } - .width(300) - .height(200) - .viewPort({ - x: 0, - y: 0, - width: 310, - height: 310 - }) - .strokeLineJoin(LineJoinStyle.Miter) - .strokeMiterLimit(5) - .onClick(() => { - // 点击后,触发复选框点击状态变化 - if (config.selected) { - config.triggerChange(false); - } else { - config.triggerChange(true); - } - }) - .margin({ left: 150 }) - } -} - -let storage: LocalStorage = new LocalStorage(); -PersistentStorage.persistProp('uiContext', undefined); - -@Entry(storage) -@Component -struct MyIndex { - @StorageLink('uiContext') p: UIContext | undefined | null = this.getUIContext(); - @State result: string = '' - private items: string[] = [ - '普通全部+沙箱随机20个context', - '普通全部+沙箱随机50个context', - '普通全部+沙箱随机100个context', - '普通全部+沙箱全部', - ] - @State modifier: ContentModifier = new MyCheckboxStyle(Color.Red); - @State click: CommonModifier = new CommonModifier().onClick(() => { - }) - - build() { - Column() { - List({ space: '10vp' }) { - ForEach(this.items, (item: string) => { - ListItem() { - Text(item) - .fontSize(16) - .fontWeight(FontWeight.Bold) - .onClick(() => { - globalThis.aaa = 'i am from host.'; - if (item === '普通全部+沙箱随机20个context') { - router.pushUrl({ url: 'pages/mixed/mixed20'}); - } else if (item === '普通全部+沙箱随机50个context') { - router.pushUrl({ url: 'pages/mixed/mixed50'}); - }else if (item === '普通全部+沙箱随机100个context') { - router.pushUrl({ url: 'pages/mixed/mixed100'}); - }else if (item === '普通全部+沙箱全部') { - router.pushUrl({ url: 'pages/mixed/mixedAll'}); - } - }) - .width('100%') - .height('100%') - .textAlign(TextAlign.Center) - - }.width('80%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) - }) - }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') - } - } -} - +// main context environment +import { UIContext, CommonModifier } from '@kit.ArkUI'; +import router from '@ohos.router'; + +class MyCheckboxStyle implements ContentModifier { + public selectedColor: Color = Color.White; + + constructor(selectedColor: Color) { + this.selectedColor = selectedColor; + } + + applyContent(): WrappedBuilder<[CheckBoxConfiguration]> { + return wrapBuilder(buildCheckbox); + } +} + +@Builder +function buildCheckbox(config: CheckBoxConfiguration) { + Column({ space: 10 }) { + Text(config.name + (config.selected ? '(选中)' : '(非选中)')) + Shape() { + // 五边形复选框样式 + Path() + .width(200) + .height(60) + .commands('M100 0 L0 100 L50 200 L150 200 L200 100 Z') + .fillOpacity(0) + .strokeWidth(3) + // 红色三角图案样式 + Path() + .width(10) + .height(10) + .commands('M50 0 L100 100 L0 100 Z') + .visibility(config.selected ? Visibility.Visible : Visibility.Hidden) + .fill(config.selected ? (config.contentModifier as MyCheckboxStyle).selectedColor : Color.Black) + .stroke((config.contentModifier as MyCheckboxStyle).selectedColor) + .margin({ left: 11, top: 10 }) + } + .width(300) + .height(200) + .viewPort({ + x: 0, + y: 0, + width: 310, + height: 310 + }) + .strokeLineJoin(LineJoinStyle.Miter) + .strokeMiterLimit(5) + .onClick(() => { + // 点击后,触发复选框点击状态变化 + if (config.selected) { + config.triggerChange(false); + } else { + config.triggerChange(true); + } + }) + .margin({ left: 150 }) + } +} + +let storage: LocalStorage = new LocalStorage(); +PersistentStorage.persistProp('uiContext', undefined); + +@Entry(storage) +@Component +struct MyIndex { + @StorageLink('uiContext') p: UIContext | undefined | null = this.getUIContext(); + @State result: string = '' + private items: string[] = [ + '普通全部+沙箱随机20个context', + '普通全部+沙箱随机50个context', + '普通全部+沙箱随机100个context', + '普通全部+沙箱全部', + ] + @State modifier: ContentModifier = new MyCheckboxStyle(Color.Red); + @State click: CommonModifier = new CommonModifier().onClick(() => { + }) + + build() { + Column() { + List({ space: '10vp' }) { + ForEach(this.items, (item: string) => { + ListItem() { + Text(item) + .fontSize(16) + .fontWeight(FontWeight.Bold) + .onClick(() => { + globalThis.aaa = 'i am from host.'; + if (item === '普通全部+沙箱随机20个context') { + router.pushUrl({ url: 'pages/mixed/mixed20'}); + } else if (item === '普通全部+沙箱随机50个context') { + router.pushUrl({ url: 'pages/mixed/mixed50'}); + }else if (item === '普通全部+沙箱随机100个context') { + router.pushUrl({ url: 'pages/mixed/mixed100'}); + }else if (item === '普通全部+沙箱全部') { + router.pushUrl({ url: 'pages/mixed/mixedAll'}); + } + }) + .width('100%') + .height('100%') + .textAlign(TextAlign.Center) + + }.width('80%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) + }) + }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') + } + } +} + diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/normal/loadAll.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/normal/loadAll.ets index 0f7b728df0cf60bd8e63ff7f553409ff2d542307..a5e55292b694cfa0aa2c373bb6b9480609bc68ae 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/normal/loadAll.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/normal/loadAll.ets @@ -1,28 +1,28 @@ -import * as comps from '../../framework/normalComponent' - -@Entry -@Component -struct MainPage { - scroller : Scroller = new Scroller() - build() { - Scroll(this.scroller) { - Column() { - comps.DatePickerComponent() - comps.CalendarPickerComponent() - comps.TimePickerComponent() - comps.TextPickerComponent() - comps.DatePickerDialogComponent() - comps.CalendarPickerDialogComponent() - comps.TimePickerDialogComponent() - comps.TextPickerDialogComponent() - comps.ImageComponent() - comps.ImageAnimatorComponent() - comps.CounterComponent() - comps.PatternLockComponent() - comps.TextClockComponent() - comps.TextTimerComponent() - } - } - } -} - +import * as comps from '../../framework/normalComponent' + +@Entry +@Component +struct MainPage { + scroller : Scroller = new Scroller() + build() { + Scroll(this.scroller) { + Column() { + comps.DatePickerComponent() + comps.CalendarPickerComponent() + comps.TimePickerComponent() + comps.TextPickerComponent() + comps.DatePickerDialogComponent() + comps.CalendarPickerDialogComponent() + comps.TimePickerDialogComponent() + comps.TextPickerDialogComponent() + comps.ImageComponent() + comps.ImageAnimatorComponent() + comps.CounterComponent() + comps.PatternLockComponent() + comps.TextClockComponent() + comps.TextTimerComponent() + } + } + } +} + diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/normal/normalIndex.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/normal/normalIndex.ets index 913e901e175c70bfb56703130af745e0bf5ed165..55ff83c99f87edd17818209a6e9362146e32b395 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/normal/normalIndex.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/normal/normalIndex.ets @@ -1,29 +1,29 @@ -import router from '@ohos.router'; - -interface ListCategories { - title: string, - url: string -} - -@Entry -@Component -struct Index { - @State message: string = 'Search' - private items: ListCategories[] = [ - { title: '加载插件', url: 'pages/normal/loadAll' }, - ] - - build() { - Column() { - List({ space: '10vp' }) { - ForEach(this.items, (item: ListCategories) => { - ListItem() { - Text(item.title).fontSize(16).fontWeight(FontWeight.Bold).onClick(() => { - router.pushUrl({ url: item.url }); - }) - }.width('90%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) - }) - }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') - }.width('100%').height('100%') - } +import router from '@ohos.router'; + +interface ListCategories { + title: string, + url: string +} + +@Entry +@Component +struct Index { + @State message: string = 'Search' + private items: ListCategories[] = [ + { title: '加载插件', url: 'pages/normal/loadAll' }, + ] + + build() { + Column() { + List({ space: '10vp' }) { + ForEach(this.items, (item: ListCategories) => { + ListItem() { + Text(item.title).fontSize(16).fontWeight(FontWeight.Bold).onClick(() => { + router.pushUrl({ url: item.url }); + }) + }.width('90%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) + }) + }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') + }.width('100%').height('100%') + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadAll.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadAll.ets index afddf88bc5c5218f58d1a653463f35fcf61a0bb7..ae05b6c1c8cfbd17c2c0396abfbfdae4b74a6ce4 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadAll.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadAll.ets @@ -1,15 +1,15 @@ -import { LoadAll } from '../../framework/PComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - LoadAll() - } - } - } +import { LoadAll } from '../../framework/PComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + LoadAll() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadOne.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadOne.ets index 78bcae74002e6940916b7eed71da7417c27d8933..6132c487b91b4324859c423d2a1662dd392c1c38 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadOne.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/loadOne.ets @@ -1,15 +1,15 @@ -import { LoadOne } from '../../framework/PComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - LoadOne() - } - } - } +import { LoadOne } from '../../framework/PComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + LoadOne() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/plugins.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/plugins.ets index e17931c4cbad328347e651ade890f4371da5f123..0126981cd7771eb2492858954fa8e110fb74382c 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/plugins.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/plugins.ets @@ -1,112 +1,112 @@ -// main context environment -import { UIContext, CommonModifier } from '@kit.ArkUI'; -import router from '@ohos.router'; - -class MyCheckboxStyle implements ContentModifier { - public selectedColor: Color = Color.White; - - constructor(selectedColor: Color) { - this.selectedColor = selectedColor; - } - - applyContent(): WrappedBuilder<[CheckBoxConfiguration]> { - return wrapBuilder(buildCheckbox); - } -} - -@Builder -function buildCheckbox(config: CheckBoxConfiguration) { - Column({ space: 10 }) { - Text(config.name + (config.selected ? '(选中)' : '(非选中)')) - Shape() { - // 五边形复选框样式 - Path() - .width(200) - .height(60) - .commands('M100 0 L0 100 L50 200 L150 200 L200 100 Z') - .fillOpacity(0) - .strokeWidth(3) - // 红色三角图案样式 - Path() - .width(10) - .height(10) - .commands('M50 0 L100 100 L0 100 Z') - .visibility(config.selected ? Visibility.Visible : Visibility.Hidden) - .fill(config.selected ? (config.contentModifier as MyCheckboxStyle).selectedColor : Color.Black) - .stroke((config.contentModifier as MyCheckboxStyle).selectedColor) - .margin({ left: 11, top: 10 }) - } - .width(300) - .height(200) - .viewPort({ - x: 0, - y: 0, - width: 310, - height: 310 - }) - .strokeLineJoin(LineJoinStyle.Miter) - .strokeMiterLimit(5) - .onClick(() => { - // 点击后,触发复选框点击状态变化 - if (config.selected) { - config.triggerChange(false); - } else { - config.triggerChange(true); - } - }) - .margin({ left: 150 }) - } -} - -let storage: LocalStorage = new LocalStorage(); -PersistentStorage.persistProp('uiContext', undefined); - -@Entry(storage) -@Component -struct MyIndex { - @StorageLink('uiContext') p: UIContext | undefined | null = this.getUIContext(); - @State result: string = '' - private items: string[] = [ - '随机加载20个context(1个context对应1个组件)', - '随机加载50个context(1个context对应1个组件)', - '随机加载100个context(1个context对应1个组件)', - '加载所有context(1个context对应1个组件)', - '加载1个context,包含所有组件', - ] - @State modifier: ContentModifier = new MyCheckboxStyle(Color.Red); - @State click: CommonModifier = new CommonModifier().onClick(() => { - }) - - build() { - Column() { - List({ space: '10vp' }) { - ForEach(this.items, (item: string) => { - ListItem() { - Text(item) - .fontSize(16) - .fontWeight(FontWeight.Bold) - .onClick(() => { - globalThis.aaa = 'i am from host.'; - if (item === '随机加载20个context(1个context对应1个组件)') { - router.pushUrl({ url: 'pages/sandbox/random20'}); - } else if (item === '随机加载50个context(1个context对应1个组件)') { - router.pushUrl({ url: 'pages/sandbox/random50'}); - } else if (item === '随机加载100个context(1个context对应1个组件)') { - router.pushUrl({ url: 'pages/sandbox/random100'}); - } else if (item === '加载所有context(1个context对应1个组件)') { - router.pushUrl({ url: 'pages/sandbox/loadAll'}); - } else if (item === '加载1个context,包含所有组件') { - router.pushUrl({ url: 'pages/sandbox/loadOne'}); - } - }) - .width('100%') - .height('100%') - .textAlign(TextAlign.Center) - - }.width('80%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) - }) - }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') - } - } -} - +// main context environment +import { UIContext, CommonModifier } from '@kit.ArkUI'; +import router from '@ohos.router'; + +class MyCheckboxStyle implements ContentModifier { + public selectedColor: Color = Color.White; + + constructor(selectedColor: Color) { + this.selectedColor = selectedColor; + } + + applyContent(): WrappedBuilder<[CheckBoxConfiguration]> { + return wrapBuilder(buildCheckbox); + } +} + +@Builder +function buildCheckbox(config: CheckBoxConfiguration) { + Column({ space: 10 }) { + Text(config.name + (config.selected ? '(选中)' : '(非选中)')) + Shape() { + // 五边形复选框样式 + Path() + .width(200) + .height(60) + .commands('M100 0 L0 100 L50 200 L150 200 L200 100 Z') + .fillOpacity(0) + .strokeWidth(3) + // 红色三角图案样式 + Path() + .width(10) + .height(10) + .commands('M50 0 L100 100 L0 100 Z') + .visibility(config.selected ? Visibility.Visible : Visibility.Hidden) + .fill(config.selected ? (config.contentModifier as MyCheckboxStyle).selectedColor : Color.Black) + .stroke((config.contentModifier as MyCheckboxStyle).selectedColor) + .margin({ left: 11, top: 10 }) + } + .width(300) + .height(200) + .viewPort({ + x: 0, + y: 0, + width: 310, + height: 310 + }) + .strokeLineJoin(LineJoinStyle.Miter) + .strokeMiterLimit(5) + .onClick(() => { + // 点击后,触发复选框点击状态变化 + if (config.selected) { + config.triggerChange(false); + } else { + config.triggerChange(true); + } + }) + .margin({ left: 150 }) + } +} + +let storage: LocalStorage = new LocalStorage(); +PersistentStorage.persistProp('uiContext', undefined); + +@Entry(storage) +@Component +struct MyIndex { + @StorageLink('uiContext') p: UIContext | undefined | null = this.getUIContext(); + @State result: string = '' + private items: string[] = [ + '随机加载20个context(1个context对应1个组件)', + '随机加载50个context(1个context对应1个组件)', + '随机加载100个context(1个context对应1个组件)', + '加载所有context(1个context对应1个组件)', + '加载1个context,包含所有组件', + ] + @State modifier: ContentModifier = new MyCheckboxStyle(Color.Red); + @State click: CommonModifier = new CommonModifier().onClick(() => { + }) + + build() { + Column() { + List({ space: '10vp' }) { + ForEach(this.items, (item: string) => { + ListItem() { + Text(item) + .fontSize(16) + .fontWeight(FontWeight.Bold) + .onClick(() => { + globalThis.aaa = 'i am from host.'; + if (item === '随机加载20个context(1个context对应1个组件)') { + router.pushUrl({ url: 'pages/sandbox/random20'}); + } else if (item === '随机加载50个context(1个context对应1个组件)') { + router.pushUrl({ url: 'pages/sandbox/random50'}); + } else if (item === '随机加载100个context(1个context对应1个组件)') { + router.pushUrl({ url: 'pages/sandbox/random100'}); + } else if (item === '加载所有context(1个context对应1个组件)') { + router.pushUrl({ url: 'pages/sandbox/loadAll'}); + } else if (item === '加载1个context,包含所有组件') { + router.pushUrl({ url: 'pages/sandbox/loadOne'}); + } + }) + .width('100%') + .height('100%') + .textAlign(TextAlign.Center) + + }.width('80%').height('80vp').backgroundColor('#ff53ecd9').borderRadius(10) + }) + }.alignListItem(ListItemAlign.Center).margin({ top: '10vp' }).width('100%').height('100%') + } + } +} + diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random100.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random100.ets index 46ab5764c95cadc0f752f8f065165e4f43bf8a56..d23a2e13334be42fb5cc81d138aa2ac3aeac5e67 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random100.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random100.ets @@ -1,15 +1,15 @@ -import { MultiComponent100 } from '../../framework/PComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - MultiComponent100() - } - } - } +import { MultiComponent100 } from '../../framework/PComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + MultiComponent100() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random20.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random20.ets index 0d69b6717f7af50eaaa2d4b1b0c34fe81b1ed96c..42a6a06ace1af7beb7e310d3612f6ce75f10117b 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random20.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random20.ets @@ -1,15 +1,15 @@ -import { MultiComponent20 } from '../../framework/PComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - MultiComponent20() - } - } - } +import { MultiComponent20 } from '../../framework/PComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + MultiComponent20() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random50.ets b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random50.ets index e1654d3fe10b98dc2f5c18bd2a68ededb72836c9..492e39d12bed759f82fadb154674ec1ec91af800 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random50.ets +++ b/examples/Picker/jscontext/entry/src/main/ets/pages/sandbox/random50.ets @@ -1,15 +1,15 @@ -import { MultiComponent50 } from '../../framework/PComponent' - -@Entry -@Component -struct Plugins { - scroller : Scroller = new Scroller() - - build() { - Scroll(this.scroller) { - Column() { - MultiComponent50() - } - } - } +import { MultiComponent50 } from '../../framework/PComponent' + +@Entry +@Component +struct Plugins { + scroller : Scroller = new Scroller() + + build() { + Scroll(this.scroller) { + Column() { + MultiComponent50() + } + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/ets/types/CarType.ts b/examples/Picker/jscontext/entry/src/main/ets/types/CarType.ts index 18fb01896c9e657cd90f3b83381642d98e6f6c48..3e8c83193f82e060b5d3985c075cbf4a07b2c9fd 100644 --- a/examples/Picker/jscontext/entry/src/main/ets/types/CarType.ts +++ b/examples/Picker/jscontext/entry/src/main/ets/types/CarType.ts @@ -1,21 +1,21 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export type Car = { - callCar(): string; - - callCarAsync(): Promise; - - callFileIo(filePath: string); +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export type Car = { + callCar(): string; + + callCarAsync(): Promise; + + callFileIo(filePath: string); } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/module.json5 b/examples/Picker/jscontext/entry/src/main/module.json5 index fe15ce216cce50e7d8bf28fabb09e7999f3e41f3..c00933eb7488794b498319cbba6ae595ee963a4a 100644 --- a/examples/Picker/jscontext/entry/src/main/module.json5 +++ b/examples/Picker/jscontext/entry/src/main/module.json5 @@ -1,64 +1,64 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "module": { - "name": "entry", - "type": "entry", - "description": "$string:module_desc", - "mainElement": "EntryAbility", - "deviceTypes": [ - "default" - ], - "deliveryWithInstall": true, - "installationFree": false, - "pages": "$profile:main_pages", - "abilities": [ - { - "name": "EntryAbility", - "srcEntry": "./ets/entryability/EntryAbility.ets", - "description": "$string:EntryAbility_desc", - "icon": "$media:layered_image", - "label": "$string:EntryAbility_label", - "startWindowIcon": "$media:startIcon", - "startWindowBackground": "$color:start_window_background", - "exported": true, - "skills": [ - { - "entities": [ - "entity.system.home" - ], - "actions": [ - "ohos.want.action.home" - ] - } - ] - } - ], - "extensionAbilities": [ - { - "name": "EntryBackupAbility", - "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", - "type": "backup", - "exported": false, - "metadata": [ - { - "name": "ohos.extension.backup", - "resource": "$profile:backup_config" - } - ] - } - ] - } +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/resources/base/element/color.json b/examples/Picker/jscontext/entry/src/main/resources/base/element/color.json index d66f9a7d4ac61fb8d215239ab3620b7bcd77bf33..3c712962da3c2751c2b9ddb53559afcbd2b54a02 100644 --- a/examples/Picker/jscontext/entry/src/main/resources/base/element/color.json +++ b/examples/Picker/jscontext/entry/src/main/resources/base/element/color.json @@ -1,8 +1,8 @@ -{ - "color": [ - { - "name": "start_window_background", - "value": "#FFFFFF" - } - ] +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/resources/base/element/float.json b/examples/Picker/jscontext/entry/src/main/resources/base/element/float.json index 5f0600c7083c3ac3776dcc13ce3e3f03c378fc6d..a0a93dd91fd48f08f3a9532c76e9b26e68d4c034 100644 --- a/examples/Picker/jscontext/entry/src/main/resources/base/element/float.json +++ b/examples/Picker/jscontext/entry/src/main/resources/base/element/float.json @@ -1,8 +1,8 @@ -{ - "float": [ - { - "name": "page_text_font_size", - "value": "50fp" - } - ] +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/resources/base/profile/backup_config.json b/examples/Picker/jscontext/entry/src/main/resources/base/profile/backup_config.json index d742c2f96e7dd0f406f499941f3147345e998f95..78f40ae7c494d71e2482278f359ec790ca73471a 100644 --- a/examples/Picker/jscontext/entry/src/main/resources/base/profile/backup_config.json +++ b/examples/Picker/jscontext/entry/src/main/resources/base/profile/backup_config.json @@ -1,3 +1,3 @@ -{ - "allowToBackupRestore": true +{ + "allowToBackupRestore": true } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/main/resources/dark/element/color.json b/examples/Picker/jscontext/entry/src/main/resources/dark/element/color.json index 438d5bc43bb23c59c210d586b96635a72da5b64a..79b11c2747aec33e710fd3a7b2b3c94dd9965499 100644 --- a/examples/Picker/jscontext/entry/src/main/resources/dark/element/color.json +++ b/examples/Picker/jscontext/entry/src/main/resources/dark/element/color.json @@ -1,8 +1,8 @@ -{ - "color": [ - { - "name": "start_window_background", - "value": "#000000" - } - ] +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] } \ No newline at end of file diff --git a/examples/Picker/jscontext/entry/src/ohosTest/module.json5 b/examples/Picker/jscontext/entry/src/ohosTest/module.json5 index ae55a7c74de9e092f16fdbbe16f3e35fba50ef51..59667117c86b64ab9863f7b382c435ae4a3c32fa 100644 --- a/examples/Picker/jscontext/entry/src/ohosTest/module.json5 +++ b/examples/Picker/jscontext/entry/src/ohosTest/module.json5 @@ -1,25 +1,25 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "module": { - "name": "entry_test", - "type": "feature", - "deviceTypes": [ - "default" - ], - "deliveryWithInstall": true, - "installationFree": false - } -} +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/examples/Picker/jscontext/hvigor/hvigor-config.json5 b/examples/Picker/jscontext/hvigor/hvigor-config.json5 index 1d24edfbfc2c718a1117749793713e7aa9e72ed5..dc688b0bfd4fcd92ebbb3049cf9de543104475a5 100644 --- a/examples/Picker/jscontext/hvigor/hvigor-config.json5 +++ b/examples/Picker/jscontext/hvigor/hvigor-config.json5 @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "modelVersion": "5.0.4", - "dependencies": { - }, - "execution": { - // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ - // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ - // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ - // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ - // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ - }, - "logging": { - // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ - }, - "debugging": { - // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ - }, - "nodeOptions": { - // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ - // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ - } -} +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "5.0.4", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/examples/Picker/jscontext/oh-package-lock.json5 b/examples/Picker/jscontext/oh-package-lock.json5 index 519ec40315a8b895ec1190e0003d62cf0988a8e3..7618269a25537b13b20024827c4051509b0b8f81 100644 --- a/examples/Picker/jscontext/oh-package-lock.json5 +++ b/examples/Picker/jscontext/oh-package-lock.json5 @@ -1,41 +1,41 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "meta": { - "stableOrder": true - }, - "lockfileVersion": 3, - "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", - "specifiers": { - "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0", - "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21" - }, - "packages": { - "@ohos/hamock@1.0.0": { - "name": "@ohos/hamock", - "version": "1.0.0", - "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", - "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har", - "registryType": "ohpm" - }, - "@ohos/hypium@1.0.21": { - "name": "@ohos/hypium", - "version": "1.0.21", - "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==", - "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har", - "registryType": "ohpm" - } - } +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "meta": { + "stableOrder": true + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0", + "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21" + }, + "packages": { + "@ohos/hamock@1.0.0": { + "name": "@ohos/hamock", + "version": "1.0.0", + "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har", + "registryType": "ohpm" + }, + "@ohos/hypium@1.0.21": { + "name": "@ohos/hypium", + "version": "1.0.21", + "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har", + "registryType": "ohpm" + } + } } \ No newline at end of file diff --git a/examples/Picker/jscontext/oh-package.json5 b/examples/Picker/jscontext/oh-package.json5 index 4dc061799a0ca9cb8c18c97124d3fa016377b706..41b8b63948628728b745e7be8cd53d68d9345b75 100644 --- a/examples/Picker/jscontext/oh-package.json5 +++ b/examples/Picker/jscontext/oh-package.json5 @@ -1,24 +1,24 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -{ - "modelVersion": "6.0.0", - "description": "Please describe the basic information.", - "dependencies": { - }, - "devDependencies": { - "@ohos/hypium": "1.0.21", - "@ohos/hamock": "1.0.0" - } -} +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.21", + "@ohos/hamock": "1.0.0" + } +} diff --git a/examples/TextComponentTest/entry/src/main/ets/pages/01-StyledString/11-imageAttachment/01-imageSpanAlignment-center.ets b/examples/TextComponentTest/entry/src/main/ets/pages/01-StyledString/11-imageAttachment/01-imageSpanAlignment-center.ets index 7d31685def310a0f54f7571211d9b574a1f965b6..bf86cafa8ac03ca762f677fe11b28fc64d0c104d 100644 --- a/examples/TextComponentTest/entry/src/main/ets/pages/01-StyledString/11-imageAttachment/01-imageSpanAlignment-center.ets +++ b/examples/TextComponentTest/entry/src/main/ets/pages/01-StyledString/11-imageAttachment/01-imageSpanAlignment-center.ets @@ -1,95 +1,95 @@ -// xxx.ets -import { image } from '@kit.ImageKit' -import { LengthMetrics } from '@kit.ArkUI' -import { MeasureText } from '@kit.ArkUI' -import { drawing, common2D, text } from '@kit.ArkGraphics2D'; - -@Entry -@Component -struct struct_01_StyledString_01_StyledStringValue_11_ImageAttachment_01_imageSpanAlignment_center { - controller: TextController = new TextController(); - - private createCustomSpan(name: string) { - // 大小 - let fontSize = 30 // fp - let textSize = MeasureText.measureTextSize({ textContent: name, fontSize: fontSize }) - let paddingLeft = vp2px(8) - let paddingTop = vp2px(8) - let width = (textSize.width as number) + paddingLeft * 2; - let height = (textSize.height as number) + paddingTop * 2; - - // 创建pixelMap - const color: ArrayBuffer = new ArrayBuffer(width * height * 4); // 为需要创建的像素buffer大小,取值为:height * width *4 - let opts: image.InitializationOptions = { pixelFormat: 3, size: { height: height, width: width } } - let pixelMap: image.PixelMap = image.createPixelMapSync(color, opts); - - // 绘制背景 - const canvas = new drawing.Canvas(pixelMap); - const brush = new drawing.Brush(); - const color2: common2D.Color = { - alpha: 255, - red: 88, - green: 0, - blue: 0 - }; - brush.setColor(color2); - canvas.attachBrush(brush); - let rect: common2D.Rect = { - left: 0, - top: 0, - right: width, - bottom: height - }; - let roundRect = new drawing.RoundRect(rect, paddingTop, paddingTop); // 自定义 x/y 方向的半径 - canvas.drawRoundRect(roundRect); - canvas.detachBrush(); - - // 绘制文字 - let myTextStyle: text.TextStyle = { - fontSize: vp2px(fontSize), - }; - let myParagraphStyle: text.ParagraphStyle = { - textStyle: myTextStyle, - align: text.TextAlign.START, - }; - let fontCollection = new text.FontCollection(); - let paragraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); - paragraphGraphBuilder.addText(name); - let paragraph = paragraphGraphBuilder.build(); - paragraph.layoutSync(textSize.width as number); - paragraph.paint(canvas, paddingLeft, paddingTop); - - // 创建ImageAttachment字符串 - let customSpan = new MutableStyledString(new ImageAttachment({ - value: pixelMap, - size: { width: px2vp(width), height: px2vp(height) }, - layoutStyle: { margin: LengthMetrics.vp(2) }, // 行内margin - verticalAlign: ImageSpanAlignment.CENTER, - objectFit: ImageFit.None - })) - return customSpan - } - - async onPageShow() { - let customSpan = this.createCustomSpan("@小喵吃鱼") - let message = - new StyledString('我是只可爱的小猫咪hhh,我每天需要吃很多好吃的,睡很多觉,这是我在论坛发布的探讨问题!') - customSpan.appendStyledString(message) - this.controller.setStyledString(customSpan) - } - - build() { - Row() { - Column({ space: 5 }) { - Text(undefined, { controller: this.controller }) - .copyOption(CopyOptions.InApp) - .draggable(true) - .fontSize(30) - .borderWidth(1) - - } - .width('100%') - } - .height('100%') - } +// xxx.ets +import { image } from '@kit.ImageKit' +import { LengthMetrics } from '@kit.ArkUI' +import { MeasureText } from '@kit.ArkUI' +import { drawing, common2D, text } from '@kit.ArkGraphics2D'; + +@Entry +@Component +struct struct_01_StyledString_01_StyledStringValue_11_ImageAttachment_01_imageSpanAlignment_center { + controller: TextController = new TextController(); + + private createCustomSpan(name: string) { + // 大小 + let fontSize = 30 // fp + let textSize = MeasureText.measureTextSize({ textContent: name, fontSize: fontSize }) + let paddingLeft = vp2px(8) + let paddingTop = vp2px(8) + let width = (textSize.width as number) + paddingLeft * 2; + let height = (textSize.height as number) + paddingTop * 2; + + // 创建pixelMap + const color: ArrayBuffer = new ArrayBuffer(width * height * 4); // 为需要创建的像素buffer大小,取值为:height * width *4 + let opts: image.InitializationOptions = { pixelFormat: 3, size: { height: height, width: width } } + let pixelMap: image.PixelMap = image.createPixelMapSync(color, opts); + + // 绘制背景 + const canvas = new drawing.Canvas(pixelMap); + const brush = new drawing.Brush(); + const color2: common2D.Color = { + alpha: 255, + red: 88, + green: 0, + blue: 0 + }; + brush.setColor(color2); + canvas.attachBrush(brush); + let rect: common2D.Rect = { + left: 0, + top: 0, + right: width, + bottom: height + }; + let roundRect = new drawing.RoundRect(rect, paddingTop, paddingTop); // 自定义 x/y 方向的半径 + canvas.drawRoundRect(roundRect); + canvas.detachBrush(); + + // 绘制文字 + let myTextStyle: text.TextStyle = { + fontSize: vp2px(fontSize), + }; + let myParagraphStyle: text.ParagraphStyle = { + textStyle: myTextStyle, + align: text.TextAlign.START, + }; + let fontCollection = new text.FontCollection(); + let paragraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); + paragraphGraphBuilder.addText(name); + let paragraph = paragraphGraphBuilder.build(); + paragraph.layoutSync(textSize.width as number); + paragraph.paint(canvas, paddingLeft, paddingTop); + + // 创建ImageAttachment字符串 + let customSpan = new MutableStyledString(new ImageAttachment({ + value: pixelMap, + size: { width: px2vp(width), height: px2vp(height) }, + layoutStyle: { margin: LengthMetrics.vp(2) }, // 行内margin + verticalAlign: ImageSpanAlignment.CENTER, + objectFit: ImageFit.None + })) + return customSpan + } + + async onPageShow() { + let customSpan = this.createCustomSpan("@小喵吃鱼") + let message = + new StyledString('我是只可爱的小猫咪hhh,我每天需要吃很多好吃的,睡很多觉,这是我在论坛发布的探讨问题!') + customSpan.appendStyledString(message) + this.controller.setStyledString(customSpan) + } + + build() { + Row() { + Column({ space: 5 }) { + Text(undefined, { controller: this.controller }) + .copyOption(CopyOptions.InApp) + .draggable(true) + .fontSize(30) + .borderWidth(1) + + } + .width('100%') + } + .height('100%') + } } \ No newline at end of file diff --git a/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/01-numberOfRows.ets b/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/01-numberOfRows.ets index 543d0e0201c5537ecb1156bbbbd77f0f3641f93f..86ba4389750e7c69e93847990e7d4e7f0a95acff 100644 --- a/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/01-numberOfRows.ets +++ b/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/01-numberOfRows.ets @@ -1,60 +1,60 @@ -// xxx.ets -@Entry -@Component -struct struct_02_TextSample_01_numberOfRows { - @State lineCount: string = ""; - @State glyphPositionAtCoordinate: string = ""; - @State lineMetrics: string = ""; - @State rectsForRangeStr: string = ""; - controller: TextController = new TextController(); - @State textStr: string = - '春天是年的封面,雨,是春天的景象,人们愿意活在美丽的封面里,愿意沉浸在雨的诗情画意里。' + - '雨季给了很多遐想,他们都期待着美好,盼望美好是追求的梦想,追求梦想虽是情非得已。' + - '在仁里这样的一个地方,花桥、鼓楼每一个景物都在印衬着春天雨季的意象中,' + - '当这些景物都展现在雨中的时候,有时候感觉像是某一个地方的“海市蜃楼”其实这就是仁里,' + - '最美的景色,在这里你能把这个季节最美的时光尽收眼底。'; - @State charIndex: string = ""; - @State inputContent: string = ""; - @State strLineCount: number = -1 - - //获取某字符所在行数 - private getLineOfNthChar(index: number): number { - let layoutManager = this.controller.getLayoutManager(); - let lineCount = layoutManager.getLineCount() - for (let line = 0; line < lineCount; line++) { - let range = layoutManager.getLineMetrics(line) - if (index >= range.startIndex && index < range.endIndex) { - return line - } - } - return -1 - } - - build() { - Scroll() { - Column() { - Text(this.textStr, { controller: this.controller }) - .textIndent(50) - .onAreaChange(() => { - let layoutManager: LayoutManager = this.controller.getLayoutManager(); - this.lineCount = "LineCount: " + layoutManager.getLineCount(); - }) - Text("第0行开始计数,字符索引:" + this.charIndex + ",所在行:" + this.strLineCount) - .margin(5) - TextInput({ text: this.inputContent, placeholder: "请输入要查找的字符索引" }) - .type(InputType.Number) - .onChange((value) => { - this.inputContent = value - }) - .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => { - this.charIndex = this.inputContent - this.inputContent = "" - this.strLineCount = this.getLineOfNthChar(Number(this.charIndex)) - // 用户名不正确会清空输入框和用户名并提示错误文本 - - }) - } - .margin({ top: 100, left: 8, right: 8 }) - } - } +// xxx.ets +@Entry +@Component +struct struct_02_TextSample_01_numberOfRows { + @State lineCount: string = ""; + @State glyphPositionAtCoordinate: string = ""; + @State lineMetrics: string = ""; + @State rectsForRangeStr: string = ""; + controller: TextController = new TextController(); + @State textStr: string = + '春天是年的封面,雨,是春天的景象,人们愿意活在美丽的封面里,愿意沉浸在雨的诗情画意里。' + + '雨季给了很多遐想,他们都期待着美好,盼望美好是追求的梦想,追求梦想虽是情非得已。' + + '在仁里这样的一个地方,花桥、鼓楼每一个景物都在印衬着春天雨季的意象中,' + + '当这些景物都展现在雨中的时候,有时候感觉像是某一个地方的“海市蜃楼”其实这就是仁里,' + + '最美的景色,在这里你能把这个季节最美的时光尽收眼底。'; + @State charIndex: string = ""; + @State inputContent: string = ""; + @State strLineCount: number = -1 + + //获取某字符所在行数 + private getLineOfNthChar(index: number): number { + let layoutManager = this.controller.getLayoutManager(); + let lineCount = layoutManager.getLineCount() + for (let line = 0; line < lineCount; line++) { + let range = layoutManager.getLineMetrics(line) + if (index >= range.startIndex && index < range.endIndex) { + return line + } + } + return -1 + } + + build() { + Scroll() { + Column() { + Text(this.textStr, { controller: this.controller }) + .textIndent(50) + .onAreaChange(() => { + let layoutManager: LayoutManager = this.controller.getLayoutManager(); + this.lineCount = "LineCount: " + layoutManager.getLineCount(); + }) + Text("第0行开始计数,字符索引:" + this.charIndex + ",所在行:" + this.strLineCount) + .margin(5) + TextInput({ text: this.inputContent, placeholder: "请输入要查找的字符索引" }) + .type(InputType.Number) + .onChange((value) => { + this.inputContent = value + }) + .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => { + this.charIndex = this.inputContent + this.inputContent = "" + this.strLineCount = this.getLineOfNthChar(Number(this.charIndex)) + // 用户名不正确会清空输入框和用户名并提示错误文本 + + }) + } + .margin({ top: 100, left: 8, right: 8 }) + } + } } \ No newline at end of file diff --git a/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/02-textNumberTransition.ets b/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/02-textNumberTransition.ets index 24fdf62b0e2ef76f41fba45860eb58e42b8d406d..fd12fa029ea6c1d709e3977048747bc488f4ca99 100644 --- a/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/02-textNumberTransition.ets +++ b/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/02-textNumberTransition.ets @@ -1,668 +1,668 @@ -import font from '@ohos.font'; -import { LengthMetrics, LengthUnit } from '@ohos.arkui.node' - -class MyTextModifier implements AttributeModifier { - trasition: NumericTextTransition | undefined | null = { flipDirection: FlipDirection.UP, enableBlur: false } - - applyNormalAttribute(instance: TextAttribute): void { - instance - .contentTransition(this.trasition) - } -} - -@Entry -@Component -struct struct_02_TextSample_02_textNumericTextTransition { - @State testText: string = "Test"; - @State testAccessibilityText: string | undefined | null = 'MyTest.accessibilityText'; - @State testAccessibilityDescription: string | undefined | null = 'MyTest.accessibilityDescription'; - @State testAccessibilityLevel: string | undefined | null = 'MyTest.auto'; - @State backgroundColor1: ResourceColor | undefined = undefined; - controller3: TextController = new TextController(); - clickGestureAttr: GestureStyle = new GestureStyle({ - onClick: () => { - console.log('click GestureAttr'); - }, - }) - mutableStyledString3: MutableStyledString = new MutableStyledString("hello world", [ - { - start: 0, - length: 5, - styledKey: StyledStringKey.GESTURE, - styledValue: this.clickGestureAttr - }, - { - start: 6, - length: 5, - styledKey: StyledStringKey.FONT, - styledValue: new TextStyle({ fontColor: Color.Pink }) - } - ]); - - async onPageShow() { - this.controller3.setStyledString(this.mutableStyledString3) - } - - // 自定义字体 - // async aboutToAppear() { - // getContext(this) - // .resourceManager - // font.registerFont({ - // familyName: 'medium', - // familySrc: $rawfile('font/cartoon.ttf') - // }) - // } - - @State message: number = 17858867166 - @State message2: number = 88 - @State trasition: NumericTextTransition | undefined | null = - new NumericTextTransition({ flipDirection: FlipDirection.UP, enableBlur: true }) - @State trasition1: NumericTextTransition = - new NumericTextTransition({ flipDirection: FlipDirection.DOWN, enableBlur: true }) - @State trasition2: NumericTextTransition = { flipDirection: undefined, enableBlur: true } - @State trasition3: NumericTextTransition = { enableBlur: true } - @State trasition4: NumericTextTransition = {} - @State trasition5: NumericTextTransition = { flipDirection: FlipDirection.UP, enableBlur: undefined } - @State color1: Color = Color.Red - @State fontsize1: string = "120px" - @State textAlign1: TextAlign = TextAlign.Start - @State lineHeight: number = 50 - @State ellipsisMode: EllipsisMode = EllipsisMode.CENTER - @State fontWeight: Array = [FontWeight.Normal, FontWeight.Lighter, FontWeight.Bolder] - @State fontWeightindex: number = 0 - private decorationStyleInterface1: DecorationStyleInterface = { - color: Color.Gray, - type: TextDecorationType.Underline, - style: TextDecorationStyle.WAVY - } - private decorationStyleInterface2: DecorationStyleInterface = { - type: TextDecorationType.None, - color: Color.Green, - style: TextDecorationStyle.DOUBLE - } - private decorationStyleInterface3: DecorationStyleInterface = { - type: TextDecorationType.LineThrough, - style: TextDecorationStyle.DASHED, - color: Color.Pink - } - @State decorationStyleInterface: DecorationStyleInterface = { - type: TextDecorationType.Underline - } - @State fontfamily: string = "" - @State copyoption: CopyOptions = CopyOptions.InApp - @State fontArray: Array = - [{ size: 30, style: FontStyle.Normal }, { size: 10, style: FontStyle.Italic }, - { size: 60, weight: FontWeight.Bold, style: FontStyle.Normal }] - @State fontindex: number = 0 - @State fontStyle: FontStyle = FontStyle.Normal - private textshadow1: ShadowOptions = { - radius: 10, - color: Color.Black, - offsetX: 0, - offsetY: 0 - } - private textshadow2: ShadowOptions = { - radius: 0, - color: Color.Pink, - offsetX: 100, - offsetY: 100 - } - @State textshadow: ShadowOptions = this.textshadow1 - @State fontFeatureIndex: number = 0; - @State fontFeature: string[] = - ["\"sups\" -1", "\"sups\" 1", "\"sinf\" on"]; - @State indent1: number = 20 - @State onlyBetweenLinesvalue: boolean = false - @State modifierText: MyTextModifier = new MyTextModifier() - @State baselineOffset: number = 20 - @State lineBreakStrategyIndex: number = 0; - @State lineBreakStrategy: LineBreakStrategy[] = - [LineBreakStrategy.HIGH_QUALITY, LineBreakStrategy.GREEDY, LineBreakStrategy.BALANCED]; - @State halfLeading: boolean = false; - @State fontwenable: number = 120 - @State autospacing: boolean = false; - @State linearGradientOptions1: LinearGradientOptions = - { - angle: 45, - colors: [[Color.Red, 0.0], [Color.Blue, 0.3], [Color.Green, 0.5]] - }; - @State linearGradientOptions2: LinearGradientOptions = - { - direction: GradientDirection.LeftTop, - colors: [[Color.Red, 0.0], [Color.Blue, 0.3], [Color.Green, 0.5]], - repeating: true, - }; - @State radialGradientOptions: RadialGradientOptions = - { - center: [50, 50], - radius: 20, - colors: [[Color.Red, 0.0], [Color.Blue, 0.3], [Color.Green, 0.5]], - repeating: true, - }; - @State textOverflowIndex: number = 0; - @State textOverflow: TextOverflow[] = - [TextOverflow.None, TextOverflow.MARQUEE, TextOverflow.Ellipsis]; - @State wordBreakIndex: number = 0; - @State wordBreakOptions: WordBreak[] = - [WordBreak.NORMAL, WordBreak.BREAK_ALL, WordBreak.BREAK_WORD, WordBreak.HYPHENATION] - @State clip1: boolean = true; - @State start: number = 0; - @State end: number = 1; - @State caretColor: Color = Color.Blue - @State padding1: number = 10 - @State enableDataDetector: boolean = true - @State enableprevieew: boolean | undefined | null = true - scrollerForList: Scroller = new Scroller(); - @State visi: Visibility = Visibility.Visible - - @Builder - MyMenu() { - Column() { - Text("hhh") - } - } - - build() { - Row() { - Column() { - Scroll() { - Column() { - Text("测试自适应字号翻牌" + "😅") - .fontSize(8) - .padding(this.padding1) - .borderWidth(1) - .shaderStyle(this.linearGradientOptions1) - Text("" + this.message) - .attributeModifier(this.modifierText) - .fontSize(this.fontsize1) - .borderWidth(1) - .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) - .width(110) - .textOverflow({ overflow: this.textOverflow[this.textOverflowIndex] }) - // .maxLines(1) - .textAlign(this.textAlign1) - .decoration(this.decorationStyleInterface) - .ellipsisMode(this.ellipsisMode) - .fontColor(this.color1) - .fontWeight(this.fontWeight[this.fontWeightindex]) - .fontFamily(this.fontfamily) - .copyOption(this.copyoption) - .font(this.fontArray[this.fontindex]) - .fontStyle(this.fontStyle) - .textShadow(this.textshadow) - .minFontSize(10) - .maxFontSize(60) - .textIndent(this.indent1) - .baselineOffset(this.baselineOffset) - .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) - .halfLeading(this.halfLeading) - .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) - .enableAutoSpacing(this.autospacing) - .shaderStyle(this.linearGradientOptions1) - .clip(this.clip1) - .selection(this.start, this.end) - .caretColor(this.caretColor) - .padding(this.padding1) - .fontFeature(this.fontFeature[this.fontFeatureIndex]) - .enableDataDetector(this.enableDataDetector) - .dataDetectorConfig({ - types: [TextDataDetectorType.PHONE_NUMBER, TextDataDetectorType.URL, TextDataDetectorType.EMAIL, - TextDataDetectorType.ADDRESS, TextDataDetectorType.DATE_TIME], - color: $r('app.color.start_window_background'), - decoration: { - type: TextDecorationType.Overline - }, - enablePreviewMenu: this.enableprevieew - }) - - Text("测试截断数字") - .fontSize(8) - .shaderStyle(this.linearGradientOptions2) - Text(this.message + "") - .contentTransition(this.trasition) - .fontSize(this.fontsize1) - .borderWidth(1) - .width(110) - // .wordBreak(WordBreak.BREAK_ALL) - .textOverflow({ overflow: this.textOverflow[this.textOverflowIndex] }) - .maxLines(1) - .textAlign(this.textAlign1) - .lineHeight(this.lineHeight) - .decoration(this.decorationStyleInterface) - .ellipsisMode(this.ellipsisMode) - // .fontColor(this.color1) - .fontWeight(this.fontWeight[this.fontWeightindex]) - .fontFamily(this.fontfamily) - .copyOption(this.copyoption) - .maxLines(1) - .font(this.fontArray[this.fontindex]) - .fontStyle(this.fontStyle) - .textShadow(this.textshadow) - .fontFeature(this.fontFeature[this.fontFeatureIndex]) - .textIndent(this.indent1) - .baselineOffset(this.baselineOffset) - .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) - .halfLeading(this.halfLeading) - .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) - .enableAutoSpacing(this.autospacing) - .lineSpacing(LengthMetrics.vp(30), { onlyBetweenLines: this.onlyBetweenLinesvalue }) - .shaderStyle(this.linearGradientOptions2) - .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) - .clip(this.clip1) - .selection(this.start, this.end) - .caretColor(this.caretColor) - .padding(this.padding1) - .align(Alignment.BottomEnd) - .enableDataDetector(true) - .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) - Text("测试属性切换88") - .fontSize(8) - .shaderStyle(this.radialGradientOptions) - Row() { - - - Text(this.message2 + "") - .contentTransition(this.trasition)// .attributeModifier(this.modifierText) - .fontSize(this.fontsize1) - .borderWidth(1) - .width(110)// .wordBreak(WordBreak.BREAK_ALL) - .textOverflow({ overflow: TextOverflow.Ellipsis })// .maxLines(1) - .textAlign(this.textAlign1) - .lineHeight(this.lineHeight) - .decoration(this.decorationStyleInterface)//删除ellipsisMode、fontColor可以测试relayout效果 - .ellipsisMode(this.ellipsisMode) - // .fontColor(this.color1) - .fontFamily(this.fontfamily) - .fontWeight(this.fontWeight[this.fontWeightindex]) - .copyOption(this.copyoption)// .font(this.fontArray[this.fontindex]) - .fontStyle(this.fontStyle)// .textShadow(this.textshadow) - .margin({ bottom: 20 }) - .fontFeature(this.fontFeature[this.fontFeatureIndex]) - .textIndent(this.indent1) - .baselineOffset(this.baselineOffset) - .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) - .halfLeading(this.halfLeading) - .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) - .enableAutoSpacing(this.autospacing) - .shaderStyle(this.radialGradientOptions) - .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) - .clip(this.clip1) - .selection(this.start, this.end) - .caretColor(this.caretColor) - .padding(this.padding1) - .backgroundColor(Color.Orange) - .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) - - Text(this.message2 + "") - .contentTransition(this.trasition) - .attributeModifier(this.modifierText) - .fontSize(this.fontsize1) - .borderWidth(1) - .width(110) - .wordBreak(WordBreak.BREAK_ALL) - .textOverflow({ overflow: TextOverflow.Ellipsis })// .maxLines(1) - .textAlign(this.textAlign1) - .lineHeight(this.lineHeight) - .decoration(this.decorationStyleInterface)//删除ellipsisMode、fontColor可以测试relayout效果 - .ellipsisMode(this.ellipsisMode) - .fontColor(this.color1) - .fontFamily(this.fontfamily) - .fontWeight(this.fontWeight[this.fontWeightindex]) - .copyOption(this.copyoption) - .font(this.fontArray[this.fontindex]) - .fontStyle(this.fontStyle) - .textShadow(this.textshadow) - .margin({ bottom: 20 }) - .fontFeature(this.fontFeature[this.fontFeatureIndex]) - .textIndent(this.indent1) - .baselineOffset(this.baselineOffset) - .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) - .halfLeading(this.halfLeading) - .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) - .enableAutoSpacing(this.autospacing) - .shaderStyle(this.radialGradientOptions) - .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) - .clip(this.clip1) - .selection(this.start, this.end) - .caretColor(this.caretColor) - .padding(this.padding1) - .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) - } - - Text("测试span不生效") - .fontSize(8) - Text() { - Span(this.message2 + "") - } - .contentTransition(this.trasition) // .attributeModifier(this.modifierText) - .fontSize(this.fontsize1) - .borderWidth(1) - // .wordBreak(WordBreak.BREAK_ALL) - .textOverflow({ overflow: TextOverflow.Ellipsis }) - // .maxLines(1) - .textAlign(this.textAlign1) - .lineHeight(this.lineHeight) - .decoration(this.decorationStyleInterface) //删除ellipsisMode、fontColor可以测试relayout效果 - .ellipsisMode(this.ellipsisMode) - .fontColor(this.color1) - .fontFamily(this.fontfamily) - .fontWeight(this.fontWeight[this.fontWeightindex]) - .copyOption(this.copyoption) - .font(this.fontArray[this.fontindex]) - .fontStyle(this.fontStyle) - .textShadow(this.textshadow) - .margin({ bottom: 20 }) - .fontFeature(this.fontFeature[this.fontFeatureIndex]) - .textIndent(this.indent1) - .baselineOffset(this.baselineOffset) - .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) - .halfLeading(this.halfLeading) - .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) - .enableAutoSpacing(this.autospacing) - .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) - - .lineSpacing(LengthMetrics.vp(30), { onlyBetweenLines: this.onlyBetweenLinesvalue }) - - - Text(this.message + "hh") - .contentTransition(this.trasition1) - .fontSize(this.fontsize1) - .fontColor(this.color1) - .borderWidth(1) - - Text(this.message + "哈") - .contentTransition(this.trasition3) - .fontSize("120px") - .borderWidth(1) - - } - } - .height(300) - - Scroll() { - Column() { - Button('switch decorationStyle1 ').onClick(() => { - this.decorationStyleInterface = - this.decorationStyleInterface1 - this.message2++ - }) - Button('switch decorationStyle2 ').onClick(() => { - this.decorationStyleInterface = - this.decorationStyleInterface2 - this.message2++ - }) - Button('switch decorationStyle3 ').onClick(() => { - this.decorationStyleInterface = - this.decorationStyleInterface3 - this.message2++ - }) - Button("change textAlign") - .onClick(() => { - this.textAlign1 = this.textAlign1 == TextAlign.Start ? TextAlign.End : TextAlign.Start - this.message2++ - }) - Button("change number++") - .onClick(() => { - this.message++ - this.message2++ - }) - - Button("change number--") - .onClick(() => { - this.message-- - this.message2-- - }) - - Button("change number 100000") - .onClick(() => { - this.message += 100000 - this.message2 += 100000 - }) - Button("change undefined") - .onClick(() => { - // this.message2++ - this.trasition = null - this.modifierText.trasition = null - }) - - Button("change trasition1") - .onClick(() => { - // this.message++ - this.trasition = this.trasition1 - this.modifierText.trasition = this.trasition1 - }) - - Button("change trasition2") - .onClick(() => { - // this.message++ - this.trasition = this.trasition2 - this.modifierText.trasition = this.trasition2 - }) - Button("change trasition3") - .onClick(() => { - // this.message++ - this.trasition = this.trasition3 - this.modifierText.trasition = this.trasition3 - }) - Button("change trasition4") - .onClick(() => { - // this.message++ - this.trasition = this.trasition4 - this.modifierText.trasition = this.trasition4 - }) - - Button("change trasition5") - .onClick(() => { - // this.message++ - this.trasition = this.trasition5 - // this.modifierText.trasition = this.trasition5 - }) - - Button("change fontWeight") - .onClick(() => { - this.fontWeightindex++ - if (this.fontWeightindex >= this.fontWeight.length) { - this.fontWeightindex = 0; - } - }) - Button("change color") - .onClick(() => { - this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red - }) - Button("change color animateTo") - .onClick(() => { - animateTo({ duration: 2000 }, () => { - this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red - }) - }) - Button("change fontsize") - .onClick(() => { - // this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red - this.fontsize1 = this.fontsize1 == "120px" ? "80px" : "120px" - this.message2++ - }) - Button("change fontsize animateTo") - .onClick(() => { - animateTo({ duration: 2000 }, () => { - // this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red - this.fontsize1 = this.fontsize1 == "120px" ? "80px" : "120px" - // this.message++ - }) - }) - Button("change ellipsisMode") - .onClick(() => { - this.ellipsisMode = this.ellipsisMode == EllipsisMode.CENTER ? EllipsisMode.START : EllipsisMode.CENTER - }) - Button("change lineHeight") - .onClick(() => { - this.lineHeight = this.lineHeight == 50 ? 100 : 50 - this.message2++ - }) - Button("change fontfamiy") - .onClick(() => { - this.fontfamily = this.fontfamily == "" ? "medium" : "" - }) - - Button("change copyOption") - .onClick(() => { - this.copyoption = this.copyoption == CopyOptions.None ? CopyOptions.InApp : CopyOptions.None - }) - - Button("change font") - .onClick(() => { - this.fontindex++ - if (this.fontindex >= this.fontArray.length) { - this.fontindex = 0; - } - }) - - Button("change fontStyle") - .onClick(() => { - this.fontStyle = this.fontStyle == FontStyle.Normal ? FontStyle.Italic : FontStyle.Normal - }) - - Button('switch animation textshadow1').onClick(() => { - animateTo({ duration: 2000 }, () => { - this.textshadow = this.textshadow1 - }) - }) - - Button('switch animation textshadow2').onClick(() => { - animateTo({ duration: 2000 }, () => { - this.textshadow = this.textshadow2 - }) - }) - - Button('switch textshadow1 static').onClick(() => { - this.textshadow = this.textshadow1 - }) - Button('switch textshadow2 static').onClick(() => { - this.textshadow = this.textshadow2 - }) - - Button('当前fontFeature模式:' + this.fontFeature[this.fontFeatureIndex]) - .onClick(() => { - this.fontFeatureIndex++; - if (this.fontFeatureIndex > (this.fontFeature.length - 1)) { - this.fontFeatureIndex = 0; - } - }) - Button("change textIndent") - .onClick(() => { - this.indent1 = this.indent1 == 20 ? 0 : 20 - }) - - Button("change onlyBetweenLines") - .onClick(() => { - this.onlyBetweenLinesvalue = !this.onlyBetweenLinesvalue - }) - - Button("change baselineOffset") - .onClick(() => { - this.baselineOffset = this.baselineOffset == 20 ? 0 : 20 - }) - Button('当前lineBreakStrategy模式:' + this.lineBreakStrategy[this.lineBreakStrategyIndex]) - .onClick(() => { - this.lineBreakStrategyIndex++; - if (this.lineBreakStrategyIndex > (this.lineBreakStrategy.length - 1)) { - this.lineBreakStrategyIndex = 0; - } - }) - - Button("change halfLeading") - .onClick(() => { - this.halfLeading = !this.halfLeading - this.message2++ - }) - - Button("change enableVariableFontWeight") - .onClick(() => { - this.fontwenable += 20 - }) - - Button("change enableAutoSpacing") - .onClick(() => { - this.autospacing = !this.autospacing - }) - - Button('当前textoverflow模式:' + this.textOverflowIndex) - .onClick(() => { - this.textOverflowIndex++; - if (this.textOverflowIndex > (this.textOverflow.length - 1)) { - this.textOverflowIndex = 0; - } - }) - - Button('当前wordbreak模式:' + this.wordBreakIndex) - .onClick(() => { - this.wordBreakIndex++; - if (this.wordBreakIndex > (this.wordBreakOptions.length - 1)) { - this.wordBreakIndex = 0; - } - }) - - Button("change clip") - .onClick(() => { - this.clip1 = !this.clip1 - }) - - Button("change select") - .onClick(() => { - this.start = this.start == -1 ? 1 : -1; - this.end = this.end == -1 ? 2 : -1 - }) - - Button("change color") - .onClick(() => { - this.caretColor = this.caretColor == Color.Blue ? Color.Orange : Color.Blue - }) - - Button("change padding") - .onClick(() => { - this.padding1 == 10 ? 1 : 10 - }) - - Button("change enableprevieew") - .onClick(() => { - this.enableprevieew == !this.enableprevieew - }) - - } - } - .height(200) - - TextInput() - - Text('' + this.message2) - .copyOption(CopyOptions.InApp) - .contentTransition(this.trasition) - .width('100%') - .height(100) - .fontSize(30) - .backgroundColor(0x00FFFF) - .visibility(this.visi) - .textAlign(TextAlign.Center) - // .overlay(this.MyMenu()) - .baselineOffset(20) - Button("change Visibility") - .onClick(() => { - this.visi = this.visi == Visibility.Visible ? Visibility.None : Visibility.Visible - }) - - Button("change visi") - .onClick(() => { - this.visi = this.visi == Visibility.Visible ? Visibility.Hidden : Visibility.Visible - }) - - Text("change 无崩溃") - .margin(10) - .onClick(() => { - this.message2++ - }) - - } - .width('100%') - } - .height('100%') - } +import font from '@ohos.font'; +import { LengthMetrics, LengthUnit } from '@ohos.arkui.node' + +class MyTextModifier implements AttributeModifier { + trasition: NumericTextTransition | undefined | null = { flipDirection: FlipDirection.UP, enableBlur: false } + + applyNormalAttribute(instance: TextAttribute): void { + instance + .contentTransition(this.trasition) + } +} + +@Entry +@Component +struct struct_02_TextSample_02_textNumericTextTransition { + @State testText: string = "Test"; + @State testAccessibilityText: string | undefined | null = 'MyTest.accessibilityText'; + @State testAccessibilityDescription: string | undefined | null = 'MyTest.accessibilityDescription'; + @State testAccessibilityLevel: string | undefined | null = 'MyTest.auto'; + @State backgroundColor1: ResourceColor | undefined = undefined; + controller3: TextController = new TextController(); + clickGestureAttr: GestureStyle = new GestureStyle({ + onClick: () => { + console.log('click GestureAttr'); + }, + }) + mutableStyledString3: MutableStyledString = new MutableStyledString("hello world", [ + { + start: 0, + length: 5, + styledKey: StyledStringKey.GESTURE, + styledValue: this.clickGestureAttr + }, + { + start: 6, + length: 5, + styledKey: StyledStringKey.FONT, + styledValue: new TextStyle({ fontColor: Color.Pink }) + } + ]); + + async onPageShow() { + this.controller3.setStyledString(this.mutableStyledString3) + } + + // 自定义字体 + // async aboutToAppear() { + // getContext(this) + // .resourceManager + // font.registerFont({ + // familyName: 'medium', + // familySrc: $rawfile('font/cartoon.ttf') + // }) + // } + + @State message: number = 17858867166 + @State message2: number = 88 + @State trasition: NumericTextTransition | undefined | null = + new NumericTextTransition({ flipDirection: FlipDirection.UP, enableBlur: true }) + @State trasition1: NumericTextTransition = + new NumericTextTransition({ flipDirection: FlipDirection.DOWN, enableBlur: true }) + @State trasition2: NumericTextTransition = { flipDirection: undefined, enableBlur: true } + @State trasition3: NumericTextTransition = { enableBlur: true } + @State trasition4: NumericTextTransition = {} + @State trasition5: NumericTextTransition = { flipDirection: FlipDirection.UP, enableBlur: undefined } + @State color1: Color = Color.Red + @State fontsize1: string = "120px" + @State textAlign1: TextAlign = TextAlign.Start + @State lineHeight: number = 50 + @State ellipsisMode: EllipsisMode = EllipsisMode.CENTER + @State fontWeight: Array = [FontWeight.Normal, FontWeight.Lighter, FontWeight.Bolder] + @State fontWeightindex: number = 0 + private decorationStyleInterface1: DecorationStyleInterface = { + color: Color.Gray, + type: TextDecorationType.Underline, + style: TextDecorationStyle.WAVY + } + private decorationStyleInterface2: DecorationStyleInterface = { + type: TextDecorationType.None, + color: Color.Green, + style: TextDecorationStyle.DOUBLE + } + private decorationStyleInterface3: DecorationStyleInterface = { + type: TextDecorationType.LineThrough, + style: TextDecorationStyle.DASHED, + color: Color.Pink + } + @State decorationStyleInterface: DecorationStyleInterface = { + type: TextDecorationType.Underline + } + @State fontfamily: string = "" + @State copyoption: CopyOptions = CopyOptions.InApp + @State fontArray: Array = + [{ size: 30, style: FontStyle.Normal }, { size: 10, style: FontStyle.Italic }, + { size: 60, weight: FontWeight.Bold, style: FontStyle.Normal }] + @State fontindex: number = 0 + @State fontStyle: FontStyle = FontStyle.Normal + private textshadow1: ShadowOptions = { + radius: 10, + color: Color.Black, + offsetX: 0, + offsetY: 0 + } + private textshadow2: ShadowOptions = { + radius: 0, + color: Color.Pink, + offsetX: 100, + offsetY: 100 + } + @State textshadow: ShadowOptions = this.textshadow1 + @State fontFeatureIndex: number = 0; + @State fontFeature: string[] = + ["\"sups\" -1", "\"sups\" 1", "\"sinf\" on"]; + @State indent1: number = 20 + @State onlyBetweenLinesvalue: boolean = false + @State modifierText: MyTextModifier = new MyTextModifier() + @State baselineOffset: number = 20 + @State lineBreakStrategyIndex: number = 0; + @State lineBreakStrategy: LineBreakStrategy[] = + [LineBreakStrategy.HIGH_QUALITY, LineBreakStrategy.GREEDY, LineBreakStrategy.BALANCED]; + @State halfLeading: boolean = false; + @State fontwenable: number = 120 + @State autospacing: boolean = false; + @State linearGradientOptions1: LinearGradientOptions = + { + angle: 45, + colors: [[Color.Red, 0.0], [Color.Blue, 0.3], [Color.Green, 0.5]] + }; + @State linearGradientOptions2: LinearGradientOptions = + { + direction: GradientDirection.LeftTop, + colors: [[Color.Red, 0.0], [Color.Blue, 0.3], [Color.Green, 0.5]], + repeating: true, + }; + @State radialGradientOptions: RadialGradientOptions = + { + center: [50, 50], + radius: 20, + colors: [[Color.Red, 0.0], [Color.Blue, 0.3], [Color.Green, 0.5]], + repeating: true, + }; + @State textOverflowIndex: number = 0; + @State textOverflow: TextOverflow[] = + [TextOverflow.None, TextOverflow.MARQUEE, TextOverflow.Ellipsis]; + @State wordBreakIndex: number = 0; + @State wordBreakOptions: WordBreak[] = + [WordBreak.NORMAL, WordBreak.BREAK_ALL, WordBreak.BREAK_WORD, WordBreak.HYPHENATION] + @State clip1: boolean = true; + @State start: number = 0; + @State end: number = 1; + @State caretColor: Color = Color.Blue + @State padding1: number = 10 + @State enableDataDetector: boolean = true + @State enableprevieew: boolean | undefined | null = true + scrollerForList: Scroller = new Scroller(); + @State visi: Visibility = Visibility.Visible + + @Builder + MyMenu() { + Column() { + Text("hhh") + } + } + + build() { + Row() { + Column() { + Scroll() { + Column() { + Text("测试自适应字号翻牌" + "😅") + .fontSize(8) + .padding(this.padding1) + .borderWidth(1) + .shaderStyle(this.linearGradientOptions1) + Text("" + this.message) + .attributeModifier(this.modifierText) + .fontSize(this.fontsize1) + .borderWidth(1) + .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) + .width(110) + .textOverflow({ overflow: this.textOverflow[this.textOverflowIndex] }) + // .maxLines(1) + .textAlign(this.textAlign1) + .decoration(this.decorationStyleInterface) + .ellipsisMode(this.ellipsisMode) + .fontColor(this.color1) + .fontWeight(this.fontWeight[this.fontWeightindex]) + .fontFamily(this.fontfamily) + .copyOption(this.copyoption) + .font(this.fontArray[this.fontindex]) + .fontStyle(this.fontStyle) + .textShadow(this.textshadow) + .minFontSize(10) + .maxFontSize(60) + .textIndent(this.indent1) + .baselineOffset(this.baselineOffset) + .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) + .halfLeading(this.halfLeading) + .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) + .enableAutoSpacing(this.autospacing) + .shaderStyle(this.linearGradientOptions1) + .clip(this.clip1) + .selection(this.start, this.end) + .caretColor(this.caretColor) + .padding(this.padding1) + .fontFeature(this.fontFeature[this.fontFeatureIndex]) + .enableDataDetector(this.enableDataDetector) + .dataDetectorConfig({ + types: [TextDataDetectorType.PHONE_NUMBER, TextDataDetectorType.URL, TextDataDetectorType.EMAIL, + TextDataDetectorType.ADDRESS, TextDataDetectorType.DATE_TIME], + color: $r('app.color.start_window_background'), + decoration: { + type: TextDecorationType.Overline + }, + enablePreviewMenu: this.enableprevieew + }) + + Text("测试截断数字") + .fontSize(8) + .shaderStyle(this.linearGradientOptions2) + Text(this.message + "") + .contentTransition(this.trasition) + .fontSize(this.fontsize1) + .borderWidth(1) + .width(110) + // .wordBreak(WordBreak.BREAK_ALL) + .textOverflow({ overflow: this.textOverflow[this.textOverflowIndex] }) + .maxLines(1) + .textAlign(this.textAlign1) + .lineHeight(this.lineHeight) + .decoration(this.decorationStyleInterface) + .ellipsisMode(this.ellipsisMode) + // .fontColor(this.color1) + .fontWeight(this.fontWeight[this.fontWeightindex]) + .fontFamily(this.fontfamily) + .copyOption(this.copyoption) + .maxLines(1) + .font(this.fontArray[this.fontindex]) + .fontStyle(this.fontStyle) + .textShadow(this.textshadow) + .fontFeature(this.fontFeature[this.fontFeatureIndex]) + .textIndent(this.indent1) + .baselineOffset(this.baselineOffset) + .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) + .halfLeading(this.halfLeading) + .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) + .enableAutoSpacing(this.autospacing) + .lineSpacing(LengthMetrics.vp(30), { onlyBetweenLines: this.onlyBetweenLinesvalue }) + .shaderStyle(this.linearGradientOptions2) + .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) + .clip(this.clip1) + .selection(this.start, this.end) + .caretColor(this.caretColor) + .padding(this.padding1) + .align(Alignment.BottomEnd) + .enableDataDetector(true) + .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) + Text("测试属性切换88") + .fontSize(8) + .shaderStyle(this.radialGradientOptions) + Row() { + + + Text(this.message2 + "") + .contentTransition(this.trasition)// .attributeModifier(this.modifierText) + .fontSize(this.fontsize1) + .borderWidth(1) + .width(110)// .wordBreak(WordBreak.BREAK_ALL) + .textOverflow({ overflow: TextOverflow.Ellipsis })// .maxLines(1) + .textAlign(this.textAlign1) + .lineHeight(this.lineHeight) + .decoration(this.decorationStyleInterface)//删除ellipsisMode、fontColor可以测试relayout效果 + .ellipsisMode(this.ellipsisMode) + // .fontColor(this.color1) + .fontFamily(this.fontfamily) + .fontWeight(this.fontWeight[this.fontWeightindex]) + .copyOption(this.copyoption)// .font(this.fontArray[this.fontindex]) + .fontStyle(this.fontStyle)// .textShadow(this.textshadow) + .margin({ bottom: 20 }) + .fontFeature(this.fontFeature[this.fontFeatureIndex]) + .textIndent(this.indent1) + .baselineOffset(this.baselineOffset) + .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) + .halfLeading(this.halfLeading) + .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) + .enableAutoSpacing(this.autospacing) + .shaderStyle(this.radialGradientOptions) + .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) + .clip(this.clip1) + .selection(this.start, this.end) + .caretColor(this.caretColor) + .padding(this.padding1) + .backgroundColor(Color.Orange) + .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) + + Text(this.message2 + "") + .contentTransition(this.trasition) + .attributeModifier(this.modifierText) + .fontSize(this.fontsize1) + .borderWidth(1) + .width(110) + .wordBreak(WordBreak.BREAK_ALL) + .textOverflow({ overflow: TextOverflow.Ellipsis })// .maxLines(1) + .textAlign(this.textAlign1) + .lineHeight(this.lineHeight) + .decoration(this.decorationStyleInterface)//删除ellipsisMode、fontColor可以测试relayout效果 + .ellipsisMode(this.ellipsisMode) + .fontColor(this.color1) + .fontFamily(this.fontfamily) + .fontWeight(this.fontWeight[this.fontWeightindex]) + .copyOption(this.copyoption) + .font(this.fontArray[this.fontindex]) + .fontStyle(this.fontStyle) + .textShadow(this.textshadow) + .margin({ bottom: 20 }) + .fontFeature(this.fontFeature[this.fontFeatureIndex]) + .textIndent(this.indent1) + .baselineOffset(this.baselineOffset) + .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) + .halfLeading(this.halfLeading) + .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) + .enableAutoSpacing(this.autospacing) + .shaderStyle(this.radialGradientOptions) + .wordBreak(this.wordBreakOptions[this.wordBreakIndex]) + .clip(this.clip1) + .selection(this.start, this.end) + .caretColor(this.caretColor) + .padding(this.padding1) + .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) + } + + Text("测试span不生效") + .fontSize(8) + Text() { + Span(this.message2 + "") + } + .contentTransition(this.trasition) // .attributeModifier(this.modifierText) + .fontSize(this.fontsize1) + .borderWidth(1) + // .wordBreak(WordBreak.BREAK_ALL) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + // .maxLines(1) + .textAlign(this.textAlign1) + .lineHeight(this.lineHeight) + .decoration(this.decorationStyleInterface) //删除ellipsisMode、fontColor可以测试relayout效果 + .ellipsisMode(this.ellipsisMode) + .fontColor(this.color1) + .fontFamily(this.fontfamily) + .fontWeight(this.fontWeight[this.fontWeightindex]) + .copyOption(this.copyoption) + .font(this.fontArray[this.fontindex]) + .fontStyle(this.fontStyle) + .textShadow(this.textshadow) + .margin({ bottom: 20 }) + .fontFeature(this.fontFeature[this.fontFeatureIndex]) + .textIndent(this.indent1) + .baselineOffset(this.baselineOffset) + .lineBreakStrategy(this.lineBreakStrategy[this.lineBreakStrategyIndex]) + .halfLeading(this.halfLeading) + .fontWeight(this.fontwenable, { enableVariableFontWeight: true }) + .enableAutoSpacing(this.autospacing) + .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) + + .lineSpacing(LengthMetrics.vp(30), { onlyBetweenLines: this.onlyBetweenLinesvalue }) + + + Text(this.message + "hh") + .contentTransition(this.trasition1) + .fontSize(this.fontsize1) + .fontColor(this.color1) + .borderWidth(1) + + Text(this.message + "哈") + .contentTransition(this.trasition3) + .fontSize("120px") + .borderWidth(1) + + } + } + .height(300) + + Scroll() { + Column() { + Button('switch decorationStyle1 ').onClick(() => { + this.decorationStyleInterface = + this.decorationStyleInterface1 + this.message2++ + }) + Button('switch decorationStyle2 ').onClick(() => { + this.decorationStyleInterface = + this.decorationStyleInterface2 + this.message2++ + }) + Button('switch decorationStyle3 ').onClick(() => { + this.decorationStyleInterface = + this.decorationStyleInterface3 + this.message2++ + }) + Button("change textAlign") + .onClick(() => { + this.textAlign1 = this.textAlign1 == TextAlign.Start ? TextAlign.End : TextAlign.Start + this.message2++ + }) + Button("change number++") + .onClick(() => { + this.message++ + this.message2++ + }) + + Button("change number--") + .onClick(() => { + this.message-- + this.message2-- + }) + + Button("change number 100000") + .onClick(() => { + this.message += 100000 + this.message2 += 100000 + }) + Button("change undefined") + .onClick(() => { + // this.message2++ + this.trasition = null + this.modifierText.trasition = null + }) + + Button("change trasition1") + .onClick(() => { + // this.message++ + this.trasition = this.trasition1 + this.modifierText.trasition = this.trasition1 + }) + + Button("change trasition2") + .onClick(() => { + // this.message++ + this.trasition = this.trasition2 + this.modifierText.trasition = this.trasition2 + }) + Button("change trasition3") + .onClick(() => { + // this.message++ + this.trasition = this.trasition3 + this.modifierText.trasition = this.trasition3 + }) + Button("change trasition4") + .onClick(() => { + // this.message++ + this.trasition = this.trasition4 + this.modifierText.trasition = this.trasition4 + }) + + Button("change trasition5") + .onClick(() => { + // this.message++ + this.trasition = this.trasition5 + // this.modifierText.trasition = this.trasition5 + }) + + Button("change fontWeight") + .onClick(() => { + this.fontWeightindex++ + if (this.fontWeightindex >= this.fontWeight.length) { + this.fontWeightindex = 0; + } + }) + Button("change color") + .onClick(() => { + this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red + }) + Button("change color animateTo") + .onClick(() => { + animateTo({ duration: 2000 }, () => { + this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red + }) + }) + Button("change fontsize") + .onClick(() => { + // this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red + this.fontsize1 = this.fontsize1 == "120px" ? "80px" : "120px" + this.message2++ + }) + Button("change fontsize animateTo") + .onClick(() => { + animateTo({ duration: 2000 }, () => { + // this.color1 = this.color1 == Color.Red ? Color.Black : Color.Red + this.fontsize1 = this.fontsize1 == "120px" ? "80px" : "120px" + // this.message++ + }) + }) + Button("change ellipsisMode") + .onClick(() => { + this.ellipsisMode = this.ellipsisMode == EllipsisMode.CENTER ? EllipsisMode.START : EllipsisMode.CENTER + }) + Button("change lineHeight") + .onClick(() => { + this.lineHeight = this.lineHeight == 50 ? 100 : 50 + this.message2++ + }) + Button("change fontfamiy") + .onClick(() => { + this.fontfamily = this.fontfamily == "" ? "medium" : "" + }) + + Button("change copyOption") + .onClick(() => { + this.copyoption = this.copyoption == CopyOptions.None ? CopyOptions.InApp : CopyOptions.None + }) + + Button("change font") + .onClick(() => { + this.fontindex++ + if (this.fontindex >= this.fontArray.length) { + this.fontindex = 0; + } + }) + + Button("change fontStyle") + .onClick(() => { + this.fontStyle = this.fontStyle == FontStyle.Normal ? FontStyle.Italic : FontStyle.Normal + }) + + Button('switch animation textshadow1').onClick(() => { + animateTo({ duration: 2000 }, () => { + this.textshadow = this.textshadow1 + }) + }) + + Button('switch animation textshadow2').onClick(() => { + animateTo({ duration: 2000 }, () => { + this.textshadow = this.textshadow2 + }) + }) + + Button('switch textshadow1 static').onClick(() => { + this.textshadow = this.textshadow1 + }) + Button('switch textshadow2 static').onClick(() => { + this.textshadow = this.textshadow2 + }) + + Button('当前fontFeature模式:' + this.fontFeature[this.fontFeatureIndex]) + .onClick(() => { + this.fontFeatureIndex++; + if (this.fontFeatureIndex > (this.fontFeature.length - 1)) { + this.fontFeatureIndex = 0; + } + }) + Button("change textIndent") + .onClick(() => { + this.indent1 = this.indent1 == 20 ? 0 : 20 + }) + + Button("change onlyBetweenLines") + .onClick(() => { + this.onlyBetweenLinesvalue = !this.onlyBetweenLinesvalue + }) + + Button("change baselineOffset") + .onClick(() => { + this.baselineOffset = this.baselineOffset == 20 ? 0 : 20 + }) + Button('当前lineBreakStrategy模式:' + this.lineBreakStrategy[this.lineBreakStrategyIndex]) + .onClick(() => { + this.lineBreakStrategyIndex++; + if (this.lineBreakStrategyIndex > (this.lineBreakStrategy.length - 1)) { + this.lineBreakStrategyIndex = 0; + } + }) + + Button("change halfLeading") + .onClick(() => { + this.halfLeading = !this.halfLeading + this.message2++ + }) + + Button("change enableVariableFontWeight") + .onClick(() => { + this.fontwenable += 20 + }) + + Button("change enableAutoSpacing") + .onClick(() => { + this.autospacing = !this.autospacing + }) + + Button('当前textoverflow模式:' + this.textOverflowIndex) + .onClick(() => { + this.textOverflowIndex++; + if (this.textOverflowIndex > (this.textOverflow.length - 1)) { + this.textOverflowIndex = 0; + } + }) + + Button('当前wordbreak模式:' + this.wordBreakIndex) + .onClick(() => { + this.wordBreakIndex++; + if (this.wordBreakIndex > (this.wordBreakOptions.length - 1)) { + this.wordBreakIndex = 0; + } + }) + + Button("change clip") + .onClick(() => { + this.clip1 = !this.clip1 + }) + + Button("change select") + .onClick(() => { + this.start = this.start == -1 ? 1 : -1; + this.end = this.end == -1 ? 2 : -1 + }) + + Button("change color") + .onClick(() => { + this.caretColor = this.caretColor == Color.Blue ? Color.Orange : Color.Blue + }) + + Button("change padding") + .onClick(() => { + this.padding1 == 10 ? 1 : 10 + }) + + Button("change enableprevieew") + .onClick(() => { + this.enableprevieew == !this.enableprevieew + }) + + } + } + .height(200) + + TextInput() + + Text('' + this.message2) + .copyOption(CopyOptions.InApp) + .contentTransition(this.trasition) + .width('100%') + .height(100) + .fontSize(30) + .backgroundColor(0x00FFFF) + .visibility(this.visi) + .textAlign(TextAlign.Center) + // .overlay(this.MyMenu()) + .baselineOffset(20) + Button("change Visibility") + .onClick(() => { + this.visi = this.visi == Visibility.Visible ? Visibility.None : Visibility.Visible + }) + + Button("change visi") + .onClick(() => { + this.visi = this.visi == Visibility.Visible ? Visibility.Hidden : Visibility.Visible + }) + + Text("change 无崩溃") + .margin(10) + .onClick(() => { + this.message2++ + }) + + } + .width('100%') + } + .height('100%') + } } \ No newline at end of file diff --git a/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/03-enablePreviewMenu.ets b/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/03-enablePreviewMenu.ets index fe380ba6a2f5067b879f94264595758c14fa449e..9300a47113e9c24fe3e8861f74b95266623049fc 100644 --- a/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/03-enablePreviewMenu.ets +++ b/examples/TextComponentTest/entry/src/main/ets/pages/02-TextSample/03-enablePreviewMenu.ets @@ -1,1284 +1,1284 @@ -import font from '@ohos.font'; -import { LengthMetrics } from '@kit.ArkUI'; - - -@Entry -@Component -struct struct_02_TextSample_03_enablePreviewMenu { - controller: TextAreaController = new TextAreaController() - @State text: string = - '姓名:张三' + '\n' + '邮箱:12345@123.com' + '\n' + '电话号码:(86) (755) ********' + '\n' + - '网址:http://www.123.com' + - '\n' + '地址:中国北京市东城区天坛东路1号' + '\n' + '时间:2024年8月16号' - @State enableDataDetector1: boolean = true - @State types: TextDataDetectorType[] = - [TextDataDetectorType.PHONE_NUMBER, TextDataDetectorType.URL, TextDataDetectorType.EMAIL, - TextDataDetectorType.ADDRESS, TextDataDetectorType.DATE_TIME] - @State lineHeight1: number = 20 - @State type: TextDecorationType = TextDecorationType.None - @State AItype: TextDecorationType = TextDecorationType.Underline - @State AIDecorationColor: Color = Color.Green - @State AIDecorationStyle: TextDecorationStyle = TextDecorationStyle.SOLID - @State AIfontColor: Color = Color.Green - @State textfontColor: Color = Color.Red - @State TextDecorationColor: Color = Color.Black - @State letterSpacing: number = 5 - @State radius: number = 0 - @State fontColor: Color = Color.Red - @State fontColor1: Color = Color.Black - @State fontColor2: Color = Color.Black - @State fontColor3: Color = Color.Black - @State fontColor4: Color = Color.Black - @State fontColor5: Color = Color.Black - @State fontColor6: Color = Color.Black - @State fontColor7: Color = Color.Black - @State fontColor8: Color = Color.Black - @State fontColor9: Color = Color.Black - @State fontColor10: Color = Color.Black - @State fontColor11: Color = Color.Black - @State fontColor12: Color = Color.Black - @State fontColor13: Color = Color.Black - @State fontColor14: Color = Color.Black - @State fontColor15: Color = Color.Black - @State fontColor16: Color = Color.Black - @State fontColor17: Color = Color.Black - @State fontColor18: Color = Color.Black - @State fontColor19: Color = Color.Black - @State fontColor20: Color = Color.Black - @State fontColor21: Color = Color.Black - @State fontColor22: Color = Color.Black - @State fontColor23: Color = Color.Black - @State fontColor24: Color = Color.Black - @State fontColor25: Color = Color.Black - @State fontColor26: Color = Color.Black - @State fontColor27: Color = Color.Black - @State fontColor28: Color = Color.Black - @State fontColor29: Color = Color.Black - @State fontColor30: Color = Color.Black - @State fontColor31: Color = Color.Black - @State fontColor32: Color = Color.Black - @State fontColor33: Color = Color.Black - @State fontColor34: Color = Color.Black - @State fontColor35: Color = Color.Black - @State fontColor36: Color = Color.Black - @State fontColor37: Color = Color.Black - @State fontColor38: Color = Color.Black - @State fontColor39: Color = Color.Black - @State fontColor40: Color = Color.Black - @State fontColor41: Color = Color.Black - @State fontColor42: Color = Color.Black - @State fontColor43: Color = Color.Black - @State fontColor44: Color = Color.Black - @State fontColor45: Color = Color.Black - @State fontColor46: Color = Color.Black - @State fontColor47: Color = Color.Black - @State fontColor48: Color = Color.Black - @State fontColor49: Color = Color.Black - @State fontColor50: Color = Color.Black - @State fontColor51: Color = Color.Black - @State fontColor52: Color = Color.Black - @State fontColor53: Color = Color.Black - @State fontColor54: Color = Color.Black - @State fontColor55: Color = Color.Black - @State fontColor56: Color = Color.Black - @State fontColor57: Color = Color.Black - @State fontColor58: Color = Color.Black - @State fontColor59: Color = Color.Black - @State fontColor60: Color = Color.Black - @State fontColor61: Color = Color.Black - @State fontColor62: Color = Color.Black - @State fontColor63: Color = Color.Black - @State fontColor64: Color = Color.Black - @State fontColor65: Color = Color.Black - @State fontColor66: Color = Color.Black - @State fontColor67: Color = Color.Black - @State fontColor68: Color = Color.Black - @State fontColor69: Color = Color.Black - @State fontColor70: Color = Color.Black - @State fontSize1: number = 16 - @State maxLines: number = 8 - @State fontStyle: FontStyle = FontStyle.Normal - @State weight: FontWeight = FontWeight.Normal - @State overflow: TextOverflow = TextOverflow.None - @State copyOption: CopyOptions = CopyOptions.None - @State arr: number[] = [0] - @State num: number = 0 - scroller: Scroller = new Scroller() - - build() { - Column() { - Scroll(this.scroller) { - Text(this.text) { - ForEach(this.arr, (item: number) => { - Span(this.text) - }) - - } - .onTextSelectionChange((selectionStart: number, selectionEnd: number) => { - console.log("onTextSelectionChange:" + selectionStart + " --- " + selectionEnd) - }) - .border({ width: 1 }) - .enableDataDetector(this.enableDataDetector1) - .dataDetectorConfig({ - types: this.types, - onDetectResultUpdate: (result: string) => { - console.error('FAN, text', result); - }, - color: this.AIfontColor, - decoration: ({ - type: this.AItype, - color: this.AIDecorationColor, - style: this.AIDecorationStyle - }), - enablePreviewMenu: true - }) - // .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) - .lineHeight(this.lineHeight1) - .decoration({ type: this.type, color: this.TextDecorationColor }) - .letterSpacing(this.letterSpacing) - .textShadow({ radius: this.radius }) - .fontColor(this.textfontColor) - .font({ size: this.fontSize1, weight: this.weight, style: this.fontStyle }) - .textOverflow({ overflow: this.overflow }) - .draggable(undefined) - .copyOption(this.copyOption) - .width('90%') - // .focusable(true) - .maxLines(this.maxLines) - .padding(15) - .height(300) - - }.height('40%') - - TextArea().margin(10) - - List({ space: 10 }) { - ListItem() { - Row({ space: 10 }) { - Text('是否使用AI接口:').fontSize('16vp') - Text('是') - .fontSize('16vp') - .width(50) - .onClick(() => { - this.enableDataDetector1 = true - }) - .focusOnTouch(true) - .fontColor(this.fontColor1) - .onFocus(() => { - this.fontColor1 = Color.Red - }) - .onBlur(() => { - this.fontColor1 = Color.Black - }) - Text('否') - .fontSize('16vp') - .width(50) - .onClick(() => { - this.enableDataDetector1 = false - }) - .focusOnTouch(true) - .fontColor(this.fontColor2) - .onFocus(() => { - this.fontColor2 = Color.Red - }) - .onBlur(() => { - this.fontColor2 = Color.Black - }) - } - } //是否使用AI接口 - ListItem() { - Column({ space: 10 }) { - Row({ space: 10 }) { - Text('支持:').fontSize('16vp') - Text('电话号码') - .onClick(() => { - if (!this.types.some(item => item == TextDataDetectorType.PHONE_NUMBER)) { - this.types.push(TextDataDetectorType.PHONE_NUMBER) - } - }) - .focusOnTouch(true) - .fontColor(this.fontColor3) - .onFocus(() => { - this.fontColor3 = Color.Red - }) - .onBlur(() => { - this.fontColor3 = Color.Black - }) - .fontSize('16vp') - - Text('网址') - .onClick(() => { - if (!this.types.some(item => item == TextDataDetectorType.URL)) { - this.types.push(TextDataDetectorType.URL) - } - }) - .fontSize('16vp') - .focusOnTouch(true) - .fontColor(this.fontColor4) - .onFocus(() => { - this.fontColor4 = Color.Red - }) - .onBlur(() => { - this.fontColor4 = Color.Black - }) - - Text('邮箱') - .onClick(() => { - if (!this.types.some(item => item == TextDataDetectorType.EMAIL)) { - this.types.push(TextDataDetectorType.EMAIL) - } - }) - .fontSize('16vp') - .focusOnTouch(true) - .fontColor(this.fontColor5) - .onFocus(() => { - this.fontColor5 = Color.Red - }) - .onBlur(() => { - this.fontColor5 = Color.Black - }) - - Text('地址') - .fontSize('16vp') - .onClick(() => { - if (!this.types.some(item => item == TextDataDetectorType.ADDRESS)) { - this.types.push(TextDataDetectorType.ADDRESS) - } - }) - .focusOnTouch(true) - .fontColor(this.fontColor6) - .onFocus(() => { - this.fontColor6 = Color.Red - }) - .onBlur(() => { - this.fontColor6 = Color.Black - }) - - Text('时间') - .fontSize('16vp') - .onClick(() => { - if (!this.types.some(item => item == TextDataDetectorType.DATE_TIME)) { - this.types.push(TextDataDetectorType.DATE_TIME) - } - }) - .focusOnTouch(true) - .fontColor(this.fontColor7) - .onFocus(() => { - this.fontColor7 = Color.Red - }) - .onBlur(() => { - this.fontColor7 = Color.Black - }) - - } - - Row({ space: 10 }) { - Text('不支持:').fontSize('16vp') - Text('电话号码') - .fontSize('16vp') - .onClick(() => { - this.types = this.types.filter(item => item != TextDataDetectorType.PHONE_NUMBER) - }) - .focusOnTouch(true) - .fontColor(this.fontColor8) - .onFocus(() => { - this.fontColor8 = Color.Red - }) - .onBlur(() => { - this.fontColor8 = Color.Black - }) - - Text('网址') - .fontSize('16vp') - .onClick(() => { - this.types = this.types.filter(item => item != TextDataDetectorType.URL) - }) - .focusOnTouch(true) - .fontColor(this.fontColor9) - .onFocus(() => { - this.fontColor9 = Color.Red - }) - .onBlur(() => { - this.fontColor9 = Color.Black - }) - - Text('邮箱') - .fontSize('16vp') - .onClick(() => { - this.types = this.types.filter(item => item != TextDataDetectorType.EMAIL) - }) - .focusOnTouch(true) - .fontColor(this.fontColor10) - .onFocus(() => { - this.fontColor10 = Color.Red - }) - .onBlur(() => { - this.fontColor10 = Color.Black - }) - - - Text('地址') - .fontSize('16vp') - .onClick(() => { - this.types = this.types.filter(item => item != TextDataDetectorType.ADDRESS) - }) - .focusOnTouch(true) - .fontColor(this.fontColor11) - .onFocus(() => { - this.fontColor11 = Color.Red - }) - .onBlur(() => { - this.fontColor11 = Color.Black - }) - - Text('时间') - .fontSize('16vp') - .onClick(() => { - this.types = this.types.filter(item => item != TextDataDetectorType.DATE_TIME) - }) - .focusOnTouch(true) - .fontColor(this.fontColor12) - .onFocus(() => { - this.fontColor12 = Color.Red - }) - .onBlur(() => { - this.fontColor12 = Color.Black - }) - - } - } - - } //支持识别样式 - ListItem() { - Row({ space: 20 }) { - Text('行高:').fontSize('16vp') - Text('-') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.lineHeight1 = this.lineHeight1 - 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor13) - .onFocus(() => { - this.fontColor13 = Color.Red - }) - .onBlur(() => { - this.fontColor13 = Color.Black - }) - Text('' + this.lineHeight1) - .fontSize('16vp') - Text('+') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.lineHeight1 = this.lineHeight1 + 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor14) - .onFocus(() => { - this.fontColor14 = Color.Red - }) - .onBlur(() => { - this.fontColor14 = Color.Black - }) - - - } - } //不支持识别的样式 - ListItem() { - Row({ space: 10 }) { - Text('文本修饰线:').fontSize('16vp') - Text('None') - .fontSize("16vp") - .width(60) - .onClick(() => { - this.type = TextDecorationType.None - }) - .focusOnTouch(true) - .fontColor(this.fontColor15) - .onFocus(() => { - this.fontColor15 = Color.Red - }) - .onBlur(() => { - this.fontColor15 = Color.Black - }) - Text('上划线') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.type = TextDecorationType.Overline - }) - .focusOnTouch(true) - .fontColor(this.fontColor16) - .onFocus(() => { - this.fontColor16 = Color.Red - }) - .onBlur(() => { - this.fontColor16 = Color.Black - }) - Text('穿透线') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.type = TextDecorationType.LineThrough - }) - .focusOnTouch(true) - .fontColor(this.fontColor17) - .onFocus(() => { - this.fontColor17 = Color.Red - }) - .onBlur(() => { - this.fontColor17 = Color.Black - }) - Text('下划线') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.type = TextDecorationType.Underline - }) - .focusOnTouch(true) - .fontColor(this.fontColor18) - .onFocus(() => { - this.fontColor18 = Color.Red - }) - .onBlur(() => { - this.fontColor18 = Color.Black - }) - } - } //普通文本修饰线样式 - ListItem() { - Row({ space: 10 }) { - Text('修饰线颜色:').fontSize('16vp') - Text('黑色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.TextDecorationColor = Color.Black - }) - .focusOnTouch(true) - .fontColor(this.fontColor45) - .onFocus(() => { - this.fontColor45 = Color.Red - }) - .onBlur(() => { - this.fontColor45 = Color.Black - }) - Text('绿色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.TextDecorationColor = Color.Green - }) - .focusOnTouch(true) - .fontColor(this.fontColor46) - .onFocus(() => { - this.fontColor46 = Color.Red - }) - .onBlur(() => { - this.fontColor46 = Color.Black - }) - Text('蓝色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.TextDecorationColor = Color.Blue - }) - .focusOnTouch(true) - .fontColor(this.fontColor47) - .onFocus(() => { - this.fontColor47 = Color.Red - }) - .onBlur(() => { - this.fontColor47 = Color.Black - }) - Text('红色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.TextDecorationColor = Color.Red - }) - .focusOnTouch(true) - .fontColor(this.fontColor48) - .onFocus(() => { - this.fontColor48 = Color.Red - }) - .onBlur(() => { - this.fontColor48 = Color.Black - }) - } - } //普通文本修饰线颜色 - ListItem() { - Row({ space: 10 }) { - Text('AI修饰线样式:').fontSize('16vp') - Text('None') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AItype = TextDecorationType.None - }) - .focusOnTouch(true) - .fontColor(this.fontColor49) - .onFocus(() => { - this.fontColor49 = Color.Red - }) - .onBlur(() => { - this.fontColor49 = Color.Black - }) - Text('上划线') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AItype = TextDecorationType.Overline - }) - .focusOnTouch(true) - .fontColor(this.fontColor50) - .onFocus(() => { - this.fontColor50 = Color.Red - }) - .onBlur(() => { - this.fontColor50 = Color.Black - }) - Text('穿透线') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AItype = TextDecorationType.LineThrough - }) - .focusOnTouch(true) - .fontColor(this.fontColor51) - .onFocus(() => { - this.fontColor51 = Color.Red - }) - .onBlur(() => { - this.fontColor51 = Color.Black - }) - Text('下划线') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AItype = TextDecorationType.Underline - }) - .focusOnTouch(true) - .fontColor(this.fontColor52) - .onFocus(() => { - this.fontColor52 = Color.Red - }) - .onBlur(() => { - this.fontColor52 = Color.Black - }) - } - } //AI文本修饰线样式 - - ListItem() { - Row({ space: 10 }) { - Text('AI修饰线颜色:').fontSize('16vp') - Text('黑色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationColor = Color.Black - }) - .focusOnTouch(true) - .fontColor(this.fontColor53) - .onFocus(() => { - this.fontColor53 = Color.Red - }) - .onBlur(() => { - this.fontColor53 = Color.Black - }) - Text('绿色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationColor = Color.Green - }) - .focusOnTouch(true) - .fontColor(this.fontColor54) - .onFocus(() => { - this.fontColor54 = Color.Red - }) - .onBlur(() => { - this.fontColor54 = Color.Black - }) - Text('蓝色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationColor = Color.Blue - }) - .focusOnTouch(true) - .fontColor(this.fontColor55) - .onFocus(() => { - this.fontColor55 = Color.Red - }) - .onBlur(() => { - this.fontColor55 = Color.Black - }) - Text('红色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationColor = Color.Red - }) - .focusOnTouch(true) - .fontColor(this.fontColor56) - .onFocus(() => { - this.fontColor56 = Color.Red - }) - .onBlur(() => { - this.fontColor56 = Color.Black - }) - } - } //AI修饰线颜色 - ListItem() { - Row({ space: 10 }) { - Text('AI修饰线类型:').fontSize('16vp') - Text('SOLID') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationStyle = TextDecorationStyle.SOLID - }) - .focusOnTouch(true) - .fontColor(this.fontColor65) - .onFocus(() => { - this.fontColor65 = Color.Red - }) - .onBlur(() => { - this.fontColor65 = Color.Black - }) - Text('DOUBLE') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationStyle = TextDecorationStyle.DOUBLE - }) - .focusOnTouch(true) - .fontColor(this.fontColor66) - .onFocus(() => { - this.fontColor66 = Color.Red - }) - .onBlur(() => { - this.fontColor66 = Color.Black - }) - Text('DOTTED') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationStyle = TextDecorationStyle.DOTTED - }) - .focusOnTouch(true) - .fontColor(this.fontColor67) - .onFocus(() => { - this.fontColor67 = Color.Red - }) - .onBlur(() => { - this.fontColor67 = Color.Black - }) - Text('DASHED') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationStyle = TextDecorationStyle.DASHED - }) - .focusOnTouch(true) - .fontColor(this.fontColor68) - .onFocus(() => { - this.fontColor68 = Color.Red - }) - .onBlur(() => { - this.fontColor68 = Color.Black - }) - - - } - - } //AI修饰线类型 - - ListItem() { - - Text('WAVY') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIDecorationStyle = TextDecorationStyle.WAVY - }) - .focusOnTouch(true) - .fontColor(this.fontColor69) - .onFocus(() => { - this.fontColor69 = Color.Red - }) - .onBlur(() => { - this.fontColor69 = Color.Black - }) - - } - - ListItem() { - Row({ space: 10 }) { - Text('AI字体颜色:').fontSize('16vp') - Text('黑色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIfontColor = Color.Black - }) - .focusOnTouch(true) - .fontColor(this.fontColor57) - .onFocus(() => { - this.fontColor57 = Color.Red - }) - .onBlur(() => { - this.fontColor57 = Color.Black - }) - Text('绿色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIfontColor = Color.Green - }) - .focusOnTouch(true) - .fontColor(this.fontColor58) - .onFocus(() => { - this.fontColor58 = Color.Red - }) - .onBlur(() => { - this.fontColor58 = Color.Black - }) - Text('蓝色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIfontColor = Color.Blue - }) - .focusOnTouch(true) - .fontColor(this.fontColor59) - .onFocus(() => { - this.fontColor59 = Color.Red - }) - .onBlur(() => { - this.fontColor59 = Color.Black - }) - Text('红色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.AIfontColor = Color.Red - }) - .focusOnTouch(true) - .fontColor(this.fontColor60) - .onFocus(() => { - this.fontColor60 = Color.Red - }) - .onBlur(() => { - this.fontColor60 = Color.Black - }) - } - } //AI文本字体颜色 - ListItem() { - Row({ space: 20 }) { - Text('文本字符间距:').fontSize('16vp') - Text('-') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.letterSpacing = this.letterSpacing - 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor19) - .onFocus(() => { - this.fontColor19 = Color.Red - }) - .onBlur(() => { - this.fontColor19 = Color.Black - }) - Text('' + this.letterSpacing) - .fontSize('16vp') - Text('+') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.letterSpacing = this.letterSpacing + 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor20) - .onFocus(() => { - this.fontColor20 = Color.Red - }) - .onBlur(() => { - this.fontColor20 = Color.Black - }) - - - } - } //文本字符间距 - ListItem() { - Row({ space: 20 }) { - Text('阴影模糊半径:').fontSize('16vp') - Text('-') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.radius = this.radius - 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor21) - .onFocus(() => { - this.fontColor21 = Color.Red - }) - .onBlur(() => { - this.fontColor21 = Color.Black - }) - Text('' + this.radius) - .fontSize('16vp') - Text('+') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.radius = this.radius + 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor22) - .onFocus(() => { - this.fontColor22 = Color.Red - }) - .onBlur(() => { - this.fontColor22 = Color.Black - }) - - - } - } //阴影模糊半径 - ListItem() { - Row({ space: 20 }) { - Text('字体大小').fontSize('16vp') - Text('-') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.fontSize1 = this.fontSize1 - 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor23) - .onFocus(() => { - this.fontColor23 = Color.Red - }) - .onBlur(() => { - this.fontColor23 = Color.Black - }) - Text('' + this.fontSize1) - .fontSize('16vp') - Text('+') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.fontSize1 = this.fontSize1 + 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor24) - .onFocus(() => { - this.fontColor24 = Color.Red - }) - .onBlur(() => { - this.fontColor24 = Color.Black - }) - - - } - } //字体大小 - ListItem() { - Row({ space: 10 }) { - Text('字体颜色:').fontSize('16vp') - Text('黑色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.textfontColor = Color.Black - }) - .focusOnTouch(true) - .fontColor(this.fontColor61) - .onFocus(() => { - this.fontColor61 = Color.Red - }) - .onBlur(() => { - this.fontColor61 = Color.Black - }) - Text('绿色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.textfontColor = Color.Green - }) - .focusOnTouch(true) - .fontColor(this.fontColor62) - .onFocus(() => { - this.fontColor62 = Color.Red - }) - .onBlur(() => { - this.fontColor62 = Color.Black - }) - Text('蓝色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.textfontColor = Color.Blue - }) - .focusOnTouch(true) - .fontColor(this.fontColor63) - .onFocus(() => { - this.fontColor63 = Color.Red - }) - .onBlur(() => { - this.fontColor63 = Color.Black - }) - Text('红色') - .fontSize('16vp') - .width(60) - .onClick(() => { - this.textfontColor = Color.Red - }) - .focusOnTouch(true) - .fontColor(this.fontColor64) - .onFocus(() => { - this.fontColor64 = Color.Red - }) - .onBlur(() => { - this.fontColor64 = Color.Black - }) - } - } //字体颜色 - ListItem() { - Row({ space: 20 }) { - Text('字体样式').fontSize('16vp') - Text('Normal') - .fontSize('16vp') - .onClick(() => { - this.fontStyle = FontStyle.Normal - }) - .focusOnTouch(true) - .fontColor(this.fontColor25) - .onFocus(() => { - this.fontColor25 = Color.Red - }) - .onBlur(() => { - this.fontColor25 = Color.Black - }) - Text('Italic') - .fontSize('16vp') - .onClick(() => { - this.fontStyle = FontStyle.Italic - }) - .focusOnTouch(true) - .fontColor(this.fontColor26) - .onFocus(() => { - this.fontColor26 = Color.Red - }) - .onBlur(() => { - this.fontColor26 = Color.Black - }) - - } - } //字体样式 - ListItem() { - Row({ space: 5 }) { - Text('字体粗细:').fontSize('16vp') - Column({ space: 10 }) { - Text('Lighter') - .fontSize('16vp') - .onClick(() => { - this.weight = FontWeight.Lighter - }) - .focusOnTouch(true) - .fontColor(this.fontColor27) - .onFocus(() => { - this.fontColor27 = Color.Red - }) - .onBlur(() => { - this.fontColor27 = Color.Black - }) - Text('Normal') - .fontSize('16vp') - .onClick(() => { - this.weight = FontWeight.Normal - }) - .focusOnTouch(true) - .fontColor(this.fontColor28) - .onFocus(() => { - this.fontColor28 = Color.Red - }) - .onBlur(() => { - this.fontColor28 = Color.Black - }) - Text('Regular') - .fontSize('16vp') - .onClick(() => { - this.weight = FontWeight.Regular - }) - .focusOnTouch(true) - .fontColor(this.fontColor29) - .onFocus(() => { - this.fontColor29 = Color.Red - }) - .onBlur(() => { - this.fontColor29 = Color.Black - }) - Text('Medium') - .fontSize('16vp') - .onClick(() => { - this.weight = FontWeight.Medium - }) - .focusOnTouch(true) - .fontColor(this.fontColor30) - .onFocus(() => { - this.fontColor30 = Color.Red - }) - .onBlur(() => { - this.fontColor30 = Color.Black - }) - Text('Bold') - .fontSize('16vp') - .onClick(() => { - this.weight = FontWeight.Bold - }) - .focusOnTouch(true) - .fontColor(this.fontColor31) - .onFocus(() => { - this.fontColor31 = Color.Red - }) - .onBlur(() => { - this.fontColor31 = Color.Black - }) - Text('Bolder') - .fontSize('16vp') - .onClick(() => { - this.weight = FontWeight.Bolder - }) - .focusOnTouch(true) - .fontColor(this.fontColor32) - .onFocus(() => { - this.fontColor32 = Color.Red - }) - .onBlur(() => { - this.fontColor32 = Color.Black - }) - } - - } - } //字体粗细 - ListItem() { - Row({ space: 5 }) { - Text('超长文本显示方式:').fontSize('16vp') - Column({ space: 10 }) { - Text('None') - .fontSize('16vp') - .onClick(() => { - this.overflow = TextOverflow.None - }) - .focusOnTouch(true) - .fontColor(this.fontColor33) - .onFocus(() => { - this.fontColor33 = Color.Red - }) - .onBlur(() => { - this.fontColor33 = Color.Black - }) - Text('裁剪') - .fontSize('16vp') - .onClick(() => { - this.overflow = TextOverflow.Clip - }) - .focusOnTouch(true) - .fontColor(this.fontColor34) - .onFocus(() => { - this.fontColor34 = Color.Red - }) - .onBlur(() => { - this.fontColor34 = Color.Black - }) - Text('省略号') - .fontSize('16vp') - .onClick(() => { - this.overflow = TextOverflow.Ellipsis - }) - .focusOnTouch(true) - .fontColor(this.fontColor35) - .onFocus(() => { - this.fontColor35 = Color.Red - }) - .onBlur(() => { - this.fontColor35 = Color.Black - }) - Text('跑马灯') - .fontSize('16vp') - .onClick(() => { - this.overflow = TextOverflow.MARQUEE - }) - .focusOnTouch(true) - .fontColor(this.fontColor36) - .onFocus(() => { - this.fontColor36 = Color.Red - }) - .onBlur(() => { - this.fontColor36 = Color.Black - }) - - } - - } - } //超长文本显示样式 - ListItem() { - Row({ space: 20 }) { - Text('最大行数:').fontSize('16vp') - Text('-') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.maxLines = this.maxLines - 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor37) - .onFocus(() => { - this.fontColor37 = Color.Red - }) - .onBlur(() => { - this.fontColor37 = Color.Black - }) - Text('' + this.maxLines) - .fontSize('16vp') - Text('+') - .fontSize('16vp') - .width(20) - .onClick(() => { - this.maxLines = this.maxLines + 1 - }) - .focusOnTouch(true) - .fontColor(this.fontColor38) - .onFocus(() => { - this.fontColor38 = Color.Red - }) - .onBlur(() => { - this.fontColor38 = Color.Black - }) - - - } - } //最大行数 - ListItem() { - Row({ space: 10 }) { - Text('文本是否可复制粘贴').fontSize('16vp') - Text('None') - .fontSize('16vp') - .width(50) - .onClick(() => { - this.copyOption = CopyOptions.None - }) - .focusOnTouch(true) - .fontColor(this.fontColor39) - .onFocus(() => { - this.fontColor39 = Color.Red - }) - .onBlur(() => { - this.fontColor39 = Color.Black - }) - Text('InApp') - .fontSize('16vp') - .width(50) - .onClick(() => { - this.copyOption = CopyOptions.InApp - }) - .focusOnTouch(true) - .fontColor(this.fontColor40) - .onFocus(() => { - this.fontColor40 = Color.Red - }) - .onBlur(() => { - this.fontColor40 = Color.Black - }) - Text('LocalDevice') - .fontSize('16vp') - .width(50) - .onClick(() => { - this.copyOption = CopyOptions.LocalDevice - }) - .focusOnTouch(true) - .fontColor(this.fontColor41) - .onFocus(() => { - this.fontColor41 = Color.Red - }) - .onBlur(() => { - this.fontColor41 = Color.Black - }) - Text('CROSS_DEVICE') - .fontSize('16vp') - .width(50) - .onClick(() => { - this.copyOption = CopyOptions.CROSS_DEVICE - }) - .focusOnTouch(true) - .fontColor(this.fontColor42) - .onFocus(() => { - this.fontColor42 = Color.Red - }) - .onBlur(() => { - this.fontColor42 = Color.Black - }) - - } - } //复制粘贴 - ListItem() { - Row({ space: 20 }) { - Text('增加span') - .fontSize('16vp') - .fontSize('16vp') - .onClick(() => { - if (this.arr.length == 0) { - this.num = 0 - } else { - let len = this.arr.length - this.num = this.arr[len - 1] - } - this.arr.push(this.num) - }) - .focusOnTouch(true) - .fontColor(this.fontColor43) - .onFocus(() => { - this.fontColor43 = Color.Red - }) - .onBlur(() => { - this.fontColor43 = Color.Black - }) - Text('减少span') - .fontSize('16vp') - .onClick(() => { - if (this.arr.length > 0) { - this.arr.pop() - } - }) - .focusOnTouch(true) - .fontColor(this.fontColor44) - .onFocus(() => { - this.fontColor44 = Color.Red - }) - .onBlur(() => { - this.fontColor44 = Color.Black - }) - } - } //增加、减少Span - - ListItem() { - Column({ space: 10 }) { - TextArea({ text: this.text, controller: this.controller }) - .fontSize('16vp') - .onChange((value: string) => { - this.text = value - }) - } - } - - } - .height('45%') - - } - } -} +import font from '@ohos.font'; +import { LengthMetrics } from '@kit.ArkUI'; + + +@Entry +@Component +struct struct_02_TextSample_03_enablePreviewMenu { + controller: TextAreaController = new TextAreaController() + @State text: string = + '姓名:张三' + '\n' + '邮箱:12345@123.com' + '\n' + '电话号码:(86) (755) ********' + '\n' + + '网址:http://www.123.com' + + '\n' + '地址:中国北京市东城区天坛东路1号' + '\n' + '时间:2024年8月16号' + @State enableDataDetector1: boolean = true + @State types: TextDataDetectorType[] = + [TextDataDetectorType.PHONE_NUMBER, TextDataDetectorType.URL, TextDataDetectorType.EMAIL, + TextDataDetectorType.ADDRESS, TextDataDetectorType.DATE_TIME] + @State lineHeight1: number = 20 + @State type: TextDecorationType = TextDecorationType.None + @State AItype: TextDecorationType = TextDecorationType.Underline + @State AIDecorationColor: Color = Color.Green + @State AIDecorationStyle: TextDecorationStyle = TextDecorationStyle.SOLID + @State AIfontColor: Color = Color.Green + @State textfontColor: Color = Color.Red + @State TextDecorationColor: Color = Color.Black + @State letterSpacing: number = 5 + @State radius: number = 0 + @State fontColor: Color = Color.Red + @State fontColor1: Color = Color.Black + @State fontColor2: Color = Color.Black + @State fontColor3: Color = Color.Black + @State fontColor4: Color = Color.Black + @State fontColor5: Color = Color.Black + @State fontColor6: Color = Color.Black + @State fontColor7: Color = Color.Black + @State fontColor8: Color = Color.Black + @State fontColor9: Color = Color.Black + @State fontColor10: Color = Color.Black + @State fontColor11: Color = Color.Black + @State fontColor12: Color = Color.Black + @State fontColor13: Color = Color.Black + @State fontColor14: Color = Color.Black + @State fontColor15: Color = Color.Black + @State fontColor16: Color = Color.Black + @State fontColor17: Color = Color.Black + @State fontColor18: Color = Color.Black + @State fontColor19: Color = Color.Black + @State fontColor20: Color = Color.Black + @State fontColor21: Color = Color.Black + @State fontColor22: Color = Color.Black + @State fontColor23: Color = Color.Black + @State fontColor24: Color = Color.Black + @State fontColor25: Color = Color.Black + @State fontColor26: Color = Color.Black + @State fontColor27: Color = Color.Black + @State fontColor28: Color = Color.Black + @State fontColor29: Color = Color.Black + @State fontColor30: Color = Color.Black + @State fontColor31: Color = Color.Black + @State fontColor32: Color = Color.Black + @State fontColor33: Color = Color.Black + @State fontColor34: Color = Color.Black + @State fontColor35: Color = Color.Black + @State fontColor36: Color = Color.Black + @State fontColor37: Color = Color.Black + @State fontColor38: Color = Color.Black + @State fontColor39: Color = Color.Black + @State fontColor40: Color = Color.Black + @State fontColor41: Color = Color.Black + @State fontColor42: Color = Color.Black + @State fontColor43: Color = Color.Black + @State fontColor44: Color = Color.Black + @State fontColor45: Color = Color.Black + @State fontColor46: Color = Color.Black + @State fontColor47: Color = Color.Black + @State fontColor48: Color = Color.Black + @State fontColor49: Color = Color.Black + @State fontColor50: Color = Color.Black + @State fontColor51: Color = Color.Black + @State fontColor52: Color = Color.Black + @State fontColor53: Color = Color.Black + @State fontColor54: Color = Color.Black + @State fontColor55: Color = Color.Black + @State fontColor56: Color = Color.Black + @State fontColor57: Color = Color.Black + @State fontColor58: Color = Color.Black + @State fontColor59: Color = Color.Black + @State fontColor60: Color = Color.Black + @State fontColor61: Color = Color.Black + @State fontColor62: Color = Color.Black + @State fontColor63: Color = Color.Black + @State fontColor64: Color = Color.Black + @State fontColor65: Color = Color.Black + @State fontColor66: Color = Color.Black + @State fontColor67: Color = Color.Black + @State fontColor68: Color = Color.Black + @State fontColor69: Color = Color.Black + @State fontColor70: Color = Color.Black + @State fontSize1: number = 16 + @State maxLines: number = 8 + @State fontStyle: FontStyle = FontStyle.Normal + @State weight: FontWeight = FontWeight.Normal + @State overflow: TextOverflow = TextOverflow.None + @State copyOption: CopyOptions = CopyOptions.None + @State arr: number[] = [0] + @State num: number = 0 + scroller: Scroller = new Scroller() + + build() { + Column() { + Scroll(this.scroller) { + Text(this.text) { + ForEach(this.arr, (item: number) => { + Span(this.text) + }) + + } + .onTextSelectionChange((selectionStart: number, selectionEnd: number) => { + console.log("onTextSelectionChange:" + selectionStart + " --- " + selectionEnd) + }) + .border({ width: 1 }) + .enableDataDetector(this.enableDataDetector1) + .dataDetectorConfig({ + types: this.types, + onDetectResultUpdate: (result: string) => { + console.error('FAN, text', result); + }, + color: this.AIfontColor, + decoration: ({ + type: this.AItype, + color: this.AIDecorationColor, + style: this.AIDecorationStyle + }), + enablePreviewMenu: true + }) + // .textSelectable(TextSelectableMode.SELECTABLE_FOCUSABLE) + .lineHeight(this.lineHeight1) + .decoration({ type: this.type, color: this.TextDecorationColor }) + .letterSpacing(this.letterSpacing) + .textShadow({ radius: this.radius }) + .fontColor(this.textfontColor) + .font({ size: this.fontSize1, weight: this.weight, style: this.fontStyle }) + .textOverflow({ overflow: this.overflow }) + .draggable(undefined) + .copyOption(this.copyOption) + .width('90%') + // .focusable(true) + .maxLines(this.maxLines) + .padding(15) + .height(300) + + }.height('40%') + + TextArea().margin(10) + + List({ space: 10 }) { + ListItem() { + Row({ space: 10 }) { + Text('是否使用AI接口:').fontSize('16vp') + Text('是') + .fontSize('16vp') + .width(50) + .onClick(() => { + this.enableDataDetector1 = true + }) + .focusOnTouch(true) + .fontColor(this.fontColor1) + .onFocus(() => { + this.fontColor1 = Color.Red + }) + .onBlur(() => { + this.fontColor1 = Color.Black + }) + Text('否') + .fontSize('16vp') + .width(50) + .onClick(() => { + this.enableDataDetector1 = false + }) + .focusOnTouch(true) + .fontColor(this.fontColor2) + .onFocus(() => { + this.fontColor2 = Color.Red + }) + .onBlur(() => { + this.fontColor2 = Color.Black + }) + } + } //是否使用AI接口 + ListItem() { + Column({ space: 10 }) { + Row({ space: 10 }) { + Text('支持:').fontSize('16vp') + Text('电话号码') + .onClick(() => { + if (!this.types.some(item => item == TextDataDetectorType.PHONE_NUMBER)) { + this.types.push(TextDataDetectorType.PHONE_NUMBER) + } + }) + .focusOnTouch(true) + .fontColor(this.fontColor3) + .onFocus(() => { + this.fontColor3 = Color.Red + }) + .onBlur(() => { + this.fontColor3 = Color.Black + }) + .fontSize('16vp') + + Text('网址') + .onClick(() => { + if (!this.types.some(item => item == TextDataDetectorType.URL)) { + this.types.push(TextDataDetectorType.URL) + } + }) + .fontSize('16vp') + .focusOnTouch(true) + .fontColor(this.fontColor4) + .onFocus(() => { + this.fontColor4 = Color.Red + }) + .onBlur(() => { + this.fontColor4 = Color.Black + }) + + Text('邮箱') + .onClick(() => { + if (!this.types.some(item => item == TextDataDetectorType.EMAIL)) { + this.types.push(TextDataDetectorType.EMAIL) + } + }) + .fontSize('16vp') + .focusOnTouch(true) + .fontColor(this.fontColor5) + .onFocus(() => { + this.fontColor5 = Color.Red + }) + .onBlur(() => { + this.fontColor5 = Color.Black + }) + + Text('地址') + .fontSize('16vp') + .onClick(() => { + if (!this.types.some(item => item == TextDataDetectorType.ADDRESS)) { + this.types.push(TextDataDetectorType.ADDRESS) + } + }) + .focusOnTouch(true) + .fontColor(this.fontColor6) + .onFocus(() => { + this.fontColor6 = Color.Red + }) + .onBlur(() => { + this.fontColor6 = Color.Black + }) + + Text('时间') + .fontSize('16vp') + .onClick(() => { + if (!this.types.some(item => item == TextDataDetectorType.DATE_TIME)) { + this.types.push(TextDataDetectorType.DATE_TIME) + } + }) + .focusOnTouch(true) + .fontColor(this.fontColor7) + .onFocus(() => { + this.fontColor7 = Color.Red + }) + .onBlur(() => { + this.fontColor7 = Color.Black + }) + + } + + Row({ space: 10 }) { + Text('不支持:').fontSize('16vp') + Text('电话号码') + .fontSize('16vp') + .onClick(() => { + this.types = this.types.filter(item => item != TextDataDetectorType.PHONE_NUMBER) + }) + .focusOnTouch(true) + .fontColor(this.fontColor8) + .onFocus(() => { + this.fontColor8 = Color.Red + }) + .onBlur(() => { + this.fontColor8 = Color.Black + }) + + Text('网址') + .fontSize('16vp') + .onClick(() => { + this.types = this.types.filter(item => item != TextDataDetectorType.URL) + }) + .focusOnTouch(true) + .fontColor(this.fontColor9) + .onFocus(() => { + this.fontColor9 = Color.Red + }) + .onBlur(() => { + this.fontColor9 = Color.Black + }) + + Text('邮箱') + .fontSize('16vp') + .onClick(() => { + this.types = this.types.filter(item => item != TextDataDetectorType.EMAIL) + }) + .focusOnTouch(true) + .fontColor(this.fontColor10) + .onFocus(() => { + this.fontColor10 = Color.Red + }) + .onBlur(() => { + this.fontColor10 = Color.Black + }) + + + Text('地址') + .fontSize('16vp') + .onClick(() => { + this.types = this.types.filter(item => item != TextDataDetectorType.ADDRESS) + }) + .focusOnTouch(true) + .fontColor(this.fontColor11) + .onFocus(() => { + this.fontColor11 = Color.Red + }) + .onBlur(() => { + this.fontColor11 = Color.Black + }) + + Text('时间') + .fontSize('16vp') + .onClick(() => { + this.types = this.types.filter(item => item != TextDataDetectorType.DATE_TIME) + }) + .focusOnTouch(true) + .fontColor(this.fontColor12) + .onFocus(() => { + this.fontColor12 = Color.Red + }) + .onBlur(() => { + this.fontColor12 = Color.Black + }) + + } + } + + } //支持识别样式 + ListItem() { + Row({ space: 20 }) { + Text('行高:').fontSize('16vp') + Text('-') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.lineHeight1 = this.lineHeight1 - 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor13) + .onFocus(() => { + this.fontColor13 = Color.Red + }) + .onBlur(() => { + this.fontColor13 = Color.Black + }) + Text('' + this.lineHeight1) + .fontSize('16vp') + Text('+') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.lineHeight1 = this.lineHeight1 + 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor14) + .onFocus(() => { + this.fontColor14 = Color.Red + }) + .onBlur(() => { + this.fontColor14 = Color.Black + }) + + + } + } //不支持识别的样式 + ListItem() { + Row({ space: 10 }) { + Text('文本修饰线:').fontSize('16vp') + Text('None') + .fontSize("16vp") + .width(60) + .onClick(() => { + this.type = TextDecorationType.None + }) + .focusOnTouch(true) + .fontColor(this.fontColor15) + .onFocus(() => { + this.fontColor15 = Color.Red + }) + .onBlur(() => { + this.fontColor15 = Color.Black + }) + Text('上划线') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.type = TextDecorationType.Overline + }) + .focusOnTouch(true) + .fontColor(this.fontColor16) + .onFocus(() => { + this.fontColor16 = Color.Red + }) + .onBlur(() => { + this.fontColor16 = Color.Black + }) + Text('穿透线') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.type = TextDecorationType.LineThrough + }) + .focusOnTouch(true) + .fontColor(this.fontColor17) + .onFocus(() => { + this.fontColor17 = Color.Red + }) + .onBlur(() => { + this.fontColor17 = Color.Black + }) + Text('下划线') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.type = TextDecorationType.Underline + }) + .focusOnTouch(true) + .fontColor(this.fontColor18) + .onFocus(() => { + this.fontColor18 = Color.Red + }) + .onBlur(() => { + this.fontColor18 = Color.Black + }) + } + } //普通文本修饰线样式 + ListItem() { + Row({ space: 10 }) { + Text('修饰线颜色:').fontSize('16vp') + Text('黑色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.TextDecorationColor = Color.Black + }) + .focusOnTouch(true) + .fontColor(this.fontColor45) + .onFocus(() => { + this.fontColor45 = Color.Red + }) + .onBlur(() => { + this.fontColor45 = Color.Black + }) + Text('绿色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.TextDecorationColor = Color.Green + }) + .focusOnTouch(true) + .fontColor(this.fontColor46) + .onFocus(() => { + this.fontColor46 = Color.Red + }) + .onBlur(() => { + this.fontColor46 = Color.Black + }) + Text('蓝色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.TextDecorationColor = Color.Blue + }) + .focusOnTouch(true) + .fontColor(this.fontColor47) + .onFocus(() => { + this.fontColor47 = Color.Red + }) + .onBlur(() => { + this.fontColor47 = Color.Black + }) + Text('红色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.TextDecorationColor = Color.Red + }) + .focusOnTouch(true) + .fontColor(this.fontColor48) + .onFocus(() => { + this.fontColor48 = Color.Red + }) + .onBlur(() => { + this.fontColor48 = Color.Black + }) + } + } //普通文本修饰线颜色 + ListItem() { + Row({ space: 10 }) { + Text('AI修饰线样式:').fontSize('16vp') + Text('None') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AItype = TextDecorationType.None + }) + .focusOnTouch(true) + .fontColor(this.fontColor49) + .onFocus(() => { + this.fontColor49 = Color.Red + }) + .onBlur(() => { + this.fontColor49 = Color.Black + }) + Text('上划线') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AItype = TextDecorationType.Overline + }) + .focusOnTouch(true) + .fontColor(this.fontColor50) + .onFocus(() => { + this.fontColor50 = Color.Red + }) + .onBlur(() => { + this.fontColor50 = Color.Black + }) + Text('穿透线') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AItype = TextDecorationType.LineThrough + }) + .focusOnTouch(true) + .fontColor(this.fontColor51) + .onFocus(() => { + this.fontColor51 = Color.Red + }) + .onBlur(() => { + this.fontColor51 = Color.Black + }) + Text('下划线') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AItype = TextDecorationType.Underline + }) + .focusOnTouch(true) + .fontColor(this.fontColor52) + .onFocus(() => { + this.fontColor52 = Color.Red + }) + .onBlur(() => { + this.fontColor52 = Color.Black + }) + } + } //AI文本修饰线样式 + + ListItem() { + Row({ space: 10 }) { + Text('AI修饰线颜色:').fontSize('16vp') + Text('黑色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationColor = Color.Black + }) + .focusOnTouch(true) + .fontColor(this.fontColor53) + .onFocus(() => { + this.fontColor53 = Color.Red + }) + .onBlur(() => { + this.fontColor53 = Color.Black + }) + Text('绿色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationColor = Color.Green + }) + .focusOnTouch(true) + .fontColor(this.fontColor54) + .onFocus(() => { + this.fontColor54 = Color.Red + }) + .onBlur(() => { + this.fontColor54 = Color.Black + }) + Text('蓝色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationColor = Color.Blue + }) + .focusOnTouch(true) + .fontColor(this.fontColor55) + .onFocus(() => { + this.fontColor55 = Color.Red + }) + .onBlur(() => { + this.fontColor55 = Color.Black + }) + Text('红色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationColor = Color.Red + }) + .focusOnTouch(true) + .fontColor(this.fontColor56) + .onFocus(() => { + this.fontColor56 = Color.Red + }) + .onBlur(() => { + this.fontColor56 = Color.Black + }) + } + } //AI修饰线颜色 + ListItem() { + Row({ space: 10 }) { + Text('AI修饰线类型:').fontSize('16vp') + Text('SOLID') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationStyle = TextDecorationStyle.SOLID + }) + .focusOnTouch(true) + .fontColor(this.fontColor65) + .onFocus(() => { + this.fontColor65 = Color.Red + }) + .onBlur(() => { + this.fontColor65 = Color.Black + }) + Text('DOUBLE') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationStyle = TextDecorationStyle.DOUBLE + }) + .focusOnTouch(true) + .fontColor(this.fontColor66) + .onFocus(() => { + this.fontColor66 = Color.Red + }) + .onBlur(() => { + this.fontColor66 = Color.Black + }) + Text('DOTTED') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationStyle = TextDecorationStyle.DOTTED + }) + .focusOnTouch(true) + .fontColor(this.fontColor67) + .onFocus(() => { + this.fontColor67 = Color.Red + }) + .onBlur(() => { + this.fontColor67 = Color.Black + }) + Text('DASHED') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationStyle = TextDecorationStyle.DASHED + }) + .focusOnTouch(true) + .fontColor(this.fontColor68) + .onFocus(() => { + this.fontColor68 = Color.Red + }) + .onBlur(() => { + this.fontColor68 = Color.Black + }) + + + } + + } //AI修饰线类型 + + ListItem() { + + Text('WAVY') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIDecorationStyle = TextDecorationStyle.WAVY + }) + .focusOnTouch(true) + .fontColor(this.fontColor69) + .onFocus(() => { + this.fontColor69 = Color.Red + }) + .onBlur(() => { + this.fontColor69 = Color.Black + }) + + } + + ListItem() { + Row({ space: 10 }) { + Text('AI字体颜色:').fontSize('16vp') + Text('黑色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIfontColor = Color.Black + }) + .focusOnTouch(true) + .fontColor(this.fontColor57) + .onFocus(() => { + this.fontColor57 = Color.Red + }) + .onBlur(() => { + this.fontColor57 = Color.Black + }) + Text('绿色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIfontColor = Color.Green + }) + .focusOnTouch(true) + .fontColor(this.fontColor58) + .onFocus(() => { + this.fontColor58 = Color.Red + }) + .onBlur(() => { + this.fontColor58 = Color.Black + }) + Text('蓝色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIfontColor = Color.Blue + }) + .focusOnTouch(true) + .fontColor(this.fontColor59) + .onFocus(() => { + this.fontColor59 = Color.Red + }) + .onBlur(() => { + this.fontColor59 = Color.Black + }) + Text('红色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.AIfontColor = Color.Red + }) + .focusOnTouch(true) + .fontColor(this.fontColor60) + .onFocus(() => { + this.fontColor60 = Color.Red + }) + .onBlur(() => { + this.fontColor60 = Color.Black + }) + } + } //AI文本字体颜色 + ListItem() { + Row({ space: 20 }) { + Text('文本字符间距:').fontSize('16vp') + Text('-') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.letterSpacing = this.letterSpacing - 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor19) + .onFocus(() => { + this.fontColor19 = Color.Red + }) + .onBlur(() => { + this.fontColor19 = Color.Black + }) + Text('' + this.letterSpacing) + .fontSize('16vp') + Text('+') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.letterSpacing = this.letterSpacing + 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor20) + .onFocus(() => { + this.fontColor20 = Color.Red + }) + .onBlur(() => { + this.fontColor20 = Color.Black + }) + + + } + } //文本字符间距 + ListItem() { + Row({ space: 20 }) { + Text('阴影模糊半径:').fontSize('16vp') + Text('-') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.radius = this.radius - 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor21) + .onFocus(() => { + this.fontColor21 = Color.Red + }) + .onBlur(() => { + this.fontColor21 = Color.Black + }) + Text('' + this.radius) + .fontSize('16vp') + Text('+') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.radius = this.radius + 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor22) + .onFocus(() => { + this.fontColor22 = Color.Red + }) + .onBlur(() => { + this.fontColor22 = Color.Black + }) + + + } + } //阴影模糊半径 + ListItem() { + Row({ space: 20 }) { + Text('字体大小').fontSize('16vp') + Text('-') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.fontSize1 = this.fontSize1 - 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor23) + .onFocus(() => { + this.fontColor23 = Color.Red + }) + .onBlur(() => { + this.fontColor23 = Color.Black + }) + Text('' + this.fontSize1) + .fontSize('16vp') + Text('+') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.fontSize1 = this.fontSize1 + 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor24) + .onFocus(() => { + this.fontColor24 = Color.Red + }) + .onBlur(() => { + this.fontColor24 = Color.Black + }) + + + } + } //字体大小 + ListItem() { + Row({ space: 10 }) { + Text('字体颜色:').fontSize('16vp') + Text('黑色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.textfontColor = Color.Black + }) + .focusOnTouch(true) + .fontColor(this.fontColor61) + .onFocus(() => { + this.fontColor61 = Color.Red + }) + .onBlur(() => { + this.fontColor61 = Color.Black + }) + Text('绿色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.textfontColor = Color.Green + }) + .focusOnTouch(true) + .fontColor(this.fontColor62) + .onFocus(() => { + this.fontColor62 = Color.Red + }) + .onBlur(() => { + this.fontColor62 = Color.Black + }) + Text('蓝色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.textfontColor = Color.Blue + }) + .focusOnTouch(true) + .fontColor(this.fontColor63) + .onFocus(() => { + this.fontColor63 = Color.Red + }) + .onBlur(() => { + this.fontColor63 = Color.Black + }) + Text('红色') + .fontSize('16vp') + .width(60) + .onClick(() => { + this.textfontColor = Color.Red + }) + .focusOnTouch(true) + .fontColor(this.fontColor64) + .onFocus(() => { + this.fontColor64 = Color.Red + }) + .onBlur(() => { + this.fontColor64 = Color.Black + }) + } + } //字体颜色 + ListItem() { + Row({ space: 20 }) { + Text('字体样式').fontSize('16vp') + Text('Normal') + .fontSize('16vp') + .onClick(() => { + this.fontStyle = FontStyle.Normal + }) + .focusOnTouch(true) + .fontColor(this.fontColor25) + .onFocus(() => { + this.fontColor25 = Color.Red + }) + .onBlur(() => { + this.fontColor25 = Color.Black + }) + Text('Italic') + .fontSize('16vp') + .onClick(() => { + this.fontStyle = FontStyle.Italic + }) + .focusOnTouch(true) + .fontColor(this.fontColor26) + .onFocus(() => { + this.fontColor26 = Color.Red + }) + .onBlur(() => { + this.fontColor26 = Color.Black + }) + + } + } //字体样式 + ListItem() { + Row({ space: 5 }) { + Text('字体粗细:').fontSize('16vp') + Column({ space: 10 }) { + Text('Lighter') + .fontSize('16vp') + .onClick(() => { + this.weight = FontWeight.Lighter + }) + .focusOnTouch(true) + .fontColor(this.fontColor27) + .onFocus(() => { + this.fontColor27 = Color.Red + }) + .onBlur(() => { + this.fontColor27 = Color.Black + }) + Text('Normal') + .fontSize('16vp') + .onClick(() => { + this.weight = FontWeight.Normal + }) + .focusOnTouch(true) + .fontColor(this.fontColor28) + .onFocus(() => { + this.fontColor28 = Color.Red + }) + .onBlur(() => { + this.fontColor28 = Color.Black + }) + Text('Regular') + .fontSize('16vp') + .onClick(() => { + this.weight = FontWeight.Regular + }) + .focusOnTouch(true) + .fontColor(this.fontColor29) + .onFocus(() => { + this.fontColor29 = Color.Red + }) + .onBlur(() => { + this.fontColor29 = Color.Black + }) + Text('Medium') + .fontSize('16vp') + .onClick(() => { + this.weight = FontWeight.Medium + }) + .focusOnTouch(true) + .fontColor(this.fontColor30) + .onFocus(() => { + this.fontColor30 = Color.Red + }) + .onBlur(() => { + this.fontColor30 = Color.Black + }) + Text('Bold') + .fontSize('16vp') + .onClick(() => { + this.weight = FontWeight.Bold + }) + .focusOnTouch(true) + .fontColor(this.fontColor31) + .onFocus(() => { + this.fontColor31 = Color.Red + }) + .onBlur(() => { + this.fontColor31 = Color.Black + }) + Text('Bolder') + .fontSize('16vp') + .onClick(() => { + this.weight = FontWeight.Bolder + }) + .focusOnTouch(true) + .fontColor(this.fontColor32) + .onFocus(() => { + this.fontColor32 = Color.Red + }) + .onBlur(() => { + this.fontColor32 = Color.Black + }) + } + + } + } //字体粗细 + ListItem() { + Row({ space: 5 }) { + Text('超长文本显示方式:').fontSize('16vp') + Column({ space: 10 }) { + Text('None') + .fontSize('16vp') + .onClick(() => { + this.overflow = TextOverflow.None + }) + .focusOnTouch(true) + .fontColor(this.fontColor33) + .onFocus(() => { + this.fontColor33 = Color.Red + }) + .onBlur(() => { + this.fontColor33 = Color.Black + }) + Text('裁剪') + .fontSize('16vp') + .onClick(() => { + this.overflow = TextOverflow.Clip + }) + .focusOnTouch(true) + .fontColor(this.fontColor34) + .onFocus(() => { + this.fontColor34 = Color.Red + }) + .onBlur(() => { + this.fontColor34 = Color.Black + }) + Text('省略号') + .fontSize('16vp') + .onClick(() => { + this.overflow = TextOverflow.Ellipsis + }) + .focusOnTouch(true) + .fontColor(this.fontColor35) + .onFocus(() => { + this.fontColor35 = Color.Red + }) + .onBlur(() => { + this.fontColor35 = Color.Black + }) + Text('跑马灯') + .fontSize('16vp') + .onClick(() => { + this.overflow = TextOverflow.MARQUEE + }) + .focusOnTouch(true) + .fontColor(this.fontColor36) + .onFocus(() => { + this.fontColor36 = Color.Red + }) + .onBlur(() => { + this.fontColor36 = Color.Black + }) + + } + + } + } //超长文本显示样式 + ListItem() { + Row({ space: 20 }) { + Text('最大行数:').fontSize('16vp') + Text('-') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.maxLines = this.maxLines - 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor37) + .onFocus(() => { + this.fontColor37 = Color.Red + }) + .onBlur(() => { + this.fontColor37 = Color.Black + }) + Text('' + this.maxLines) + .fontSize('16vp') + Text('+') + .fontSize('16vp') + .width(20) + .onClick(() => { + this.maxLines = this.maxLines + 1 + }) + .focusOnTouch(true) + .fontColor(this.fontColor38) + .onFocus(() => { + this.fontColor38 = Color.Red + }) + .onBlur(() => { + this.fontColor38 = Color.Black + }) + + + } + } //最大行数 + ListItem() { + Row({ space: 10 }) { + Text('文本是否可复制粘贴').fontSize('16vp') + Text('None') + .fontSize('16vp') + .width(50) + .onClick(() => { + this.copyOption = CopyOptions.None + }) + .focusOnTouch(true) + .fontColor(this.fontColor39) + .onFocus(() => { + this.fontColor39 = Color.Red + }) + .onBlur(() => { + this.fontColor39 = Color.Black + }) + Text('InApp') + .fontSize('16vp') + .width(50) + .onClick(() => { + this.copyOption = CopyOptions.InApp + }) + .focusOnTouch(true) + .fontColor(this.fontColor40) + .onFocus(() => { + this.fontColor40 = Color.Red + }) + .onBlur(() => { + this.fontColor40 = Color.Black + }) + Text('LocalDevice') + .fontSize('16vp') + .width(50) + .onClick(() => { + this.copyOption = CopyOptions.LocalDevice + }) + .focusOnTouch(true) + .fontColor(this.fontColor41) + .onFocus(() => { + this.fontColor41 = Color.Red + }) + .onBlur(() => { + this.fontColor41 = Color.Black + }) + Text('CROSS_DEVICE') + .fontSize('16vp') + .width(50) + .onClick(() => { + this.copyOption = CopyOptions.CROSS_DEVICE + }) + .focusOnTouch(true) + .fontColor(this.fontColor42) + .onFocus(() => { + this.fontColor42 = Color.Red + }) + .onBlur(() => { + this.fontColor42 = Color.Black + }) + + } + } //复制粘贴 + ListItem() { + Row({ space: 20 }) { + Text('增加span') + .fontSize('16vp') + .fontSize('16vp') + .onClick(() => { + if (this.arr.length == 0) { + this.num = 0 + } else { + let len = this.arr.length + this.num = this.arr[len - 1] + } + this.arr.push(this.num) + }) + .focusOnTouch(true) + .fontColor(this.fontColor43) + .onFocus(() => { + this.fontColor43 = Color.Red + }) + .onBlur(() => { + this.fontColor43 = Color.Black + }) + Text('减少span') + .fontSize('16vp') + .onClick(() => { + if (this.arr.length > 0) { + this.arr.pop() + } + }) + .focusOnTouch(true) + .fontColor(this.fontColor44) + .onFocus(() => { + this.fontColor44 = Color.Red + }) + .onBlur(() => { + this.fontColor44 = Color.Black + }) + } + } //增加、减少Span + + ListItem() { + Column({ space: 10 }) { + TextArea({ text: this.text, controller: this.controller }) + .fontSize('16vp') + .onChange((value: string) => { + this.text = value + }) + } + } + + } + .height('45%') + + } + } +} diff --git a/test/unittest/core/pattern/ui_extension/dynamic_component/dynamic_pattern_test_two.cpp b/test/unittest/core/pattern/ui_extension/dynamic_component/dynamic_pattern_test_two.cpp index ee435b9f6735a326180b53bfc0c8e370c59fc2d5..89eb479e4af14e323038b6694ceb92a7694f79c0 100644 --- a/test/unittest/core/pattern/ui_extension/dynamic_component/dynamic_pattern_test_two.cpp +++ b/test/unittest/core/pattern/ui_extension/dynamic_component/dynamic_pattern_test_two.cpp @@ -1,620 +1,620 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "gtest/gtest.h" -#include "base/memory/ace_type.h" -#define private public -#define protected public -#include "accessibility_element_info.h" -#include "adapter/ohos/entrance/dynamic_component/dynamic_component_renderer_impl.h" -#include "adapter/ohos/entrance/mmi_event_convertor.h" -#include "adapter/ohos/osal/want_wrap_ohos.h" -#include "core/common/window.h" -#include "core/components_ng/base/view_stack_processor.h" -#include "core/components_ng/pattern/ui_extension/dynamic_component/dynamic_pattern.h" -#include "core/components_ng/pattern/ui_extension/session_wrapper.h" -#include "core/components_ng/pattern/ui_extension/ui_extension_model.h" -#include "core/components_ng/pattern/ui_extension/ui_extension_model_ng.h" -#include "frameworks/core/components_ng/pattern/ui_extension/platform_pattern.h" -#include "frameworks/core/event/pointer_event.h" -#include "test/mock/base/mock_task_executor.h" -#include "test/mock/core/common/mock_container.h" -#include "test/mock/core/pipeline/mock_pipeline_context.h" -#include "test/mock/core/common/mock_frontend.h" - -using namespace testing; -using namespace testing::ext; - -namespace OHOS::Ace::NG { -namespace { - const std::string DYNAMIC_COMPONENT_ETS_TAG = "DynamicComponent"; - const std::string TAG = "Test node tag"; -} // namespace - -class DynamicPatternTestNgTwo : public testing::Test { -public: - void SetUp() override; - void TearDown() override; - void JsonExpect(std::unique_ptr& json, - RefPtr dynamicPattern); -}; - -void DynamicPatternTestNgTwo::SetUp() -{ - MockPipelineContext::SetUp(); - MockContainer::SetUp(); - MockContainer::Current()->pipelineContext_ = PipelineBase::GetCurrentContext(); -} - -void DynamicPatternTestNgTwo::TearDown() -{ - MockContainer::Current()->pipelineContext_ = nullptr; - MockPipelineContext::TearDown(); -} - -/** - * @tc.name: DynamicPatternTest001 - * @tc.desc: Test DynamicPattern OnFrameNodeChanged - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest001, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - - /** - * @tc.steps: step2. call OnFrameNodeChanged. - */ - FrameNodeChangeInfoFlag flag = FRAME_NODE_CHANGE_INFO_NONE; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); - - flag = FRAME_NODE_CHANGE_START_SCROLL; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); - - flag = FRAME_NODE_CHANGE_END_SCROLL; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); - - flag = FRAME_NODE_CHANGE_START_ANIMATION; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); - - flag = FRAME_NODE_CHANGE_GEOMETRY_CHANGE; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); - - flag = FRAME_NODE_CHANGE_TRANSFORM_CHANGE; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); - - flag = FRAME_NODE_CHANGE_TRANSITION_START; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); - - flag = FRAME_NODE_CONTENT_CLIP_CHANGE; - dynamicPattern->OnFrameNodeChanged(flag); - EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); - EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); -} - -/** - * @tc.name: DynamicPatternTest002 - * @tc.desc: Test DynamicPattern IsAncestorNodeGeometryChange - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest002, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - - /** - * @tc.steps: step2. call IsAncestorNodeGeometryChange. - */ - FrameNodeChangeInfoFlag flag = FRAME_NODE_CHANGE_GEOMETRY_CHANGE | FRAME_NODE_CHANGE_TRANSFORM_CHANGE; - bool result = dynamicPattern->IsAncestorNodeGeometryChange(flag); - EXPECT_TRUE(result); - - flag = FRAME_NODE_CHANGE_TRANSFORM_CHANGE; - result = dynamicPattern->IsAncestorNodeGeometryChange(flag); - EXPECT_FALSE(result); -} - -/** - * @tc.name: DynamicPatternTest003 - * @tc.desc: Test DynamicPattern IsAncestorNodeTransformChange - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest003, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - - /** - * @tc.steps: step2. call IsAncestorNodeTransformChange. - */ - FrameNodeChangeInfoFlag flag = FRAME_NODE_CHANGE_TRANSFORM_CHANGE | FRAME_NODE_CHANGE_GEOMETRY_CHANGE; - bool result = dynamicPattern->IsAncestorNodeTransformChange(flag); - EXPECT_TRUE(result); - - flag = FRAME_NODE_CHANGE_GEOMETRY_CHANGE; - result = dynamicPattern->IsAncestorNodeTransformChange(flag); - EXPECT_FALSE(result); -} - -/** - * @tc.name: DynamicPatternTest004 - * @tc.desc: Test DynamicPattern OnDetachContext - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest004, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - auto pipeline = MockPipelineContext::GetCurrent(); - EXPECT_NE(pipeline, nullptr); - - /** - * @tc.steps: step2. call OnDetachContext. - */ - auto host = dynamicPattern->GetHost(); - EXPECT_NE(host, nullptr); - pipeline->SetInstanceId(123); - auto rawPipeline = reinterpret_cast(Referenced::RawPtr(pipeline)); - dynamicPattern->OnDetachContext(rawPipeline); - dynamicPattern->OnDetachContext(nullptr); - - dynamicPattern->host_ = nullptr; - dynamicPattern->OnDetachContext(rawPipeline); - dynamicPattern->OnDetachContext(nullptr); -} - -/** - * @tc.name: DynamicPatternTest005 - * @tc.desc: Test DynamicPattern UnregisterSingleHandTransformChangedCallback - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest005, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - auto pipeline = MockPipelineContext::GetCurrent(); - EXPECT_NE(pipeline, nullptr); - - /** - * @tc.steps: step2. call UnregisterSingleHandTransformChangedCallback. - */ - auto host = dynamicPattern->GetHost(); - EXPECT_NE(host, nullptr); - int32_t instanceId = 1; - dynamicPattern->UnRegisterSingleHandTransformChangedCallback(instanceId); - - dynamicPattern->host_ = nullptr; - dynamicPattern->UnRegisterSingleHandTransformChangedCallback(instanceId); -} - -/** - * @tc.name: DynamicPatternTest006 - * @tc.desc: Test DynamicPattern UnRegisterAccessibilitySAObserverCallback - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest006, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - auto pipeline = MockPipelineContext::GetCurrent(); - EXPECT_NE(pipeline, nullptr); - - /** - * @tc.steps: step2. call UnRegisterAccessibilitySAObserverCallback. - */ - auto host = dynamicPattern->GetHost(); - EXPECT_NE(host, nullptr); - int32_t instanceId = 1; - auto frontend = pipeline->GetFrontend(); - EXPECT_EQ(frontend, nullptr); - frontend = AceType::MakeRefPtr(); - pipeline->weakFrontend_ = frontend; - dynamicPattern->UnRegisterAccessibilitySAObserverCallback(instanceId); - - pipeline->weakFrontend_ = nullptr; - dynamicPattern->host_ = nullptr; - dynamicPattern->UnRegisterAccessibilitySAObserverCallback(instanceId); -} - -/** - * @tc.name: DynamicPatternTest007 - * @tc.desc: Test DynamicPattern RegisterPipelineEvent - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest007, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - - /** - * @tc.steps: step2. call RegisterPipelineEvent. - */ - EXPECT_NE(dynamicPattern->frameNode_.Upgrade(), nullptr); - auto frameNode = FrameNode::CreateFrameNode(V2::DYNAMIC_COMPONENT_TAG, 0, dynamicPattern); - dynamicPattern->host_ = frameNode; - int32_t instanceId = 1; - auto context = PipelineContext::GetContextByContainerId(instanceId); - CHECK_NULL_VOID(context); - auto uiExtManager = context->GetUIExtensionManager(); - CHECK_NULL_VOID(uiExtManager); - context->uiExtensionManager_ = nullptr; - dynamicPattern->RegisterPipelineEvent(instanceId); - - EXPECT_NE(dynamicPattern->host_.Upgrade(), nullptr); - dynamicPattern->RegisterSingleHandTransformChangedCallback(instanceId); -} - -/** - * @tc.name: DynamicPatternTest008 - * @tc.desc: Test DynamicPattern ResetAccessibilityChildTreeCallback - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest008, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - dynamicPattern->accessibilityChildTreeCallback_ = - std::make_shared(dynamicPattern, 1); - dynamicPattern->instanceId_ = 1; - auto host = dynamicPattern->GetHost(); - EXPECT_NE(host, nullptr); - EXPECT_NE(dynamicPattern->accessibilityChildTreeCallback_, nullptr); - auto pipeline = NG::PipelineContext::GetCurrentContext(); - EXPECT_NE(pipeline, nullptr); - auto frontend = pipeline->GetFrontend(); - EXPECT_EQ(frontend, nullptr); - frontend = AceType::MakeRefPtr(); - /** - * @tc.steps: step2. call ResetAccessibilityChildTreeCallback. - */ - dynamicPattern->ResetAccessibilityChildTreeCallback(); - EXPECT_NE(dynamicPattern->accessibilityChildTreeCallback_, nullptr); - - dynamicPattern->accessibilityChildTreeCallback_ = - std::make_shared(dynamicPattern, 1); - - dynamicPattern->host_ = nullptr; - dynamicPattern->ResetAccessibilityChildTreeCallback(); - EXPECT_NE(dynamicPattern->accessibilityChildTreeCallback_, nullptr); -} - -/** - * @tc.name: DynamicPatternTest009 - * @tc.desc: Test DynamicPattern AddToPageEventController - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest009, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - auto host = dynamicPattern->GetHost(); - EXPECT_NE(host, nullptr); - dynamicPattern->instanceId_ = 100000; - - /** - * @tc.steps: step2. call ResetAccessibilityChildTreeCallback. - */ - auto pipeline = host->GetContext(); - EXPECT_NE(pipeline, nullptr); - auto frontend = pipeline->GetFrontend(); - EXPECT_EQ(frontend, nullptr); - frontend = AceType::MakeRefPtr(); - pipeline->weakFrontend_ = frontend; - dynamicPattern->AddToPageEventController(); - - dynamicPattern->host_ = nullptr; - dynamicPattern->AddToPageEventController(); -} - -void DynamicPatternTestNgTwo::JsonExpect(std::unique_ptr& json, RefPtr dynamicPattern) -{ - EXPECT_NE(dynamicPattern->dynamicComponentRenderer_, nullptr); - dynamicPattern->DumpInfo(json); - - const auto& dynamicId = json->GetValue("dynamicId"); - bool hasDynamicId = !(dynamicId->IsNull()); - EXPECT_FALSE(hasDynamicId); - - const auto& resourcePath = json->GetValue("resourcePath"); - bool hasResourcePath = !(resourcePath->IsNull()); - EXPECT_FALSE(hasResourcePath); - - const auto& entryPoint = json->GetValue("entryPoint"); - bool hasEntryPoint = !(entryPoint->IsNull()); - EXPECT_FALSE(hasEntryPoint); - - const auto& createLimitedWorkerTime = json->GetValue("createLimitedWorkerTime"); - bool hasCreateLimitedWorkerTime = !(createLimitedWorkerTime->IsNull()); - EXPECT_FALSE(hasCreateLimitedWorkerTime); - - const auto& createUiContenTime = json->GetValue("createUiContenTime"); - bool hasCreateUiContenTime = !(createUiContenTime->IsNull()); - EXPECT_FALSE(hasCreateUiContenTime); - - const auto& limitedWorkerInitTime = json->GetValue("limitedWorkerInitTime"); - bool hasLimitedWorkerInitTime = !(limitedWorkerInitTime->IsNull()); - EXPECT_FALSE(hasLimitedWorkerInitTime); - - const auto& loadAbcTime = json->GetValue("loadAbcTime"); - bool hasLoadAbcTime = !(loadAbcTime->IsNull()); - EXPECT_FALSE(hasLoadAbcTime); - - const auto& isReportFrameEvent = json->GetValue("isReportFrameEvent"); - bool hasIsReportFrameEvent = !(isReportFrameEvent->IsNull()); - EXPECT_FALSE(hasIsReportFrameEvent); -} - -/** - * @tc.name: DynamicPatternTest010 - * @tc.desc: Test DynamicPattern DumpInfo - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest010, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - - std::unique_ptr json = std::make_unique(); - dynamicPattern->platformId_ = 123; - dynamicPattern->curDynamicInfo_.resourcePath = "test/path"; - dynamicPattern->curDynamicInfo_.entryPoint = "test/entry"; - dynamicPattern->dynamicDumpInfo_.createLimitedWorkerTime = 100; - dynamicPattern->hostConfig_.isReportFrameEvent = true; - IsolatedInfo curIsolatedInfo; - void* runtime = nullptr; - dynamicPattern->dynamicComponentRenderer_ = DynamicComponentRenderer::Create( - dynamicNode, runtime, curIsolatedInfo); - RendererDumpInfo rendererDumpInfo; - rendererDumpInfo.createUiContenTime = 200; - rendererDumpInfo.limitedWorkerInitTime = 300; - rendererDumpInfo.loadAbcTime = 400; - - /** - * @tc.steps: step2. call DumpInfo. - */ - JsonExpect(json, dynamicPattern); -} - -/** - * @tc.name: DynamicPatternTest011 - * @tc.desc: Test DynamicPattern DumpInfo - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest011, TestSize.Level1) -{ - /** - * @tc.steps: step1. get DynamicPattern - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - - dynamicPattern->platformId_ = 123; - dynamicPattern->curDynamicInfo_.entryPoint = "test/entry"; - dynamicPattern->dynamicDumpInfo_.createLimitedWorkerTime = 100; - dynamicPattern->hostConfig_.isReportFrameEvent = true; - IsolatedInfo curIsolatedInfo; - void* runtime = nullptr; - dynamicPattern->dynamicComponentRenderer_ = DynamicComponentRenderer::Create( - dynamicNode, runtime, curIsolatedInfo); - RendererDumpInfo rendererDumpInfo; - rendererDumpInfo.createUiContenTime = 200; - rendererDumpInfo.limitedWorkerInitTime = 300; - rendererDumpInfo.loadAbcTime = 400; - - /** - * @tc.steps: step2. call DumpInfo. - */ - EXPECT_NE(dynamicPattern->dynamicComponentRenderer_, nullptr); - dynamicPattern->DumpInfo(); - - ASSERT_EQ(DumpLog::GetInstance().description_.size(), 7); - EXPECT_EQ(DumpLog::GetInstance().description_[0], "dynamicId: 123\n"); - EXPECT_EQ(DumpLog::GetInstance().description_[1], "entryPoint: test/entry\n"); - EXPECT_EQ(DumpLog::GetInstance().description_[2], "createLimitedWorkerTime: 100\n"); - EXPECT_EQ(DumpLog::GetInstance().description_[3], "createUiContenTime: 0\n"); - EXPECT_EQ(DumpLog::GetInstance().description_[4], "limitedWorkerInitTime: 0\n"); - EXPECT_EQ(DumpLog::GetInstance().description_[5], "loadAbcTime: 0\n"); - EXPECT_EQ(DumpLog::GetInstance().description_[6], "isReportFrameEvent: true\n"); -} - -/** - * @tc.name: DynamicPatternTest012 - * @tc.desc: Test DynamicPattern OnAttachContext - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest012, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create DynamicPattern and set initial instanceId. - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - - int oldInstanceId = 123; - int newInstanceId = 124; - dynamicPattern->instanceId_ = oldInstanceId; - auto pipeline = MockPipelineContext::GetCurrent(); - EXPECT_NE(pipeline, nullptr); - pipeline->SetInstanceId(124); - - /** - * @tc.steps: step2. Call OnAttachContext with nullptr context. - */ - pipeline->uiExtensionManager_ = nullptr; - auto rawPipeline = reinterpret_cast(Referenced::RawPtr(pipeline)); - dynamicPattern->OnAttachContext(nullptr); - EXPECT_EQ(dynamicPattern->instanceId_, oldInstanceId); - - dynamicPattern->OnAttachContext(rawPipeline); - EXPECT_NE(dynamicPattern->instanceId_, oldInstanceId); - EXPECT_EQ(dynamicPattern->instanceId_, newInstanceId); -} - -/** - * @tc.name: DynamicPatternTest013 - * @tc.desc: Test DynamicPattern SetIsReportFrameEvent - * @tc.type: FUNC - */ -HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest013, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create DynamicPattern and set initial instanceId. - */ - auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); - auto dynamicNode = FrameNode::GetOrCreateFrameNode( - DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { - return AceType::MakeRefPtr(); - }); - EXPECT_NE(dynamicNode, nullptr); - EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); - auto dynamicPattern = dynamicNode->GetPattern(); - EXPECT_NE(dynamicPattern, nullptr); - EXPECT_FALSE(dynamicPattern->hostConfig_.isReportFrameEvent); - - /** - * @tc.steps: step2. Call SetIsReportFrameEvent - */ - dynamicPattern->SetIsReportFrameEvent(true); - EXPECT_TRUE(dynamicPattern->hostConfig_.isReportFrameEvent); -} -} // namespace OHOS::Ace::NG +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include "base/memory/ace_type.h" +#define private public +#define protected public +#include "accessibility_element_info.h" +#include "adapter/ohos/entrance/dynamic_component/dynamic_component_renderer_impl.h" +#include "adapter/ohos/entrance/mmi_event_convertor.h" +#include "adapter/ohos/osal/want_wrap_ohos.h" +#include "core/common/window.h" +#include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/pattern/ui_extension/dynamic_component/dynamic_pattern.h" +#include "core/components_ng/pattern/ui_extension/session_wrapper.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_model.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_model_ng.h" +#include "frameworks/core/components_ng/pattern/ui_extension/platform_pattern.h" +#include "frameworks/core/event/pointer_event.h" +#include "test/mock/base/mock_task_executor.h" +#include "test/mock/core/common/mock_container.h" +#include "test/mock/core/pipeline/mock_pipeline_context.h" +#include "test/mock/core/common/mock_frontend.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS::Ace::NG { +namespace { + const std::string DYNAMIC_COMPONENT_ETS_TAG = "DynamicComponent"; + const std::string TAG = "Test node tag"; +} // namespace + +class DynamicPatternTestNgTwo : public testing::Test { +public: + void SetUp() override; + void TearDown() override; + void JsonExpect(std::unique_ptr& json, + RefPtr dynamicPattern); +}; + +void DynamicPatternTestNgTwo::SetUp() +{ + MockPipelineContext::SetUp(); + MockContainer::SetUp(); + MockContainer::Current()->pipelineContext_ = PipelineBase::GetCurrentContext(); +} + +void DynamicPatternTestNgTwo::TearDown() +{ + MockContainer::Current()->pipelineContext_ = nullptr; + MockPipelineContext::TearDown(); +} + +/** + * @tc.name: DynamicPatternTest001 + * @tc.desc: Test DynamicPattern OnFrameNodeChanged + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + + /** + * @tc.steps: step2. call OnFrameNodeChanged. + */ + FrameNodeChangeInfoFlag flag = FRAME_NODE_CHANGE_INFO_NONE; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); + + flag = FRAME_NODE_CHANGE_START_SCROLL; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); + + flag = FRAME_NODE_CHANGE_END_SCROLL; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); + + flag = FRAME_NODE_CHANGE_START_ANIMATION; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); + + flag = FRAME_NODE_CHANGE_GEOMETRY_CHANGE; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); + + flag = FRAME_NODE_CHANGE_TRANSFORM_CHANGE; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); + + flag = FRAME_NODE_CHANGE_TRANSITION_START; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); + + flag = FRAME_NODE_CONTENT_CLIP_CHANGE; + dynamicPattern->OnFrameNodeChanged(flag); + EXPECT_EQ(dynamicPattern->rectInfo_.left, dynamicPattern->GetAccessibilityRectInfo().left); + EXPECT_EQ(dynamicPattern->rectInfo_.scaleX, dynamicPattern->GetAccessibilityRectInfo().scaleX); +} + +/** + * @tc.name: DynamicPatternTest002 + * @tc.desc: Test DynamicPattern IsAncestorNodeGeometryChange + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + + /** + * @tc.steps: step2. call IsAncestorNodeGeometryChange. + */ + FrameNodeChangeInfoFlag flag = FRAME_NODE_CHANGE_GEOMETRY_CHANGE | FRAME_NODE_CHANGE_TRANSFORM_CHANGE; + bool result = dynamicPattern->IsAncestorNodeGeometryChange(flag); + EXPECT_TRUE(result); + + flag = FRAME_NODE_CHANGE_TRANSFORM_CHANGE; + result = dynamicPattern->IsAncestorNodeGeometryChange(flag); + EXPECT_FALSE(result); +} + +/** + * @tc.name: DynamicPatternTest003 + * @tc.desc: Test DynamicPattern IsAncestorNodeTransformChange + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest003, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + + /** + * @tc.steps: step2. call IsAncestorNodeTransformChange. + */ + FrameNodeChangeInfoFlag flag = FRAME_NODE_CHANGE_TRANSFORM_CHANGE | FRAME_NODE_CHANGE_GEOMETRY_CHANGE; + bool result = dynamicPattern->IsAncestorNodeTransformChange(flag); + EXPECT_TRUE(result); + + flag = FRAME_NODE_CHANGE_GEOMETRY_CHANGE; + result = dynamicPattern->IsAncestorNodeTransformChange(flag); + EXPECT_FALSE(result); +} + +/** + * @tc.name: DynamicPatternTest004 + * @tc.desc: Test DynamicPattern OnDetachContext + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest004, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + auto pipeline = MockPipelineContext::GetCurrent(); + EXPECT_NE(pipeline, nullptr); + + /** + * @tc.steps: step2. call OnDetachContext. + */ + auto host = dynamicPattern->GetHost(); + EXPECT_NE(host, nullptr); + pipeline->SetInstanceId(123); + auto rawPipeline = reinterpret_cast(Referenced::RawPtr(pipeline)); + dynamicPattern->OnDetachContext(rawPipeline); + dynamicPattern->OnDetachContext(nullptr); + + dynamicPattern->host_ = nullptr; + dynamicPattern->OnDetachContext(rawPipeline); + dynamicPattern->OnDetachContext(nullptr); +} + +/** + * @tc.name: DynamicPatternTest005 + * @tc.desc: Test DynamicPattern UnregisterSingleHandTransformChangedCallback + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest005, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + auto pipeline = MockPipelineContext::GetCurrent(); + EXPECT_NE(pipeline, nullptr); + + /** + * @tc.steps: step2. call UnregisterSingleHandTransformChangedCallback. + */ + auto host = dynamicPattern->GetHost(); + EXPECT_NE(host, nullptr); + int32_t instanceId = 1; + dynamicPattern->UnRegisterSingleHandTransformChangedCallback(instanceId); + + dynamicPattern->host_ = nullptr; + dynamicPattern->UnRegisterSingleHandTransformChangedCallback(instanceId); +} + +/** + * @tc.name: DynamicPatternTest006 + * @tc.desc: Test DynamicPattern UnRegisterAccessibilitySAObserverCallback + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest006, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + auto pipeline = MockPipelineContext::GetCurrent(); + EXPECT_NE(pipeline, nullptr); + + /** + * @tc.steps: step2. call UnRegisterAccessibilitySAObserverCallback. + */ + auto host = dynamicPattern->GetHost(); + EXPECT_NE(host, nullptr); + int32_t instanceId = 1; + auto frontend = pipeline->GetFrontend(); + EXPECT_EQ(frontend, nullptr); + frontend = AceType::MakeRefPtr(); + pipeline->weakFrontend_ = frontend; + dynamicPattern->UnRegisterAccessibilitySAObserverCallback(instanceId); + + pipeline->weakFrontend_ = nullptr; + dynamicPattern->host_ = nullptr; + dynamicPattern->UnRegisterAccessibilitySAObserverCallback(instanceId); +} + +/** + * @tc.name: DynamicPatternTest007 + * @tc.desc: Test DynamicPattern RegisterPipelineEvent + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest007, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + + /** + * @tc.steps: step2. call RegisterPipelineEvent. + */ + EXPECT_NE(dynamicPattern->frameNode_.Upgrade(), nullptr); + auto frameNode = FrameNode::CreateFrameNode(V2::DYNAMIC_COMPONENT_TAG, 0, dynamicPattern); + dynamicPattern->host_ = frameNode; + int32_t instanceId = 1; + auto context = PipelineContext::GetContextByContainerId(instanceId); + CHECK_NULL_VOID(context); + auto uiExtManager = context->GetUIExtensionManager(); + CHECK_NULL_VOID(uiExtManager); + context->uiExtensionManager_ = nullptr; + dynamicPattern->RegisterPipelineEvent(instanceId); + + EXPECT_NE(dynamicPattern->host_.Upgrade(), nullptr); + dynamicPattern->RegisterSingleHandTransformChangedCallback(instanceId); +} + +/** + * @tc.name: DynamicPatternTest008 + * @tc.desc: Test DynamicPattern ResetAccessibilityChildTreeCallback + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest008, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + dynamicPattern->accessibilityChildTreeCallback_ = + std::make_shared(dynamicPattern, 1); + dynamicPattern->instanceId_ = 1; + auto host = dynamicPattern->GetHost(); + EXPECT_NE(host, nullptr); + EXPECT_NE(dynamicPattern->accessibilityChildTreeCallback_, nullptr); + auto pipeline = NG::PipelineContext::GetCurrentContext(); + EXPECT_NE(pipeline, nullptr); + auto frontend = pipeline->GetFrontend(); + EXPECT_EQ(frontend, nullptr); + frontend = AceType::MakeRefPtr(); + /** + * @tc.steps: step2. call ResetAccessibilityChildTreeCallback. + */ + dynamicPattern->ResetAccessibilityChildTreeCallback(); + EXPECT_NE(dynamicPattern->accessibilityChildTreeCallback_, nullptr); + + dynamicPattern->accessibilityChildTreeCallback_ = + std::make_shared(dynamicPattern, 1); + + dynamicPattern->host_ = nullptr; + dynamicPattern->ResetAccessibilityChildTreeCallback(); + EXPECT_NE(dynamicPattern->accessibilityChildTreeCallback_, nullptr); +} + +/** + * @tc.name: DynamicPatternTest009 + * @tc.desc: Test DynamicPattern AddToPageEventController + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest009, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + auto host = dynamicPattern->GetHost(); + EXPECT_NE(host, nullptr); + dynamicPattern->instanceId_ = 100000; + + /** + * @tc.steps: step2. call ResetAccessibilityChildTreeCallback. + */ + auto pipeline = host->GetContext(); + EXPECT_NE(pipeline, nullptr); + auto frontend = pipeline->GetFrontend(); + EXPECT_EQ(frontend, nullptr); + frontend = AceType::MakeRefPtr(); + pipeline->weakFrontend_ = frontend; + dynamicPattern->AddToPageEventController(); + + dynamicPattern->host_ = nullptr; + dynamicPattern->AddToPageEventController(); +} + +void DynamicPatternTestNgTwo::JsonExpect(std::unique_ptr& json, RefPtr dynamicPattern) +{ + EXPECT_NE(dynamicPattern->dynamicComponentRenderer_, nullptr); + dynamicPattern->DumpInfo(json); + + const auto& dynamicId = json->GetValue("dynamicId"); + bool hasDynamicId = !(dynamicId->IsNull()); + EXPECT_FALSE(hasDynamicId); + + const auto& resourcePath = json->GetValue("resourcePath"); + bool hasResourcePath = !(resourcePath->IsNull()); + EXPECT_FALSE(hasResourcePath); + + const auto& entryPoint = json->GetValue("entryPoint"); + bool hasEntryPoint = !(entryPoint->IsNull()); + EXPECT_FALSE(hasEntryPoint); + + const auto& createLimitedWorkerTime = json->GetValue("createLimitedWorkerTime"); + bool hasCreateLimitedWorkerTime = !(createLimitedWorkerTime->IsNull()); + EXPECT_FALSE(hasCreateLimitedWorkerTime); + + const auto& createUiContenTime = json->GetValue("createUiContenTime"); + bool hasCreateUiContenTime = !(createUiContenTime->IsNull()); + EXPECT_FALSE(hasCreateUiContenTime); + + const auto& limitedWorkerInitTime = json->GetValue("limitedWorkerInitTime"); + bool hasLimitedWorkerInitTime = !(limitedWorkerInitTime->IsNull()); + EXPECT_FALSE(hasLimitedWorkerInitTime); + + const auto& loadAbcTime = json->GetValue("loadAbcTime"); + bool hasLoadAbcTime = !(loadAbcTime->IsNull()); + EXPECT_FALSE(hasLoadAbcTime); + + const auto& isReportFrameEvent = json->GetValue("isReportFrameEvent"); + bool hasIsReportFrameEvent = !(isReportFrameEvent->IsNull()); + EXPECT_FALSE(hasIsReportFrameEvent); +} + +/** + * @tc.name: DynamicPatternTest010 + * @tc.desc: Test DynamicPattern DumpInfo + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest010, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + + std::unique_ptr json = std::make_unique(); + dynamicPattern->platformId_ = 123; + dynamicPattern->curDynamicInfo_.resourcePath = "test/path"; + dynamicPattern->curDynamicInfo_.entryPoint = "test/entry"; + dynamicPattern->dynamicDumpInfo_.createLimitedWorkerTime = 100; + dynamicPattern->hostConfig_.isReportFrameEvent = true; + IsolatedInfo curIsolatedInfo; + void* runtime = nullptr; + dynamicPattern->dynamicComponentRenderer_ = DynamicComponentRenderer::Create( + dynamicNode, runtime, curIsolatedInfo); + RendererDumpInfo rendererDumpInfo; + rendererDumpInfo.createUiContenTime = 200; + rendererDumpInfo.limitedWorkerInitTime = 300; + rendererDumpInfo.loadAbcTime = 400; + + /** + * @tc.steps: step2. call DumpInfo. + */ + JsonExpect(json, dynamicPattern); +} + +/** + * @tc.name: DynamicPatternTest011 + * @tc.desc: Test DynamicPattern DumpInfo + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest011, TestSize.Level1) +{ + /** + * @tc.steps: step1. get DynamicPattern + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + + dynamicPattern->platformId_ = 123; + dynamicPattern->curDynamicInfo_.entryPoint = "test/entry"; + dynamicPattern->dynamicDumpInfo_.createLimitedWorkerTime = 100; + dynamicPattern->hostConfig_.isReportFrameEvent = true; + IsolatedInfo curIsolatedInfo; + void* runtime = nullptr; + dynamicPattern->dynamicComponentRenderer_ = DynamicComponentRenderer::Create( + dynamicNode, runtime, curIsolatedInfo); + RendererDumpInfo rendererDumpInfo; + rendererDumpInfo.createUiContenTime = 200; + rendererDumpInfo.limitedWorkerInitTime = 300; + rendererDumpInfo.loadAbcTime = 400; + + /** + * @tc.steps: step2. call DumpInfo. + */ + EXPECT_NE(dynamicPattern->dynamicComponentRenderer_, nullptr); + dynamicPattern->DumpInfo(); + + ASSERT_EQ(DumpLog::GetInstance().description_.size(), 7); + EXPECT_EQ(DumpLog::GetInstance().description_[0], "dynamicId: 123\n"); + EXPECT_EQ(DumpLog::GetInstance().description_[1], "entryPoint: test/entry\n"); + EXPECT_EQ(DumpLog::GetInstance().description_[2], "createLimitedWorkerTime: 100\n"); + EXPECT_EQ(DumpLog::GetInstance().description_[3], "createUiContenTime: 0\n"); + EXPECT_EQ(DumpLog::GetInstance().description_[4], "limitedWorkerInitTime: 0\n"); + EXPECT_EQ(DumpLog::GetInstance().description_[5], "loadAbcTime: 0\n"); + EXPECT_EQ(DumpLog::GetInstance().description_[6], "isReportFrameEvent: true\n"); +} + +/** + * @tc.name: DynamicPatternTest012 + * @tc.desc: Test DynamicPattern OnAttachContext + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest012, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create DynamicPattern and set initial instanceId. + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + + int oldInstanceId = 123; + int newInstanceId = 124; + dynamicPattern->instanceId_ = oldInstanceId; + auto pipeline = MockPipelineContext::GetCurrent(); + EXPECT_NE(pipeline, nullptr); + pipeline->SetInstanceId(124); + + /** + * @tc.steps: step2. Call OnAttachContext with nullptr context. + */ + pipeline->uiExtensionManager_ = nullptr; + auto rawPipeline = reinterpret_cast(Referenced::RawPtr(pipeline)); + dynamicPattern->OnAttachContext(nullptr); + EXPECT_EQ(dynamicPattern->instanceId_, oldInstanceId); + + dynamicPattern->OnAttachContext(rawPipeline); + EXPECT_NE(dynamicPattern->instanceId_, oldInstanceId); + EXPECT_EQ(dynamicPattern->instanceId_, newInstanceId); +} + +/** + * @tc.name: DynamicPatternTest013 + * @tc.desc: Test DynamicPattern SetIsReportFrameEvent + * @tc.type: FUNC + */ +HWTEST_F(DynamicPatternTestNgTwo, DynamicPatternTest013, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create DynamicPattern and set initial instanceId. + */ + auto dynamicNodeId = ElementRegister::GetInstance()->MakeUniqueId(); + auto dynamicNode = FrameNode::GetOrCreateFrameNode( + DYNAMIC_COMPONENT_ETS_TAG, dynamicNodeId, []() { + return AceType::MakeRefPtr(); + }); + EXPECT_NE(dynamicNode, nullptr); + EXPECT_EQ(dynamicNode->GetTag(), V2::DYNAMIC_COMPONENT_ETS_TAG); + auto dynamicPattern = dynamicNode->GetPattern(); + EXPECT_NE(dynamicPattern, nullptr); + EXPECT_FALSE(dynamicPattern->hostConfig_.isReportFrameEvent); + + /** + * @tc.steps: step2. Call SetIsReportFrameEvent + */ + dynamicPattern->SetIsReportFrameEvent(true); + EXPECT_TRUE(dynamicPattern->hostConfig_.isReportFrameEvent); +} +} // namespace OHOS::Ace::NG diff --git a/test/unittest/interfaces/ace_ui_input_event/BUILD.gn b/test/unittest/interfaces/ace_ui_input_event/BUILD.gn index 1f7c8b73ce3c294e497d2597be446fb178992b17..8e5f49268be6b56fc4bf79c134eab1c6cd3b52b1 100644 --- a/test/unittest/interfaces/ace_ui_input_event/BUILD.gn +++ b/test/unittest/interfaces/ace_ui_input_event/BUILD.gn @@ -75,6 +75,20 @@ ohos_unittest("ui_input_event_test") { "oh_arkui_uiinputevent_gety_test.cpp", "oh_arkui_uiinputevent_getybyindex_test.cpp", "oh_arkui_uiinputevent_gewindowxbyindex_test.cpp", +<<<<<<< HEAD + "oh_arkui_pointerevent_gethistorysize_test.cpp", + "oh_arkui_pointerevent_gethistoryeventtime_test.cpp", + "oh_arkui_pointerevent_gethistorypointercount_test.cpp", + "oh_arkui_axisevent_getverticalaxisvalue_test.cpp", + "oh_arkui_axisevent_gethorizontalaxisvalue_test.cpp", + "oh_arkui_axisevent_getpinchaxisscalevalue_test.cpp", + "oh_arkui_axisevent_getaxisaction_test.cpp", + "oh_arkui_pointerevent_setintercepthittestmode_test.cpp", + "oh_arkui_pointerevent_setstoppropagation_test.cpp", + "oh_arkui_mouseevent_getmouseaction_test.cpp", + "oh_arkui_mouseevent_getmousebutton_test.cpp", +======= +>>>>>>> 3de5880d5a85d0988144b236ec7bf1a5cf9a6c5f "oh_arkui_uiinputevent_getmodifierkeystates_test.cpp", "oh_arkui_uiinputevent_gettargetdisplayid_test.cpp", "oh_arkui_axisevent_setpropagation_test.cpp", diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getaxisaction_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getaxisaction_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1793f9264c5c6d41f82320b7b3ddc694569d1932 --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getaxisaction_test.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace { +constexpr int32_t TEST_AXIS_ACTION_BEGIN = 1; +constexpr int32_t TEST_AXIS_ACTION_UPDATE = 2; +constexpr int32_t TEST_AXIS_ACTION_END = 3; +constexpr int32_t TEST_AXIS_ACTION_NONE = 0; +} // namespace + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetAxisAction001 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetAxisAction with null event pointer + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetAxisAction001, TestSize.Level0) +{ + auto result = OH_ArkUI_AxisEvent_GetAxisAction(nullptr); + EXPECT_EQ(result, UI_AXIS_EVENT_ACTION_NONE); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetAxisAction002 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetAxisAction with all unsupported event types + * @tc.type: FUNC + */ +/** + * @tc.name: OH_ArkUI_AxisEvent_GetAxisAction002 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetAxisAction with all unsupported event types + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetAxisAction002, TestSize.Level0) +{ + std::vector> unsupportedEventTypes = { + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, TOUCH_EVENT_ID }, // 1 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_TOUCH_EVENT_ID }, // 2 + { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID }, // 3 + { ARKUI_UIINPUTEVENT_TYPE_KEY, C_KEY_EVENT_ID }, // 5 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_FOCUS_AXIS_EVENT_ID },// 6 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_CLICK_EVENT_ID }, // 7 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID }, // 8 + }; + + // Test each unsupported event type + for (const auto& [inputType, eventTypeId] : unsupportedEventTypes) { + ArkUITouchEvent inputEvent; + ArkUI_UIInputEvent event = { inputType, eventTypeId, &inputEvent, false }; + auto result = OH_ArkUI_AxisEvent_GetAxisAction(&event); + EXPECT_EQ(result, UI_AXIS_EVENT_ACTION_NONE) << "Failed for event type: " << static_cast(eventTypeId); + } +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetAxisAction101 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetAxisAction with AXIS_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetAxisAction101, TestSize.Level0) +{ + // Prepare test data + OHOS::Ace::AxisEvent axisEvent; + axisEvent.action = OHOS::Ace::AxisAction::BEGIN; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetAxisAction(&event); + EXPECT_EQ(result, TEST_AXIS_ACTION_BEGIN); + + // Test null inputEvent case + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetAxisAction(&nullEvent); + EXPECT_EQ(result, UI_AXIS_EVENT_ACTION_NONE); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetAxisAction102 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetAxisAction with C_AXIS_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetAxisAction102, TestSize.Level0) +{ + // Prepare test data + ArkUIAxisEvent axisEvent; + axisEvent.action = TEST_AXIS_ACTION_UPDATE; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetAxisAction(&event); + EXPECT_EQ(result, TEST_AXIS_ACTION_UPDATE); + + // Test null inputEvent case + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetAxisAction(&nullEvent); + EXPECT_EQ(result, UI_AXIS_EVENT_ACTION_NONE); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetAxisAction103 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetAxisAction with all action types + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetAxisAction103, TestSize.Level0) +{ + // Test BEGIN action + OHOS::Ace::AxisEvent beginEvent; + beginEvent.action = OHOS::Ace::AxisAction::BEGIN; + ArkUI_UIInputEvent event1 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &beginEvent }; + auto result = OH_ArkUI_AxisEvent_GetAxisAction(&event1); + EXPECT_EQ(result, TEST_AXIS_ACTION_BEGIN); + + // Test UPDATE action + ArkUIAxisEvent updateEvent; + updateEvent.action = TEST_AXIS_ACTION_UPDATE; + ArkUI_UIInputEvent event2 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &updateEvent }; + result = OH_ArkUI_AxisEvent_GetAxisAction(&event2); + EXPECT_EQ(result, TEST_AXIS_ACTION_UPDATE); + + // Test END action + OHOS::Ace::AxisEvent endEvent; + endEvent.action = OHOS::Ace::AxisAction::END; + ArkUI_UIInputEvent event3 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &endEvent }; + result = OH_ArkUI_AxisEvent_GetAxisAction(&event3); + EXPECT_EQ(result, TEST_AXIS_ACTION_END); + + // Test NONE action + ArkUIAxisEvent noneEvent; + noneEvent.action = TEST_AXIS_ACTION_NONE; + ArkUI_UIInputEvent event4 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &noneEvent }; + result = OH_ArkUI_AxisEvent_GetAxisAction(&event4); + EXPECT_EQ(result, TEST_AXIS_ACTION_NONE); +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_gethorizontalaxisvalue_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_gethorizontalaxisvalue_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69046d5894c7843a66e1b79ed9552aa1ceea129b --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_gethorizontalaxisvalue_test.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace { +constexpr double TEST_HORIZONTAL_AXIS = 2.5; +constexpr double TEST_HORIZONTAL_AXIS_2 = -1.8; +} // namespace + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetHorizontalAxisValue001 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetHorizontalAxisValue with null event pointer + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetHorizontalAxisValue001, TestSize.Level0) +{ + auto result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(nullptr); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetHorizontalAxisValue002 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetHorizontalAxisValue with all unsupported event types + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetHorizontalAxisValue002, TestSize.Level0) +{ + std::vector> unsupportedEventTypes = { + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, TOUCH_EVENT_ID }, // 1 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_TOUCH_EVENT_ID }, // 2 + { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID }, // 3 + { ARKUI_UIINPUTEVENT_TYPE_KEY, C_KEY_EVENT_ID }, // 5 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_FOCUS_AXIS_EVENT_ID },// 6 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_CLICK_EVENT_ID }, // 7 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID }, // 8 + }; + + // Test each unsupported event type + for (const auto& [inputType, eventTypeId] : unsupportedEventTypes) { + ArkUITouchEvent inputEvent; + ArkUI_UIInputEvent event = { inputType, eventTypeId, &inputEvent, false }; + auto result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event); + EXPECT_DOUBLE_EQ(result, 0.0) << "Failed for event type: " << static_cast(eventTypeId); + } +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetHorizontalAxisValue101 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetHorizontalAxisValue with AXIS_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetHorizontalAxisValue101, TestSize.Level0) +{ + // Prepare test data + OHOS::Ace::AxisEvent axisEvent; + axisEvent.horizontalAxis = TEST_HORIZONTAL_AXIS; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event); + EXPECT_DOUBLE_EQ(result, TEST_HORIZONTAL_AXIS); + + // Test null inputEvent case + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&nullEvent); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetHorizontalAxisValue102 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetHorizontalAxisValue with C_AXIS_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetHorizontalAxisValue102, TestSize.Level0) +{ + // Prepare test data + ArkUIAxisEvent axisEvent; + axisEvent.horizontalAxis = TEST_HORIZONTAL_AXIS_2; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event); + EXPECT_DOUBLE_EQ(result, TEST_HORIZONTAL_AXIS_2); + + // Test null inputEvent case + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&nullEvent); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetHorizontalAxisValue103 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetHorizontalAxisValue with boundary values for both event types + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetHorizontalAxisValue103, TestSize.Level0) +{ + // Test zero value for AXIS_EVENT_ID + OHOS::Ace::AxisEvent zeroEvent; + zeroEvent.horizontalAxis = 0.0; + ArkUI_UIInputEvent event1 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &zeroEvent }; + auto result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event1); + EXPECT_DOUBLE_EQ(result, 0.0); + + // Test maximum value for AXIS_EVENT_ID + OHOS::Ace::AxisEvent largeAceEvent; + largeAceEvent.horizontalAxis = DBL_MAX; + ArkUI_UIInputEvent event2 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &largeAceEvent }; + result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event2); + EXPECT_DOUBLE_EQ(result, DBL_MAX); + + // Test minimum value for AXIS_EVENT_ID + OHOS::Ace::AxisEvent smallAceEvent; + smallAceEvent.horizontalAxis = -DBL_MAX; + ArkUI_UIInputEvent event3 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &smallAceEvent }; + result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event3); + EXPECT_DOUBLE_EQ(result, -DBL_MAX); + + // Test zero value for C_AXIS_EVENT_ID + ArkUIAxisEvent zeroCEvent; + zeroCEvent.horizontalAxis = 0.0; + ArkUI_UIInputEvent event4 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &zeroCEvent }; + result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event4); + EXPECT_DOUBLE_EQ(result, 0.0); + + // Test maximum value for C_AXIS_EVENT_ID + ArkUIAxisEvent largeCEvent; + largeCEvent.horizontalAxis = DBL_MAX; + ArkUI_UIInputEvent event5 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &largeCEvent }; + result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event5); + EXPECT_DOUBLE_EQ(result, DBL_MAX); + + // Test minimum value for C_AXIS_EVENT_ID + ArkUIAxisEvent smallCEvent; + smallCEvent.horizontalAxis = -DBL_MAX; + ArkUI_UIInputEvent event6 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &smallCEvent }; + result = OH_ArkUI_AxisEvent_GetHorizontalAxisValue(&event6); + EXPECT_DOUBLE_EQ(result, -DBL_MAX); +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getpinchaxisscalevalue_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getpinchaxisscalevalue_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47f4931fc2cfc66bc3783344068af6c36b2405cd --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getpinchaxisscalevalue_test.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace { +constexpr double TEST_PINCH_SCALE = 1.2; +constexpr double TEST_PINCH_SCALE_2 = 0.8; +} // namespace + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetPinchAxisScaleValue001 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetPinchAxisScaleValue with null event pointer + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetPinchAxisScaleValue001, TestSize.Level0) +{ + auto result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(nullptr); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetPinchAxisScaleValue002 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetPinchAxisScaleValue with all unsupported event types + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetPinchAxisScaleValue002, TestSize.Level0) +{ + std::vector> unsupportedEventTypes = { + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, TOUCH_EVENT_ID }, // 1 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_TOUCH_EVENT_ID }, // 2 + { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID }, // 3 + { ARKUI_UIINPUTEVENT_TYPE_KEY, C_KEY_EVENT_ID }, // 5 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_FOCUS_AXIS_EVENT_ID },// 6 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_CLICK_EVENT_ID }, // 7 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID }, // 8 + }; + + // Test each unsupported event type + for (const auto& [inputType, eventTypeId] : unsupportedEventTypes) { + ArkUITouchEvent inputEvent; + ArkUI_UIInputEvent event = { inputType, eventTypeId, &inputEvent, false }; + auto result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&event); + EXPECT_DOUBLE_EQ(result, 0.0) << "Failed for event type: " << static_cast(eventTypeId); + } +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetPinchAxisScaleValue101 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetPinchAxisScaleValue with AXIS_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetPinchAxisScaleValue101, TestSize.Level0) +{ + // Prepare test data + OHOS::Ace::AxisEvent axisEvent; + axisEvent.pinchAxisScale = TEST_PINCH_SCALE; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&event); + EXPECT_DOUBLE_EQ(result, TEST_PINCH_SCALE); + + // Test null inputEvent case + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&nullEvent); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetPinchAxisScaleValue102 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetPinchAxisScaleValue with C_AXIS_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetPinchAxisScaleValue102, TestSize.Level0) +{ + // Prepare test data + ArkUIAxisEvent axisEvent; + axisEvent.pinchAxisScale = TEST_PINCH_SCALE_2; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&event); + EXPECT_DOUBLE_EQ(result, TEST_PINCH_SCALE_2); + + // Test null inputEvent case + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&nullEvent); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetPinchAxisScaleValue103 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetPinchAxisScaleValue with boundary values + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetPinchAxisScaleValue103, TestSize.Level0) +{ + // Test minimum scale value + OHOS::Ace::AxisEvent minEvent; + minEvent.pinchAxisScale = 0.0; + ArkUI_UIInputEvent event1 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &minEvent }; + auto result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&event1); + EXPECT_DOUBLE_EQ(result, 0.0); + + // Test normal scale value + ArkUIAxisEvent normalEvent; + normalEvent.pinchAxisScale = 1.0; + ArkUI_UIInputEvent event2 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &normalEvent }; + result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&event2); + EXPECT_DOUBLE_EQ(result, 1.0); + + // Test maximum scale value + ArkUIAxisEvent maxEvent; + maxEvent.pinchAxisScale = DBL_MAX; + ArkUI_UIInputEvent event3 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &maxEvent }; + result = OH_ArkUI_AxisEvent_GetPinchAxisScaleValue(&event3); + EXPECT_DOUBLE_EQ(result, DBL_MAX); +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getverticalaxisvalue_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getverticalaxisvalue_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..738bc7e47774dc0368abeeb8d26b2b5aada96953 --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_axisevent_getverticalaxisvalue_test.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace { +constexpr double TEST_VERTICAL_AXIS = 1.5; +constexpr double TEST_VERTICAL_AXIS_2 = -2.3; +} // namespace + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetVerticalAxisValue001 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetVerticalAxisValue with null event pointer + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetVerticalAxisValue001, TestSize.Level0) +{ + auto result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(nullptr); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetVerticalAxisValue002 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetVerticalAxisValue with all unsupported event types + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetVerticalAxisValue002, TestSize.Level0) +{ + // Define all unsupported event types (excluding AXIS_EVENT_ID which should be supported) + std::vector> unsupportedEventTypes = { + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, TOUCH_EVENT_ID }, // 1 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_TOUCH_EVENT_ID }, // 2 + { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID }, // 3 + { ARKUI_UIINPUTEVENT_TYPE_KEY, C_KEY_EVENT_ID }, // 5 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_FOCUS_AXIS_EVENT_ID },// 6 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_CLICK_EVENT_ID }, // 7 + { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID }, // 8 + }; + + // Test each unsupported event type + for (const auto& [inputType, eventTypeId] : unsupportedEventTypes) { + ArkUITouchEvent inputEvent; + ArkUI_UIInputEvent event = { inputType, eventTypeId, &inputEvent, false }; + auto result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&event); + EXPECT_DOUBLE_EQ(result, 0.0) << "Failed for event type: " << static_cast(eventTypeId); + } +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetVerticalAxisValue101 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetVerticalAxisValue with AXIS_EVENT_ID type event + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetVerticalAxisValue101, TestSize.Level0) +{ + // Prepare test data + OHOS::Ace::AxisEvent axisEvent; + axisEvent.verticalAxis = TEST_VERTICAL_AXIS; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&event); + EXPECT_DOUBLE_EQ(result, TEST_VERTICAL_AXIS); + + // Test case with null inputEvent + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&nullEvent); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetVerticalAxisValue102 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetVerticalAxisValue with C_AXIS_EVENT_ID type event + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetVerticalAxisValue102, TestSize.Level0) +{ + // Prepare test data + + ArkUIAxisEvent axisEvent; + + axisEvent.verticalAxis = TEST_VERTICAL_AXIS_2; + + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &axisEvent }; + + // Test normal case + auto result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&event); + EXPECT_DOUBLE_EQ(result, TEST_VERTICAL_AXIS_2); + + // Test case with null inputEvent + ArkUI_UIInputEvent nullEvent = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, nullptr }; + result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&nullEvent); + EXPECT_DOUBLE_EQ(result, 0.0); +} + +/** + * @tc.name: OH_ArkUI_AxisEvent_GetVerticalAxisValue103 + * @tc.desc: Test OH_ArkUI_AxisEvent_GetVerticalAxisValue with boundary values + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_AxisEvent_GetVerticalAxisValue103, TestSize.Level0) +{ + // Test zero value + OHOS::Ace::AxisEvent zeroEvent; + zeroEvent.verticalAxis = 0.0; + ArkUI_UIInputEvent event1 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, &zeroEvent }; + auto result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&event1); + EXPECT_DOUBLE_EQ(result, 0.0); + + // Test maximum value + ArkUIAxisEvent largeEvent; + largeEvent.verticalAxis = DBL_MAX; + ArkUI_UIInputEvent event2 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &largeEvent }; + result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&event2); + EXPECT_DOUBLE_EQ(result, DBL_MAX); + + // Test minimum value + ArkUIAxisEvent smallEvent; + smallEvent.verticalAxis = -DBL_MAX; + ArkUI_UIInputEvent event3 = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &smallEvent }; + result = OH_ArkUI_AxisEvent_GetVerticalAxisValue(&event3); + EXPECT_DOUBLE_EQ(result, -DBL_MAX); +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_mouseevent_getmouseaction_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_mouseevent_getmouseaction_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10f777585f6b866b89cb77f44d4079065e3a9439 --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_mouseevent_getmouseaction_test.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" +#include "interfaces/native/event/ui_input_event_impl.h" +#include "interfaces/native/ui_input_event.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS::Ace { + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseAction_NullEvent, TestSize.Level0) +{ + int32_t result = OH_ArkUI_MouseEvent_GetMouseAction(nullptr); + EXPECT_EQ(result, -1) << "Input event is nullptr, expected -1, got " << result; +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseAction_EventTypeNotMouse, TestSize.Level0) +{ + ArkUIMouseEvent mouseEvent = {}; + mouseEvent.action = 1; // Press action + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, + C_CLICK_EVENT_ID, // Not mouse event + &mouseEvent }; + int32_t result = OH_ArkUI_MouseEvent_GetMouseAction(&inputEvent); + EXPECT_EQ(result, -1); +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseAction_NullInputEvent, TestSize.Level0) +{ + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID, nullptr }; + int32_t result = OH_ArkUI_MouseEvent_GetMouseAction(&inputEvent); + EXPECT_EQ(result, -1); +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseAction_Normal, TestSize.Level0) +{ + ArkUIMouseEvent mouseEvent = {}; + mouseEvent.action = 1; // Press action + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID, &mouseEvent }; + int32_t result = OH_ArkUI_MouseEvent_GetMouseAction(&inputEvent); + EXPECT_EQ(result, 1); +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseAction_ActionVariants, TestSize.Level0) +{ + struct ActionTestCase { + int32_t rawAction; // Raw action value from event + int32_t expected; // Expected converted value + const char* desc; + }; + std::vector cases = { { 0, 0, "No action" }, { 1, 1, "Press action" }, { 2, 2, "Release action" }, + { 3, 3, "Move action" }, { 4, 0, "Hover enter (unsupported)" }, { 5, 0, "Hover exit (unsupported)" }, + { 6, 0, "Drag action (unsupported)" }, { 7, 0, "Unsupported action type" } }; + + ArkUIMouseEvent mouseEvent = {}; + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID, &mouseEvent }; + int count = 0; + for (const auto& testCase : cases) { + mouseEvent.action = testCase.rawAction; + int32_t result = OH_ArkUI_MouseEvent_GetMouseAction(&inputEvent); + EXPECT_EQ(result, testCase.expected) + << "Test case " << count << " failed: " << testCase.desc << ", rawAction=" << testCase.rawAction + << ", expected=" << testCase.expected << ", actual=" << result; + count++; + } +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseAction_ConvertedValues, TestSize.Level0) +{ + // Test that the conversion function returns expected values + EXPECT_EQ(OHOS::Ace::NodeModel::ConvertToCMouseActionType(1), 1) << "Press action conversion failed"; + EXPECT_EQ(OHOS::Ace::NodeModel::ConvertToCMouseActionType(2), 2) << "Release action conversion failed"; + EXPECT_EQ(OHOS::Ace::NodeModel::ConvertToCMouseActionType(3), 3) << "Move action conversion failed"; + EXPECT_EQ(OHOS::Ace::NodeModel::ConvertToCMouseActionType(4), 0) << "Unsupported action should return 0"; +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_mouseevent_getmousebutton_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_mouseevent_getmousebutton_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..07d9e3276219110cc2890537d9d794f22db69338 --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_mouseevent_getmousebutton_test.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" +#include "interfaces/native/event/ui_input_event_impl.h" +#include "interfaces/native/ui_input_event.h" + +using namespace testing; +using namespace testing::ext; +namespace OHOS::Ace { + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseButton_NullEvent, TestSize.Level0) +{ + int32_t result = OH_ArkUI_MouseEvent_GetMouseButton(nullptr); + EXPECT_EQ(result, -1); +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseButton_EventTypeNotMouse, TestSize.Level0) +{ + ArkUIMouseEvent mouseEvent = {}; + mouseEvent.button = 1; // Left button + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, + C_CLICK_EVENT_ID, // Not mouse event + &mouseEvent }; + int32_t result = OH_ArkUI_MouseEvent_GetMouseButton(&inputEvent); + EXPECT_EQ(result, -1); +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseButton_NullInputEvent, TestSize.Level0) +{ + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID, nullptr }; + int32_t result = OH_ArkUI_MouseEvent_GetMouseButton(&inputEvent); + EXPECT_EQ(result, -1); +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseButton_Normal, TestSize.Level0) +{ + ArkUIMouseEvent mouseEvent = {}; + mouseEvent.button = 1; // Left button + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID, &mouseEvent }; + int32_t result = OH_ArkUI_MouseEvent_GetMouseButton(&inputEvent); + EXPECT_EQ(result, 1); +} + +HWTEST_F(UIInputEventTest, OH_ArkUI_MouseEvent_GetMouseButton_ButtonVariants, TestSize.Level0) +{ + struct ButtonTestCase { + int32_t rawButton; // Raw button value from event + int32_t expected; // Expected converted value + const char* desc; + }; + std::vector cases = { { 0, 0, "No button pressed" }, { 1, 1, "Left button pressed" }, + { 2, 2, "Right button pressed" }, { 4, 3, "Middle button pressed" }, { 8, 4, "Back button pressed" }, + { 16, 5, "Forward button pressed" }, { 3, 0, "Invalid combination" }, { 32, 0, "Unsupported button" } }; + + ArkUIMouseEvent mouseEvent = {}; + ArkUI_UIInputEvent inputEvent = { ARKUI_UIINPUTEVENT_TYPE_MOUSE, C_MOUSE_EVENT_ID, &mouseEvent }; + int count = 0; + for (const auto& testCase : cases) { + mouseEvent.button = testCase.rawButton; + int32_t result = OH_ArkUI_MouseEvent_GetMouseButton(&inputEvent); + EXPECT_EQ(result, testCase.expected) + << "Test case " << count << " failed: " << testCase.desc << ", rawButton=" << testCase.rawButton + << ", expected=" << testCase.expected << ", actual=" << result; + count++; + } +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistoryeventtime_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistoryeventtime_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6dd1a961f957760a362e1cc32b99082ffbd8c4e --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistoryeventtime_test.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace { +constexpr int64_t ARKUI_EVENT_TIME = 1234567890; +constexpr uint32_t ARKUI_HISTORY_SIZE = 2; +} // namespace + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistoryEventTime001 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistoryEventTime function with null event. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistoryEventTime001, TestSize.Level0) +{ + auto result = OH_ArkUI_PointerEvent_GetHistoryEventTime(nullptr, 0); + EXPECT_EQ(result, 0); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistoryEventTime101 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistoryEventTime function with touch event. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistoryEventTime101, TestSize.Level0) +{ + ArkUITouchEvent inputEvent; + ArkUIEventTypeId eventTypeId = C_TOUCH_EVENT_ID; + + // Setup valid history events + ArkUIHistoryTouchEvent historyEvents[ARKUI_HISTORY_SIZE]; + historyEvents[0].timeStamp = ARKUI_EVENT_TIME; + historyEvents[1].timeStamp = ARKUI_EVENT_TIME + 1000; + inputEvent.historyEvents = historyEvents; + inputEvent.historySize = ARKUI_HISTORY_SIZE; + + ArkUITouchEvent nullHistoryEvent; + nullHistoryEvent.historyEvents = nullptr; + nullHistoryEvent.historySize = ARKUI_HISTORY_SIZE; + + ArkUITouchEvent emptyEvent; + + std::vector> testCases = { + // case 1: null touch event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, nullptr }, 0, 0 }, + // case 2: null history events + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &nullHistoryEvent }, 0, 0 }, + // case 3: empty touch event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &emptyEvent }, 0, 0 }, + // case 4: invalid history index (negative) + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, -1, 0 }, + // case 5: invalid history index (out of range) + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, ARKUI_HISTORY_SIZE, 0 }, + // case 6: valid history index 0 + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, 0, ARKUI_EVENT_TIME }, + // case 7: valid history index 1 + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, 1, + ARKUI_EVENT_TIME + 1000 }, + }; + + for (size_t i = 0; i < testCases.size(); ++i) { + const auto& testCase = testCases[i]; + auto result = OH_ArkUI_PointerEvent_GetHistoryEventTime(&std::get<0>(testCase), std::get<1>(testCase)); + EXPECT_EQ(result, std::get<2>(testCase)) << "Test case " << i << " failed"; + } +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistoryEventTime102 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistoryEventTime function with unsupported event types. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistoryEventTime102, TestSize.Level0) +{ + ArkUIMouseEvent mouseEvent; + ArkUIAxisEvent axisEvent; + + std::vector> testCases = { + // case 1: mouse event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_MOUSE_EVENT_ID, &mouseEvent }, C_MOUSE_EVENT_ID }, + // case 2: axis event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &axisEvent }, C_AXIS_EVENT_ID }, + // case 3: key event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_KEY_EVENT_ID, nullptr }, C_KEY_EVENT_ID }, + // case 4: hover event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID, nullptr }, C_HOVER_EVENT_ID }, + }; + + for (size_t i = 0; i < testCases.size(); ++i) { + const auto& testCase = testCases[i]; + auto result = OH_ArkUI_PointerEvent_GetHistoryEventTime(&testCase.first, 0); + EXPECT_EQ(result, 0) << "Unsupported type test " << i << " failed"; + } +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistorypointercount_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistorypointercount_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f0ce353a945eae109fc862979bc7b9eb3fb98a0 --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistorypointercount_test.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace { +constexpr uint32_t ARKUI_HISTORY_POINTER_COUNT = 2; +constexpr uint32_t ARKUI_HISTORY_SIZE = 3; +} // namespace + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistoryPointerCount001 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistoryPointerCount function with null event. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistoryPointerCount001, TestSize.Level0) +{ + auto result = OH_ArkUI_PointerEvent_GetHistoryPointerCount(nullptr, 0); + EXPECT_EQ(result, 0u); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistoryPointerCount101 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistoryPointerCount function with touch event. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistoryPointerCount101, TestSize.Level0) +{ + ArkUITouchEvent inputEvent; + ArkUIEventTypeId eventTypeId = C_TOUCH_EVENT_ID; + + // Setup valid history events with different pointer counts + ArkUIHistoryTouchEvent historyEvents[ARKUI_HISTORY_SIZE]; + historyEvents[0].touchPointSize = ARKUI_HISTORY_POINTER_COUNT; + historyEvents[1].touchPointSize = ARKUI_HISTORY_POINTER_COUNT + 1; + historyEvents[2].touchPointSize = ARKUI_HISTORY_POINTER_COUNT + 2; + inputEvent.historyEvents = historyEvents; + inputEvent.historySize = ARKUI_HISTORY_SIZE; + + ArkUITouchEvent nullHistoryEvent; + nullHistoryEvent.historyEvents = nullptr; + nullHistoryEvent.historySize = ARKUI_HISTORY_SIZE; + + ArkUITouchEvent emptyEvent; + + std::vector> testCases = { + // case 1: null touch event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, nullptr }, 0, 0 }, + // case 2: null history events + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &nullHistoryEvent }, 0, 0 }, + // case 3: empty touch event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &emptyEvent }, 0, 0 }, + // case 4: invalid history index (negative) + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, -1, 0 }, + // case 5: invalid history index (out of range) + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, ARKUI_HISTORY_SIZE, 0 }, + // case 6: valid history index 0 + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, 0, + ARKUI_HISTORY_POINTER_COUNT }, + // case 7: valid history index 1 + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, 1, + ARKUI_HISTORY_POINTER_COUNT + 1 }, + // case 8: valid history index 2 + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, 2, + ARKUI_HISTORY_POINTER_COUNT + 2 }, + }; + + for (size_t i = 0; i < testCases.size(); ++i) { + const auto& testCase = testCases[i]; + auto result = OH_ArkUI_PointerEvent_GetHistoryPointerCount(&std::get<0>(testCase), std::get<1>(testCase)); + EXPECT_EQ(result, std::get<2>(testCase)) << "Test case " << i << " failed"; + } +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistoryPointerCount102 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistoryPointerCount function with unsupported event types. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistoryPointerCount102, TestSize.Level0) +{ + ArkUIMouseEvent mouseEvent; + ArkUIAxisEvent axisEvent; + + std::vector> testCases = { + // case 1: mouse event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_MOUSE_EVENT_ID, &mouseEvent }, C_MOUSE_EVENT_ID }, + // case 2: axis event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &axisEvent }, C_AXIS_EVENT_ID }, + // case 3: key event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_KEY_EVENT_ID, nullptr }, C_KEY_EVENT_ID }, + // case 4: hover event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID, nullptr }, C_HOVER_EVENT_ID }, + }; + + for (size_t i = 0; i < testCases.size(); ++i) { + const auto& testCase = testCases[i]; + auto result = OH_ArkUI_PointerEvent_GetHistoryPointerCount(&testCase.first, 0); + EXPECT_EQ(result, 0u) << "Unsupported type test " << i << " failed"; + } +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistorysize_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistorysize_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8923de9a126b50084d6c9af25c2fb8f8be0219f --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_gethistorysize_test.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace { +constexpr uint32_t ARKUI_HISTORY_SIZE = 5; +} // namespace + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistorySize001 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistorySize function with null event. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistorySize001, TestSize.Level0) +{ + auto result = OH_ArkUI_PointerEvent_GetHistorySize(nullptr); + EXPECT_EQ(result, 0u); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistorySize101 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistorySize function with touch event. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistorySize101, TestSize.Level0) +{ + ArkUITouchEvent inputEvent; + ArkUIEventTypeId eventTypeId = C_TOUCH_EVENT_ID; + + ArkUIHistoryTouchEvent historyEvents[ARKUI_HISTORY_SIZE]; + inputEvent.historyEvents = historyEvents; + inputEvent.historySize = ARKUI_HISTORY_SIZE; + + ArkUITouchEvent nullHistoryEvent; + nullHistoryEvent.historyEvents = nullptr; + nullHistoryEvent.historySize = ARKUI_HISTORY_SIZE; + + ArkUITouchEvent emptyEvent; + + std::vector> testCases = { + // case 1: null touch event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, nullptr }, 0 }, + // case 2: null history events + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &nullHistoryEvent }, 0 }, + // case 3: empty touch event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &emptyEvent }, 0 }, + // case 4: valid history size + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, eventTypeId, &inputEvent }, ARKUI_HISTORY_SIZE }, + }; + + for (size_t i = 0; i < testCases.size(); ++i) { + const auto& testCase = testCases[i]; + auto result = OH_ArkUI_PointerEvent_GetHistorySize(&testCase.first); + EXPECT_EQ(result, testCase.second) << "Test case " << i << " failed"; + } +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_GetHistorySize102 + * @tc.desc: Test the OH_ArkUI_PointerEvent_GetHistorySize function with unsupported event types. + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_GetHistorySize102, TestSize.Level0) +{ + ArkUIMouseEvent mouseEvent; + ArkUIAxisEvent axisEvent; + + std::vector> testCases = { + // case 1: mouse event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_MOUSE_EVENT_ID, &mouseEvent }, C_MOUSE_EVENT_ID }, + // case 2: axis event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_AXIS_EVENT_ID, &axisEvent }, C_AXIS_EVENT_ID }, + // case 3: key event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_KEY_EVENT_ID, nullptr }, C_KEY_EVENT_ID }, + // case 4: hover event + { ArkUI_UIInputEvent { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID, nullptr }, C_HOVER_EVENT_ID }, + }; + + for (size_t i = 0; i < testCases.size(); ++i) { + const auto& testCase = testCases[i]; + auto result = OH_ArkUI_PointerEvent_GetHistorySize(&testCase.first); + EXPECT_EQ(result, 0u) << "Unsupported type test " << i << " failed"; + } +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_setintercepthittestmode_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_setintercepthittestmode_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3504d5cde5eb41bfbcb77cf5a772169b13e09f1 --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_setintercepthittestmode_test.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetInterceptHitTestMode001 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetInterceptHitTestMode with null event pointer + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetInterceptHitTestMode001, TestSize.Level0) +{ + auto result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(nullptr, HTM_DEFAULT); + EXPECT_EQ(result, ARKUI_ERROR_CODE_PARAM_INVALID); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetInterceptHitTestMode002 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetInterceptHitTestMode with unsupported event type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetInterceptHitTestMode002, TestSize.Level0) +{ + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, nullptr }; + auto result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_DEFAULT); + EXPECT_EQ(result, ARKUI_ERROR_CODE_PARAM_INVALID); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetInterceptHitTestMode101 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetInterceptHitTestMode with C_TOUCH_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetInterceptHitTestMode101, TestSize.Level0) +{ + // Prepare test data + ArkUITouchEvent touchEvent; + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_TOUCH_EVENT_ID, &touchEvent }; + + // Test HTM_DEFAULT mode + auto result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_DEFAULT); + EXPECT_EQ(result, ARKUI_ERROR_CODE_NO_ERROR); + EXPECT_EQ(touchEvent.interceptResult, HTM_DEFAULT); + + // Test HTM_BLOCK mode + result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_BLOCK); + EXPECT_EQ(result, ARKUI_ERROR_CODE_NO_ERROR); + EXPECT_EQ(touchEvent.interceptResult, HTM_BLOCK); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetInterceptHitTestMode102 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetInterceptHitTestMode with C_MOUSE_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetInterceptHitTestMode102, TestSize.Level0) +{ + // Prepare test data + ArkUIMouseEvent mouseEvent; + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_MOUSE_EVENT_ID, &mouseEvent }; + + // Test HTM_TRANSPARENT mode + auto result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_TRANSPARENT); + EXPECT_EQ(result, static_cast(HTM_TRANSPARENT)); + EXPECT_EQ(mouseEvent.interceptResult, HTM_TRANSPARENT); + + // Test HTM_NONE mode + result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_NONE); + EXPECT_EQ(result, static_cast(HTM_NONE)); + EXPECT_EQ(mouseEvent.interceptResult, HTM_NONE); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetInterceptHitTestMode103 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetInterceptHitTestMode with null inputEvent for C_MOUSE_EVENT_ID + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetInterceptHitTestMode103, TestSize.Level0) +{ + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_MOUSE_EVENT_ID, nullptr }; + auto result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_DEFAULT); + EXPECT_EQ(result, ARKUI_ERROR_CODE_PARAM_INVALID); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetInterceptHitTestMode104 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetInterceptHitTestMode with all HitTestMode values + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetInterceptHitTestMode104, TestSize.Level0) +{ + ArkUITouchEvent touchEvent; + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_TOUCH_EVENT_ID, &touchEvent }; + + // Test all possible HitTestMode values + auto result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_DEFAULT); + EXPECT_EQ(result, ARKUI_ERROR_CODE_NO_ERROR); + EXPECT_EQ(touchEvent.interceptResult, HTM_DEFAULT); + + result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_BLOCK); + EXPECT_EQ(result, ARKUI_ERROR_CODE_NO_ERROR); + EXPECT_EQ(touchEvent.interceptResult, HTM_BLOCK); + + result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_TRANSPARENT); + EXPECT_EQ(result, ARKUI_ERROR_CODE_NO_ERROR); + EXPECT_EQ(touchEvent.interceptResult, HTM_TRANSPARENT); + + result = OH_ArkUI_PointerEvent_SetInterceptHitTestMode(&event, HTM_NONE); + EXPECT_EQ(result, ARKUI_ERROR_CODE_NO_ERROR); + EXPECT_EQ(touchEvent.interceptResult, HTM_NONE); +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_setstoppropagation_test.cpp b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_setstoppropagation_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b47ef037d29aa1fa96bfbe22dce5e73d595b295 --- /dev/null +++ b/test/unittest/interfaces/ace_ui_input_event/oh_arkui_pointerevent_setstoppropagation_test.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../ui_input_event_test.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS::Ace { + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetStopPropagation001 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetStopPropagation with null event pointer + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetStopPropagation001, TestSize.Level0) +{ + auto result = OH_ArkUI_PointerEvent_SetStopPropagation(nullptr, true); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_PARAM_INVALID); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetStopPropagation002 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetStopPropagation with unsupported event type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetStopPropagation002, TestSize.Level0) +{ + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, AXIS_EVENT_ID, nullptr }; + auto result = OH_ArkUI_PointerEvent_SetStopPropagation(&event, true); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_PARAM_INVALID); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetStopPropagation101 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetStopPropagation with C_TOUCH_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetStopPropagation101, TestSize.Level0) +{ + // Prepare test data + ArkUITouchEvent touchEvent; + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_TOUCH_EVENT_ID, &touchEvent }; + + // Test stop propagation true + auto result = OH_ArkUI_PointerEvent_SetStopPropagation(&event, true); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_NO_ERROR); + EXPECT_TRUE(touchEvent.stopPropagation); + + // Test stop propagation false + result = OH_ArkUI_PointerEvent_SetStopPropagation(&event, false); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_NO_ERROR); + EXPECT_FALSE(touchEvent.stopPropagation); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetStopPropagation102 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetStopPropagation with C_MOUSE_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetStopPropagation102, TestSize.Level0) +{ + // Prepare test data + ArkUIMouseEvent mouseEvent; + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_MOUSE_EVENT_ID, &mouseEvent }; + + // Test stop propagation true + auto result = OH_ArkUI_PointerEvent_SetStopPropagation(&event, true); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_NO_ERROR); + EXPECT_TRUE(mouseEvent.stopPropagation); + + // Test stop propagation false + result = OH_ArkUI_PointerEvent_SetStopPropagation(&event, false); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_NO_ERROR); + EXPECT_FALSE(mouseEvent.stopPropagation); +} + +/** + * @tc.name: OH_ArkUI_PointerEvent_SetStopPropagation103 + * @tc.desc: Test OH_ArkUI_PointerEvent_SetStopPropagation with C_HOVER_EVENT_ID type + * @tc.type: FUNC + */ +HWTEST_F(UIInputEventTest, OH_ArkUI_PointerEvent_SetStopPropagation103, TestSize.Level0) +{ + // Prepare test data + ArkUIHoverEvent hoverEvent; + ArkUI_UIInputEvent event = { ARKUI_UIINPUTEVENT_TYPE_UNKNOWN, C_HOVER_EVENT_ID, &hoverEvent }; + + // Test stop propagation true + auto result = OH_ArkUI_PointerEvent_SetStopPropagation(&event, true); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_NO_ERROR); + EXPECT_TRUE(hoverEvent.stopPropagation); + + // Test stop propagation false + result = OH_ArkUI_PointerEvent_SetStopPropagation(&event, false); + EXPECT_EQ(result, OHOS::Ace::ERROR_CODE_NO_ERROR); + EXPECT_FALSE(hoverEvent.stopPropagation); +} + +} // namespace OHOS::Ace \ No newline at end of file