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