1 /*
2 * Copyright (c) 2021-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
16 #include "frameworks/bridge/declarative_frontend/jsview/js_button.h"
17
18 #include "base/geometry/dimension.h"
19 #include "base/log/ace_scoring_log.h"
20 #include "base/log/ace_trace.h"
21 #include "base/utils/utils.h"
22 #include "core/components/button/button_component.h"
23 #include "core/components/button/button_theme.h"
24 #include "core/components_ng/base/view_stack_processor.h"
25 #include "core/components_ng/pattern/button/button_model_ng.h"
26 #include "frameworks/bridge/declarative_frontend/engine/functions/js_click_function.h"
27 #include "frameworks/bridge/declarative_frontend/jsview/js_utils.h"
28 #include "frameworks/bridge/declarative_frontend/jsview/models/button_model_impl.h"
29 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
30
31 namespace OHOS::Ace {
32 std::unique_ptr<ButtonModel> ButtonModel::instance_ = nullptr;
33 std::mutex ButtonModel::mutex_;
34
GetInstance()35 ButtonModel* ButtonModel::GetInstance()
36 {
37 if (!instance_) {
38 std::lock_guard<std::mutex> lock(mutex_);
39 if (!instance_) {
40 #ifdef NG_BUILD
41 instance_.reset(new NG::ButtonModelNG());
42 #else
43 if (Container::IsCurrentUseNewPipeline()) {
44 instance_.reset(new NG::ButtonModelNG());
45 } else {
46 instance_.reset(new Framework::ButtonModelImpl());
47 }
48 #endif
49 }
50 }
51 return instance_.get();
52 }
53 } // namespace OHOS::Ace
54
55 namespace OHOS::Ace::Framework {
56 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
57 TextOverflow::MARQUEE };
58 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
59 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICY = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
60 TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
61
62 bool JSButton::isLabelButton_ = false;
63
SetFontSize(const JSCallbackInfo & info)64 void JSButton::SetFontSize(const JSCallbackInfo& info)
65 {
66 auto buttonTheme = GetTheme<ButtonTheme>();
67 CHECK_NULL_VOID(buttonTheme);
68 CalcDimension fontSize = buttonTheme->GetTextStyle().GetFontSize();
69 if (ParseJsDimensionVpNG(info[0], fontSize) && fontSize.Unit() != DimensionUnit::PERCENT &&
70 GreatOrEqual(fontSize.Value(), 0.0)) {
71 ParseJsDimensionFp(info[0], fontSize);
72 } else {
73 fontSize = buttonTheme->GetTextStyle().GetFontSize();
74 }
75 ButtonModel::GetInstance()->SetFontSize(fontSize);
76 }
77
SetFontWeight(const std::string & value)78 void JSButton::SetFontWeight(const std::string& value)
79 {
80 ButtonModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(value));
81 }
82
SetFontStyle(int32_t value)83 void JSButton::SetFontStyle(int32_t value)
84 {
85 const std::vector<FontStyle> fontStyles = { FontStyle::NORMAL, FontStyle::ITALIC };
86 if (value < 0 || value >= static_cast<int32_t>(fontStyles.size())) {
87 return;
88 }
89
90 ButtonModel::GetInstance()->SetFontStyle(fontStyles[value]);
91 }
92
SetFontFamily(const JSCallbackInfo & info)93 void JSButton::SetFontFamily(const JSCallbackInfo& info)
94 {
95 std::vector<std::string> fontFamilies;
96 if (!ParseJsFontFamilies(info[0], fontFamilies)) {
97 return;
98 }
99
100 ButtonModel::GetInstance()->SetFontFamily(fontFamilies);
101 }
102
SetTextColor(const JSCallbackInfo & info)103 void JSButton::SetTextColor(const JSCallbackInfo& info)
104 {
105 Color textColor;
106 if (!ParseJsColor(info[0], textColor)) {
107 auto buttonTheme = PipelineBase::GetCurrentContext()->GetTheme<ButtonTheme>();
108 textColor = buttonTheme->GetTextStyle().GetTextColor();
109 }
110
111 ButtonModel::GetInstance()->SetFontColor(textColor);
112 }
113
SetType(const JSCallbackInfo & info)114 void JSButton::SetType(const JSCallbackInfo& info)
115 {
116 int32_t value = 1;
117 if (info[0]->IsNumber()) {
118 value = info[0]->ToNumber<int32_t>();
119 }
120 if ((ButtonType)value == ButtonType::CAPSULE || (ButtonType)value == ButtonType::CIRCLE ||
121 (ButtonType)value == ButtonType::ARC || (ButtonType)value == ButtonType::NORMAL) {
122 ButtonModel::GetInstance()->SetType(value);
123 }
124 }
125
SetButtonStyle(const JSCallbackInfo & info)126 void JSButton::SetButtonStyle(const JSCallbackInfo& info)
127 {
128 int32_t value = static_cast<int32_t>(ButtonStyleMode::EMPHASIZE);
129 if (info[0]->IsNumber()) {
130 auto valueT = info[0]->ToNumber<int32_t>();
131 if (valueT >= static_cast<int32_t>(ButtonStyleMode::NORMAL) &&
132 valueT <= static_cast<int32_t>(ButtonStyleMode::TEXT)) {
133 value = valueT;
134 }
135 }
136 ButtonModel::GetInstance()->SetButtonStyle(static_cast<ButtonStyleMode>(value));
137 }
138
SetControlSize(const JSCallbackInfo & info)139 void JSButton::SetControlSize(const JSCallbackInfo& info)
140 {
141 int32_t value = static_cast<int32_t>(ControlSize::NORMAL);
142 if (info[0]->IsNumber()) {
143 auto valueT = info[0]->ToNumber<int32_t>();
144 if (valueT >= static_cast<int32_t>(ControlSize::SMALL) && valueT <= static_cast<int32_t>(ControlSize::NORMAL)) {
145 value = valueT;
146 }
147 }
148 ButtonModel::GetInstance()->SetControlSize(static_cast<ControlSize>(value));
149 }
150
SetStateEffect(const JSCallbackInfo & info)151 void JSButton::SetStateEffect(const JSCallbackInfo& info)
152 {
153 bool value = info[0]->IsBoolean() ? info[0]->ToBoolean() : true;
154 ButtonModel::GetInstance()->SetStateEffect(value);
155 }
156
HandleDifferentRadius(const JSRef<JSVal> & args)157 void JSButton::HandleDifferentRadius(const JSRef<JSVal>& args)
158 {
159 std::optional<CalcDimension> radiusTopLeft;
160 std::optional<CalcDimension> radiusTopRight;
161 std::optional<CalcDimension> radiusBottomLeft;
162 std::optional<CalcDimension> radiusBottomRight;
163 if (args->IsObject()) {
164 JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
165 CalcDimension topLeft;
166 if (ParseJsDimensionVp(object->GetProperty("topLeft"), topLeft)) {
167 radiusTopLeft = topLeft;
168 }
169 CalcDimension topRight;
170 if (ParseJsDimensionVp(object->GetProperty("topRight"), topRight)) {
171 radiusTopRight = topRight;
172 }
173 CalcDimension bottomLeft;
174 if (ParseJsDimensionVp(object->GetProperty("bottomLeft"), bottomLeft)) {
175 radiusBottomLeft = bottomLeft;
176 }
177 CalcDimension bottomRight;
178 if (ParseJsDimensionVp(object->GetProperty("bottomRight"), bottomRight)) {
179 radiusBottomRight = bottomRight;
180 }
181 if (!radiusTopLeft.has_value() && !radiusTopRight.has_value() && !radiusBottomLeft.has_value() &&
182 !radiusBottomRight.has_value()) {
183 return;
184 }
185 ButtonModel::GetInstance()->SetBorderRadius(radiusTopLeft, radiusTopRight, radiusBottomLeft, radiusBottomRight);
186 }
187 }
188
GetFontContent(JSRef<JSVal> & font,ButtonParameters & buttonParameters)189 void JSButton::GetFontContent(JSRef<JSVal>& font, ButtonParameters& buttonParameters)
190 {
191 JSRef<JSObject> obj = JSRef<JSObject>::Cast(font);
192 JSRef<JSVal> size = obj->GetProperty("size");
193 CalcDimension fontSize;
194 if (ParseJsDimensionFp(size, fontSize)) {
195 buttonParameters.fontSize = fontSize;
196 }
197
198 JSRef<JSVal> weight = obj->GetProperty("weight");
199 if (weight->IsString() || weight->IsNumber()) {
200 buttonParameters.fontWeight = ConvertStrToFontWeight(weight->ToString());
201 }
202
203 JSRef<JSVal> family = obj->GetProperty("family");
204 std::vector<std::string> fontFamilies;
205 if (ParseJsFontFamilies(family, fontFamilies)) {
206 buttonParameters.fontFamily = fontFamilies;
207 }
208
209 JSRef<JSVal> style = obj->GetProperty("style");
210 if (style->IsNumber()) {
211 auto value = style->ToNumber<int32_t>();
212 if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
213 buttonParameters.fontStyle = FONT_STYLES[value];
214 }
215 }
216 }
217
CompleteParameters(ButtonParameters & buttonParameters)218 void JSButton::CompleteParameters(ButtonParameters& buttonParameters)
219 {
220 auto buttonTheme = GetTheme<ButtonTheme>();
221 if (!buttonTheme) {
222 return;
223 }
224 auto textStyle = buttonTheme->GetTextStyle();
225 if (!buttonParameters.maxLines.has_value()) {
226 buttonParameters.maxLines = buttonTheme->GetTextMaxLines();
227 }
228 if (!buttonParameters.fontSize.has_value()) {
229 buttonParameters.fontSize = textStyle.GetFontSize();
230 }
231 if (!buttonParameters.fontWeight.has_value()) {
232 buttonParameters.fontWeight = textStyle.GetFontWeight();
233 }
234 if (!buttonParameters.fontStyle.has_value()) {
235 buttonParameters.fontStyle = textStyle.GetFontStyle();
236 }
237 if (!buttonParameters.heightAdaptivePolicy.has_value()) {
238 buttonParameters.heightAdaptivePolicy = TextHeightAdaptivePolicy::MAX_LINES_FIRST;
239 }
240 if (!buttonParameters.textOverflow.has_value()) {
241 buttonParameters.textOverflow = TextOverflow::CLIP;
242 }
243 }
244
SetLableStyle(const JSCallbackInfo & info)245 void JSButton::SetLableStyle(const JSCallbackInfo& info)
246 {
247 if (!info[0]->IsObject()) {
248 return;
249 }
250
251 ButtonParameters buttonParameters;
252 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
253 JSRef<JSVal> overflowValue = obj->GetProperty("overflow");
254 buttonParameters.textOverflow = TextOverflow::ELLIPSIS;
255 if (!overflowValue->IsNull() && overflowValue->IsNumber()) {
256 auto overflow = overflowValue->ToNumber<int32_t>();
257 if (overflow >= 0 && overflow < static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
258 buttonParameters.textOverflow = TEXT_OVERFLOWS[overflow];
259 }
260 }
261
262 JSRef<JSVal> maxLines = obj->GetProperty("maxLines");
263 if (!maxLines->IsNull() && maxLines->IsNumber()) {
264 buttonParameters.maxLines = Positive(maxLines->ToNumber<int32_t>()) ? maxLines->ToNumber<int32_t>() : 1;
265 }
266
267 JSRef<JSVal> minFontSizeValue = obj->GetProperty("minFontSize");
268 CalcDimension minFontSize;
269 if (ParseJsDimensionFp(minFontSizeValue, minFontSize)) {
270 buttonParameters.minFontSize = minFontSize;
271 }
272
273 JSRef<JSVal> maxFontSizeValue = obj->GetProperty("maxFontSize");
274 CalcDimension maxFontSize;
275 if (ParseJsDimensionFp(maxFontSizeValue, maxFontSize)) {
276 buttonParameters.maxFontSize = maxFontSize;
277 }
278
279 JSRef<JSVal> adaptHeightValue = obj->GetProperty("heightAdaptivePolicy");
280 if (!adaptHeightValue->IsNull() && adaptHeightValue->IsNumber()) {
281 auto adaptHeight = adaptHeightValue->ToNumber<int32_t>();
282 if (adaptHeight >= 0 && adaptHeight < static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
283 buttonParameters.heightAdaptivePolicy = HEIGHT_ADAPTIVE_POLICY[adaptHeight];
284 }
285 }
286
287 JSRef<JSVal> font = obj->GetProperty("font");
288 if (!font->IsNull() && font->IsObject()) {
289 GetFontContent(font, buttonParameters);
290 }
291
292 CompleteParameters(buttonParameters);
293 ButtonModel::GetInstance()->SetLableStyle(buttonParameters);
294 }
295
JsRemoteMessage(const JSCallbackInfo & info)296 void JSButton::JsRemoteMessage(const JSCallbackInfo& info)
297 {
298 RemoteCallback remoteCallback;
299 JSInteractableView::JsRemoteMessage(info, remoteCallback);
300 ButtonModel::GetInstance()->SetRemoteMessage(std::move(remoteCallback));
301 }
302
JSBind(BindingTarget globalObj)303 void JSButton::JSBind(BindingTarget globalObj)
304 {
305 JSClass<JSButton>::Declare("Button");
306 JSClass<JSButton>::StaticMethod("fontColor", &JSButton::SetTextColor, MethodOptions::NONE);
307 JSClass<JSButton>::StaticMethod("fontSize", &JSButton::SetFontSize, MethodOptions::NONE);
308 JSClass<JSButton>::StaticMethod("fontWeight", &JSButton::SetFontWeight, MethodOptions::NONE);
309 JSClass<JSButton>::StaticMethod("fontStyle", &JSButton::SetFontStyle, MethodOptions::NONE);
310 JSClass<JSButton>::StaticMethod("fontFamily", &JSButton::SetFontFamily, MethodOptions::NONE);
311 JSClass<JSButton>::StaticMethod("type", &JSButton::SetType, MethodOptions::NONE);
312 JSClass<JSButton>::StaticMethod("stateEffect", &JSButton::SetStateEffect);
313 JSClass<JSButton>::StaticMethod("labelStyle", &JSButton::SetLableStyle, MethodOptions::NONE);
314 JSClass<JSButton>::StaticMethod("onClick", &JSButton::JsOnClick);
315 JSClass<JSButton>::StaticMethod("remoteMessage", &JSButton::JsRemoteMessage);
316 JSClass<JSButton>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
317 JSClass<JSButton>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
318 JSClass<JSButton>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
319 JSClass<JSButton>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
320 JSClass<JSButton>::StaticMethod("backgroundColor", &JSButton::JsBackgroundColor);
321 JSClass<JSButton>::StaticMethod("width", &JSButton::JsWidth);
322 JSClass<JSButton>::StaticMethod("height", &JSButton::JsHeight);
323 JSClass<JSButton>::StaticMethod("aspectRatio", &JSButton::JsAspectRatio);
324 JSClass<JSButton>::StaticMethod("borderRadius", &JSButton::JsRadius);
325 JSClass<JSButton>::StaticMethod("border", &JSButton::JsBorder);
326 JSClass<JSButton>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
327 JSClass<JSButton>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
328 JSClass<JSButton>::StaticMethod("size", &JSButton::JsSize);
329 JSClass<JSButton>::StaticMethod("padding", &JSButton::JsPadding);
330 JSClass<JSButton>::StaticMethod("buttonStyle", &JSButton::SetButtonStyle);
331 JSClass<JSButton>::StaticMethod("controlSize", &JSButton::SetControlSize);
332 JSClass<JSButton>::StaticMethod("createWithLabel", &JSButton::CreateWithLabel, MethodOptions::NONE);
333 JSClass<JSButton>::StaticMethod("createWithChild", &JSButton::CreateWithChild, MethodOptions::NONE);
334 JSClass<JSButton>::InheritAndBind<JSContainerBase>(globalObj);
335 }
336
CreateWithLabel(const JSCallbackInfo & info)337 void JSButton::CreateWithLabel(const JSCallbackInfo& info)
338 {
339 std::list<RefPtr<Component>> buttonChildren;
340 CreateWithPara para = ParseCreatePara(info, true);
341 ButtonModel::GetInstance()->CreateWithLabel(para, buttonChildren);
342 ButtonModel::GetInstance()->Create(para, buttonChildren);
343 isLabelButton_ = true;
344 }
345
CreateWithChild(const JSCallbackInfo & info)346 void JSButton::CreateWithChild(const JSCallbackInfo& info)
347 {
348 CreateWithPara para = ParseCreatePara(info, false);
349 ButtonModel::GetInstance()->CreateWithChild(para);
350 isLabelButton_ = false;
351 }
352
JsPadding(const JSCallbackInfo & info)353 void JSButton::JsPadding(const JSCallbackInfo& info)
354 {
355 NG::PaddingProperty paddingNew = GetNewPadding(info);
356 Edge paddingOld = Edge(GetOldPadding(info));
357 ButtonModel::GetInstance()->Padding(paddingNew, paddingOld);
358 }
359
GetOldPadding(const JSCallbackInfo & info)360 Edge JSButton::GetOldPadding(const JSCallbackInfo& info)
361 {
362 Edge padding;
363
364 if (info[0]->IsNumber()) {
365 CalcDimension edgeValue;
366 if (ParseJsDimensionVp(info[0], edgeValue)) {
367 padding = Edge(edgeValue);
368 }
369 } else if (info[0]->IsObject()) {
370 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
371 CalcDimension left = CalcDimension(0.0, DimensionUnit::VP);
372 CalcDimension top = CalcDimension(0.0, DimensionUnit::VP);
373 CalcDimension right = CalcDimension(0.0, DimensionUnit::VP);
374 CalcDimension bottom = CalcDimension(0.0, DimensionUnit::VP);
375 if (jsObj->HasProperty("top") || jsObj->HasProperty("bottom")
376 || jsObj->HasProperty("left") || jsObj->HasProperty("right")) {
377 ParseJsDimensionVp(jsObj->GetProperty("left"), left);
378 ParseJsDimensionVp(jsObj->GetProperty("top"), top);
379 ParseJsDimensionVp(jsObj->GetProperty("right"), right);
380 ParseJsDimensionVp(jsObj->GetProperty("bottom"), bottom);
381 }
382 padding = Edge(left, top, right, bottom);
383 }
384
385 return padding;
386 }
387
GetNewPadding(const JSCallbackInfo & info)388 NG::PaddingProperty JSButton::GetNewPadding(const JSCallbackInfo& info)
389 {
390 NG::PaddingProperty padding = { NG::CalcLength(0.0), NG::CalcLength(0.0), NG::CalcLength(0.0),
391 NG::CalcLength(0.0) };
392 if (isLabelButton_) {
393 auto buttonTheme = GetTheme<ButtonTheme>();
394 auto defaultPadding = buttonTheme->GetPadding();
395 padding = { NG::CalcLength(defaultPadding.Left()), NG::CalcLength(defaultPadding.Right()),
396 NG::CalcLength(defaultPadding.Top()), NG::CalcLength(defaultPadding.Bottom()) };
397 }
398 if (info[0]->IsObject()) {
399 std::optional<CalcDimension> left;
400 std::optional<CalcDimension> right;
401 std::optional<CalcDimension> top;
402 std::optional<CalcDimension> bottom;
403 JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info[0]);
404
405 CalcDimension leftDimen;
406 if (ParseJsDimensionVp(paddingObj->GetProperty("left"), leftDimen)) {
407 left = leftDimen;
408 }
409 CalcDimension rightDimen;
410 if (ParseJsDimensionVp(paddingObj->GetProperty("right"), rightDimen)) {
411 right = rightDimen;
412 }
413 CalcDimension topDimen;
414 if (ParseJsDimensionVp(paddingObj->GetProperty("top"), topDimen)) {
415 top = topDimen;
416 }
417 CalcDimension bottomDimen;
418 if (ParseJsDimensionVp(paddingObj->GetProperty("bottom"), bottomDimen)) {
419 bottom = bottomDimen;
420 }
421 if (left.has_value() || right.has_value() || top.has_value() || bottom.has_value()) {
422 padding = SetPaddings(top, bottom, left, right);
423 return padding;
424 }
425 }
426
427 CalcDimension length(-1);
428 ParseJsDimensionVp(info[0], length);
429 if (length.IsNonNegative()) {
430 padding.SetEdges(NG::CalcLength(length));
431 }
432 return padding;
433 }
434
SetPaddings(const std::optional<CalcDimension> & top,const std::optional<CalcDimension> & bottom,const std::optional<CalcDimension> & left,const std::optional<CalcDimension> & right)435 NG::PaddingProperty JSButton::SetPaddings(const std::optional<CalcDimension>& top,
436 const std::optional<CalcDimension>& bottom, const std::optional<CalcDimension>& left,
437 const std::optional<CalcDimension>& right)
438 {
439 NG::PaddingProperty paddings;
440 if (top.has_value()) {
441 if (top.value().Unit() == DimensionUnit::CALC) {
442 paddings.top =
443 NG::CalcLength(top.value().IsNonNegative() ? top.value().CalcValue() : CalcDimension().CalcValue());
444 } else {
445 paddings.top = NG::CalcLength(top.value().IsNonNegative() ? top.value() : CalcDimension());
446 }
447 }
448 if (bottom.has_value()) {
449 if (bottom.value().Unit() == DimensionUnit::CALC) {
450 paddings.bottom = NG::CalcLength(
451 bottom.value().IsNonNegative() ? bottom.value().CalcValue() : CalcDimension().CalcValue());
452 } else {
453 paddings.bottom = NG::CalcLength(bottom.value().IsNonNegative() ? bottom.value() : CalcDimension());
454 }
455 }
456 if (left.has_value()) {
457 if (left.value().Unit() == DimensionUnit::CALC) {
458 paddings.left =
459 NG::CalcLength(left.value().IsNonNegative() ? left.value().CalcValue() : CalcDimension().CalcValue());
460 } else {
461 paddings.left = NG::CalcLength(left.value().IsNonNegative() ? left.value() : CalcDimension());
462 }
463 }
464 if (right.has_value()) {
465 if (right.value().Unit() == DimensionUnit::CALC) {
466 paddings.right =
467 NG::CalcLength(right.value().IsNonNegative() ? right.value().CalcValue() : CalcDimension().CalcValue());
468 } else {
469 paddings.right = NG::CalcLength(right.value().IsNonNegative() ? right.value() : CalcDimension());
470 }
471 }
472
473 return paddings;
474 }
475
JsOnClick(const JSCallbackInfo & info)476 void JSButton::JsOnClick(const JSCallbackInfo& info)
477 {
478 if (info[0]->IsUndefined() && IsDisableEventVersion()) {
479 ViewAbstractModel::GetInstance()->DisableOnClick();
480 return;
481 }
482 if (!info[0]->IsFunction()) {
483 return;
484 }
485
486 auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
487 WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
488 auto onTap = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = targetNode](GestureEvent& info) {
489 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
490 ACE_SCORING_EVENT("onClick");
491 PipelineContext::SetCallBackNode(node);
492 func->Execute(info);
493 };
494 auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = targetNode](
495 const ClickInfo* info) {
496 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
497 ACE_SCORING_EVENT("onClick");
498 PipelineContext::SetCallBackNode(node);
499 func->Execute(*info);
500 };
501
502 ButtonModel::GetInstance()->OnClick(std::move(onTap), std::move(onClick));
503 }
504
JsBackgroundColor(const JSCallbackInfo & info)505 void JSButton::JsBackgroundColor(const JSCallbackInfo& info)
506 {
507 Color backgroundColor;
508 bool colorFlag = ParseJsColor(info[0], backgroundColor);
509 if (!colorFlag) {
510 auto buttonTheme = GetTheme<ButtonTheme>();
511 if (buttonTheme) {
512 backgroundColor = buttonTheme->GetBgColor();
513 }
514 }
515
516 ButtonModel::GetInstance()->BackgroundColor(backgroundColor, colorFlag);
517 info.ReturnSelf();
518 }
519
JsWidth(const JSCallbackInfo & info)520 void JSButton::JsWidth(const JSCallbackInfo& info)
521 {
522 JSViewAbstract::JsWidth(info);
523 CalcDimension value = GetSizeValue(info);
524 if (LessNotEqual(value.Value(), 0.0)) {
525 return;
526 }
527
528 ButtonModel::GetInstance()->SetWidth(value);
529 }
530
JsHeight(const JSCallbackInfo & info)531 void JSButton::JsHeight(const JSCallbackInfo& info)
532 {
533 JSViewAbstract::JsHeight(info);
534 CalcDimension value = GetSizeValue(info);
535 if (LessNotEqual(value.Value(), 0.0)) {
536 return;
537 }
538
539 ButtonModel::GetInstance()->SetHeight(value);
540 }
541
JsAspectRatio(const JSCallbackInfo & info)542 void JSButton::JsAspectRatio(const JSCallbackInfo& info)
543 {
544 JSViewAbstract::JsAspectRatio(info);
545 double value = 0.0;
546 if (!ParseJsDouble(info[0], value)) {
547 return;
548 }
549
550 ButtonModel::GetInstance()->SetAspectRatio(value);
551 }
552
JsSize(const JSCallbackInfo & info)553 void JSButton::JsSize(const JSCallbackInfo& info)
554 {
555 if (!info[0]->IsObject()) {
556 return;
557 }
558
559 std::optional<CalcDimension> widthInfo;
560 std::optional<CalcDimension> heightInfo;
561 JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
562 CalcDimension width;
563 if (ParseJsDimensionVp(sizeObj->GetProperty("width"), width)) {
564 widthInfo = width;
565 }
566 CalcDimension height;
567 if (ParseJsDimensionVp(sizeObj->GetProperty("height"), height)) {
568 heightInfo = height;
569 }
570
571 ButtonModel::GetInstance()->SetSize(widthInfo, heightInfo);
572 }
573
JsRadius(const JSCallbackInfo & info)574 void JSButton::JsRadius(const JSCallbackInfo& info)
575 {
576 CalcDimension radius;
577 ParseJsDimensionVp(info[0], radius);
578 ButtonModel::GetInstance()->SetBorderRadius(radius);
579 HandleDifferentRadius(info[0]);
580 }
581
JsBorder(const JSCallbackInfo & info)582 void JSButton::JsBorder(const JSCallbackInfo& info)
583 {
584 JSViewAbstract::JsBorder(info);
585 if (!info[0]->IsObject()) {
586 return;
587 }
588 JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
589 CalcDimension borderRadius;
590 auto valueRadius = object->GetProperty("radius");
591 ParseJsDimensionVp(valueRadius, borderRadius);
592 ButtonModel::GetInstance()->SetBorderRadius(borderRadius);
593 HandleDifferentRadius(valueRadius);
594 }
595
GetSizeValue(const JSCallbackInfo & info)596 CalcDimension JSButton::GetSizeValue(const JSCallbackInfo& info)
597 {
598 CalcDimension value;
599 if (!ParseJsDimensionVp(info[0], value)) {
600 return { -1.0 };
601 }
602 return value;
603 }
604
ParseCreatePara(const JSCallbackInfo & info,bool hasLabel)605 CreateWithPara JSButton::ParseCreatePara(const JSCallbackInfo& info, bool hasLabel)
606 {
607 std::string label;
608 CreateWithPara para;
609 para.parseSuccess = false;
610 para.optionSetFirst = false;
611 if (info.Length() < 1) {
612 para.label = label;
613 return para;
614 }
615 int32_t optionIndex = 0;
616 if (hasLabel) {
617 para.parseSuccess = ParseJsString(info[0], label);
618 if (para.parseSuccess) {
619 // resource string
620 if (info[0]->IsObject() && JSRef<JSObject>::Cast(info[0])->HasProperty("id")) {
621 optionIndex++;
622 // string
623 } else if (info[0]->IsString()) {
624 optionIndex++;
625 }
626 }
627 para.label = label;
628 }
629 if (optionIndex >= info.Length() || !info[optionIndex]->IsObject()) {
630 return para;
631 }
632 if (optionIndex == 0) {
633 para.optionSetFirst = true;
634 }
635 JSRef<JSObject> optionObj = JSRef<JSObject>::Cast(info[optionIndex]);
636 if (optionObj->GetProperty(JSButton::TYPE)->IsNumber()) {
637 para.type = static_cast<ButtonType>(optionObj->GetProperty(JSButton::TYPE)->ToNumber<int32_t>());
638 }
639 if (optionObj->GetProperty(JSButton::STATE_EFFECT)->IsBoolean()) {
640 para.stateEffect = optionObj->GetProperty(JSButton::STATE_EFFECT)->ToBoolean();
641 }
642 if (optionObj->HasProperty(JSButton::BUTTON_STYLE)) {
643 para.buttonStyleMode = ButtonStyleMode::EMPHASIZE;
644 }
645 if (optionObj->GetProperty(JSButton::BUTTON_STYLE)->IsNumber()) {
646 auto styleModeIntValue = optionObj->GetProperty(JSButton::BUTTON_STYLE)->ToNumber<int32_t>();
647 if (styleModeIntValue >= static_cast<int32_t>(ButtonStyleMode::NORMAL) &&
648 styleModeIntValue <= static_cast<int32_t>(ButtonStyleMode::TEXT)) {
649 para.buttonStyleMode = static_cast<ButtonStyleMode>(styleModeIntValue);
650 }
651 }
652 if (optionObj->HasProperty(JSButton::CONTROL_SIZE)) {
653 para.controlSize = ControlSize::NORMAL;
654 }
655 if (optionObj->GetProperty(JSButton::CONTROL_SIZE)->IsNumber()) {
656 auto controlSizeIntValue = optionObj->GetProperty(JSButton::CONTROL_SIZE)->ToNumber<int32_t>();
657 if (controlSizeIntValue >= static_cast<int32_t>(ControlSize::SMALL) &&
658 controlSizeIntValue <= static_cast<int32_t>(ControlSize::NORMAL)) {
659 para.controlSize = static_cast<ControlSize>(controlSizeIntValue);
660 }
661 }
662 return para;
663 }
664 } // namespace OHOS::Ace::Framework
665