1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.h"
16 #include "core/interfaces/arkoala/arkoala_api.h"
17 #include "frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
18
19 namespace OHOS::Ace::NG {
20 const std::string FORMAT_FONT = "%s|%s|%s";
21 const std::string DEFAULT_ERR_CODE = "-1";
22 constexpr int ARG_INDEX_0 = 0;
23 constexpr int ARG_INDEX_1 = 1;
24 constexpr int ARG_INDEX_2 = 2;
25 constexpr int ARG_INDEX_3 = 3;
26 constexpr int ARG_INDEX_4 = 4;
27
BuildMenuDividerOptions(EcmaVM * vm,Local<JSValueRef> strokeWidthArg,Local<JSValueRef> colorArg,Local<JSValueRef> startMarginArg,Local<JSValueRef> endMarginArg)28 ArkUIMenuDividerOptions BuildMenuDividerOptions(EcmaVM* vm, Local<JSValueRef> strokeWidthArg,
29 Local<JSValueRef> colorArg, Local<JSValueRef> startMarginArg, Local<JSValueRef> endMarginArg)
30 {
31 ArkUIDimensionType strokeWidthOption;
32 ArkUIDimensionType startMarginOption;
33 ArkUIDimensionType endMarginOption;
34
35 CalcDimension strokeWidth;
36 if (!ArkTSUtils::ParseJsLengthMetrics(vm, strokeWidthArg, strokeWidth)) {
37 strokeWidth = Dimension(0.0);
38 }
39 strokeWidthOption.value = strokeWidth.Value();
40 strokeWidthOption.units = static_cast<int32_t>(strokeWidth.Unit());
41
42 Color color;
43 if (!ArkTSUtils::ParseJsColorAlpha(vm, colorArg, color)) {
44 color = Color::TRANSPARENT;
45 }
46
47 CalcDimension startMargin;
48 if (!ArkTSUtils::ParseJsLengthMetrics(vm, startMarginArg, startMargin)) {
49 startMargin = Dimension(0.0);
50 }
51 startMarginOption.value = startMargin.Value();
52 startMarginOption.units = static_cast<int32_t>(startMargin.Unit());
53
54 CalcDimension endMargin;
55 if (!ArkTSUtils::ParseJsLengthMetrics(vm, endMarginArg, endMargin)) {
56 endMargin = Dimension(0.0);
57 }
58 endMarginOption.value = endMargin.Value();
59 endMarginOption.units = static_cast<int32_t>(endMargin.Unit());
60
61 ArkUIMenuDividerOptions dividerOptions;
62 dividerOptions.strokeWidth = strokeWidthOption;
63 dividerOptions.color = color.GetValue();
64 dividerOptions.startMargin = startMarginOption;
65 dividerOptions.endMargin = endMarginOption;
66 return dividerOptions;
67 }
68
SetMenuDivider(ArkUIRuntimeCallInfo * runtimeCallInfo,bool isGroupDivider)69 ArkUINativeModuleValue SetMenuDivider(ArkUIRuntimeCallInfo* runtimeCallInfo, bool isGroupDivider)
70 {
71 EcmaVM* vm = runtimeCallInfo->GetVM();
72 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
73 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(ARG_INDEX_0);
74 Local<JSValueRef> strokeWidthArg = runtimeCallInfo->GetCallArgRef(ARG_INDEX_1);
75 Local<JSValueRef> colorArg = runtimeCallInfo->GetCallArgRef(ARG_INDEX_2);
76 Local<JSValueRef> startMarginArg = runtimeCallInfo->GetCallArgRef(ARG_INDEX_3);
77 Local<JSValueRef> endMarginArg = runtimeCallInfo->GetCallArgRef(ARG_INDEX_4);
78 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
79 if (strokeWidthArg->IsUndefined() && colorArg->IsUndefined() && startMarginArg->IsUndefined()
80 && endMarginArg->IsUndefined()) {
81 if (isGroupDivider) {
82 GetArkUINodeModifiers()->getMenuModifier()->resetMenuItemGroupDivider(nativeNode);
83 } else {
84 GetArkUINodeModifiers()->getMenuModifier()->resetMenuItemDivider(nativeNode);
85 }
86 return panda::JSValueRef::Undefined(vm);
87 }
88 auto dividerOptions = BuildMenuDividerOptions(vm, strokeWidthArg, colorArg, startMarginArg,
89 endMarginArg);
90 if (isGroupDivider) {
91 GetArkUINodeModifiers()->getMenuModifier()->setMenuItemGroupDivider(nativeNode, ÷rOptions);
92 } else {
93 GetArkUINodeModifiers()->getMenuModifier()->setMenuItemDivider(nativeNode, ÷rOptions);
94 }
95 return panda::JSValueRef::Undefined(vm);
96 }
97
ResetMenuDivider(ArkUIRuntimeCallInfo * runtimeCallInfo,bool isGroupDivider)98 ArkUINativeModuleValue ResetMenuDivider(ArkUIRuntimeCallInfo* runtimeCallInfo, bool isGroupDivider)
99 {
100 EcmaVM* vm = runtimeCallInfo->GetVM();
101 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
102 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
103 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
104 if (isGroupDivider) {
105 GetArkUINodeModifiers()->getMenuModifier()->resetMenuItemGroupDivider(nativeNode);
106 } else {
107 GetArkUINodeModifiers()->getMenuModifier()->resetMenuItemDivider(nativeNode);
108 }
109 return panda::JSValueRef::Undefined(vm);
110 }
111
SetMenuFontColor(ArkUIRuntimeCallInfo * runtimeCallInfo)112 ArkUINativeModuleValue MenuBridge::SetMenuFontColor(ArkUIRuntimeCallInfo* runtimeCallInfo)
113 {
114 EcmaVM* vm = runtimeCallInfo->GetVM();
115 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
116 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
117 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
118 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
119 Color color;
120 if (!ArkTSUtils::ParseJsColorAlpha(vm, secondArg, color)) {
121 GetArkUINodeModifiers()->getMenuModifier()->resetMenuFontColor(nativeNode);
122 } else {
123 GetArkUINodeModifiers()->getMenuModifier()->setMenuFontColor(nativeNode, color.GetValue());
124 }
125
126 return panda::JSValueRef::Undefined(vm);
127 }
128
ResetMenuFontColor(ArkUIRuntimeCallInfo * runtimeCallInfo)129 ArkUINativeModuleValue MenuBridge::ResetMenuFontColor(ArkUIRuntimeCallInfo* runtimeCallInfo)
130 {
131 EcmaVM* vm = runtimeCallInfo->GetVM();
132 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
133 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
134 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
135 GetArkUINodeModifiers()->getMenuModifier()->resetMenuFontColor(nativeNode);
136 return panda::JSValueRef::Undefined(vm);
137 }
138
SetFont(ArkUIRuntimeCallInfo * runtimeCallInfo)139 ArkUINativeModuleValue MenuBridge::SetFont(ArkUIRuntimeCallInfo* runtimeCallInfo)
140 {
141 EcmaVM* vm = runtimeCallInfo->GetVM();
142 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
143 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
144 Local<JSValueRef> sizeArg = runtimeCallInfo->GetCallArgRef(1); // 1: index of font size value
145 Local<JSValueRef> weightArg = runtimeCallInfo->GetCallArgRef(2); // 2: index of font weight value
146 Local<JSValueRef> familyArg = runtimeCallInfo->GetCallArgRef(3); // 3: index of font family value
147 Local<JSValueRef> styleArg = runtimeCallInfo->GetCallArgRef(4); // 4: index of font style value
148 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
149 if (sizeArg->IsUndefined() && weightArg->IsUndefined() && familyArg->IsUndefined() && styleArg->IsUndefined()) {
150 GetArkUINodeModifiers()->getMenuModifier()->resetFont(nativeNode);
151 return panda::JSValueRef::Undefined(vm);
152 }
153
154 CalcDimension fontSize;
155 if (!ArkTSUtils::ParseJsDimensionFp(vm, sizeArg, fontSize, false)) {
156 fontSize = Dimension(0.0);
157 }
158 std::string weight = DEFAULT_ERR_CODE;
159 if (weightArg->IsNumber()) {
160 weight = std::to_string(weightArg->Int32Value(vm));
161 } else {
162 if (!ArkTSUtils::ParseJsString(vm, weightArg, weight) || weight.empty()) {
163 weight = DEFAULT_ERR_CODE;
164 }
165 }
166
167 int32_t style = -1;
168 if (styleArg->IsNumber()) {
169 style = styleArg->Int32Value(vm);
170 }
171
172 std::string family;
173 if (!ArkTSUtils::ParseJsFontFamiliesToString(vm, familyArg, family) || family.empty()) {
174 family = DEFAULT_ERR_CODE;
175 }
176 std::string fontSizeStr = fontSize.ToString();
177 std::string fontInfo =
178 StringUtils::FormatString(FORMAT_FONT.c_str(), fontSizeStr.c_str(), weight.c_str(), family.c_str());
179
180 GetArkUINodeModifiers()->getMenuModifier()->setFont(nativeNode, fontInfo.c_str(), style);
181 return panda::JSValueRef::Undefined(vm);
182 }
183
ResetFont(ArkUIRuntimeCallInfo * runtimeCallInfo)184 ArkUINativeModuleValue MenuBridge::ResetFont(ArkUIRuntimeCallInfo* runtimeCallInfo)
185 {
186 EcmaVM* vm = runtimeCallInfo->GetVM();
187 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
188 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
189 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
190 GetArkUINodeModifiers()->getMenuModifier()->resetFont(nativeNode);
191 return panda::JSValueRef::Undefined(vm);
192 }
193
ParseRadius(EcmaVM * vm,ArkUIRuntimeCallInfo * runtimeCallInfo,ArkUINodeHandle nativeNode,std::vector<ArkUI_Float32> & radiusValues,std::vector<int32_t> & radiusUnits)194 bool MenuBridge::ParseRadius(EcmaVM* vm, ArkUIRuntimeCallInfo* runtimeCallInfo, ArkUINodeHandle nativeNode,
195 std::vector<ArkUI_Float32>& radiusValues, std::vector<int32_t>& radiusUnits)
196 {
197 Local<JSValueRef> topLeftArgs = runtimeCallInfo->GetCallArgRef(1); // 1: index of top left value
198 Local<JSValueRef> topRightArgs = runtimeCallInfo->GetCallArgRef(2); // 2: index of top right value
199 Local<JSValueRef> bottomLeftArgs = runtimeCallInfo->GetCallArgRef(3); // 3: index of bottom left value
200 Local<JSValueRef> bottomRightArgs = runtimeCallInfo->GetCallArgRef(4); // 4: index of bottom right value
201 Local<JSValueRef> isObjectArgs = runtimeCallInfo->GetCallArgRef(5); // 5: check is object radius
202 if (topLeftArgs->IsUndefined() && topRightArgs->IsUndefined() && bottomLeftArgs->IsUndefined() &&
203 bottomRightArgs->IsUndefined()) {
204 GetArkUINodeModifiers()->getMenuModifier()->resetRadius(nativeNode);
205 return false;
206 }
207
208 CalcDimension topLeft;
209 CalcDimension topRight;
210 CalcDimension bottomLeft;
211 CalcDimension bottomRight;
212 if (isObjectArgs->IsBoolean() && !isObjectArgs->ToBoolean(vm)->Value()) {
213 if (!ArkTSUtils::ParseJsDimensionVpNG(vm, topLeftArgs, topLeft, true)) {
214 GetArkUINodeModifiers()->getMenuModifier()->resetRadius(nativeNode);
215 return false;
216 }
217 if (LessNotEqual(topLeft.Value(), 0.0)) {
218 GetArkUINodeModifiers()->getMenuModifier()->resetRadius(nativeNode);
219 return false;
220 }
221 topRight = topLeft;
222 bottomLeft = topLeft;
223 bottomRight = topLeft;
224 } else {
225 if (!ArkTSUtils::ParseJsDimensionVpNG(vm, topLeftArgs, topLeft, true)) {
226 topLeft = CalcDimension(0.0, DimensionUnit::VP);
227 }
228
229 if (!ArkTSUtils::ParseJsDimensionVpNG(vm, topRightArgs, topRight, true)) {
230 topRight = CalcDimension(0.0, DimensionUnit::VP);
231 }
232
233 if (!ArkTSUtils::ParseJsDimensionVpNG(vm, bottomLeftArgs, bottomLeft, true)) {
234 bottomLeft = CalcDimension(0.0, DimensionUnit::VP);
235 }
236
237 if (!ArkTSUtils::ParseJsDimensionVpNG(vm, bottomRightArgs, bottomRight, true)) {
238 bottomRight = CalcDimension(0.0, DimensionUnit::VP);
239 }
240 }
241 radiusUnits.push_back(static_cast<int32_t>(topLeft.Unit()));
242 radiusUnits.push_back(static_cast<int32_t>(topRight.Unit()));
243 radiusUnits.push_back(static_cast<int32_t>(bottomLeft.Unit()));
244 radiusUnits.push_back(static_cast<int32_t>(bottomRight.Unit()));
245 radiusValues.push_back(topLeft.Value());
246 radiusValues.push_back(topRight.Value());
247 radiusValues.push_back(bottomLeft.Value());
248 radiusValues.push_back(bottomRight.Value());
249 return true;
250 }
251
SetRadius(ArkUIRuntimeCallInfo * runtimeCallInfo)252 ArkUINativeModuleValue MenuBridge::SetRadius(ArkUIRuntimeCallInfo* runtimeCallInfo)
253 {
254 EcmaVM* vm = runtimeCallInfo->GetVM();
255 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
256 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
257 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
258 std::vector<ArkUI_Float32> radiusValues;
259 std::vector<int32_t> radiusUnits;
260 if (!ParseRadius(vm, runtimeCallInfo, nativeNode, radiusValues, radiusUnits)) {
261 return panda::JSValueRef::Undefined(vm);
262 }
263 GetArkUINodeModifiers()->getMenuModifier()->setRadius(nativeNode, radiusValues.data(), radiusUnits.data());
264 return panda::JSValueRef::Undefined(vm);
265 }
266
ResetRadius(ArkUIRuntimeCallInfo * runtimeCallInfo)267 ArkUINativeModuleValue MenuBridge::ResetRadius(ArkUIRuntimeCallInfo* runtimeCallInfo)
268 {
269 EcmaVM* vm = runtimeCallInfo->GetVM();
270 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
271 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
272 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
273 GetArkUINodeModifiers()->getMenuModifier()->resetRadius(nativeNode);
274 return panda::JSValueRef::Undefined(vm);
275 }
276
SetWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)277 ArkUINativeModuleValue MenuBridge::SetWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
278 {
279 EcmaVM* vm = runtimeCallInfo->GetVM();
280 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
281 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
282 Local<JSValueRef> widthArg = runtimeCallInfo->GetCallArgRef(1);
283 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
284 CalcDimension width;
285 if (!ArkTSUtils::ParseJsDimensionVp(vm, widthArg, width, false)) {
286 GetArkUINodeModifiers()->getMenuModifier()->resetMenuWidth(nativeNode);
287 return panda::JSValueRef::Undefined(vm);
288 }
289 GetArkUINodeModifiers()->getMenuModifier()->setMenuWidth(
290 nativeNode, width.Value(), static_cast<int32_t>(width.Unit()));
291 return panda::JSValueRef::Undefined(vm);
292 }
293
ResetWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)294 ArkUINativeModuleValue MenuBridge::ResetWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
295 {
296 EcmaVM* vm = runtimeCallInfo->GetVM();
297 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
298 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
299 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
300 GetArkUINodeModifiers()->getMenuModifier()->resetMenuWidth(nativeNode);
301 return panda::JSValueRef::Undefined(vm);
302 }
303
SetMenuItemDivider(ArkUIRuntimeCallInfo * runtimeCallInfo)304 ArkUINativeModuleValue MenuBridge::SetMenuItemDivider(ArkUIRuntimeCallInfo* runtimeCallInfo)
305 {
306 return SetMenuDivider(runtimeCallInfo, false);
307 }
308
ResetMenuItemDivider(ArkUIRuntimeCallInfo * runtimeCallInfo)309 ArkUINativeModuleValue MenuBridge::ResetMenuItemDivider(ArkUIRuntimeCallInfo* runtimeCallInfo)
310 {
311 return ResetMenuDivider(runtimeCallInfo, false);
312 }
313
SetMenuItemGroupDivider(ArkUIRuntimeCallInfo * runtimeCallInfo)314 ArkUINativeModuleValue MenuBridge::SetMenuItemGroupDivider(ArkUIRuntimeCallInfo* runtimeCallInfo)
315 {
316 return SetMenuDivider(runtimeCallInfo, true);
317 }
318
ResetMenuItemGroupDivider(ArkUIRuntimeCallInfo * runtimeCallInfo)319 ArkUINativeModuleValue MenuBridge::ResetMenuItemGroupDivider(ArkUIRuntimeCallInfo* runtimeCallInfo)
320 {
321 return ResetMenuDivider(runtimeCallInfo, true);
322 }
323
SetSubMenuExpandingMode(ArkUIRuntimeCallInfo * runtimeCallInfo)324 ArkUINativeModuleValue MenuBridge::SetSubMenuExpandingMode(ArkUIRuntimeCallInfo* runtimeCallInfo)
325 {
326 EcmaVM* vm = runtimeCallInfo->GetVM();
327 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
328 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
329 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
330 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
331 if (secondArg->IsUndefined() || secondArg->IsNull()) {
332 GetArkUINodeModifiers()->getMenuModifier()->resetSubMenuExpandingMode(nativeNode);
333 return panda::JSValueRef::Undefined(vm);
334 }
335 if (secondArg->IsNumber()) {
336 GetArkUINodeModifiers()->getMenuModifier()->setSubMenuExpandingMode(nativeNode,
337 secondArg->ToNumber(vm)->Value());
338 } else {
339 GetArkUINodeModifiers()->getMenuModifier()->resetSubMenuExpandingMode(nativeNode);
340 }
341 return panda::JSValueRef::Undefined(vm);
342 }
343
ResetSubMenuExpandingMode(ArkUIRuntimeCallInfo * runtimeCallInfo)344 ArkUINativeModuleValue MenuBridge::ResetSubMenuExpandingMode(ArkUIRuntimeCallInfo* runtimeCallInfo)
345 {
346 EcmaVM* vm = runtimeCallInfo->GetVM();
347 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
348 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
349 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
350 GetArkUINodeModifiers()->getMenuModifier()->resetSubMenuExpandingMode(nativeNode);
351 return panda::JSValueRef::Undefined(vm);
352 }
353 } // namespace OHOS::Ace::NG
354