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