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/core/components/declaration/button/button_declaration.h"
17 
18 #include "base/log/event_report.h"
19 #include "core/components/button/button_theme.h"
20 #include "frameworks/bridge/common/utils/utils.h"
21 #include "frameworks/core/components/declaration/common/declaration_constants.h"
22 
23 namespace OHOS::Ace {
24 namespace {
25 
26 constexpr uint32_t METHOD_SET_PROGRESS_ARGS_SIZE = 1;
27 
28 } // namespace
29 
30 using namespace Framework;
31 
InitSpecialized()32 void ButtonDeclaration::InitSpecialized()
33 {
34     AddSpecializedAttribute(DeclarationConstants::DEFAULT_BUTTON_ATTR);
35     AddSpecializedStyle(DeclarationConstants::DEFAULT_BUTTON_STYLE);
36     AddSpecializedEvent(DeclarationConstants::DEFAULT_BUTTON_EVENT);
37     AddSpecializedRemoteMessageEvent(DeclarationConstants::DEFAULT_BUTTON_EVENT);
38     AddSpecializedMethod(DeclarationConstants::DEFAULT_BUTTON_METHOD);
39 }
40 
InitializeStyle()41 void ButtonDeclaration::InitializeStyle()
42 {
43     buttonController_ = AceType::MakeRefPtr<ButtonProgressController>();
44     auto& style = MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
45     if (!style.IsValid()) {
46         return;
47     }
48     RefPtr<ButtonTheme> buttonTheme = GetTheme<ButtonTheme>();
49     if (!buttonTheme) {
50         return;
51     }
52     style.padding = buttonTheme->GetPadding();
53     style.blendOpacity = buttonTheme->GetBgDisabledAlpha();
54     style.borderEdge.SetColor(buttonTheme->GetDownloadBorderColor());
55     style.progressColor = buttonTheme->GetProgressColor();
56     style.diameter = buttonTheme->GetProgressDiameter();
57     style.innerLeftPadding = buttonTheme->GetInnerPadding();
58     style.minWidth = buttonTheme->GetMinWidth();
59     style.radius = buttonTheme->GetRadius();
60     style.backgroundColor = buttonTheme->GetBgColor();
61     style.clickedColor = buttonTheme->GetClickedColor();
62     style.focusColor = buttonTheme->GetBgFocusColor();
63     style.hoverColor = buttonTheme->GetHoverColor();
64     style.focusAnimationColor = buttonTheme->GetBgFocusColor();
65     style.progressFocusColor = buttonTheme->GetProgressFocusColor();
66     style.textFocusColor = buttonTheme->GetTextFocusColor();
67     style.textStyle = buttonTheme->GetTextStyle();
68     style.textStyle.SetAdaptTextSize(style.textStyle.GetFontSize(), buttonTheme->GetMinFontSize());
69     style.textStyle.SetMaxLines(buttonTheme->GetTextMaxLines());
70     style.textStyle.SetTextOverflow(TextOverflow::ELLIPSIS);
71     style.textStyle.SetTextAlign(TextAlign::LEFT);
72 }
73 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)74 bool ButtonDeclaration::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
75 {
76     static const LinearMapNode<void (*)(ButtonDeclaration&, const std::string&)> buttonAttrOperators[] = {
77         { DOM_BUTTON_AUTO_FOCUS, [](ButtonDeclaration& button, const std::string& value) {
78             auto& buttonAttr = button.MaybeResetAttribute<ButtonAttribute>(AttributeTag::SPECIALIZED_ATTR);
79             buttonAttr.isAutoFocus = StringToBool(value);
80         } },
81         { DOM_DISABLED, [](ButtonDeclaration& button, const std::string& value) {
82             auto& buttonAttr = button.MaybeResetAttribute<ButtonAttribute>(AttributeTag::SPECIALIZED_ATTR);
83             buttonAttr.isDisabled = StringToBool(value);
84         } },
85         { DOM_BUTTON_ICON, [](ButtonDeclaration& button, const std::string& value) {
86             auto& buttonAttr = button.MaybeResetAttribute<ButtonAttribute>(AttributeTag::SPECIALIZED_ATTR);
87             buttonAttr.iconSrc = value;
88         } },
89         { DOM_PLACEMENT, [](ButtonDeclaration& button, const std::string& value) {
90             auto& buttonAttr = button.MaybeResetAttribute<ButtonAttribute>(AttributeTag::SPECIALIZED_ATTR);
91             buttonAttr.placement = value;
92         } },
93         { DOM_BUTTON_TYPE, [](ButtonDeclaration& button, const std::string& value) {
94             auto& buttonAttr = button.MaybeResetAttribute<ButtonAttribute>(AttributeTag::SPECIALIZED_ATTR);
95             buttonAttr.buttonType = value;
96         } },
97         { DOM_BUTTON_TEXT_DATA, [](ButtonDeclaration& button, const std::string& value) {
98             auto& buttonAttr = button.MaybeResetAttribute<ButtonAttribute>(AttributeTag::SPECIALIZED_ATTR);
99             buttonAttr.textData = value;
100         } },
101         { DOM_BUTTON_WAITING, [](ButtonDeclaration& button, const std::string& value) {
102             auto& buttonAttr = button.MaybeResetAttribute<ButtonAttribute>(AttributeTag::SPECIALIZED_ATTR);
103             buttonAttr.isWaiting = StringToBool(value);
104         } },
105     };
106     auto operatorIter = BinarySearchFindIndex(buttonAttrOperators, ArraySize(buttonAttrOperators), attr.first.c_str());
107     if (operatorIter != -1) {
108         buttonAttrOperators[operatorIter].value(*this, attr.second);
109         return true;
110     }
111     return false;
112 }
113 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)114 bool ButtonDeclaration::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
115 {
116     // Static linear map should be sorted by key.
117     const static LinearMapNode<void (*)(ButtonDeclaration&, const std::string&)> buttonStyleOperators[] = {
118         { DOM_TEXT_ALLOW_SCALE, [](ButtonDeclaration& button, const std::string& value) {
119             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
120             buttonStyle.textStyle.SetAllowScale(StringToBool(value));
121         } },
122         { DOM_BUTTON_DEFAULT_COLOR, [](ButtonDeclaration& button, const std::string& value) {
123             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
124             buttonStyle.backgroundColor = button.ParseColor(value);
125             buttonStyle.bgColorDefined = true;
126         } },
127         { DOM_BUTTON_BORDER_COLOR, [](ButtonDeclaration& button, const std::string& value) {
128             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
129             buttonStyle.borderEdge.SetColor(button.ParseColor(value));
130         } },
131         { DOM_BUTTON_BORDER_WIDTH, [](ButtonDeclaration& button, const std::string& value) {
132             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
133             buttonStyle.borderEdge.SetWidth(button.ParseDimension(value));
134         } },
135         { DOM_BUTTON_ICON_DIRECTION, [](ButtonDeclaration& button, const std::string& value) {
136             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
137             buttonStyle.matchTextDirection = StringToBool(value);
138         } },
139         { DOM_BUTTON_CLICKED_COLOR, [](ButtonDeclaration& button, const std::string& value) {
140             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
141             buttonStyle.clickedColor = button.ParseColor(value);
142         } },
143         { DOM_BUTTON_PROGRESS_DIAMETER, [](ButtonDeclaration& button, const std::string& value) {
144             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
145             buttonStyle.diameter = button.ParseDimension(value);
146         } },
147         { DOM_BUTTON_DISABLE_COLOR, [](ButtonDeclaration& button, const std::string& value) {
148             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
149             buttonStyle.disabledColor = button.ParseColor(value);
150         } },
151         { DOM_BUTTON_TEXT_DISABLE_COLOR, [](ButtonDeclaration& button, const std::string& value) {
152             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
153             buttonStyle.disabledTextColor = button.ParseColor(value);
154         } },
155         { DOM_BUTTON_FOCUS_COLOR, [](ButtonDeclaration& button, const std::string& value) {
156             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
157             buttonStyle.focusColor = button.ParseColor(value);
158         } },
159         { DOM_BUTTON_FONT_FAMILY, [](ButtonDeclaration& button, const std::string& value) {
160             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
161             buttonStyle.textStyle.SetFontFamilies(button.ParseFontFamilies(value));
162         } },
163         { DOM_BUTTON_FONT_SIZE, [](ButtonDeclaration& button, const std::string& value) {
164             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
165             buttonStyle.textStyle.SetFontSize(button.ParseDimension(value));
166             buttonStyle.fontSizeDefined = true;
167         } },
168         { DOM_BUTTON_FONT_STYLE, [](ButtonDeclaration& button, const std::string& value) {
169             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
170             buttonStyle.textStyle.SetFontStyle(ConvertStrToFontStyle(value));
171         } },
172         { DOM_BUTTON_FONT_WEIGHT, [](ButtonDeclaration& button, const std::string& value) {
173             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
174             buttonStyle.textStyle.SetFontWeight(ConvertStrToFontWeight(value));
175         } },
176         { DOM_BUTTON_HEIGHT, [](ButtonDeclaration& button, const std::string& value) {
177             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
178             buttonStyle.height = button.ParseDimension(value);
179             buttonStyle.heightDefined = true;
180         } },
181         { DOM_BUTTON_ICON_HEIGHT, [](ButtonDeclaration& button, const std::string& value) {
182             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
183             buttonStyle.iconHeight = button.ParseDimension(value);
184         } },
185         { DOM_BUTTON_ICON_WIDTH, [](ButtonDeclaration& button, const std::string& value) {
186             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
187             buttonStyle.iconWidth = button.ParseDimension(value);
188         } },
189         { DOM_BUTTON_INNER_PADDING, [](ButtonDeclaration& button, const std::string& value) {
190             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
191             buttonStyle.innerLeftPadding = button.ParseDimension(value);
192         } },
193         { DOM_BUTTON_MIN_WIDTH, [](ButtonDeclaration& button, const std::string& value) {
194             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
195             buttonStyle.minWidth = button.ParseDimension(value);
196         } },
197         { DOM_BUTTON_PROGRESS_COLOR, [](ButtonDeclaration& button, const std::string& value) {
198             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
199             buttonStyle.progressColor = button.ParseColor(value);
200         } },
201         { DOM_BUTTON_PROGRESS_FOCUS_COLOR, [](ButtonDeclaration& button, const std::string& value) {
202             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
203             buttonStyle.progressFocusColor = button.ParseColor(value);
204         } },
205         { DOM_BUTTON_RRECT_RADIUS, [](ButtonDeclaration& button, const std::string& value) {
206             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
207             buttonStyle.radius = button.ParseDimension(value);
208             buttonStyle.radiusDefined = true;
209         } },
210         { DOM_BUTTON_TEXT_COLOR, [](ButtonDeclaration& button, const std::string& value) {
211             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
212             buttonStyle.textStyle.SetTextColor(button.ParseColor(value));
213             buttonStyle.textColorDefined = true;
214         } },
215         { DOM_BUTTON_WIDTH, [](ButtonDeclaration& button, const std::string& value) {
216             auto& buttonStyle = button.MaybeResetStyle<ButtonStyle>(StyleTag::SPECIALIZED_STYLE);
217             buttonStyle.width = button.ParseDimension(value);
218         } },
219     };
220     auto operatorIter =
221         BinarySearchFindIndex(buttonStyleOperators, ArraySize(buttonStyleOperators), style.first.c_str());
222     if (operatorIter != -1) {
223         buttonStyleOperators[operatorIter].value(*this, style.second);
224         return true;
225     }
226     return false;
227 }
228 
SetSpecializedEvent(int32_t pageId,const std::string & eventId,const std::string & event)229 bool ButtonDeclaration::SetSpecializedEvent(int32_t pageId, const std::string& eventId, const std::string& event)
230 {
231     if (event == DOM_CLICK) {
232         EventMarker eventMarker(eventId, event, pageId);
233         eventMarker.SetCatchMode(false);
234         SetClickedEventId(eventMarker);
235         return true;
236     } else if (event == DOM_CATCH_BUBBLE_CLICK) {
237         EventMarker eventMarker(eventId, event, pageId);
238         eventMarker.SetCatchMode(true);
239         SetClickedEventId(eventMarker);
240         return true;
241     }
242     return false;
243 }
244 
CallSpecializedMethod(const std::string & method,const std::string & args)245 void ButtonDeclaration::CallSpecializedMethod(const std::string& method, const std::string& args)
246 {
247     if (!buttonController_) {
248         EventReport::SendComponentException(ComponentExcepType::BUTTON_COMPONENT_ERR);
249         return;
250     }
251     if (method == DOM_BUTTON_METHOD_SET_PROGRESS) {
252         std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
253         if ((!argsValue) || (!argsValue->IsArray()) || (argsValue->GetArraySize() != METHOD_SET_PROGRESS_ARGS_SIZE)) {
254             return;
255         }
256         std::unique_ptr<JsonValue> progressValue = argsValue->GetArrayItem(0)->GetValue("progress");
257         if ((!progressValue) || (!progressValue->IsNumber())) {
258             return;
259         }
260         uint32_t progress = progressValue->GetUInt();
261         buttonController_->SetProgress(progress);
262     }
263 }
264 
265 } // namespace OHOS::Ace
266