• 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     if (para.labelSetInfoFirst.value()) {
132         SetTypeAndStateEffect(para.typeFirst, para.stateEffectFirst, buttonComponent);
133     }
134     if (para.labelSetInfoSecond.value()) {
135         SetTypeAndStateEffect(para.typeSecond, para.stateEffectSecond, buttonComponent);
136     }
137     ViewStackProcessor::GetInstance()->Push(buttonComponent);
138     auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent();
139     if (focusableComponent) {
140         focusableComponent->SetFocusable(true);
141     }
142     auto focusNodeComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent(false);
143     if (focusNodeComponent) {
144         focusNodeComponent->SetFocusNode(false);
145     }
146 
147     buttonComponent->SetMouseAnimationType(HoverAnimationType::SCALE);
148 }
149 
CreateWithChild(const CreateWithPara & para)150 void ButtonModelImpl::CreateWithChild(const CreateWithPara& para)
151 {
152     std::list<RefPtr<Component>> buttonChildren;
153     auto buttonComponent = AceType::MakeRefPtr<ButtonComponent>(buttonChildren);
154     ViewStackProcessor::GetInstance()->ClaimElementId(buttonComponent);
155     buttonComponent->SetHasCustomChild(true);
156     buttonComponent->SetCatchMode(false);
157     SetDefaultAttributes(buttonComponent);
158     if (para.labelSetInfoFirst.value()) {
159         SetTypeAndStateEffect(para.typeFirst, para.stateEffectFirst, buttonComponent);
160     }
161     if (para.labelSetInfoSecond.value()) {
162         SetTypeAndStateEffect(para.typeSecond, para.stateEffectSecond, buttonComponent);
163     }
164     ViewStackProcessor::GetInstance()->Push(buttonComponent);
165     JSInteractableView::SetFocusable(true);
166     JSInteractableView::SetFocusNode(true);
167     buttonComponent->SetMouseAnimationType(HoverAnimationType::SCALE);
168     if (buttonComponent->NeedResetHeight()) {
169         ResetButtonHeight();
170     }
171 }
172 
Padding(const NG::PaddingProperty & paddingNew,const Edge & paddingOld)173 void ButtonModelImpl::Padding(const NG::PaddingProperty& paddingNew, const Edge& paddingOld)
174 {
175     auto stack = ViewStackProcessor::GetInstance();
176     auto component = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
177     if (component) {
178         auto paddingChild = AceType::DynamicCast<PaddingComponent>(component->GetChildren().front());
179         if (paddingChild) {
180             paddingChild->SetPadding(paddingOld);
181         }
182         if (component->NeedResetHeight()) {
183             ResetButtonHeight();
184         }
185     }
186 }
187 
OnClick(GestureEventFunc && tapEventFunc,ClickEventFunc && clickEventFunc)188 void ButtonModelImpl::OnClick(GestureEventFunc&& tapEventFunc, ClickEventFunc&& clickEventFunc)
189 {
190     auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
191     CHECK_NULL_VOID(inspector);
192     auto impl = inspector->GetInspectorFunctionImpl();
193     RefPtr<Gesture> tapGesture = AceType::MakeRefPtr<TapGesture>(1, 1);
194     tapGesture->SetOnActionId([func = std::move(tapEventFunc), impl](GestureEvent& info) {
195         if (impl) {
196             impl->UpdateEventInfo(info);
197         }
198         func(info);
199     });
200     auto click = ViewStackProcessor::GetInstance()->GetBoxComponent();
201     click->SetOnClick(tapGesture);
202 
203     auto onClickId = EventMarker([func = std::move(clickEventFunc), impl](const BaseEventInfo* info) {
204         const auto* clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
205         if (!clickInfo) {
206             return;
207         }
208         auto newInfo = *clickInfo;
209         if (impl) {
210             impl->UpdateEventInfo(newInfo);
211         }
212         func(clickInfo);
213     });
214     auto buttonComponent =
215         AceType::DynamicCast<ButtonComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
216     if (buttonComponent) {
217         buttonComponent->SetKeyEnterEventId(onClickId);
218     }
219     auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent(false);
220     if (focusableComponent) {
221         focusableComponent->SetOnClickId(onClickId);
222     }
223 }
224 
BackgroundColor(const Color & color,const bool & colorFlag)225 void ButtonModelImpl::BackgroundColor(const Color& color, const bool& colorFlag)
226 {
227     if (!colorFlag) {
228         return;
229     }
230 
231     auto stack = ViewStackProcessor::GetInstance();
232     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
233     AnimationOption option = ViewStackProcessor::GetInstance()->GetImplicitAnimationOption();
234     CHECK_NULL_VOID(buttonComponent);
235 
236     if (!stack->IsVisualStateSet()) {
237         buttonComponent->SetBackgroundColor(color);
238         auto pipeline = PipelineBase::GetCurrentContext();
239         CHECK_NULL_VOID(pipeline);
240         auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
241         if (buttonTheme) {
242             Color blendColor = buttonTheme->GetClickedColor();
243             buttonComponent->SetClickedColor(buttonComponent->GetBackgroundColor().BlendColor(blendColor));
244         }
245     } else {
246         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableColor>(
247             ButtonStateAttribute::COLOR, AnimatableColor(color, option), stack->GetVisualState());
248         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::COLOR, VisualState::NORMAL)) {
249             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableColor>(ButtonStateAttribute::COLOR,
250                 AnimatableColor(buttonComponent->GetBackgroundColor(), option), VisualState::NORMAL);
251         }
252     }
253 }
254 
SetWidth(const Dimension & width)255 void ButtonModelImpl::SetWidth(const Dimension& width)
256 {
257     auto stack = ViewStackProcessor::GetInstance();
258     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
259     AnimationOption option = stack->GetImplicitAnimationOption();
260     CHECK_NULL_VOID(buttonComponent);
261     if (!stack->IsVisualStateSet()) {
262         buttonComponent->SetWidth(width, stack->GetImplicitAnimationOption());
263     } else {
264         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
265             ButtonStateAttribute::WIDTH, AnimatableDimension(width, option), stack->GetVisualState());
266         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::WIDTH, VisualState::NORMAL)) {
267             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::WIDTH,
268                 AnimatableDimension(buttonComponent->GetWidth(), option), VisualState::NORMAL);
269         }
270     }
271 }
272 
SetHeight(const Dimension & height)273 void ButtonModelImpl::SetHeight(const Dimension& height)
274 {
275     auto stack = ViewStackProcessor::GetInstance();
276     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
277     auto option = stack->GetImplicitAnimationOption();
278     CHECK_NULL_VOID(buttonComponent);
279     buttonComponent->IsNeedResetHeight(false);
280     if (!stack->IsVisualStateSet()) {
281         buttonComponent->SetHeight(height, option);
282         buttonComponent->SetDeclareHeight(true);
283     } else {
284         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
285             ButtonStateAttribute::HEIGHT, AnimatableDimension(height, option), stack->GetVisualState());
286         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::HEIGHT, VisualState::NORMAL)) {
287             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::HEIGHT,
288                 AnimatableDimension(buttonComponent->GetHeight(), option), VisualState::NORMAL);
289         }
290     }
291 }
292 
SetAspectRatio(const double & ratio)293 void ButtonModelImpl::SetAspectRatio(const double& ratio)
294 {
295     auto stack = ViewStackProcessor::GetInstance();
296     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
297     CHECK_NULL_VOID(buttonComponent);
298     buttonComponent->SetAspectRatio(ratio);
299 }
300 
SetSize(const std::optional<Dimension> & width,const std::optional<Dimension> & height)301 void ButtonModelImpl::SetSize(const std::optional<Dimension>& width, const std::optional<Dimension>& height)
302 {
303     if (width.has_value()) {
304         SetWidth(width.value());
305     } else {
306         SetHeight(height.value());
307     }
308 }
309 
SetBorderRadius(const Dimension & radius)310 void ButtonModelImpl::SetBorderRadius(const Dimension& radius)
311 {
312     auto stack = ViewStackProcessor::GetInstance();
313     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
314     auto option = stack->GetImplicitAnimationOption();
315     CHECK_NULL_VOID(buttonComponent);
316     buttonComponent->SetRadiusState(true);
317     if (!stack->IsVisualStateSet()) {
318         buttonComponent->SetRectRadius(radius);
319         ViewAbstractModel::GetInstance()->SetBorderRadius(radius);
320     } else {
321         buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
322             ButtonStateAttribute::RADIUS, AnimatableDimension(radius, option), stack->GetVisualState());
323         auto boxComponent = stack->GetBoxComponent();
324         boxComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(
325             BoxStateAttribute::BORDER_RADIUS, AnimatableDimension(radius, option), stack->GetVisualState());
326 
327         if (!buttonComponent->GetStateAttributes()->HasAttribute(ButtonStateAttribute::RADIUS, VisualState::NORMAL)) {
328             buttonComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(ButtonStateAttribute::RADIUS,
329                 AnimatableDimension(buttonComponent->GetRectRadius(), option), VisualState::NORMAL);
330             auto defaultRadius = BoxComponentHelper::GetBorderRadius(boxComponent->GetBackDecoration());
331             boxComponent->GetStateAttributes()->AddAttribute<AnimatableDimension>(BoxStateAttribute::BORDER_RADIUS,
332                 AnimatableDimension(defaultRadius.GetX(), option), VisualState::NORMAL);
333         }
334     }
335 }
336 
SetHoverEffect(const int32_t & hoverEffectNum)337 void ButtonModelImpl::SetHoverEffect(const int32_t& hoverEffectNum)
338 {
339     auto buttonComponent =
340         AceType::DynamicCast<ButtonComponent>(ViewStackProcessor::GetInstance()->GetMainComponent());
341     CHECK_NULL_VOID(buttonComponent);
342     buttonComponent->SetMouseAnimationType(static_cast<HoverAnimationType>(hoverEffectNum));
343 }
344 
GetTextComponent()345 RefPtr<TextComponent> ButtonModelImpl::GetTextComponent()
346 {
347     auto stack = ViewStackProcessor::GetInstance();
348     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
349     if (buttonComponent == nullptr) {
350         LOGE("Button component create failed");
351         return nullptr;
352     }
353     auto paddingComponent = AceType::DynamicCast<PaddingComponent>(buttonComponent->GetChildren().front());
354     if (!paddingComponent) {
355         LOGE("Padding component create failed");
356         return nullptr;
357     }
358     auto textComponent = AceType::DynamicCast<TextComponent>(paddingComponent->GetChild());
359     return textComponent;
360 }
361 
ResetButtonHeight()362 void ButtonModelImpl::ResetButtonHeight()
363 {
364     auto stack = ViewStackProcessor::GetInstance();
365     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
366     if (buttonComponent) {
367         if (buttonComponent->GetType() == ButtonType::CIRCLE) {
368             return;
369         }
370         const Dimension initialHeight = Dimension(-1.0, DimensionUnit::VP);
371         buttonComponent->SetHeight(initialHeight);
372     }
373 }
374 
SetTypeAndStateEffect(const std::optional<ButtonType> & type,const std::optional<bool> & stateEffect,const RefPtr<ButtonComponent> & buttonComponent)375 void ButtonModelImpl::SetTypeAndStateEffect(const std::optional<ButtonType>& type,
376     const std::optional<bool>& stateEffect, const RefPtr<ButtonComponent>& buttonComponent)
377 {
378     if (type.has_value()) {
379         buttonComponent->SetType(type.value());
380     } else {
381         // undefined use capsule type.
382         buttonComponent->SetType(ButtonType::CAPSULE);
383     }
384 
385     if (stateEffect.has_value()) {
386         buttonComponent->SetStateEffect(stateEffect.value());
387     }
388 }
389 
SetDefaultAttributes(const RefPtr<ButtonComponent> & buttonComponent)390 void ButtonModelImpl::SetDefaultAttributes(const RefPtr<ButtonComponent>& buttonComponent)
391 {
392     buttonComponent->SetType(ButtonType::CAPSULE);
393     buttonComponent->SetDeclarativeFlag(true);
394     auto pipeline = PipelineBase::GetCurrentContext();
395     CHECK_NULL_VOID(pipeline);
396     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
397     CHECK_NULL_VOID(buttonTheme);
398     buttonComponent->SetHeight(buttonTheme->GetHeight());
399     buttonComponent->SetBackgroundColor(buttonTheme->GetBgColor());
400     buttonComponent->SetClickedColor(buttonComponent->GetBackgroundColor().BlendColor(buttonTheme->GetClickedColor()));
401     buttonComponent->SetHoverColor(buttonTheme->GetHoverColor());
402 }
403 
SetRemoteMessage(RemoteCallback && remoteCallback)404 void ButtonModelImpl::SetRemoteMessage(RemoteCallback&& remoteCallback)
405 {
406     EventMarker remoteMessageEventId(std::move(remoteCallback));
407     auto stack = ViewStackProcessor::GetInstance();
408     auto buttonComponent = AceType::DynamicCast<ButtonComponent>(stack->GetMainComponent());
409     if (buttonComponent) {
410         buttonComponent->SetRemoteMessageEventId(remoteMessageEventId);
411     }
412 }
413 } // namespace OHOS::Ace::Framework
414