• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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