• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "core/components/declaration/textfield/textfield_declaration.h"
17 
18 #include "base/utils/string_utils.h"
19 #include "core/components/declaration/common/declaration_constants.h"
20 #include "frameworks/bridge/common/utils/utils.h"
21 #include "frameworks/core/components/text_field/textfield_theme.h"
22 
23 namespace OHOS::Ace {
24 namespace {
25 
26 constexpr uint32_t METHOD_SHOW_ERROR_ARGS_SIZE = 1;
27 const TextInputAction INPUT_TEXTINPUTACTION_VALUE_DEFAULT = TextInputAction::UNSPECIFIED;
28 const std::vector<std::string> INPUT_FONT_FAMILY_VALUE = {
29     "sans-serif",
30 };
31 
IsRadiusStyle(const std::string & style)32 bool IsRadiusStyle(const std::string& style)
33 {
34     return (style == DOM_BORDER_TOP_LEFT_RADIUS || style == DOM_BORDER_TOP_RIGHT_RADIUS ||
35             style == DOM_BORDER_BOTTOM_LEFT_RADIUS || style == DOM_BORDER_BOTTOM_RIGHT_RADIUS ||
36             style == DOM_BORDER_RADIUS);
37 }
38 
39 } // namespace
40 
41 using namespace Framework;
42 
InitSpecialized()43 void TextFieldDeclaration::InitSpecialized()
44 {
45     AddCommonStyle(StyleTag::COMMON_IMAGE_STYLE);
46     AddSpecializedAttribute(DeclarationConstants::DEFAULT_TEXTFIELD_ATTR);
47     AddSpecializedStyle(DeclarationConstants::DEFAULT_TEXTFIELD_STYLE);
48     AddSpecializedEvent(DeclarationConstants::DEFAULT_TEXTFIELD_EVENT);
49     AddSpecializedMethod(DeclarationConstants::DEFAULT_TEXTFIELD_METHOD);
50 }
51 
InitializeStyle()52 void TextFieldDeclaration::InitializeStyle()
53 {
54     auto theme = GetTheme<TextFieldTheme>();
55     if (!theme) {
56         return;
57     }
58 
59     auto& attribute = static_cast<TextFieldAttribute&>(GetAttribute(AttributeTag::SPECIALIZED_ATTR));
60     attribute.action = INPUT_TEXTINPUTACTION_VALUE_DEFAULT;
61     attribute.showEllipsis = theme->ShowEllipsis();
62     attribute.needFade = theme->NeedFade();
63     attribute.iconSize = theme->GetIconSize();
64     attribute.iconHotZoneSize = theme->GetIconHotZoneSize();
65 
66     auto& style = static_cast<TextFieldStyle&>(GetStyle(StyleTag::SPECIALIZED_STYLE));
67     style.height = theme->GetHeight();
68     style.cursorColor = theme->GetCursorColor();
69     style.cursorColorIsSet = true;
70     style.cursorRadius = theme->GetCursorRadius();
71     style.textColor = theme->GetTextColor();
72     style.focusTextColor = theme->GetFocusTextColor();
73     style.placeholderColor = theme->GetPlaceholderColor();
74     style.focusPlaceholderColor = theme->GetFocusPlaceholderColor();
75     style.bgColor = theme->GetBgColor();
76     style.focusBgColor = theme->GetFocusBgColor();
77     style.selectedColor = theme->GetSelectedColor();
78     style.hoverColor = theme->GetHoverColor();
79     style.pressColor = theme->GetPressColor();
80 
81     style.textStyle.SetTextColor(theme->GetTextColor());
82     style.textStyle.SetFontSize(theme->GetFontSize());
83     style.textStyle.SetFontWeight(theme->GetFontWeight());
84     style.textStyle.SetFontFamilies(INPUT_FONT_FAMILY_VALUE);
85 
86     style.countTextStyle = theme->GetCountTextStyle();
87     style.overCountStyle = theme->GetOverCountStyle();
88     style.countTextStyleOuter = theme->GetCountTextStyleOuter();
89     style.overCountStyleOuter = theme->GetOverCountStyleOuter();
90 
91     style.errorTextStyle = theme->GetErrorTextStyle();
92     style.errorSpacing = theme->GetErrorSpacing();
93     style.errorIsInner = theme->GetErrorIsInner();
94     style.errorBorderWidth = theme->GetErrorBorderWidth();
95     style.errorBorderColor = theme->GetErrorBorderColor();
96 
97     RefPtr<Decoration> decoration = AceType::MakeRefPtr<Decoration>();
98     decoration->SetPadding(theme->GetPadding());
99     decoration->SetBackgroundColor(theme->GetBgColor());
100     decoration->SetBorderRadius(theme->GetBorderRadius());
101     auto boxDecoration = GetDecoration();
102     if (boxDecoration) {
103         decoration->SetImage(boxDecoration->GetImage());
104         decoration->SetGradient(boxDecoration->GetGradient());
105     }
106     style.decoration = decoration;
107 
108     textEditController_ = AceType::MakeRefPtr<TextEditController>();
109     textFieldController_ = AceType::MakeRefPtr<TextFieldController>();
110 }
111 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)112 bool TextFieldDeclaration::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
113 {
114     // this static map should be sorted by key.
115     static const LinearMapNode<void (*)(TextFieldDeclaration&, const std::string&)> attrOperators[] = {
116         { DOM_AUTO_FOCUS, [](TextFieldDeclaration& declaration,
117                               const std::string& value) { declaration.SetAutoFocus(StringToBool(value)); } },
118         { DOM_DISABLED, [](TextFieldDeclaration& declaration,
119                             const std::string& value) { declaration.SetEnabled(!StringToBool(value)); } },
120         { DOM_INPUT_ENTERKEYTYPE,
121             [](TextFieldDeclaration& declaration, const std::string& value) {
122                 declaration.SetAction(ConvertStrToTextInputAction(value));
123             } },
124         { DOM_ICON_SRC,
125             [](TextFieldDeclaration& declaration, const std::string& value) { declaration.SetIconImage(value); } },
126         { DOM_HIDE_ICON_SRC,
127             [](TextFieldDeclaration& declaration, const std::string& value) { declaration.SetHideIconImage(value); } },
128         { DOM_INPUT_MAXLENGTH,
129             [](TextFieldDeclaration& declaration, const std::string& value) {
130                 int32_t tmp = StringUtils::StringToInt(value);
131                 declaration.SetMaxLength(tmp >= 0 ? (uint32_t)(tmp) : std::numeric_limits<uint32_t>::max());
132             } },
133         { DOM_INPUT_OBSCURE, [](TextFieldDeclaration& declaration,
134                                  const std::string& value) { declaration.SetObscure(StringToBool(value)); } },
135         { DOM_TEXTAREA_OVERFLOWX,
136             [](TextFieldDeclaration& declaration, const std::string& value) {
137                 declaration.SetOverflowX(ConvertStrToTextFieldOverflowX(value));
138             } },
139         { DOM_INPUT_PLACEHOLDER,
140             [](TextFieldDeclaration& declaration, const std::string& value) {
141                 declaration.SetPlaceholder(value);
142             } },
143         { DOM_INPUT_SELECTED_END, [](TextFieldDeclaration& declaration,
144                                       const std::string& value) { declaration.SetSelectedEnd(StringToInt(value)); } },
145         { DOM_INPUT_SELECTED_START,
146             [](TextFieldDeclaration& declaration, const std::string& value) {
147                 declaration.SetSelectedStart(StringToInt(value));
148             } },
149         { DOM_INPUT_SHOW_COUNTER, [](TextFieldDeclaration& declaration,
150                                       const std::string& value) { declaration.SetShowCounter(StringToBool(value)); } },
151         { DOM_SHOW_ICON_SRC,
152             [](TextFieldDeclaration& declaration, const std::string& value) { declaration.SetShowIconImage(value); } },
153         { DOM_INPUT_SHOW_PASSWORD_ICON,
154             [](TextFieldDeclaration& declaration, const std::string& value) {
155                 declaration.SetShowPasswordIcon(StringToBool(value));
156             } },
157         { DOM_INPUT_SOFT_KEYBOARD_ENABLED,
158             [](TextFieldDeclaration& declaration, const std::string& value) {
159                 declaration.SetSoftKeyboardEnabled(StringToBool(value));
160             } },
161         { DOM_INPUT_TYPE,
162             [](TextFieldDeclaration& declaration, const std::string& value) {
163                 declaration.SetTextInputType(ConvertStrToTextInputType(value));
164                 declaration.SetObscure(value == DOM_INPUT_TYPE_PASSWORD);
165             } },
166         { DOM_INPUT_VALUE,
167             [](TextFieldDeclaration& declaration, const std::string& value) { declaration.SetValue(value); } },
168     };
169     auto operatorIter = BinarySearchFindIndex(attrOperators, ArraySize(attrOperators), attr.first.c_str());
170     if (operatorIter != -1) {
171         attrOperators[operatorIter].value(*this, attr.second);
172         return true;
173     }
174     return false;
175 }
176 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)177 bool TextFieldDeclaration::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
178 {
179     // static linear map must be sorted by key.
180     static const LinearMapNode<void (*)(TextFieldDeclaration&, const std::string&)> styleOperators[] = {
181         { DOM_TEXT_ALLOW_SCALE,
182             [](TextFieldDeclaration& declaration, const std::string& value) {
183                 declaration.GetTextStyle().SetAllowScale(StringToBool(value));
184             } },
185         { DOM_BACKGROUND_COLOR,
186             [](TextFieldDeclaration& declaration, const std::string& value) {
187                 declaration.SetBgColor(declaration.ParseColor(value));
188                 declaration.SetFocusBgColor(declaration.ParseColor(value));
189             } },
190         { DOM_CARET_COLOR,
191             [](TextFieldDeclaration& declaration, const std::string& value) {
192                 declaration.SetCursorColor(declaration.ParseColor(value));
193             } },
194         { DOM_INPUT_COLOR,
195             [](TextFieldDeclaration& declaration, const std::string& value) {
196                 declaration.GetTextStyle().SetTextColor(declaration.ParseColor(value));
197                 declaration.SetFocusTextColor(declaration.ParseColor(value));
198             } },
199         { DOM_INPUT_CURSOR_COLOR,
200             [](TextFieldDeclaration& declaration, const std::string& value) {
201                 declaration.SetCursorColor(declaration.ParseColor(value));
202             } },
203         { DOM_INPUT_FONT_FAMILY,
204             [](TextFieldDeclaration& declaration, const std::string& value) {
205                 std::vector<std::string> fontFamilies;
206                 std::stringstream sstr(value);
207                 std::string fontFamily;
208                 while (getline(sstr, fontFamily, ',')) {
209                     fontFamilies.emplace_back(fontFamily);
210                 }
211                 declaration.GetTextStyle().SetFontFamilies(fontFamilies);
212             } },
213         { DOM_INPUT_FONT_SIZE,
214             [](TextFieldDeclaration& declaration, const std::string& value) {
215                 declaration.GetTextStyle().SetFontSize(declaration.ParseDimension(value));
216             } },
217         { DOM_INPUT_FONT_WEIGHT,
218             [](TextFieldDeclaration& declaration, const std::string& value) {
219                 declaration.GetTextStyle().SetFontWeight(ConvertStrToFontWeight(value));
220             } },
221         { DOM_PADDING,
222             [](TextFieldDeclaration& declaration, const std::string& value) {
223                 Edge padding;
224                 if (Edge::FromString(value, padding)) {
225                     declaration.GetDecoration()->SetPadding(padding);
226                 }
227             } },
228         { DOM_PADDING_BOTTOM,
229             [](TextFieldDeclaration& declaration, const std::string& value) {
230                 auto padding = declaration.GetDecoration()->GetPadding();
231                 padding.SetBottom(declaration.ParseDimension(value));
232                 declaration.GetDecoration()->SetPadding(padding);
233             } },
234         { DOM_PADDING_END,
235             [](TextFieldDeclaration& declaration, const std::string& value) {
236                 auto padding = declaration.GetDecoration()->GetPadding();
237                 declaration.IsRightToLeft() ? padding.SetLeft(declaration.ParseDimension(value))
238                                             : padding.SetRight(declaration.ParseDimension(value));
239                 declaration.GetDecoration()->SetPadding(padding);
240             } },
241         { DOM_PADDING_LEFT,
242             [](TextFieldDeclaration& declaration, const std::string& value) {
243                 auto padding = declaration.GetDecoration()->GetPadding();
244                 padding.SetLeft(declaration.ParseDimension(value));
245                 declaration.GetDecoration()->SetPadding(padding);
246             } },
247         { DOM_PADDING_RIGHT,
248             [](TextFieldDeclaration& declaration, const std::string& value) {
249                 auto padding = declaration.GetDecoration()->GetPadding();
250                 padding.SetRight(declaration.ParseDimension(value));
251                 declaration.GetDecoration()->SetPadding(padding);
252             } },
253         { DOM_PADDING_START,
254             [](TextFieldDeclaration& declaration, const std::string& value) {
255                 auto padding = declaration.GetDecoration()->GetPadding();
256                 declaration.IsRightToLeft() ? padding.SetRight(declaration.ParseDimension(value))
257                                             : padding.SetLeft(declaration.ParseDimension(value));
258                 declaration.GetDecoration()->SetPadding(padding);
259             } },
260         { DOM_PADDING_TOP,
261             [](TextFieldDeclaration& declaration, const std::string& value) {
262                 auto padding = declaration.GetDecoration()->GetPadding();
263                 padding.SetTop(declaration.ParseDimension(value));
264                 declaration.GetDecoration()->SetPadding(padding);
265             } },
266         { DOM_INPUT_PLACEHOLDER_COLOR,
267             [](TextFieldDeclaration& declaration, const std::string& value) {
268                 declaration.SetPlaceholderColor(declaration.ParseColor(value));
269                 declaration.SetFocusPlaceholderColor(declaration.ParseColor(value));
270             } },
271     };
272     if (IsRadiusStyle(style.first)) {
273         hasBoxRadius_ = true;
274     }
275     auto operatorIter = BinarySearchFindIndex(styleOperators, ArraySize(styleOperators), style.first.c_str());
276     if (operatorIter != -1) {
277         styleOperators[operatorIter].value(*this, style.second);
278         return true;
279     }
280     return false;
281 }
282 
SetSpecializedEvent(int32_t pageId,const std::string & eventId,const std::string & event)283 bool TextFieldDeclaration::SetSpecializedEvent(int32_t pageId, const std::string& eventId, const std::string& event)
284 {
285     static const LinearMapNode<void (*)(TextFieldDeclaration&, const EventMarker&)> eventOperators[] = {
286         { DOM_CATCH_BUBBLE_CLICK,
287             [](TextFieldDeclaration& declaration, const EventMarker& event) {
288                 EventMarker eventMarker(event);
289                 eventMarker.SetCatchMode(true);
290                 declaration.SetOnTap(eventMarker);
291             } },
292         { DOM_CHANGE,
293             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnTextChange(event); } },
294         { DOM_CLICK, [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnTap(event); } },
295         { DOM_INPUT_EVENT_ENTERKEYCLICK,
296             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnFinishInput(event); } },
297         { DOM_LONG_PRESS,
298             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnLongPress(event); } },
299         { DOM_INPUT_EVENT_OPTION_SELECT,
300             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnOptionsClick(event); } },
301         { DOM_INPUT_EVENT_SEARCH,
302             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnSearch(event); } },
303         { DOM_INPUT_EVENT_SELECT_CHANGE,
304             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnSelectChange(event); } },
305         { DOM_INPUT_EVENT_SHARE,
306             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnShare(event); } },
307         { DOM_INPUT_EVENT_TRANSLATE,
308             [](TextFieldDeclaration& declaration, const EventMarker& event) { declaration.SetOnTranslate(event); } },
309     };
310     auto operatorIter = BinarySearchFindIndex(eventOperators, ArraySize(eventOperators), event.c_str());
311     if (operatorIter != -1) {
312         eventOperators[operatorIter].value(*this, EventMarker(eventId, event, pageId));
313         return true;
314     }
315     return false;
316 }
317 
CallSpecializedMethod(const std::string & method,const std::string & args)318 void TextFieldDeclaration::CallSpecializedMethod(const std::string& method, const std::string& args)
319 {
320     if (!textFieldController_) {
321         return;
322     }
323     if (method == DOM_INPUT_METHOD_SHOW_ERROR) {
324         std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
325         if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != METHOD_SHOW_ERROR_ARGS_SIZE) {
326             LOGE("parse args error");
327             return;
328         }
329 
330         std::unique_ptr<JsonValue> error = argsValue->GetArrayItem(0)->GetValue("error");
331         if (!error || !error->IsString()) {
332             LOGE("get error text failed");
333             return;
334         }
335         std::string errorText = error->GetString();
336         textFieldController_->ShowError(errorText);
337     } else if (method == DOM_INPUT_METHOD_DELETE) {
338         textFieldController_->Delete();
339     }
340 }
341 
OnRequestFocus(bool shouldFocus)342 void TextFieldDeclaration::OnRequestFocus(bool shouldFocus)
343 {
344     if (textFieldController_) {
345         textFieldController_->Focus(shouldFocus);
346     }
347 }
348 
349 } // namespace OHOS::Ace
350