1 /*
2 * Copyright (c) 2021-2022 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/log/log_wrapper.h"
22 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
23 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
24 #include "core/common/ace_page.h"
25 #include "core/components/box/box_component_helper.h"
26 #include "core/components/button/button_component.h"
27 #include "core/components/button/button_theme.h"
28 #include "core/components/padding/padding_component.h"
29 #include "core/components_ng/base/view_abstract.h"
30 #include "core/components_ng/base/view_abstract_model.h"
31 #include "core/components_ng/pattern/button/button_view.h"
32 #include "core/components_v2/inspector/inspector_constants.h"
33 #include "frameworks/bridge/common/utils/utils.h"
34 #include "frameworks/bridge/declarative_frontend/engine/bindings.h"
35 #include "frameworks/bridge/declarative_frontend/engine/functions/js_click_function.h"
36 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
37 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
38
39 namespace OHOS::Ace::Framework {
40
SetFontSize(const JSCallbackInfo & info)41 void JSButton::SetFontSize(const JSCallbackInfo& info)
42 {
43 if (info.Length() < 1) {
44 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
45 return;
46 }
47 Dimension fontSize;
48 if (!ParseJsDimensionFp(info[0], fontSize)) {
49 return;
50 }
51 if (Container::IsCurrentUseNewPipeline()) {
52 NG::ButtonView::SetFontSize(fontSize);
53 return;
54 }
55 auto textComponent = GetTextComponent();
56 if (textComponent) {
57 auto textStyle = textComponent->GetTextStyle();
58 textStyle.SetFontSize(fontSize);
59 textStyle.SetAdaptTextSize(fontSize, fontSize);
60 textComponent->SetTextStyle(textStyle);
61 }
62
63 auto stack = ViewStackProcessor::GetInstance();
64 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
65 if (!buttonComponent) {
66 return;
67 }
68 if (buttonComponent->NeedResetHeight()) {
69 ResetButtonHeight();
70 }
71 }
72
SetFontWeight(const std::string & value)73 void JSButton::SetFontWeight(const std::string& value)
74 {
75 if (Container::IsCurrentUseNewPipeline()) {
76 NG::ButtonView::SetFontWeight(ConvertStrToFontWeight(value));
77 return;
78 }
79 auto textComponent = GetTextComponent();
80 if (textComponent) {
81 auto textStyle = textComponent->GetTextStyle();
82 textStyle.SetFontWeight(ConvertStrToFontWeight(value));
83 textComponent->SetTextStyle(textStyle);
84 }
85 }
86
SetFontStyle(int32_t value)87 void JSButton::SetFontStyle(int32_t value)
88 {
89 const std::vector<FontStyle> fontStyles = { FontStyle::NORMAL, FontStyle::ITALIC };
90 if (value < 0 || value >= static_cast<int32_t>(fontStyles.size())) {
91 LOGE("Text fontStyle(%d) is invalid value", value);
92 return;
93 }
94 if (Container::IsCurrentUseNewPipeline()) {
95 NG::ButtonView::SetFontStyle(fontStyles[value]);
96 return;
97 }
98 auto textComponent = GetTextComponent();
99 if (textComponent) {
100 auto textStyle = textComponent->GetTextStyle();
101 textStyle.SetFontStyle(fontStyles[value]);
102 textComponent->SetTextStyle(textStyle);
103 }
104 }
105
SetFontFamily(const JSCallbackInfo & info)106 void JSButton::SetFontFamily(const JSCallbackInfo& info)
107 {
108 if (info.Length() < 1) {
109 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
110 return;
111 }
112 std::vector<std::string> fontFamilies;
113 if (!ParseJsFontFamilies(info[0], fontFamilies)) {
114 LOGE("Parse FontFamilies failed");
115 return;
116 }
117 if (Container::IsCurrentUseNewPipeline()) {
118 NG::ButtonView::SetFontFamily(fontFamilies);
119 return;
120 }
121 auto textComponent = GetTextComponent();
122 if (textComponent) {
123 auto textStyle = textComponent->GetTextStyle();
124 textStyle.SetFontFamilies(fontFamilies);
125 textComponent->SetTextStyle(textStyle);
126 }
127 }
128
SetTextColor(const JSCallbackInfo & info)129 void JSButton::SetTextColor(const JSCallbackInfo& info)
130 {
131 if (info.Length() < 1) {
132 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
133 return;
134 }
135 Color textColor;
136 if (!ParseJsColor(info[0], textColor)) {
137 LOGI("Set text color is invalid, use default text color.");
138 auto buttonTheme = PipelineBase::GetCurrentContext()->GetTheme<ButtonTheme>();
139 textColor = buttonTheme->GetTextStyle().GetTextColor();
140 }
141 if (Container::IsCurrentUseNewPipeline()) {
142 NG::ButtonView::SetFontColor(textColor);
143 return;
144 }
145 auto textComponent = GetTextComponent();
146 if (textComponent) {
147 auto textStyle = textComponent->GetTextStyle();
148 textStyle.SetTextColor(textColor);
149 textComponent->SetTextStyle(textStyle);
150 }
151 }
152
GetTextComponent()153 RefPtr<TextComponent> JSButton::GetTextComponent()
154 {
155 auto stack = ViewStackProcessor::GetInstance();
156 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
157 if (buttonComponent == nullptr) {
158 LOGE("Button component create failed");
159 return nullptr;
160 }
161 auto paddingComponent = AceType::DynamicCast<PaddingComponent>(buttonComponent->GetChildren().front());
162 if (!paddingComponent) {
163 LOGE("Padding component create failed");
164 return nullptr;
165 }
166 auto textComponent = AceType::DynamicCast<TextComponent>(paddingComponent->GetChild());
167 return textComponent;
168 }
169
SetType(const JSCallbackInfo & info)170 void JSButton::SetType(const JSCallbackInfo& info)
171 {
172 if (info.Length() < 1) {
173 return;
174 }
175 int32_t value = 1;
176 if (info[0]->IsNumber()) {
177 value = info[0]->ToNumber<int32_t>();
178 }
179 if ((ButtonType)value == ButtonType::CAPSULE || (ButtonType)value == ButtonType::CIRCLE ||
180 (ButtonType)value == ButtonType::ARC || (ButtonType)value == ButtonType::NORMAL) {
181 if (Container::IsCurrentUseNewPipeline()) {
182 NG::ButtonView::SetType(static_cast<ButtonType>(value));
183 return;
184 }
185 auto stack = ViewStackProcessor::GetInstance();
186 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
187 if (buttonComponent) {
188 buttonComponent->SetType((ButtonType)value);
189 }
190 } else {
191 LOGE("Setting button to non valid ButtonType %d", value);
192 }
193 }
194
SetStateEffect(bool stateEffect)195 void JSButton::SetStateEffect(bool stateEffect)
196 {
197 if (Container::IsCurrentUseNewPipeline()) {
198 NG::ButtonView::SetStateEffect(stateEffect);
199 return;
200 }
201 auto stack = ViewStackProcessor::GetInstance();
202 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
203 if (buttonComponent) {
204 buttonComponent->SetStateEffect(stateEffect);
205 }
206 }
207
JsRemoteMessage(const JSCallbackInfo & info)208 void JSButton::JsRemoteMessage(const JSCallbackInfo& info)
209 {
210 RemoteCallback remoteCallback;
211 JSInteractableView::JsRemoteMessage(info, remoteCallback);
212 EventMarker remoteMessageEventId(std::move(remoteCallback));
213 auto stack = ViewStackProcessor::GetInstance();
214 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
215 if (buttonComponent) {
216 buttonComponent->SetRemoteMessageEventId(remoteMessageEventId);
217 }
218 }
219
JSBind(BindingTarget globalObj)220 void JSButton::JSBind(BindingTarget globalObj)
221 {
222 JSClass<JSButton>::Declare("Button");
223 JSClass<JSButton>::StaticMethod("fontColor", &JSButton::SetTextColor, MethodOptions::NONE);
224 JSClass<JSButton>::StaticMethod("fontSize", &JSButton::SetFontSize, MethodOptions::NONE);
225 JSClass<JSButton>::StaticMethod("fontWeight", &JSButton::SetFontWeight, MethodOptions::NONE);
226 JSClass<JSButton>::StaticMethod("fontStyle", &JSButton::SetFontStyle, MethodOptions::NONE);
227 JSClass<JSButton>::StaticMethod("fontFamily", &JSButton::SetFontFamily, MethodOptions::NONE);
228 JSClass<JSButton>::StaticMethod("type", &JSButton::SetType, MethodOptions::NONE);
229 JSClass<JSButton>::StaticMethod("stateEffect", &JSButton::SetStateEffect, MethodOptions::NONE);
230 JSClass<JSButton>::StaticMethod("onClick", &JSButton::JsOnClick);
231 JSClass<JSButton>::StaticMethod("remoteMessage", &JSButton::JsRemoteMessage);
232 JSClass<JSButton>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
233 JSClass<JSButton>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
234 JSClass<JSButton>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
235 JSClass<JSButton>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
236 JSClass<JSButton>::StaticMethod("backgroundColor", &JSButton::JsBackgroundColor);
237 JSClass<JSButton>::StaticMethod("width", &JSButton::JsWidth);
238 JSClass<JSButton>::StaticMethod("height", &JSButton::JsHeight);
239 JSClass<JSButton>::StaticMethod("aspectRatio", &JSButton::JsAspectRatio);
240 JSClass<JSButton>::StaticMethod("borderRadius", &JSButton::JsRadius);
241 JSClass<JSButton>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
242 JSClass<JSButton>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
243 JSClass<JSButton>::StaticMethod("size", &JSButton::JsSize);
244 JSClass<JSButton>::StaticMethod("padding", &JSButton::JsPadding);
245 JSClass<JSButton>::StaticMethod("hoverEffect", &JSButton::JsHoverEffect);
246
247 JSClass<JSButton>::StaticMethod("createWithLabel", &JSButton::CreateWithLabel, MethodOptions::NONE);
248 JSClass<JSButton>::StaticMethod("createWithChild", &JSButton::CreateWithChild, MethodOptions::NONE);
249 JSClass<JSButton>::Inherit<JSContainerBase>();
250 JSClass<JSButton>::Inherit<JSViewAbstract>();
251 JSClass<JSButton>::Bind<>(globalObj);
252 }
253
CreateWithLabel(const JSCallbackInfo & info)254 void JSButton::CreateWithLabel(const JSCallbackInfo& info)
255 {
256 std::list<RefPtr<Component>> buttonChildren;
257 std::string label;
258 bool labelSet = false;
259 if (ParseJsString(info[0], label)) {
260 labelSet = true;
261 if (Container::IsCurrentUseNewPipeline()) {
262 NG::ButtonView::CreateWithLabel(label);
263 if (!labelSet && info[0]->IsObject()) {
264 SetTypeAndStateEffect(JSRef<JSObject>::Cast(info[0]));
265 }
266 if ((info.Length() > 1) && info[1]->IsObject()) {
267 SetTypeAndStateEffect(JSRef<JSObject>::Cast(info[1]));
268 }
269 NG::ViewAbstract::SetHoverEffectAuto(HoverEffectType::SCALE);
270 return;
271 }
272 auto textComponent = AceType::MakeRefPtr<TextComponent>(label);
273 auto buttonTheme = GetTheme<ButtonTheme>();
274 auto textStyle = buttonTheme ? buttonTheme->GetTextStyle() : textComponent->GetTextStyle();
275 textStyle.SetMaxLines(buttonTheme ? buttonTheme->GetTextMaxLines() : 1);
276 textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
277 textComponent->SetTextStyle(textStyle);
278 auto padding = AceType::MakeRefPtr<PaddingComponent>();
279 padding->SetPadding(buttonTheme ? buttonTheme->GetPadding() : Edge());
280 padding->SetChild(textComponent);
281 Component::MergeRSNode(padding, textComponent);
282 buttonChildren.emplace_back(padding);
283 }
284
285 if (Container::IsCurrentUseNewPipeline()) {
286 NG::ButtonView::Create(V2::BUTTON_ETS_TAG);
287 if (!labelSet && info[0]->IsObject()) {
288 SetTypeAndStateEffect(JSRef<JSObject>::Cast(info[0]));
289 }
290 if ((info.Length() > 1) && info[1]->IsObject()) {
291 SetTypeAndStateEffect(JSRef<JSObject>::Cast(info[1]));
292 }
293 NG::ViewAbstract::SetHoverEffectAuto(HoverEffectType::SCALE);
294 return;
295 }
296 auto buttonComponent = AceType::MakeRefPtr<ButtonComponent>(buttonChildren);
297 ViewStackProcessor::GetInstance()->ClaimElementId(buttonComponent);
298 buttonComponent->SetHasCustomChild(false);
299 buttonComponent->SetCatchMode(false);
300 SetDefaultAttributes(buttonComponent);
301 if (!labelSet && info[0]->IsObject()) {
302 SetTypeAndStateEffect(JSRef<JSObject>::Cast(info[0]), buttonComponent);
303 }
304 if ((info.Length() > 1) && info[1]->IsObject()) {
305 SetTypeAndStateEffect(JSRef<JSObject>::Cast(info[1]), buttonComponent);
306 }
307 ViewStackProcessor::GetInstance()->Push(buttonComponent);
308 JSInteractableView::SetFocusable(true);
309 JSInteractableView::SetFocusNode(true);
310
311 buttonComponent->SetMouseAnimationType(HoverAnimationType::SCALE);
312 }
313
CreateWithChild(const JSCallbackInfo & info)314 void JSButton::CreateWithChild(const JSCallbackInfo& info)
315 {
316 if (Container::IsCurrentUseNewPipeline()) {
317 NG::ButtonView::Create(V2::BUTTON_ETS_TAG);
318 if (info[0]->IsObject()) {
319 auto obj = JSRef<JSObject>::Cast(info[0]);
320 SetTypeAndStateEffect(obj);
321 }
322 NG::ViewAbstract::SetHoverEffectAuto(HoverEffectType::SCALE);
323 return;
324 }
325 std::list<RefPtr<Component>> buttonChildren;
326 auto buttonComponent = AceType::MakeRefPtr<ButtonComponent>(buttonChildren);
327 ViewStackProcessor::GetInstance()->ClaimElementId(buttonComponent);
328 buttonComponent->SetHasCustomChild(true);
329 buttonComponent->SetCatchMode(false);
330 SetDefaultAttributes(buttonComponent);
331 if (info[0]->IsObject()) {
332 auto obj = JSRef<JSObject>::Cast(info[0]);
333 SetTypeAndStateEffect(obj, buttonComponent);
334 }
335 if ((info.Length() > 1) && info[1]->IsObject()) {
336 SetTypeAndStateEffect(JSRef<JSObject>::Cast(info[1]), buttonComponent);
337 }
338 ViewStackProcessor::GetInstance()->Push(buttonComponent);
339 JSInteractableView::SetFocusable(true);
340 JSInteractableView::SetFocusNode(true);
341 buttonComponent->SetMouseAnimationType(HoverAnimationType::SCALE);
342 if (buttonComponent->NeedResetHeight()) {
343 ResetButtonHeight();
344 }
345 }
346
SetDefaultAttributes(const RefPtr<ButtonComponent> & buttonComponent)347 void JSButton::SetDefaultAttributes(const RefPtr<ButtonComponent>& buttonComponent)
348 {
349 buttonComponent->SetType(ButtonType::CAPSULE);
350 buttonComponent->SetDeclarativeFlag(true);
351 auto buttonTheme = GetTheme<ButtonTheme>();
352 if (!buttonTheme) {
353 return;
354 }
355 buttonComponent->SetHeight(buttonTheme->GetHeight());
356 buttonComponent->SetBackgroundColor(buttonTheme->GetBgColor());
357 buttonComponent->SetClickedColor(buttonComponent->GetBackgroundColor().BlendColor(buttonTheme->GetClickedColor()));
358 buttonComponent->SetHoverColor(buttonTheme->GetHoverColor());
359 }
360
SetTypeAndStateEffect(const JSRef<JSObject> & obj)361 void JSButton::SetTypeAndStateEffect(const JSRef<JSObject>& obj)
362 {
363 auto type = obj->GetProperty("type");
364 if (type->IsNumber()) {
365 auto buttonType = static_cast<ButtonType>(type->ToNumber<int32_t>());
366 NG::ButtonView::SetType(buttonType);
367 }
368 auto stateEffect = obj->GetProperty("stateEffect");
369 if (stateEffect->IsBoolean()) {
370 NG::ButtonView::SetStateEffect(stateEffect->ToBoolean());
371 }
372 }
373
SetTypeAndStateEffect(const JSRef<JSObject> & obj,const RefPtr<ButtonComponent> & buttonComponent)374 void JSButton::SetTypeAndStateEffect(const JSRef<JSObject>& obj, const RefPtr<ButtonComponent>& buttonComponent)
375 {
376 auto type = obj->GetProperty("type");
377 if (type->IsNumber()) {
378 auto buttonType = (ButtonType)type->ToNumber<int32_t>();
379 buttonComponent->SetType(buttonType);
380 }
381 auto stateEffect = obj->GetProperty("stateEffect");
382 if (stateEffect->IsBoolean()) {
383 buttonComponent->SetStateEffect(stateEffect->ToBoolean());
384 }
385 }
386
ResetButtonHeight()387 void JSButton::ResetButtonHeight()
388 {
389 auto stack = ViewStackProcessor::GetInstance();
390 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
391 if (buttonComponent) {
392 if (buttonComponent->GetType() == ButtonType::CIRCLE) {
393 return;
394 }
395 const Dimension initialHeight = Dimension(-1.0, DimensionUnit::VP);
396 buttonComponent->SetHeight(initialHeight);
397 }
398 }
399
JsPadding(const JSCallbackInfo & info)400 void JSButton::JsPadding(const JSCallbackInfo& info)
401 {
402 if (Container::IsCurrentUseNewPipeline()) {
403 JSViewAbstract::JsPadding(info);
404 return;
405 }
406 if (!info[0]->IsString() && !info[0]->IsNumber() && !info[0]->IsObject()) {
407 LOGE("arg is not a string, number or object.");
408 return;
409 }
410 Edge padding;
411 if (info[0]->IsNumber()) {
412 Dimension edgeValue;
413 if (ParseJsDimensionVp(info[0], edgeValue)) {
414 padding = Edge(edgeValue);
415 }
416 }
417 if (info[0]->IsObject()) {
418 auto object = JsonUtil::ParseJsonString(info[0]->ToString());
419 if (!object) {
420 LOGE("Js Parse object failed. argsPtr is null.");
421 return;
422 }
423 Dimension left = Dimension(0.0, DimensionUnit::VP);
424 Dimension top = Dimension(0.0, DimensionUnit::VP);
425 Dimension right = Dimension(0.0, DimensionUnit::VP);
426 Dimension bottom = Dimension(0.0, DimensionUnit::VP);
427 if (object->Contains("top") || object->Contains("bottom") || object->Contains("left") ||
428 object->Contains("right")) {
429 ParseJsonDimensionVp(object->GetValue("left"), left);
430 ParseJsonDimensionVp(object->GetValue("top"), top);
431 ParseJsonDimensionVp(object->GetValue("right"), right);
432 ParseJsonDimensionVp(object->GetValue("bottom"), bottom);
433 }
434 padding = Edge(left, top, right, bottom);
435 }
436 auto stack = ViewStackProcessor::GetInstance();
437 auto component = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
438 if (component) {
439 auto paddingChild = AceType::DynamicCast<PaddingComponent>(component->GetChildren().front());
440 if (paddingChild) {
441 paddingChild->SetPadding(padding);
442 }
443 if (component->NeedResetHeight()) {
444 ResetButtonHeight();
445 }
446 }
447 }
448
JsOnClick(const JSCallbackInfo & info)449 void JSButton::JsOnClick(const JSCallbackInfo& info)
450 {
451 LOGD("JSButton JsOnClick");
452 if (!info[0]->IsFunction()) {
453 LOGE("OnClick parameter need a function.");
454 return;
455 }
456 if (Container::IsCurrentUseNewPipeline()) {
457 JSInteractableView::JsOnClick(info);
458 return;
459 }
460 auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
461 if (!inspector) {
462 LOGE("fail to get inspector for on click event");
463 return;
464 }
465 auto impl = inspector->GetInspectorFunctionImpl();
466
467 RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
468 auto clickId = [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), impl](GestureEvent& info) {
469 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
470 if (impl) {
471 impl->UpdateEventInfo(info);
472 }
473 ACE_SCORING_EVENT("onClick");
474 func->Execute(info);
475 };
476 RefPtr<Gesture> tapGesture = AceType::MakeRefPtr<TapGesture>(DEFAULT_TAP_COUNTS, DEFAULT_TAP_FINGERS);
477 if (!tapGesture) {
478 LOGE("tapGesture is null");
479 return;
480 }
481 tapGesture->SetOnActionId(clickId);
482 auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
483 if (tapGesture) {
484 box->SetOnClick(tapGesture);
485 }
486
487 RefPtr<JsClickFunction> jsClickEventFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
488 EventMarker clickEventId(
489 [execCtx = info.GetExecutionContext(), func = std::move(jsClickEventFunc), impl](const BaseEventInfo* info) {
490 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
491 auto clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
492 auto newInfo = *clickInfo;
493 if (impl) {
494 impl->UpdateEventInfo(newInfo);
495 }
496 ACE_SCORING_EVENT("Button.onClick");
497 func->Execute(newInfo);
498 });
499 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
500 if (buttonComponent) {
501 buttonComponent->SetKeyEnterEventId(clickEventId);
502 }
503 auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent(false);
504 if (focusableComponent) {
505 focusableComponent->SetOnClickId(clickEventId);
506 }
507 }
508
JsBackgroundColor(const JSCallbackInfo & info)509 void JSButton::JsBackgroundColor(const JSCallbackInfo& info)
510 {
511 if (Container::IsCurrentUseNewPipeline()) {
512 JSViewAbstract::JsBackgroundColor(info);
513 return;
514 }
515 if (info.Length() < 1) {
516 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
517 return;
518 }
519 Color backgroundColor;
520 if (!ParseJsColor(info[0], backgroundColor)) {
521 return;
522 }
523 auto stack = ViewStackProcessor::GetInstance();
524 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
525 AnimationOption option = ViewStackProcessor::GetInstance()->GetImplicitAnimationOption();
526 if (buttonComponent == nullptr) {
527 LOGE("Button component create failed");
528 return;
529 }
530 if (!stack->IsVisualStateSet()) {
531 buttonComponent->SetBackgroundColor(backgroundColor);
532 auto buttonTheme = GetTheme<ButtonTheme>();
533 if (buttonTheme) {
534 Color blendColor = buttonTheme->GetClickedColor();
535 buttonComponent->SetClickedColor(buttonComponent->GetBackgroundColor().BlendColor(blendColor));
536 }
537 } else {
538 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableColor>(
539 ButtonStateAttribute::COLOR, AnimatableColor(backgroundColor, option), stack->GetVisualState());
540 if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::COLOR, VisualState::NORMAL)) {
541 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableColor>(ButtonStateAttribute::COLOR,
542 AnimatableColor(buttonComponent->GetBackgroundColor(), option), VisualState::NORMAL);
543 }
544 }
545 info.ReturnSelf();
546 }
547
JsWidth(const JSCallbackInfo & info)548 void JSButton::JsWidth(const JSCallbackInfo& info)
549 {
550 if (Container::IsCurrentUseNewPipeline()) {
551 JSViewAbstract::JsWidth(info);
552 return;
553 }
554 JSViewAbstract::JsWidth(info);
555 Dimension value = GetSizeValue(info);
556 if (LessNotEqual(value.Value(), 0.0)) {
557 return;
558 }
559 auto stack = ViewStackProcessor::GetInstance();
560 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
561 AnimationOption option = stack->GetImplicitAnimationOption();
562 if (!buttonComponent) {
563 return;
564 }
565 if (!stack->IsVisualStateSet()) {
566 buttonComponent->SetWidth(value, stack->GetImplicitAnimationOption());
567 } else {
568 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
569 ButtonStateAttribute::WIDTH, AnimatableDimension(value, option), stack->GetVisualState());
570 if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::WIDTH, VisualState::NORMAL)) {
571 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::WIDTH,
572 AnimatableDimension(buttonComponent->GetWidth(), option), VisualState::NORMAL);
573 }
574 }
575 }
576
JsHeight(const JSCallbackInfo & info)577 void JSButton::JsHeight(const JSCallbackInfo& info)
578 {
579 if (Container::IsCurrentUseNewPipeline()) {
580 JSViewAbstract::JsHeight(info);
581 return;
582 }
583 JSViewAbstract::JsHeight(info);
584 Dimension value = GetSizeValue(info);
585 if (LessNotEqual(value.Value(), 0.0)) {
586 return;
587 }
588 auto stack = ViewStackProcessor::GetInstance();
589 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
590 auto option = stack->GetImplicitAnimationOption();
591 if (!buttonComponent) {
592 return;
593 }
594 buttonComponent->IsNeedResetHeight(false);
595 if (!stack->IsVisualStateSet()) {
596 buttonComponent->SetHeight(value, option);
597 buttonComponent->SetDeclareHeight(true);
598 } else {
599 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
600 ButtonStateAttribute::HEIGHT, AnimatableDimension(value, option), stack->GetVisualState());
601 if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::HEIGHT, VisualState::NORMAL)) {
602 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::HEIGHT,
603 AnimatableDimension(buttonComponent->GetHeight(), option), VisualState::NORMAL);
604 }
605 }
606 }
607
JsAspectRatio(const JSCallbackInfo & info)608 void JSButton::JsAspectRatio(const JSCallbackInfo& info)
609 {
610 if (Container::IsCurrentUseNewPipeline()) {
611 JSViewAbstract::JsAspectRatio(info);
612 return;
613 }
614 JSViewAbstract::JsAspectRatio(info);
615 if (info.Length() < 1) {
616 LOGE("The arg is wrong, it is supposed to have at least 1 arguments");
617 return;
618 }
619 double value = 0.0;
620 if (!ParseJsDouble(info[0], value)) {
621 return;
622 }
623 auto stack = ViewStackProcessor::GetInstance();
624 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
625 if (!buttonComponent) {
626 return;
627 }
628 buttonComponent->SetAspectRatio(value);
629 }
630
JsSize(const JSCallbackInfo & info)631 void JSButton::JsSize(const JSCallbackInfo& info)
632 {
633 if (info.Length() < 0) {
634 LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
635 return;
636 }
637
638 if (!info[0]->IsObject()) {
639 LOGE("arg is not Object or String.");
640 return;
641 }
642
643 if (Container::IsCurrentUseNewPipeline()) {
644 JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
645 Dimension width;
646 if (ParseJsDimensionVp(sizeObj->GetProperty("width"), width)) {
647 NG::ViewAbstract::SetWidth(NG::CalcLength(width));
648 }
649 Dimension height;
650 if (ParseJsDimensionVp(sizeObj->GetProperty("height"), height)) {
651 NG::ViewAbstract::SetHeight(NG::CalcLength(height));
652 }
653 return;
654 }
655 auto stack = ViewStackProcessor::GetInstance();
656 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
657 auto option = stack->GetImplicitAnimationOption();
658 if (buttonComponent == nullptr) {
659 LOGE("Button component create failed");
660 return;
661 }
662 JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
663 JSRef<JSVal> widthValue = sizeObj->GetProperty("width");
664 Dimension width;
665 if (ParseJsDimensionVp(widthValue, width)) {
666 if (!stack->IsVisualStateSet()) {
667 buttonComponent->SetWidth(width, stack->GetImplicitAnimationOption());
668 } else {
669 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
670 ButtonStateAttribute::WIDTH, AnimatableDimension(width, option), stack->GetVisualState());
671 if (!buttonComponent->GetStateAttributes()->HasAttribute(
672 ButtonStateAttribute::WIDTH, VisualState::NORMAL)) {
673 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::WIDTH,
674 AnimatableDimension(buttonComponent->GetWidth(), option), VisualState::NORMAL);
675 }
676 }
677 }
678 JSRef<JSVal> heightValue = sizeObj->GetProperty("height");
679 Dimension height;
680 if (ParseJsDimensionVp(heightValue, height)) {
681 buttonComponent->IsNeedResetHeight(false);
682 if (!stack->IsVisualStateSet()) {
683 buttonComponent->SetHeight(height, stack->GetImplicitAnimationOption());
684 buttonComponent->SetDeclareHeight(true);
685 } else {
686 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
687 ButtonStateAttribute::HEIGHT, AnimatableDimension(height, option), stack->GetVisualState());
688 if (!buttonComponent->GetStateAttributes()->HasAttribute(
689 ButtonStateAttribute::HEIGHT, VisualState::NORMAL)) {
690 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::HEIGHT,
691 AnimatableDimension(buttonComponent->GetHeight(), option), VisualState::NORMAL);
692 }
693 }
694 }
695 }
696
JsRadius(const JSCallbackInfo & info)697 void JSButton::JsRadius(const JSCallbackInfo& info)
698 {
699 if (info.Length() < 1) {
700 LOGE("The argv is wrong, it is supposed to have at least 1 argument");
701 return;
702 }
703 Dimension radius;
704 if (!ParseJsDimensionVp(info[0], radius)) {
705 return;
706 }
707 if (Container::IsCurrentUseNewPipeline()) {
708 NG::ButtonView::SetBorderRadius(radius);
709 return;
710 }
711 auto stack = ViewStackProcessor::GetInstance();
712 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
713 auto option = stack->GetImplicitAnimationOption();
714 if (buttonComponent == nullptr) {
715 LOGE("Button component create failed");
716 return;
717 }
718 buttonComponent->SetRadiusState(true);
719 if (!stack->IsVisualStateSet()) {
720 buttonComponent->SetRectRadius(radius);
721 ViewAbstractModel::GetInstance()->SetBorderRadius(radius);
722 } else {
723 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
724 ButtonStateAttribute::RADIUS, AnimatableDimension(radius, option), stack->GetVisualState());
725 auto boxComponent = stack->GetBoxComponent();
726 boxComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
727 BoxStateAttribute::BORDER_RADIUS, AnimatableDimension(radius, option), stack->GetVisualState());
728
729 if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::RADIUS, VisualState::NORMAL)) {
730 buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::RADIUS,
731 AnimatableDimension(buttonComponent->GetRectRadius(), option), VisualState::NORMAL);
732 auto defaultRadius = BoxComponentHelper::GetBorderRadius(boxComponent->GetBackDecoration());
733 boxComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(BoxStateAttribute::BORDER_RADIUS,
734 AnimatableDimension(defaultRadius.GetX(), option), VisualState::NORMAL);
735 }
736 }
737 }
738
GetSizeValue(const JSCallbackInfo & info)739 Dimension JSButton::GetSizeValue(const JSCallbackInfo& info)
740 {
741 if (info.Length() < 1) {
742 LOGE("The arg is wrong, it is supposed to have at least 1 arguments");
743 return Dimension(-1.0);
744 }
745 Dimension value;
746 if (!ParseJsDimensionVp(info[0], value)) {
747 return Dimension(-1.0);
748 }
749 return value;
750 }
751
JsHoverEffect(const JSCallbackInfo & info)752 void JSButton::JsHoverEffect(const JSCallbackInfo& info)
753 {
754 if (!info[0]->IsNumber()) {
755 LOGE("The arg is not a number");
756 return;
757 }
758 if (Container::IsCurrentUseNewPipeline()) {
759 NG::ViewAbstract::SetHoverEffect(static_cast<HoverEffectType>(info[0]->ToNumber<int32_t>()));
760 return;
761 }
762 auto buttonComponent = AceType::DynamicCast<ButtonComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
763 if (buttonComponent) {
764 buttonComponent->SetMouseAnimationType(static_cast<HoverAnimationType>(info[0]->ToNumber<int32_t>()));
765 }
766 }
767
768 } // namespace OHOS::Ace::Framework
769