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/common/dom/dom_button.h"
17 
18 namespace OHOS::Ace::Framework {
19 namespace {
20 
21 // Button types definition
22 const char BUTTON_TYPE_CAPSULE[] = "capsule";
23 const char BUTTON_TYPE_TEXT[] = "text";
24 const char BUTTON_TYPE_CIRCLE[] = "circle";
25 const char BUTTON_TYPE_DOWNLOAD[] = "download";
26 const char BUTTON_TYPE_ICON[] = "icon";
27 const char BUTTON_TYPE_ARC[] = "arc"; // for watch
28 
29 // Button children placement definition
30 const char PLACEMENT_START[] = "start";
31 const char PLACEMENT_TOP[] = "top";
32 const char PLACEMENT_BOTTOM[] = "bottom";
33 
34 // Watch button definitions
35 constexpr Dimension ARC_FONT_SIZE = 19.0_fp;
36 constexpr Dimension ARC_FONT_MIN_SIZE = 16.0_fp;
37 constexpr Dimension ARC_PADDING_TOP = 8.0_vp;
38 constexpr Dimension ARC_PADDING_BOTTOM = 0.0_vp;
39 constexpr Dimension ARC_PADDING_HORIZONTAL = 30.0_vp;
40 constexpr Dimension WATCH_TEXT_PADDING = 2.0_vp;
41 constexpr Dimension WATCH_TEXT_RADIUS = 4.0_vp;
42 constexpr uint32_t MAX_LINES = 2;
43 
44 // TV button definitions
45 constexpr Dimension TEXT_PADDING_HORIZONTAL = 8.0_vp;
46 constexpr Dimension TEXT_PADDING_VERTICAL = 0.0_vp;
47 constexpr Dimension TEXT_FONT_MIN_SIZE = 12.0_fp;
48 constexpr double TEXT_FOCUS_HEIGHT = 24.0;
49 
50 constexpr uint32_t TRANSPARENT_COLOR = 0x00000000;
51 constexpr double FLEX_ITEM_SHRINK = 1.0;
52 constexpr double INIT_HEIGHT = -1.0;
53 constexpr Dimension DOWNLOAD_BORDER_WIDTH = Dimension(1.0, DimensionUnit::VP);
54 constexpr Dimension ICON_BUTTON_PADDING = 0.0_vp;
55 constexpr Dimension ICON_BUTTON_RADIUS = 0.0_vp;
56 constexpr Dimension INNER_PADDING = 4.0_vp;
57 
58 } // namespace
59 
DOMButton(NodeId nodeId,const std::string & nodeName)60 DOMButton::DOMButton(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
61 {
62     std::list<RefPtr<Component>> buttonChildren;
63     buttonChild_ = AceType::MakeRefPtr<ButtonComponent>(buttonChildren);
64     buttonChild_->SetCatchMode(false);
65     textChild_ = AceType::MakeRefPtr<TextComponent>("");
66     imageChild_ = AceType::MakeRefPtr<ImageComponent>("");
67     paddingChild_ = AceType::MakeRefPtr<PaddingComponent>();
68     buttonChild_->AppendChild(paddingChild_);
69     isWatch_ = (SystemProperties::GetDeviceType() == DeviceType::WATCH);
70     isTv_ = (SystemProperties::GetDeviceType() == DeviceType::TV);
71     Component::MergeRSNode(textChild_);
72     Component::MergeRSNode(imageChild_);
73 }
74 
ResetInitializedStyle()75 void DOMButton::ResetInitializedStyle()
76 {
77     if (declaration_) {
78         declaration_->InitializeStyle();
79     }
80 }
81 
PrepareSpecializedComponent()82 void DOMButton::PrepareSpecializedComponent()
83 {
84     buttonTheme_ = GetTheme<ButtonTheme>();
85     buttonDeclaration_ = AceType::DynamicCast<ButtonDeclaration>(declaration_);
86     if (!buttonDeclaration_ || !buttonTheme_) {
87         return;
88     }
89     textChild_->SetTextDirection(IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
90     imageChild_->SetTextDirection(IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
91     buttonChild_->SetLayoutFlag(LAYOUT_FLAG_EXTEND_TO_PARENT);
92     buttonType_ = buttonDeclaration_->GetType();
93     textStyle_ = buttonDeclaration_->GetTextStyle();
94     edge_ = buttonDeclaration_->GetBorderEdge();
95     blendOpacity_ = buttonDeclaration_->GetBlendOpacity();
96     diameter_ = buttonDeclaration_->GetProgressDiameter();
97     imageChild_->SetSrc(buttonDeclaration_->GetIconSrc());
98     imageChild_->SetImageFill(GetImageFill());
99     imageChild_->SetWidth(buttonDeclaration_->GetIconWidth());
100     imageChild_->SetHeight(buttonDeclaration_->GetIconHeight());
101     imageChild_->SetFitMaxSize(false);
102     paddingChild_->SetPadding(buttonDeclaration_->GetPadding());
103     textChild_->SetData(buttonDeclaration_->GetTextData());
104     bool isCard = AceApplicationInfo::GetInstance().GetIsCardType();
105     if (isCard) {
106         textStyle_.SetAllowScale(false);
107         if (textStyle_.GetFontSize().Unit() == DimensionUnit::FP) {
108             textStyle_.SetAllowScale(true);
109         }
110     }
111     if (!focusColorChanged_) {
112         focusColor_ = buttonDeclaration_->GetFocusColor();
113     }
114     paddingChild_->SetChild(textChild_);
115     PrepareBoxSize();
116     PrepareUniversalButton();
117     PrepareBorderStyle();
118     PrepareBackDecorationStyle();
119     PrepareButtonState();
120     PreparePseudoStyle();
121     if (!isTv_) {
122         textChild_->SetFocusColor(textStyle_.GetTextColor());
123         if (!isWatch_) {
124             PrepareClickedColor();
125         }
126     }
127     if (buttonDeclaration_->GetFontSizeState()) {
128         textStyle_.SetAdaptTextSize(textStyle_.GetFontSize(), textStyle_.GetFontSize());
129     }
130     textChild_->SetTextStyle(textStyle_);
131     buttonDeclaration_->SetBorderEdge(edge_);
132     buttonChild_->SetDeclaration(buttonDeclaration_);
133     AddPadding();
134 }
135 
PrepareBoxSize()136 void DOMButton::PrepareBoxSize()
137 {
138     if (!boxComponent_) {
139         return;
140     }
141     boxComponent_->SetDeliverMinToChild(true);
142     backDecoration_ = boxComponent_->GetBackDecoration();
143     if (buttonType_ == BUTTON_TYPE_ARC) {
144         return;
145     }
146     buttonChild_->SetWidth(buttonDeclaration_->GetWidth());
147     buttonChild_->SetHeight(buttonDeclaration_->GetHeight());
148     if (GreatOrEqual(buttonChild_->GetWidth().Value(), 0.0)) {
149         boxComponent_->SetWidth(buttonChild_->GetWidth().Value(), buttonChild_->GetWidth().Unit());
150     }
151     if (GreatOrEqual(buttonChild_->GetHeight().Value(), 0.0)) {
152         boxComponent_->SetHeight(buttonChild_->GetHeight().Value(), buttonChild_->GetHeight().Unit());
153     }
154     // Use theme height if user not define. Circle button will calculate height when rendering.
155     if ((buttonType_ != BUTTON_TYPE_CIRCLE) && (LessNotEqual(buttonChild_->GetHeight().Value(), 0.0))) {
156         if ((buttonType_ == BUTTON_TYPE_DOWNLOAD) && (SystemProperties::GetDeviceType() == DeviceType::PHONE)) {
157             boxComponent_->SetHeight(buttonTheme_->GetDownloadHeight().Value(),
158                 buttonTheme_->GetDownloadHeight().Unit());
159             return;
160         }
161         boxComponent_->SetHeight(buttonTheme_->GetHeight().Value(), buttonTheme_->GetHeight().Unit());
162     }
163 }
164 
PreparePseudoStyle()165 void DOMButton::PreparePseudoStyle()
166 {
167     if (!HasPseudo()) {
168         return;
169     }
170     if (HasActivePseudo()) {
171         buttonDeclaration_->SetClickedColor(buttonDeclaration_->GetBackgroundColor());
172     }
173     if (HasFocusPseudo()) {
174         buttonDeclaration_->SetFocusColor(buttonDeclaration_->GetBackgroundColor());
175     }
176 }
177 
PrepareUniversalButton()178 void DOMButton::PrepareUniversalButton()
179 {
180     UpdateCustomizedColorFlag();
181     if (buttonType_ == BUTTON_TYPE_ICON) {
182         PrepareIconButton();
183     } else if (buttonType_ == BUTTON_TYPE_CAPSULE) {
184         PrepareCapsuleButton();
185     } else if (buttonType_ == BUTTON_TYPE_TEXT) {
186         PrepareTextButton();
187     } else if (buttonType_ == BUTTON_TYPE_CIRCLE) {
188         PrepareCircleButton();
189     } else if (buttonType_ == BUTTON_TYPE_DOWNLOAD) {
190         PrepareDownloadButton();
191     } else if (buttonType_ == BUTTON_TYPE_ARC) {
192         PrepareArcButton();
193     } else {
194         PrepareDefaultButton();
195     }
196 }
197 
PrepareDefaultButton()198 void DOMButton::PrepareDefaultButton()
199 {
200     paddingChild_->SetPadding(Edge());
201     if (!buttonDeclaration_->GetHeightState()) {
202         ResetBoxHeight(INIT_HEIGHT);
203     }
204     if (!imageChild_->GetSrc().empty()) {
205         if (textChild_->GetData().empty()) {
206             paddingChild_->SetChild(imageChild_);
207             return;
208         }
209         textStyle_.DisableAdaptTextSize();
210         PrepareChildren();
211     }
212 }
213 
PrepareIconButton()214 void DOMButton::PrepareIconButton()
215 {
216     buttonChild_->SetType(ButtonType::ICON);
217     buttonDeclaration_->SetRectRadius(ICON_BUTTON_RADIUS);
218     paddingChild_->SetChild(imageChild_);
219     paddingChild_->SetPadding(Edge(ICON_BUTTON_PADDING));
220     ResetBoxHeight(INIT_HEIGHT);
221 }
222 
PrepareCapsuleButton()223 void DOMButton::PrepareCapsuleButton()
224 {
225     buttonChild_->SetType(ButtonType::CAPSULE);
226     if (!buttonDeclaration_->GetRadiusState()) {
227         if (!NearZero(buttonChild_->GetHeight().Value())) {
228             buttonDeclaration_->SetRectRadius(buttonChild_->GetHeight() / 2.0);
229         }
230     } else {
231         ResetBoxHeight(buttonDeclaration_->GetRectRadius().Value() * 2.0, buttonDeclaration_->GetRectRadius().Unit());
232     }
233     if (isCustomizedColor_ && isTv_) {
234         buttonDeclaration_->SetFocusColor(buttonDeclaration_->GetBackgroundColor());
235         textChild_->SetFocusColor(textStyle_.GetTextColor());
236     }
237 }
238 
PrepareTextButton()239 void DOMButton::PrepareTextButton()
240 {
241     buttonChild_->SetType(ButtonType::TEXT);
242     if (!isCustomizedColor_) {
243         buttonDeclaration_->SetBackgroundColor(Color(TRANSPARENT_COLOR));
244     }
245     textStyle_.SetTextAlign(TextAlign::CENTER);
246     if (isTv_) {
247         textStyle_.SetAdaptTextSize(textStyle_.GetFontSize(), TEXT_FONT_MIN_SIZE);
248         paddingChild_->SetPadding(Edge(TEXT_PADDING_HORIZONTAL, TEXT_PADDING_VERTICAL,
249             TEXT_PADDING_HORIZONTAL, TEXT_PADDING_VERTICAL));
250         if (!buttonDeclaration_->GetFontSizeState()) {
251             ResetBoxHeight(TEXT_FOCUS_HEIGHT, DimensionUnit::VP);
252             buttonDeclaration_->SetRectRadius(Dimension(TEXT_FOCUS_HEIGHT / 2.0, DimensionUnit::VP));
253         }
254         return;
255     }
256     if (isWatch_) {
257         if (!buttonDeclaration_->GetFontSizeState()) {
258             std::vector<TextSizeGroup> preferTextSizeGroups;
259             preferTextSizeGroups.push_back({ buttonTheme_->GetTextStyle().GetFontSize(), 1 });
260             preferTextSizeGroups.push_back({ buttonTheme_->GetMinFontSize(), MAX_LINES, TextOverflow::ELLIPSIS });
261             textStyle_.SetPreferTextSizeGroups(preferTextSizeGroups);
262         }
263         ResetBoxHeight(INIT_HEIGHT);
264         paddingChild_->SetPadding(Edge(WATCH_TEXT_PADDING));
265         buttonDeclaration_->SetRectRadius(WATCH_TEXT_RADIUS);
266         return;
267     }
268     if (!buttonDeclaration_->GetTextColorState()) {
269         textStyle_.SetTextColor(buttonTheme_->GetNormalTextColor());
270     }
271 }
272 
PrepareCircleButton()273 void DOMButton::PrepareCircleButton()
274 {
275     buttonChild_->SetType(ButtonType::CIRCLE);
276     paddingChild_->SetPadding(Edge());
277     if (!imageChild_->GetSrc().empty()) {
278         paddingChild_->SetChild(imageChild_);
279     }
280     if (isCustomizedColor_ && isTv_) {
281         buttonDeclaration_->SetFocusColor(buttonDeclaration_->GetBackgroundColor());
282     }
283 }
284 
PrepareDownloadButton()285 void DOMButton::PrepareDownloadButton()
286 {
287     buttonChild_->SetType(ButtonType::DOWNLOAD);
288     if (!isWatch_) {
289         edge_.SetWidth(DOWNLOAD_BORDER_WIDTH);
290         buttonDeclaration_->SetProgressColor(buttonTheme_->GetDownloadProgressColor());
291         if (!isTv_) {
292             if (!buttonDeclaration_->GetRadiusState()) {
293                 buttonDeclaration_->SetRectRadius(buttonTheme_->GetDownloadHeight() / 2.0);
294             }
295             if (!buttonDeclaration_->GetBgColorState()) {
296                 buttonDeclaration_->SetBackgroundColor(buttonTheme_->GetDownloadBackgroundColor());
297             }
298             if (!buttonDeclaration_->GetTextColorState()) {
299                 textStyle_.SetTextColor(buttonTheme_->GetDownloadTextColor());
300             }
301             if (!buttonDeclaration_->GetFontSizeState()) {
302                 textStyle_.SetFontSize(buttonTheme_->GetDownloadFontSize());
303             }
304         }
305         return;
306     }
307     if (!isCustomizedColor_) {
308         buttonDeclaration_->SetBackgroundColor(Color(TRANSPARENT_COLOR));
309     }
310     if (!imageChild_->GetSrc().empty()) {
311         paddingChild_->SetChild(imageChild_);
312     }
313     paddingChild_->SetPadding(Edge());
314     buttonDeclaration_->SetProgressDiameter(diameter_);
315     buttonDeclaration_->SetProgressColor(buttonDeclaration_->GetProgressColor());
316     ResetBoxHeight(INIT_HEIGHT);
317 }
318 
PrepareArcButton()319 void DOMButton::PrepareArcButton()
320 {
321     buttonChild_->SetType(ButtonType::ARC);
322     textStyle_.SetAdaptTextSize(ARC_FONT_SIZE, ARC_FONT_MIN_SIZE);
323     paddingChild_->SetPadding(Edge(ARC_PADDING_HORIZONTAL, ARC_PADDING_TOP,
324         ARC_PADDING_HORIZONTAL, ARC_PADDING_BOTTOM));
325 }
326 
PrepareButtonState()327 void DOMButton::PrepareButtonState()
328 {
329     UpdateCustomizedColorFlag();
330     if (buttonDeclaration_->GetWaitingState()) {
331         PrepareWaiting();
332     } else {
333         if (!textColorChanged_) {
334             textColor_ = textStyle_.GetTextColor();
335         }
336         textStyle_.SetTextColor(textColor_);
337         if (!disabledColorEffected_) {
338             edgeColor_ = edge_.GetColor();
339             disabledColor_ = buttonDeclaration_->GetDisabledColor();
340         }
341         edge_.SetColor(edgeColor_);
342         if (focusColorChanged_) {
343             buttonDeclaration_->SetFocusColor(focusColor_);
344         }
345     }
346     if (buttonDeclaration_->GetDisabledState()) {
347         if (HasDisabledPseudo()) {
348             buttonDeclaration_->SetDisabledColor(buttonDeclaration_->GetBackgroundColor());
349         } else {
350             PrepareDisabledBackgroundColor();
351             PrepareDisabledChildStyle();
352         }
353     }
354 }
355 
PrepareDisabledBackgroundColor()356 void DOMButton::PrepareDisabledBackgroundColor()
357 {
358     edge_.SetColor(edge_.GetColor().BlendOpacity(blendOpacity_));
359     if ((SystemProperties::GetDeviceType() == DeviceType::PHONE) && (buttonType_ == BUTTON_TYPE_DOWNLOAD)) {
360         buttonDeclaration_->SetProgressColor(buttonDeclaration_->GetProgressColor().BlendOpacity(blendOpacity_));
361     }
362 
363     // Disabled background color not defined by user.
364     if (disabledColor_ == Color()) {
365         Color bgColor = buttonDeclaration_->GetBackgroundColor();
366         Color customizedColor = (isWatch_ ? bgColor : bgColor.BlendOpacity(blendOpacity_));
367         buttonDeclaration_->SetDisabledColor(isCustomizedColor_ ? customizedColor : buttonTheme_->GetDisabledColor());
368     } else {
369         buttonDeclaration_->SetDisabledColor(disabledColor_);
370     }
371     disabledColorEffected_ = true;
372 }
373 
PrepareDisabledChildStyle()374 void DOMButton::PrepareDisabledChildStyle()
375 {
376     bool isWatchDownload = isWatch_ && (buttonType_ == BUTTON_TYPE_DOWNLOAD);
377     if ((buttonType_ == BUTTON_TYPE_CIRCLE) || isWatchDownload || buttonDeclaration_->GetWaitingState()) {
378         auto displayChild = AceType::MakeRefPtr<DisplayComponent>(paddingChild_->GetChild());
379         displayChild->SetOpacity(blendOpacity_);
380         paddingChild_->SetChild(displayChild);
381         return;
382     }
383 
384     // Disabled text color not defined by user.
385     Color disabledTextColor = buttonDeclaration_->GetDisabledTextColor();
386     if (disabledTextColor == Color()) {
387         Color textColor = textStyle_.GetTextColor().BlendOpacity(blendOpacity_);
388         textStyle_.SetTextColor(isCustomizedColor_ ? textColor : buttonTheme_->GetTextDisabledColor());
389     } else {
390         textStyle_.SetTextColor(disabledTextColor);
391     }
392     textColorChanged_ = true;
393 }
394 
PrepareClickedColor()395 void DOMButton::PrepareClickedColor()
396 {
397     if (buttonDeclaration_->GetClickedColor() != buttonTheme_->GetClickedColor()) {
398         return;
399     }
400     Color defaultClickedColor = buttonDeclaration_->GetBackgroundColor().BlendColor(buttonTheme_->GetClickedColor());
401     buttonDeclaration_->SetClickedColor(defaultClickedColor);
402 }
403 
PrepareWaiting()404 void DOMButton::PrepareWaiting()
405 {
406     if ((!buttonTheme_) || isWatch_ || (buttonType_ == BUTTON_TYPE_DOWNLOAD)) {
407         return;
408     }
409     buttonDeclaration_->SetFocusColor(focusColor_.BlendOpacity(blendOpacity_));
410     buttonDeclaration_->SetFocusAnimationColor(buttonTheme_->GetBgFocusColor().BlendOpacity(blendOpacity_));
411     focusColorChanged_ = true;
412     if (buttonType_ == BUTTON_TYPE_CIRCLE) {
413         diameter_ = LessNotEqual(buttonChild_->GetWidth().Value(), 0.0)
414                     ? buttonDeclaration_->GetRectRadius()
415                     : std::min(buttonChild_->GetHeight(), buttonChild_->GetWidth()) / 2.0;
416     }
417     auto progressComponent = AceType::MakeRefPtr<LoadingProgressComponent>();
418     progressComponent->SetDiameter(diameter_);
419     progressComponent->SetProgressColor(buttonDeclaration_->GetProgressColor());
420     if ((buttonType_ == BUTTON_TYPE_CIRCLE) || (buttonType_ == BUTTON_TYPE_TEXT) || textChild_->GetData().empty()) {
421         paddingChild_->SetChild(progressComponent);
422         return;
423     }
424     PrepareWaitingWithText(progressComponent);
425 }
426 
PrepareWaitingWithText(const RefPtr<LoadingProgressComponent> & progressComponent)427 void DOMButton::PrepareWaitingWithText(const RefPtr<LoadingProgressComponent>& progressComponent)
428 {
429     if (!progressComponent) {
430         return;
431     }
432     if (!isCustomizedColor_) {
433         textStyle_.SetTextColor(buttonTheme_->GetTextWaitingColor());
434         textColorChanged_ = true;
435     }
436     textStyle_.DisableAdaptTextSize();
437     auto innerPadding = AceType::MakeRefPtr<PaddingComponent>();
438     Edge edge;
439     edge.SetLeft(buttonDeclaration_->GetInnerPadding());
440     innerPadding->SetChild(textChild_);
441     innerPadding->SetPadding(edge);
442     auto flexItemProgress = AceType::MakeRefPtr<FlexItemComponent>(0.0, 0.0, 0.0, progressComponent);
443     auto flexItemText = AceType::MakeRefPtr<FlexItemComponent>(0.0, 0.0, 0.0, innerPadding);
444     flexItemText->SetFlexShrink(FLEX_ITEM_SHRINK);
445     std::list<RefPtr<Component>> children;
446     children.emplace_back(flexItemProgress);
447     children.emplace_back(flexItemText);
448     auto rowComponent = AceType::MakeRefPtr<RowComponent>(FlexAlign::CENTER, FlexAlign::CENTER, children);
449     paddingChild_->SetChild(rowComponent);
450 }
451 
PrepareBorderStyle()452 void DOMButton::PrepareBorderStyle()
453 {
454     if (!isCustomizedColor_) {
455         return;
456     }
457     if ((buttonType_ == BUTTON_TYPE_CAPSULE) || (buttonType_ == BUTTON_TYPE_CIRCLE)) {
458         edge_.SetColor(buttonTheme_->GetBorderColor());
459         edge_.SetWidth(buttonTheme_->GetBorderWidth());
460     }
461 }
462 
PrepareBackDecorationStyle()463 void DOMButton::PrepareBackDecorationStyle()
464 {
465     if (!backDecoration_) {
466         return;
467     }
468     if (backDecoration_->GetImage() || backDecoration_->GetGradient().IsValid()) {
469         buttonDeclaration_->SetBackgroundColor(Color(TRANSPARENT_COLOR));
470     }
471     if (buttonChild_->GetType() == ButtonType::CIRCLE) {
472         return;
473     }
474     auto border = backDecoration_->GetBorder();
475     if (!HasBorderRadiusStyle() || buttonDeclaration_->GetRadiusState()) {
476         if (buttonDeclaration_->GetRectRadius().Unit() == border.Top().GetWidth().Unit()) {
477             backDecoration_->SetBorderRadius(Radius(buttonDeclaration_->GetRectRadius() + border.Top().GetWidth()));
478         }
479     } else {
480         if (border.TopLeftRadius().GetX().Unit() == border.Top().GetWidth().Unit()) {
481             buttonDeclaration_->SetRectRadius(border.TopLeftRadius().GetX() - border.Top().GetWidth());
482         }
483     }
484 }
485 
PrepareChildren()486 void DOMButton::PrepareChildren()
487 {
488     Edge edge;
489     placement_ = buttonDeclaration_->GetPlacement();
490     if (placement_ == PLACEMENT_BOTTOM) {
491         edge.SetBottom(INNER_PADDING);
492     } else if (placement_ == PLACEMENT_TOP) {
493         edge.SetTop(INNER_PADDING);
494     } else if (placement_ == PLACEMENT_START) {
495         edge.SetLeft(INNER_PADDING);
496     } else {
497         edge.SetRight(INNER_PADDING);
498         edge.SetBottom(Dimension(1.0, DimensionUnit::PX));
499     }
500     innerPaddingChild_ = AceType::MakeRefPtr<PaddingComponent>();
501     innerPaddingChild_->SetChild(textChild_);
502     innerPaddingChild_->SetPadding(edge);
503     PrepareChildrenLayout();
504 }
505 
PrepareChildrenLayout()506 void DOMButton::PrepareChildrenLayout()
507 {
508     auto flexItemText = AceType::MakeRefPtr<FlexItemComponent>(0.0, 1.0, 0.0, innerPaddingChild_);
509     auto flexItemIcon = AceType::MakeRefPtr<FlexItemComponent>(0.0, 0.0, 0.0, imageChild_);
510     std::list<RefPtr<Component>> children;
511     if ((placement_ == PLACEMENT_START) || (placement_ == PLACEMENT_TOP)) {
512         children.emplace_back(flexItemIcon);
513         children.emplace_back(flexItemText);
514     } else {
515         children.emplace_back(flexItemText);
516         children.emplace_back(flexItemIcon);
517     }
518     auto flexComponent = AceType::MakeRefPtr<FlexComponent>(FlexDirection::ROW, FlexAlign::CENTER,
519         FlexAlign::CENTER, children);
520     if ((placement_ == PLACEMENT_TOP) || (placement_ == PLACEMENT_BOTTOM)) {
521         flexComponent->SetDirection(FlexDirection::COLUMN);
522     }
523     flexComponent->SetMainAxisSize(MainAxisSize::MIN);
524     paddingChild_->SetChild(flexComponent);
525 }
526 
AddPadding()527 void DOMButton::AddPadding()
528 {
529     if (!boxComponent_) {
530         return;
531     }
532     auto edge = boxComponent_->GetPadding();
533     if (edge == Edge::NONE) {
534         return;
535     }
536     paddingChild_->SetPadding(edge);
537     boxComponent_->SetPadding(Edge());
538 }
539 
ResetBoxHeight(double height,DimensionUnit unit)540 void DOMButton::ResetBoxHeight(double height, DimensionUnit unit)
541 {
542     if (!boxComponent_) {
543         return;
544     }
545     boxComponent_->SetHeight(height, unit);
546 }
547 
UpdateCustomizedColorFlag()548 void DOMButton::UpdateCustomizedColorFlag()
549 {
550     isCustomizedColor_ = buttonDeclaration_->GetBackgroundColor() != buttonTheme_->GetBgColor();
551 }
552 
GetHeight() const553 Dimension DOMButton::GetHeight() const
554 {
555     Dimension height = Dimension(-1.0, DimensionUnit::PX);
556     auto buttonDeclaration = buttonDeclaration_;
557     if (IsPlatformFive()) {
558         // less api 5 should set height of box component in UpdateBoxSize, buttonDeclaration_ != nullptr after
559         // PrepareSpecializedComponent
560         buttonDeclaration = AceType::DynamicCast<ButtonDeclaration>(declaration_);
561     }
562     if (buttonDeclaration) {
563         height = buttonDeclaration->GetHeight();
564     }
565     return height;
566 }
567 
GetWidth() const568 Dimension DOMButton::GetWidth() const
569 {
570     Dimension width = Dimension(-1.0, DimensionUnit::PX);
571     auto buttonDeclaration = buttonDeclaration_;
572     if (IsPlatformFive()) {
573         // less api 5 should set width of box component in UpdateBoxSize, buttonDeclaration_ != nullptr after
574         // PrepareSpecializedComponent
575         buttonDeclaration = AceType::DynamicCast<ButtonDeclaration>(declaration_);
576     }
577     if (buttonDeclaration) {
578         width = buttonDeclaration->GetWidth();
579     }
580 
581     return width;
582 }
583 
IsPlatformFive() const584 bool DOMButton::IsPlatformFive() const
585 {
586     const static int32_t PLATFORM_VERSION_FIVE = 5;
587     auto context = GetPipelineContext().Upgrade();
588     return context && context->GetMinPlatformVersion() <= PLATFORM_VERSION_FIVE;
589 }
590 
591 } // namespace OHOS::Ace::Framework
592