• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/declarative_frontend/jsview/models/button_model_impl.h"
17 
18 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
19 #include "bridge/declarative_frontend/view_stack_processor.h"
20 #include "core/components/box/box_component_helper.h"
21 #include "core/components/button/button_component.h"
22 #include "core/components/padding/padding_component.h"
23 #include "core/pipeline/pipeline_base.h"
24 
25 namespace OHOS::Ace::Framework {
SetFontSize(const Dimension & fontSize)26 void ButtonModelImpl::SetFontSize(const Dimension& fontSize)
27 {
28     auto textComponent = GetTextComponent();
29     if (textComponent) {
30         auto textStyle = textComponent->GetTextStyle();
31         textStyle.SetFontSize(fontSize);
32         textStyle.SetAdaptTextSize(fontSize, fontSize);
33         textComponent->SetTextStyle(textStyle);
34     }
35 
36     auto stack = ViewStackProcessor::GetInstance();
37     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
38     if (!buttonComponent) {
39         return;
40     }
41     if (buttonComponent->NeedResetHeight()) {
42         ResetButtonHeight();
43     }
44 }
45 
SetFontWeight(const Ace::FontWeight & fontWeight)46 void ButtonModelImpl::SetFontWeight(const Ace::FontWeight& fontWeight)
47 {
48     auto textComponent = GetTextComponent();
49     if (textComponent) {
50         auto textStyle = textComponent->GetTextStyle();
51         textStyle.SetFontWeight(fontWeight);
52         textComponent->SetTextStyle(textStyle);
53     }
54 }
55 
SetFontStyle(const Ace::FontStyle & fontStyle)56 void ButtonModelImpl::SetFontStyle(const Ace::FontStyle& fontStyle)
57 {
58     auto textComponent = GetTextComponent();
59     if (textComponent) {
60         auto textStyle = textComponent->GetTextStyle();
61         textStyle.SetFontStyle(fontStyle);
62         textComponent->SetTextStyle(textStyle);
63     }
64 }
65 
SetFontFamily(const std::vector<std::string> & fontFamily)66 void ButtonModelImpl::SetFontFamily(const std::vector<std::string>& fontFamily)
67 {
68     auto textComponent = GetTextComponent();
69     if (textComponent) {
70         auto textStyle = textComponent->GetTextStyle();
71         textStyle.SetFontFamilies(fontFamily);
72         textComponent->SetTextStyle(textStyle);
73     }
74 }
75 
SetFontColor(const Color & textColor)76 void ButtonModelImpl::SetFontColor(const Color& textColor)
77 {
78     auto textComponent = GetTextComponent();
79     if (textComponent) {
80         auto textStyle = textComponent->GetTextStyle();
81         textStyle.SetTextColor(textColor);
82         textComponent->SetTextStyle(textStyle);
83     }
84 }
85 
SetType(const int value)86 void ButtonModelImpl::SetType(const int value)
87 {
88     auto stack = ViewStackProcessor::GetInstance();
89     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
90     if (buttonComponent) {
91         buttonComponent->SetType((ButtonType)value);
92     }
93 }
94 
SetStateEffect(const bool stateEffect)95 void ButtonModelImpl::SetStateEffect(const bool stateEffect)
96 {
97     auto stack = ViewStackProcessor::GetInstance();
98     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
99     if (buttonComponent) {
100         buttonComponent->SetStateEffect(stateEffect);
101     }
102 }
103 
CreateWithLabel(const CreateWithPara & para,std::list<RefPtr<Component>> & buttonChildren)104 void ButtonModelImpl::CreateWithLabel(const CreateWithPara& para, std::list<RefPtr<Component>>& buttonChildren)
105 {
106     if (para.parseSuccess.value()) {
107         auto textComponent = AceType::MakeRefPtr<TextComponent>(para.label.value());
108         auto pipeline = PipelineBase::GetCurrentContext();
109         CHECK_NULL_VOID(pipeline);
110         auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
111         CHECK_NULL_VOID(buttonTheme);
112         auto textStyle = buttonTheme ? buttonTheme->GetTextStyle() : textComponent->GetTextStyle();
113         textStyle.SetMaxLines(buttonTheme ? buttonTheme->GetTextMaxLines() : 1);
114         textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
115         textComponent->SetTextStyle(textStyle);
116         auto padding = AceType::MakeRefPtr<PaddingComponent>();
117         padding->SetPadding(buttonTheme ? buttonTheme->GetPadding() : Edge());
118         padding->SetChild(textComponent);
119         Component::MergeRSNode(padding, textComponent);
120         buttonChildren.emplace_back(padding);
121     }
122 }
123 
Create(const CreateWithPara & para,std::list<RefPtr<Component>> & buttonChildren)124 void ButtonModelImpl::Create(const CreateWithPara& para, std::list<RefPtr<Component>>& buttonChildren)
125 {
126     auto buttonComponent = AceType::MakeRefPtr<ButtonComponent>(buttonChildren);
127     ViewStackProcessor::GetInstance()->ClaimElementId(buttonComponent);
128     buttonComponent->SetHasCustomChild(false);
129     buttonComponent->SetCatchMode(false);
130     SetDefaultAttributes(buttonComponent);
131     SetTypeAndStateEffect(para.type, para.stateEffect, buttonComponent);
132     ViewStackProcessor::GetInstance()->Push(buttonComponent);
133     auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent();
134     if (focusableComponent) {
135         focusableComponent->SetFocusable(true);
136     }
137     auto focusNodeComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent(false);
138     if (focusNodeComponent) {
139         focusNodeComponent->SetFocusNode(false);
140     }
141 
142     buttonComponent->SetMouseAnimationType(HoverAnimationType::SCALE);
143 }
144 
CreateWithChild(const CreateWithPara & para)145 void ButtonModelImpl::CreateWithChild(const CreateWithPara& para)
146 {
147     std::list<RefPtr<Component>> buttonChildren;
148     auto buttonComponent = AceType::MakeRefPtr<ButtonComponent>(buttonChildren);
149     ViewStackProcessor::GetInstance()->ClaimElementId(buttonComponent);
150     buttonComponent->SetHasCustomChild(true);
151     buttonComponent->SetCatchMode(false);
152     SetDefaultAttributes(buttonComponent);
153     SetTypeAndStateEffect(para.type, para.stateEffect, buttonComponent);
154     ViewStackProcessor::GetInstance()->Push(buttonComponent);
155     JSInteractableView::SetFocusable(true);
156     JSInteractableView::SetFocusNode(true);
157     buttonComponent->SetMouseAnimationType(HoverAnimationType::SCALE);
158     if (buttonComponent->NeedResetHeight()) {
159         ResetButtonHeight();
160     }
161 }
162 
Padding(const NG::PaddingProperty & paddingNew,const Edge & paddingOld)163 void ButtonModelImpl::Padding(const NG::PaddingProperty& paddingNew, const Edge& paddingOld)
164 {
165     auto stack = ViewStackProcessor::GetInstance();
166     auto component = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
167     if (component) {
168         auto paddingChild = AceType::DynamicCast<PaddingComponent>(component->GetChildren().front());
169         if (paddingChild) {
170             paddingChild->SetPadding(paddingOld);
171         }
172         if (component->NeedResetHeight()) {
173             ResetButtonHeight();
174         }
175     }
176 }
177 
OnClick(GestureEventFunc && tapEventFunc,ClickEventFunc && clickEventFunc,double distanceThreshold)178 void ButtonModelImpl::OnClick(GestureEventFunc&& tapEventFunc, ClickEventFunc&& clickEventFunc,
179     double distanceThreshold)
180 {
181     auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
182     CHECK_NULL_VOID(inspector);
183     auto impl = inspector->GetInspectorFunctionImpl();
184     RefPtr<Gesture> tapGesture = AceType::MakeRefPtr<TapGesture>(1, 1);
185     tapGesture->SetOnActionId([func = std::move(tapEventFunc), impl](GestureEvent& info) {
186         if (impl) {
187             impl->UpdateEventInfo(info);
188         }
189         func(info);
190     });
191     auto click = ViewStackProcessor::GetInstance()->GetBoxComponent();
192     click->SetOnClick(tapGesture);
193 
194     auto onClickId = EventMarker([func = std::move(clickEventFunc), impl](const BaseEventInfo* info) {
195         const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
196         if (!clickInfo) {
197             return;
198         }
199         auto newInfo = *clickInfo;
200         if (impl) {
201             impl->UpdateEventInfo(newInfo);
202         }
203         func(clickInfo);
204     });
205     auto buttonComponent =
206         AceType::DynamicCast<ButtonComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
207     if (buttonComponent) {
208         buttonComponent->SetKeyEnterEventId(onClickId);
209     }
210     auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent(false);
211     if (focusableComponent) {
212         focusableComponent->SetOnClickId(onClickId);
213     }
214 }
215 
BackgroundColor(const Color & color,const bool & colorFlag)216 void ButtonModelImpl::BackgroundColor(const Color& color, const bool& colorFlag)
217 {
218     if (!colorFlag) {
219         return;
220     }
221 
222     auto stack = ViewStackProcessor::GetInstance();
223     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
224     AnimationOption option = ViewStackProcessor::GetInstance()->GetImplicitAnimationOption();
225     CHECK_NULL_VOID(buttonComponent);
226 
227     if (!stack->IsVisualStateSet()) {
228         buttonComponent->SetBackgroundColor(color);
229         auto pipeline = PipelineBase::GetCurrentContext();
230         CHECK_NULL_VOID(pipeline);
231         auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
232         if (buttonTheme) {
233             Color blendColor = buttonTheme->GetClickedColor();
234             buttonComponent->SetClickedColor(buttonComponent->GetBackgroundColor().BlendColor(blendColor));
235         }
236     } else {
237         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableColor>(
238             ButtonStateAttribute::COLOR, AnimatableColor(color, option), stack->GetVisualState());
239         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::COLOR, VisualState::NORMAL)) {
240             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableColor>(ButtonStateAttribute::COLOR,
241                 AnimatableColor(buttonComponent->GetBackgroundColor(), option), VisualState::NORMAL);
242         }
243     }
244 }
245 
SetWidth(const Dimension & width)246 void ButtonModelImpl::SetWidth(const Dimension& width)
247 {
248     auto stack = ViewStackProcessor::GetInstance();
249     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
250     AnimationOption option = stack->GetImplicitAnimationOption();
251     CHECK_NULL_VOID(buttonComponent);
252     if (!stack->IsVisualStateSet()) {
253         buttonComponent->SetWidth(width, stack->GetImplicitAnimationOption());
254     } else {
255         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
256             ButtonStateAttribute::WIDTH, AnimatableDimension(width, option), stack->GetVisualState());
257         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::WIDTH, VisualState::NORMAL)) {
258             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::WIDTH,
259                 AnimatableDimension(buttonComponent->GetWidth(), option), VisualState::NORMAL);
260         }
261     }
262 }
263 
SetHeight(const Dimension & height)264 void ButtonModelImpl::SetHeight(const Dimension& height)
265 {
266     auto stack = ViewStackProcessor::GetInstance();
267     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
268     auto option = stack->GetImplicitAnimationOption();
269     CHECK_NULL_VOID(buttonComponent);
270     buttonComponent->IsNeedResetHeight(false);
271     if (!stack->IsVisualStateSet()) {
272         buttonComponent->SetHeight(height, option);
273         buttonComponent->SetDeclareHeight(true);
274     } else {
275         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
276             ButtonStateAttribute::HEIGHT, AnimatableDimension(height, option), stack->GetVisualState());
277         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::HEIGHT, VisualState::NORMAL)) {
278             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::HEIGHT,
279                 AnimatableDimension(buttonComponent->GetHeight(), option), VisualState::NORMAL);
280         }
281     }
282 }
283 
SetAspectRatio(const double & ratio)284 void ButtonModelImpl::SetAspectRatio(const double& ratio)
285 {
286     auto stack = ViewStackProcessor::GetInstance();
287     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
288     CHECK_NULL_VOID(buttonComponent);
289     buttonComponent->SetAspectRatio(ratio);
290 }
291 
SetSize(const std::optional<Dimension> & width,const std::optional<Dimension> & height)292 void ButtonModelImpl::SetSize(const std::optional<Dimension>& width, const std::optional<Dimension>& height)
293 {
294     if (width.has_value()) {
295         SetWidth(width.value());
296     }
297     if (height.has_value()) {
298         SetHeight(height.value());
299     }
300 }
301 
SetBorderRadius(const Dimension & radius)302 void ButtonModelImpl::SetBorderRadius(const Dimension& radius)
303 {
304     auto stack = ViewStackProcessor::GetInstance();
305     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
306     auto option = stack->GetImplicitAnimationOption();
307     CHECK_NULL_VOID(buttonComponent);
308     buttonComponent->SetRadiusState(true);
309     if (!stack->IsVisualStateSet()) {
310         buttonComponent->SetRectRadius(radius);
311         ViewAbstractModel::GetInstance()->SetBorderRadius(radius);
312     } else {
313         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
314             ButtonStateAttribute::RADIUS, AnimatableDimension(radius, option), stack->GetVisualState());
315         auto boxComponent = stack->GetBoxComponent();
316         boxComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
317             BoxStateAttribute::BORDER_RADIUS, AnimatableDimension(radius, option), stack->GetVisualState());
318 
319         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::RADIUS, VisualState::NORMAL)) {
320             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::RADIUS,
321                 AnimatableDimension(buttonComponent->GetRectRadius(), option), VisualState::NORMAL);
322             auto defaultRadius = BoxComponentHelper::GetBorderRadius(boxComponent->GetBackDecoration());
323             boxComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(BoxStateAttribute::BORDER_RADIUS,
324                 AnimatableDimension(defaultRadius.GetX(), option), VisualState::NORMAL);
325         }
326     }
327 }
328 
GetTextComponent()329 RefPtr<TextComponent> ButtonModelImpl::GetTextComponent()
330 {
331     auto stack = ViewStackProcessor::GetInstance();
332     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
333     if (buttonComponent == nullptr) {
334         LOGE("Button component create failed");
335         return nullptr;
336     }
337     auto paddingComponent = AceType::DynamicCast<PaddingComponent>(buttonComponent->GetChildren().front());
338     if (!paddingComponent) {
339         LOGE("Padding component create failed");
340         return nullptr;
341     }
342     auto textComponent = AceType::DynamicCast<TextComponent>(paddingComponent->GetChild());
343     return textComponent;
344 }
345 
ResetButtonHeight()346 void ButtonModelImpl::ResetButtonHeight()
347 {
348     auto stack = ViewStackProcessor::GetInstance();
349     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
350     if (buttonComponent) {
351         if (buttonComponent->GetType() == ButtonType::CIRCLE) {
352             return;
353         }
354         const Dimension initialHeight = Dimension(-1.0, DimensionUnit::VP);
355         buttonComponent->SetHeight(initialHeight);
356     }
357 }
358 
SetTypeAndStateEffect(const std::optional<ButtonType> & type,const std::optional<bool> & stateEffect,const RefPtr<ButtonComponent> & buttonComponent)359 void ButtonModelImpl::SetTypeAndStateEffect(const std::optional<ButtonType>& type,
360     const std::optional<bool>& stateEffect, const RefPtr<ButtonComponent>& buttonComponent)
361 {
362     if (type.has_value()) {
363         buttonComponent->SetType(type.value());
364     } else {
365         // undefined use capsule type.
366         buttonComponent->SetType(ButtonType::CAPSULE);
367     }
368 
369     if (stateEffect.has_value()) {
370         buttonComponent->SetStateEffect(stateEffect.value());
371     }
372 }
373 
SetDefaultAttributes(const RefPtr<ButtonComponent> & buttonComponent)374 void ButtonModelImpl::SetDefaultAttributes(const RefPtr<ButtonComponent>& buttonComponent)
375 {
376     buttonComponent->SetType(ButtonType::CAPSULE);
377     buttonComponent->SetDeclarativeFlag(true);
378     auto pipeline = PipelineBase::GetCurrentContext();
379     CHECK_NULL_VOID(pipeline);
380     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
381     CHECK_NULL_VOID(buttonTheme);
382     buttonComponent->SetHeight(buttonTheme->GetHeight());
383     buttonComponent->SetBackgroundColor(buttonTheme->GetBgColor());
384     buttonComponent->SetClickedColor(buttonComponent->GetBackgroundColor().BlendColor(buttonTheme->GetClickedColor()));
385     buttonComponent->SetHoverColor(buttonTheme->GetHoverColor());
386 }
387 
SetRemoteMessage(RemoteCallback && remoteCallback)388 void ButtonModelImpl::SetRemoteMessage(RemoteCallback&& remoteCallback)
389 {
390     EventMarker remoteMessageEventId(std::move(remoteCallback));
391     auto stack = ViewStackProcessor::GetInstance();
392     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
393     if (buttonComponent) {
394         buttonComponent->SetRemoteMessageEventId(remoteMessageEventId);
395     }
396 }
397 } // namespace OHOS::Ace::Framework
398