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/search/search_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/search/search_theme.h"
22 #include "frameworks/core/components/text_field/textfield_theme.h"
23 
24 namespace OHOS::Ace {
25 
26 using namespace Framework;
27 
SearchDeclaration()28 SearchDeclaration::SearchDeclaration()
29 {
30     textFieldDeclaration_ = AceType::MakeRefPtr<TextFieldDeclaration>();
31     textFieldDeclaration_->BindPipelineContext(pipelineContext_);
32     textFieldDeclaration_->Init();
33 }
34 
InitSpecialized()35 void SearchDeclaration::InitSpecialized()
36 {
37     AddSpecializedAttribute(DeclarationConstants::DEFAULT_SEARCH_ATTR);
38     AddSpecializedStyle(DeclarationConstants::DEFAULT_SEARCH_STYLE);
39     AddSpecializedEvent(DeclarationConstants::DEFAULT_SEARCH_EVENT);
40     AddSpecializedMethod(DeclarationConstants::DEFAULT_SEARCH_METHOD);
41 }
42 
InitializeStyle()43 void SearchDeclaration::InitializeStyle()
44 {
45     textFieldDeclaration_->InitializeStyle();
46 
47     auto textFieldTheme = GetTheme<TextFieldTheme>();
48     auto searchTheme = GetTheme<SearchTheme>();
49     if (!textFieldTheme || !searchTheme) {
50         // theme is null, set default decoration to text field component
51         RefPtr<Decoration> decoration = AceType::MakeRefPtr<Decoration>();
52         textFieldDeclaration_->SetDecoration(decoration);
53         LOGE("textFieldTheme or searchTheme is null");
54         return;
55     }
56 
57     auto& paddingStyle = static_cast<CommonPaddingStyle&>(GetStyle(StyleTag::COMMON_PADDING_STYLE));
58     if (paddingStyle.IsValid()) {
59         paddingStyle.padding = Edge();
60     }
61 
62     auto& sizeStyle = static_cast<CommonSizeStyle&>(GetStyle(StyleTag::COMMON_SIZE_STYLE));
63     if (sizeStyle.IsValid()) {
64         sizeStyle.height = searchTheme->GetHeight();
65     }
66 
67     SetBackDecoration(nullptr);
68 
69     textFieldDeclaration_->SetIconSize(searchTheme->GetIconSize());
70     textFieldDeclaration_->SetIconHotZoneSize(searchTheme->GetCloseIconHotZoneSize());
71     Edge decorationPadding;
72     Dimension leftPadding = searchTheme->GetLeftPadding();
73     Dimension rightPadding = searchTheme->GetRightPadding();
74     if (IsRightToLeft()) {
75         decorationPadding = Edge(rightPadding.Value(), 0.0, leftPadding.Value(), 0.0, leftPadding.Unit());
76     } else {
77         decorationPadding = Edge(leftPadding.Value(), 0.0, rightPadding.Value(), 0.0, leftPadding.Unit());
78     }
79     auto textFieldDecoration = textFieldDeclaration_->GetDecoration();
80     if (textFieldDecoration) {
81         textFieldDecoration->SetPadding(decorationPadding);
82         textFieldDecoration->SetBorderRadius(searchTheme->GetBorderRadius());
83         textFieldDeclaration_->SetOriginBorder(textFieldDecoration->GetBorder());
84     }
85     textFieldDeclaration_->SetAction(TextInputAction::SEARCH);
86     textFieldDeclaration_->SetWidthReserved(searchTheme->GetTextFieldWidthReserved());
87     textFieldDeclaration_->SetTextColor(searchTheme->GetTextColor());
88     textFieldDeclaration_->SetFocusTextColor(searchTheme->GetFocusTextColor());
89     textFieldDeclaration_->SetPlaceholderColor(searchTheme->GetPlaceholderColor());
90     textFieldDeclaration_->SetFocusPlaceholderColor(searchTheme->GetFocusPlaceholderColor());
91     textFieldDeclaration_->SetBlockRightShade(searchTheme->GetBlockRightShade());
92 
93     std::function<void(const std::string&)> submitEvent;
94     SetSubmitEvent(submitEvent);
95     SetTextEditController(textFieldDeclaration_->GetTextEditController());
96     SetCloseIconSize(searchTheme->GetCloseIconSize());
97     SetCloseIconHotZoneHorizontal(searchTheme->GetCloseIconHotZoneSize());
98     SetHoverColor(textFieldTheme->GetHoverColor());
99     SetPressColor(textFieldTheme->GetPressColor());
100     isPaddingChanged_ = true;
101 }
102 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)103 bool SearchDeclaration::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
104 {
105     static const LinearMapNode<void (*)(const std::string&, SearchDeclaration&, TextFieldDeclaration&)>
106         searchAttrOperators[] = {
107             { DOM_AUTO_FOCUS,
108                 [](const std::string& val, SearchDeclaration& searchDeclaration,
109                     TextFieldDeclaration& textFieldDeclaration) {
110                     textFieldDeclaration.SetAutoFocus(StringToBool(val));
111                 } },
112             { DOM_SEARCH_HINT,
113                 [](const std::string& val, SearchDeclaration& searchDeclaration,
114                     TextFieldDeclaration& textFieldDeclaration) { textFieldDeclaration.SetPlaceholder(val); } },
115             { DOM_SEARCH_ICON,
116                 [](const std::string& val, SearchDeclaration& searchDeclaration,
117                     TextFieldDeclaration& textFieldDeclaration) {
118                     if (SystemProperties::GetDeviceType() == DeviceType::TV) {
119                         return;
120                     }
121                     textFieldDeclaration.SetIconImage(val);
122                 } },
123             { DOM_SEARCH_BUTTON,
124                 [](const std::string& val, SearchDeclaration& searchDeclaration,
125                     TextFieldDeclaration& textFieldDeclaration) { searchDeclaration.SetSearchText(val); } },
126             { DOM_INPUT_SELECTED_END,
127                 [](const std::string& val, SearchDeclaration& searchDeclaration,
128                     TextFieldDeclaration& textFieldDeclaration) {
129                     textFieldDeclaration.SetSelectedEnd(StringToInt(val));
130                 } },
131             { DOM_INPUT_SELECTED_START,
132                 [](const std::string& val, SearchDeclaration& searchDeclaration,
133                     TextFieldDeclaration& textFieldDeclaration) {
134                     textFieldDeclaration.SetSelectedStart(StringToInt(val));
135                 } },
136             { DOM_INPUT_SOFT_KEYBOARD_ENABLED,
137                 [](const std::string& val, SearchDeclaration& searchDeclaration,
138                     TextFieldDeclaration& textFieldDeclaration) {
139                     textFieldDeclaration.SetSoftKeyboardEnabled(StringToBool(val));
140                 } },
141             { DOM_SEARCH_VALUE,
142                 [](const std::string& val, SearchDeclaration& searchDeclaration,
143                     TextFieldDeclaration& textFieldDeclaration) {
144                     textFieldDeclaration.SetValue(val);
145                     textFieldDeclaration.SetResetToStart(false);
146                 } },
147         };
148     auto operatorIter = BinarySearchFindIndex(searchAttrOperators, ArraySize(searchAttrOperators), attr.first.c_str());
149     if (operatorIter != -1) {
150         searchAttrOperators[operatorIter].value(attr.second, *this, *textFieldDeclaration_);
151         return true;
152     }
153     return false;
154 }
155 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)156 bool SearchDeclaration::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
157 {
158     // static linear map must be sorted by key.
159     static const LinearMapNode<void (*)(const std::string&, SearchDeclaration&, TextFieldDeclaration&)>
160         searchStyleSize[] = {
161             { DOM_TEXT_ALLOW_SCALE,
162                 [](const std::string& val, SearchDeclaration& searchDeclaration,
163                     TextFieldDeclaration& textFieldDeclaration) {
164                     textFieldDeclaration.GetTextStyle().SetAllowScale(StringToBool(val));
165                 } },
166             { DOM_BACKGROUND_COLOR,
167                 [](const std::string& val, SearchDeclaration& searchDeclaration,
168                     TextFieldDeclaration& textFieldDeclaration) {
169                     textFieldDeclaration.SetBgColor(searchDeclaration.ParseColor(val));
170                     textFieldDeclaration.SetFocusBgColor(searchDeclaration.ParseColor(val));
171                 } },
172             { DOM_CARET_COLOR,
173                 [](const std::string& val, SearchDeclaration& searchDeclaration,
174                     TextFieldDeclaration& textFieldDeclaration) {
175                     textFieldDeclaration.SetCursorColor(searchDeclaration.ParseColor(val));
176                 } },
177             { DOM_COLOR,
178                 [](const std::string& val, SearchDeclaration& searchDeclaration,
179                     TextFieldDeclaration& textFieldDeclaration) {
180                     textFieldDeclaration.SetFocusTextColor(searchDeclaration.ParseColor(val));
181                 } },
182             { DOM_TEXT_FONT_FAMILY,
183                 [](const std::string& val, SearchDeclaration& searchDeclaration,
184                     TextFieldDeclaration& textFieldDeclaration) {
185                     textFieldDeclaration.GetTextStyle().SetFontFamilies(searchDeclaration.ParseFontFamilies(val));
186                 } },
187             { DOM_TEXT_FONT_SIZE,
188                 [](const std::string& val, SearchDeclaration& searchDeclaration,
189                     TextFieldDeclaration& textFieldDeclaration) {
190                     textFieldDeclaration.GetTextStyle().SetFontSize(searchDeclaration.ParseDimension(val));
191                 } },
192             { DOM_TEXT_FONT_WEIGHT,
193                 [](const std::string& val, SearchDeclaration& searchDeclaration,
194                     TextFieldDeclaration& textFieldDeclaration) {
195                     textFieldDeclaration.GetTextStyle().SetFontWeight(ConvertStrToFontWeight(val));
196                 } },
197             { DOM_PADDING,
198                 [](const std::string& val, SearchDeclaration& searchDeclaration,
199                     TextFieldDeclaration& textFieldDeclaration) {
200                     Edge padding;
201                     if (Edge::FromString(val, padding)) {
202                         textFieldDeclaration.GetDecoration()->SetPadding(padding);
203                         searchDeclaration.isPaddingChanged_ = true;
204                     }
205                 } },
206             { DOM_PADDING_BOTTOM,
207                 [](const std::string& val, SearchDeclaration& searchDeclaration,
208                     TextFieldDeclaration& textFieldDeclaration) {
209                     auto padding = textFieldDeclaration.GetDecoration()->GetPadding();
210                     padding.SetBottom(searchDeclaration.ParseDimension(val));
211                     textFieldDeclaration.GetDecoration()->SetPadding(padding);
212                     searchDeclaration.isPaddingChanged_ = true;
213                 } },
214             { DOM_PADDING_END,
215                 [](const std::string& val, SearchDeclaration& searchDeclaration,
216                     TextFieldDeclaration& textFieldDeclaration) {
217                     auto padding = textFieldDeclaration.GetDecoration()->GetPadding();
218                     searchDeclaration.IsRightToLeft() ? padding.SetLeft(searchDeclaration.ParseDimension(val))
219                                                       : padding.SetRight(searchDeclaration.ParseDimension(val));
220                     textFieldDeclaration.GetDecoration()->SetPadding(padding);
221                     searchDeclaration.isPaddingChanged_ = true;
222                 } },
223             { DOM_PADDING_LEFT,
224                 [](const std::string& val, SearchDeclaration& searchDeclaration,
225                     TextFieldDeclaration& textFieldDeclaration) {
226                     auto padding = textFieldDeclaration.GetDecoration()->GetPadding();
227                     padding.SetLeft(searchDeclaration.ParseDimension(val));
228                     textFieldDeclaration.GetDecoration()->SetPadding(padding);
229                     searchDeclaration.isPaddingChanged_ = true;
230                 } },
231             { DOM_PADDING_RIGHT,
232                 [](const std::string& val, SearchDeclaration& searchDeclaration,
233                     TextFieldDeclaration& textFieldDeclaration) {
234                     auto padding = textFieldDeclaration.GetDecoration()->GetPadding();
235                     padding.SetRight(searchDeclaration.ParseDimension(val));
236                     textFieldDeclaration.GetDecoration()->SetPadding(padding);
237                     searchDeclaration.isPaddingChanged_ = true;
238                 } },
239             { DOM_PADDING_START,
240                 [](const std::string& val, SearchDeclaration& searchDeclaration,
241                     TextFieldDeclaration& textFieldDeclaration) {
242                     auto padding = textFieldDeclaration.GetDecoration()->GetPadding();
243                     searchDeclaration.IsRightToLeft() ? padding.SetRight(searchDeclaration.ParseDimension(val))
244                                                       : padding.SetLeft(searchDeclaration.ParseDimension(val));
245                     textFieldDeclaration.GetDecoration()->SetPadding(padding);
246                     searchDeclaration.isPaddingChanged_ = true;
247                 } },
248             { DOM_PADDING_TOP,
249                 [](const std::string& val, SearchDeclaration& searchDeclaration,
250                     TextFieldDeclaration& textFieldDeclaration) {
251                     auto padding = textFieldDeclaration.GetDecoration()->GetPadding();
252                     padding.SetTop(searchDeclaration.ParseDimension(val));
253                     textFieldDeclaration.GetDecoration()->SetPadding(padding);
254                     searchDeclaration.isPaddingChanged_ = true;
255                 } },
256             { DOM_INPUT_PLACEHOLDER_COLOR,
257                 [](const std::string& val, SearchDeclaration& searchDeclaration,
258                     TextFieldDeclaration& textFieldDeclaration) {
259                     textFieldDeclaration.SetPlaceholderColor(searchDeclaration.ParseColor(val));
260                 } },
261         };
262     auto operatorIter = BinarySearchFindIndex(searchStyleSize, ArraySize(searchStyleSize), style.first.c_str());
263     if (operatorIter != -1) {
264         searchStyleSize[operatorIter].value(style.second, *this, *textFieldDeclaration_);
265         return true;
266     }
267     if (style.first == DOM_BORDER_TOP_LEFT_RADIUS || style.first == DOM_BORDER_TOP_RIGHT_RADIUS ||
268         style.first == DOM_BORDER_BOTTOM_LEFT_RADIUS || style.first == DOM_BORDER_BOTTOM_RIGHT_RADIUS ||
269         style.first == DOM_BORDER_RADIUS) {
270         hasBoxRadius_ = true;
271     }
272     return false;
273 }
274 
SetSpecializedEvent(int32_t pageId,const std::string & eventId,const std::string & event)275 bool SearchDeclaration::SetSpecializedEvent(int32_t pageId, const std::string& eventId, const std::string& event)
276 {
277     static const LinearMapNode<void (*)(SearchDeclaration&, TextFieldDeclaration&, const EventMarker&)>
278         eventOperators[] = {
279             { DOM_CHANGE, [](SearchDeclaration& searchDeclaration, TextFieldDeclaration& textFieldDeclaration,
280                               const EventMarker& event) { searchDeclaration.SetChangeEventId(event); } },
281             { DOM_INPUT_EVENT_OPTION_SELECT,
282                 [](SearchDeclaration& searchDeclaration, TextFieldDeclaration& textFieldDeclaration,
283                     const EventMarker& event) { textFieldDeclaration.SetOnOptionsClick(event); } },
284             { DOM_INPUT_EVENT_SEARCH,
285                 [](SearchDeclaration& searchDeclaration, TextFieldDeclaration& textFieldDeclaration,
286                     const EventMarker& event) { textFieldDeclaration.SetOnSearch(event); } },
287             { DOM_INPUT_EVENT_SELECT_CHANGE,
288                 [](SearchDeclaration& searchDeclaration, TextFieldDeclaration& textFieldDeclaration,
289                     const EventMarker& event) { textFieldDeclaration.SetOnSelectChange(event); } },
290             { DOM_INPUT_EVENT_SHARE,
291                 [](SearchDeclaration& searchDeclaration, TextFieldDeclaration& textFieldDeclaration,
292                     const EventMarker& event) { textFieldDeclaration.SetOnShare(event); } },
293             { DOM_SUBMIT, [](SearchDeclaration& searchDeclaration, TextFieldDeclaration& textFieldDeclaration,
294                               const EventMarker& event) { searchDeclaration.SetSubmitEventId(event); } },
295             { DOM_INPUT_EVENT_TRANSLATE,
296                 [](SearchDeclaration& searchDeclaration, TextFieldDeclaration& textFieldDeclaration,
297                     const EventMarker& event) { textFieldDeclaration.SetOnTranslate(event); } },
298         };
299     auto operatorIter = BinarySearchFindIndex(eventOperators, ArraySize(eventOperators), event.c_str());
300     if (operatorIter != -1) {
301         eventOperators[operatorIter].value(*this, *textFieldDeclaration_, EventMarker(eventId, event, pageId));
302         return true;
303     }
304     return false;
305 }
306 
CallSpecializedMethod(const std::string & method,const std::string & args)307 void SearchDeclaration::CallSpecializedMethod(const std::string& method, const std::string& args)
308 {
309     textFieldDeclaration_->CallSpecializedMethod(method, args);
310 }
311 
OnRequestFocus(bool shouldFocus)312 void SearchDeclaration::OnRequestFocus(bool shouldFocus)
313 {
314     textFieldDeclaration_->OnRequestFocus(shouldFocus);
315 }
316 
317 } // namespace OHOS::Ace
318