1 /*
2 * Copyright (c) 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 "bridge/declarative_frontend/jsview/models/search_model_impl.h"
17
18 #include <utility>
19
20 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
21 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
22 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
23 #include "bridge/declarative_frontend/view_stack_processor.h"
24
25 namespace OHOS::Ace::Framework {
26
27 namespace {
28 const TextInputAction INPUT_TEXTINPUTACTION_VALUE_DEFAULT = TextInputAction::UNSPECIFIED;
29 const std::vector<std::string> INPUT_FONT_FAMILY_VALUE = {
30 "sans-serif",
31 };
32 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END };
33 Radius defaultRadius;
34 constexpr Dimension BOX_HOVER_RADIUS = 18.0_vp;
35 bool isPaddingChanged;
36 } // namespace
37
Create(const std::optional<std::string> & value,const std::optional<std::string> & placeholder,const std::optional<std::string> & icon)38 RefPtr<TextFieldControllerBase> SearchModelImpl::Create(const std::optional<std::string>& value,
39 const std::optional<std::string>& placeholder, const std::optional<std::string>& icon)
40 {
41 auto searchComponent = AceType::MakeRefPtr<OHOS::Ace::SearchComponent>();
42 ViewStackProcessor::GetInstance()->ClaimElementId(searchComponent);
43 ViewStackProcessor::GetInstance()->Push(searchComponent);
44 auto textFieldComponent = AceType::MakeRefPtr<OHOS::Ace::TextFieldComponent>();
45 auto textFieldTheme = JSViewAbstract::GetTheme<TextFieldTheme>();
46 auto searchTheme = JSViewAbstract::GetTheme<SearchTheme>();
47 InitializeComponent(searchComponent, textFieldComponent, searchTheme, textFieldTheme);
48 PrepareSpecializedComponent(searchComponent, textFieldComponent);
49 if (value.has_value()) {
50 textFieldComponent->SetValue(value.value());
51 }
52 if (placeholder.has_value()) {
53 textFieldComponent->SetPlaceholder(placeholder.value());
54 }
55 if (icon.has_value()) {
56 textFieldComponent->SetIconImage(icon.value());
57 }
58 return textFieldComponent->GetTextFieldController();
59 }
60
SetSearchButton(const std::string & text)61 void SearchModelImpl::SetSearchButton(const std::string& text)
62 {
63 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
64 auto searchComponent = AceType::DynamicCast<SearchComponent>(component);
65 if (!searchComponent) {
66 LOGE("component error");
67 return;
68 }
69 searchComponent->SetSearchText(text);
70 }
71
SetPlaceholderColor(const Color & color)72 void SearchModelImpl::SetPlaceholderColor(const Color& color)
73 {
74 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
75 auto searchComponent = AceType::DynamicCast<SearchComponent>(component);
76 if (!searchComponent) {
77 LOGE("search component error");
78 return;
79 }
80 auto childComponent = searchComponent->GetChild();
81 if (!childComponent) {
82 LOGE("component error");
83 return;
84 }
85 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
86 if (!textFieldComponent) {
87 LOGE("text component error");
88 return;
89 }
90 textFieldComponent->SetPlaceholderColor(color);
91 textFieldComponent->SetFocusPlaceholderColor(color);
92 }
93
SetPlaceholderFont(const Font & font)94 void SearchModelImpl::SetPlaceholderFont(const Font& font)
95 {
96 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
97 auto searchComponent = AceType::DynamicCast<SearchComponent>(component);
98 if (!searchComponent) {
99 LOGE("search component error");
100 return;
101 }
102 auto childComponent = searchComponent->GetChild();
103 if (!childComponent) {
104 LOGE("component error");
105 return;
106 }
107 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
108 if (!textFieldComponent) {
109 LOGE("text component error");
110 return;
111 }
112 TextStyle textStyle = searchComponent->GetPlaceHoldStyle();
113 if (font.fontSize && font.fontSize->IsNonNegative()) {
114 textStyle.SetFontSize(font.fontSize.value());
115 }
116 if (font.fontWeight) {
117 textStyle.SetFontWeight(font.fontWeight.value());
118 }
119 if (font.fontStyle) {
120 textStyle.SetFontStyle(font.fontStyle.value());
121 }
122 if (!font.fontFamilies.empty()) {
123 textStyle.SetFontFamilies(font.fontFamilies);
124 }
125 textFieldComponent->SetPlaceHoldStyle(textStyle);
126 }
127
SetTextFont(const Font & font)128 void SearchModelImpl::SetTextFont(const Font& font)
129 {
130 auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
131 auto searchComponent = AceType::DynamicCast<SearchComponent>(component);
132 if (!searchComponent) {
133 LOGE("search component error");
134 return;
135 }
136 auto childComponent = searchComponent->GetChild();
137 if (!childComponent) {
138 LOGE("component error");
139 return;
140 }
141 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
142 if (!textFieldComponent) {
143 LOGE("text component error");
144 return;
145 }
146 TextStyle textStyle = searchComponent->GetEditingStyle();
147 if (font.fontSize && font.fontSize->IsNonNegative()) {
148 textStyle.SetFontSize(font.fontSize.value());
149 }
150 if (font.fontWeight) {
151 textStyle.SetFontWeight(font.fontWeight.value());
152 }
153 if (font.fontStyle) {
154 textStyle.SetFontStyle(font.fontStyle.value());
155 }
156 if (!font.fontFamilies.empty()) {
157 textStyle.SetFontFamilies(font.fontFamilies);
158 }
159 textFieldComponent->SetEditingStyle(textStyle);
160 }
161
SetTextAlign(const TextAlign & textAlign)162 void SearchModelImpl::SetTextAlign(const TextAlign& textAlign)
163 {
164 auto* stack = ViewStackProcessor::GetInstance();
165 auto component = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
166 CHECK_NULL_VOID(component);
167 auto childComponent = component->GetChild();
168 CHECK_NULL_VOID(childComponent);
169 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
170 CHECK_NULL_VOID(textFieldComponent);
171 textFieldComponent->SetTextAlign(textAlign);
172 }
173
SetCopyOption(const CopyOptions & copyOptions)174 void SearchModelImpl::SetCopyOption(const CopyOptions& copyOptions)
175 {
176 JSViewSetProperty(&TextFieldComponent::SetCopyOption, copyOptions);
177 }
178
SetMenuOptionItems(std::vector<NG::MenuOptionsParam> && menuOptionsItems)179 void SearchModelImpl::SetMenuOptionItems(std::vector<NG::MenuOptionsParam>&& menuOptionsItems)
180 {
181 LOGI("only newPipeline supply");
182 }
183
SetFocusable(bool focusable)184 void SearchModelImpl::SetFocusable(bool focusable)
185 {
186 auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent();
187 CHECK_NULL_VOID(focusableComponent);
188 focusableComponent->SetFocusable(focusable);
189 }
190
SetFocusNode(bool isFocusNode)191 void SearchModelImpl::SetFocusNode(bool isFocusNode)
192 {
193 auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent(false);
194 CHECK_NULL_VOID(focusableComponent);
195 focusableComponent->SetFocusNode(!isFocusNode);
196 }
197
SetHeight(const Dimension & value)198 void SearchModelImpl::SetHeight(const Dimension& value)
199 {
200 auto stack = ViewStackProcessor::GetInstance();
201 auto searchComponent = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
202 CHECK_NULL_VOID(searchComponent);
203 auto childComponent = searchComponent->GetChild();
204 CHECK_NULL_VOID(childComponent);
205 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
206 CHECK_NULL_VOID(textFieldComponent);
207 textFieldComponent->SetHeight(value);
208 }
209
SetBackBorder()210 void SearchModelImpl::SetBackBorder()
211 {
212 auto stack = ViewStackProcessor::GetInstance();
213 auto searchComponent = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
214 CHECK_NULL_VOID(searchComponent);
215 auto childComponent = searchComponent->GetChild();
216 CHECK_NULL_VOID(childComponent);
217 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
218 CHECK_NULL_VOID(textFieldComponent);
219 auto decoration = textFieldComponent->GetDecoration();
220 CHECK_NULL_VOID(decoration);
221 auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
222 auto boxDecoration = box->GetBackDecoration();
223 if (boxDecoration) {
224 decoration->SetBorder(boxDecoration->GetBorder());
225 Border border = {};
226 boxDecoration->SetBorder(border);
227 }
228 textFieldComponent->SetOriginBorder(decoration->GetBorder());
229 }
230
SetOnSubmit(std::function<void (const std::string &)> && onSubmit)231 void SearchModelImpl::SetOnSubmit(std::function<void(const std::string&)>&& onSubmit)
232 {
233 auto* stack = ViewStackProcessor::GetInstance();
234 auto component = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
235 CHECK_NULL_VOID(component);
236 component->SetOnSubmit(std::move(onSubmit));
237 }
238
SetOnChange(std::function<void (const std::string &)> && onChange)239 void SearchModelImpl::SetOnChange(std::function<void(const std::string&)>&& onChange)
240 {
241 auto* stack = ViewStackProcessor::GetInstance();
242 auto component = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
243 CHECK_NULL_VOID(component);
244 component->SetOnChange(std::move(onChange));
245 }
246
SetOnCopy(std::function<void (const std::string &)> && func)247 void SearchModelImpl::SetOnCopy(std::function<void(const std::string&)>&& func)
248 {
249 auto* stack = ViewStackProcessor::GetInstance();
250 auto component = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
251 CHECK_NULL_VOID(component);
252 auto childComponent = component->GetChild();
253 CHECK_NULL_VOID(childComponent);
254 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
255 CHECK_NULL_VOID(textFieldComponent);
256 textFieldComponent->SetOnCopy(std::move(func));
257 }
258
SetOnCut(std::function<void (const std::string &)> && func)259 void SearchModelImpl::SetOnCut(std::function<void(const std::string&)>&& func)
260 {
261 auto* stack = ViewStackProcessor::GetInstance();
262 auto component = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
263 CHECK_NULL_VOID(component);
264 auto childComponent = component->GetChild();
265 CHECK_NULL_VOID(childComponent);
266 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
267 CHECK_NULL_VOID(textFieldComponent);
268 textFieldComponent->SetOnCut(std::move(func));
269 }
270
SetOnPaste(std::function<void (const std::string &)> && func)271 void SearchModelImpl::SetOnPaste(std::function<void(const std::string&)>&& func)
272 {
273 auto* stack = ViewStackProcessor::GetInstance();
274 auto component = AceType::DynamicCast<SearchComponent>(stack->GetMainComponent());
275 CHECK_NULL_VOID(component);
276 auto childComponent = component->GetChild();
277 CHECK_NULL_VOID(childComponent);
278 auto textFieldComponent = AceType::DynamicCast<TextFieldComponent>(childComponent);
279 CHECK_NULL_VOID(textFieldComponent);
280 textFieldComponent->SetOnPaste(std::move(func));
281 }
282
InitializeDefaultValue(const RefPtr<BoxComponent> & boxComponent,const RefPtr<TextFieldComponent> & component,const RefPtr<TextFieldTheme> & theme)283 void SearchModelImpl::InitializeDefaultValue(const RefPtr<BoxComponent>& boxComponent,
284 const RefPtr<TextFieldComponent>& component, const RefPtr<TextFieldTheme>& theme)
285 {
286 component->SetAction(INPUT_TEXTINPUTACTION_VALUE_DEFAULT);
287 component->SetCursorColor(theme->GetCursorColor());
288 component->SetCursorRadius(theme->GetCursorRadius());
289 component->SetPlaceholderColor(theme->GetPlaceholderColor());
290
291 component->SetFocusBgColor(theme->GetFocusBgColor());
292 component->SetFocusPlaceholderColor(theme->GetFocusPlaceholderColor());
293 component->SetFocusTextColor(theme->GetFocusTextColor());
294 component->SetBgColor(theme->GetBgColor());
295 component->SetTextColor(theme->GetTextColor());
296 component->SetSelectedColor(theme->GetSelectedColor());
297 component->SetHoverColor(theme->GetHoverColor());
298 component->SetPressColor(theme->GetPressColor());
299 component->SetNeedFade(theme->NeedFade());
300 component->SetShowEllipsis(theme->ShowEllipsis());
301
302 TextStyle textStyle = component->GetTextStyle();
303 textStyle.SetTextColor(theme->GetTextColor());
304 textStyle.SetFontSize(theme->GetFontSize());
305 textStyle.SetFontWeight(theme->GetFontWeight());
306 textStyle.SetFontFamilies(INPUT_FONT_FAMILY_VALUE);
307 component->SetTextStyle(textStyle);
308
309 component->SetCountTextStyle(theme->GetCountTextStyle());
310 component->SetOverCountStyle(theme->GetOverCountStyle());
311 component->SetCountTextStyleOuter(theme->GetCountTextStyleOuter());
312 component->SetOverCountStyleOuter(theme->GetOverCountStyleOuter());
313
314 component->SetErrorTextStyle(theme->GetErrorTextStyle());
315 component->SetErrorSpacing(theme->GetErrorSpacing());
316 component->SetErrorIsInner(theme->GetErrorIsInner());
317 component->SetErrorBorderWidth(theme->GetErrorBorderWidth());
318 component->SetErrorBorderColor(theme->GetErrorBorderColor());
319
320 RefPtr<Decoration> decoration = AceType::MakeRefPtr<Decoration>();
321 decoration->SetPadding(theme->GetPadding());
322 decoration->SetBackgroundColor(theme->GetBgColor());
323 decoration->SetBorderRadius(theme->GetBorderRadius());
324 defaultRadius = theme->GetBorderRadius();
325 const auto& boxDecoration = boxComponent->GetBackDecoration();
326 if (boxDecoration) {
327 decoration->SetImage(boxDecoration->GetImage());
328 decoration->SetGradient(boxDecoration->GetGradient());
329 }
330 component->SetDecoration(decoration);
331
332 component->SetIconSize(theme->GetIconSize());
333 component->SetIconHotZoneSize(theme->GetIconHotZoneSize());
334
335 boxComponent->SetPadding(theme->GetPadding());
336 component->SetHeight(theme->GetHeight());
337 }
338
UpdateDecorationStyle(const RefPtr<BoxComponent> & boxComponent,const RefPtr<TextFieldComponent> & component,const Border & boxBorder,bool hasBoxRadius)339 void SearchModelImpl::UpdateDecorationStyle(const RefPtr<BoxComponent>& boxComponent,
340 const RefPtr<TextFieldComponent>& component, const Border& boxBorder, bool hasBoxRadius)
341 {
342 RefPtr<Decoration> decoration = component->GetDecoration();
343 if (!decoration) {
344 decoration = AceType::MakeRefPtr<Decoration>();
345 }
346 if (hasBoxRadius) {
347 decoration->SetBorder(boxBorder);
348 } else {
349 Border border = decoration->GetBorder();
350 border.SetLeftEdge(boxBorder.Left());
351 border.SetRightEdge(boxBorder.Right());
352 border.SetTopEdge(boxBorder.Top());
353 border.SetBottomEdge(boxBorder.Bottom());
354 border.SetBorderRadius(defaultRadius);
355 decoration->SetBorder(border);
356 }
357 component->SetOriginBorder(decoration->GetBorder());
358
359 if (!boxComponent) {
360 return;
361 }
362 RefPtr<Decoration> boxDecoration = boxComponent->GetBackDecoration();
363 if (boxDecoration && (boxDecoration->GetImage() || boxDecoration->GetGradient().IsValid())) {
364 // clear box properties except background image and radius.
365 boxDecoration->SetBackgroundColor(Color::TRANSPARENT);
366 Border border;
367 if (!hasBoxRadius) {
368 border.SetBorderRadius(defaultRadius);
369 } else {
370 border.SetTopLeftRadius(boxBorder.TopLeftRadius());
371 border.SetTopRightRadius(boxBorder.TopRightRadius());
372 border.SetBottomLeftRadius(boxBorder.BottomLeftRadius());
373 border.SetBottomRightRadius(boxBorder.BottomRightRadius());
374 }
375 boxDecoration->SetBorder(border);
376 } else {
377 RefPtr<Decoration> backDecoration = AceType::MakeRefPtr<Decoration>();
378 backDecoration->SetBorderRadius(Radius(BOX_HOVER_RADIUS));
379 boxComponent->SetBackDecoration(backDecoration);
380 }
381 boxComponent->SetPadding(Edge());
382 }
383
InitializeComponent(OHOS::Ace::RefPtr<OHOS::Ace::SearchComponent> & searchComponent,OHOS::Ace::RefPtr<OHOS::Ace::TextFieldComponent> & textFieldComponent,const OHOS::Ace::RefPtr<OHOS::Ace::SearchTheme> & searchTheme,const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme> & textFieldTheme)384 void SearchModelImpl::InitializeComponent(OHOS::Ace::RefPtr<OHOS::Ace::SearchComponent>& searchComponent,
385 OHOS::Ace::RefPtr<OHOS::Ace::TextFieldComponent>& textFieldComponent,
386 const OHOS::Ace::RefPtr<OHOS::Ace::SearchTheme>& searchTheme,
387 const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)
388 {
389 textFieldComponent->SetTextFieldController(AceType::MakeRefPtr<TextFieldController>());
390 textFieldComponent->SetTextEditController(AceType::MakeRefPtr<TextEditController>());
391 auto boxComponent = ViewStackProcessor::GetInstance()->GetBoxComponent();
392 InitializeDefaultValue(boxComponent, textFieldComponent, textFieldTheme);
393 boxComponent->SetBackDecoration(nullptr);
394 boxComponent->SetPadding(Edge());
395 textFieldComponent->SetIconSize(searchTheme->GetIconSize());
396 textFieldComponent->SetIconHotZoneSize(searchTheme->GetCloseIconHotZoneSize());
397 Edge decorationPadding;
398 Dimension leftPadding = searchTheme->GetLeftPadding();
399 Dimension rightPadding = searchTheme->GetRightPadding();
400 decorationPadding = Edge(rightPadding.Value(), 0.0, leftPadding.Value(), 0.0, leftPadding.Unit());
401 auto textFieldDecoration = textFieldComponent->GetDecoration();
402 if (textFieldDecoration) {
403 textFieldDecoration->SetPadding(decorationPadding);
404 textFieldDecoration->SetBorderRadius(searchTheme->GetBorderRadius());
405 textFieldComponent->SetOriginBorder(textFieldDecoration->GetBorder());
406 }
407 textFieldComponent->SetAction(TextInputAction::SEARCH);
408 textFieldComponent->SetWidthReserved(searchTheme->GetTextFieldWidthReserved());
409 textFieldComponent->SetTextColor(searchTheme->GetTextColor());
410 textFieldComponent->SetFocusTextColor(searchTheme->GetFocusTextColor());
411 textFieldComponent->SetPlaceholderColor(searchTheme->GetPlaceholderColor());
412 textFieldComponent->SetFocusPlaceholderColor(searchTheme->GetFocusPlaceholderColor());
413 textFieldComponent->SetBlockRightShade(searchTheme->GetBlockRightShade());
414
415 auto textStyle = textFieldComponent->GetTextStyle();
416 searchComponent->SetPlaceHoldStyle(textStyle);
417 searchComponent->SetEditingStyle(textStyle);
418
419 std::function<void(const std::string&)> submitEvent;
420 searchComponent->SetSubmitEvent(submitEvent);
421 searchComponent->SetChild(textFieldComponent);
422 searchComponent->SetTextEditController(textFieldComponent->GetTextEditController());
423 searchComponent->SetCloseIconSize(searchTheme->GetCloseIconSize());
424 searchComponent->SetCloseIconHotZoneHorizontal(searchTheme->GetCloseIconHotZoneSize());
425 searchComponent->SetHoverColor(textFieldTheme->GetHoverColor());
426 searchComponent->SetPressColor(textFieldTheme->GetPressColor());
427 isPaddingChanged = false;
428 }
429
PrepareSpecializedComponent(OHOS::Ace::RefPtr<OHOS::Ace::SearchComponent> & searchComponent,OHOS::Ace::RefPtr<OHOS::Ace::TextFieldComponent> & textFieldComponent)430 void SearchModelImpl::PrepareSpecializedComponent(OHOS::Ace::RefPtr<OHOS::Ace::SearchComponent>& searchComponent,
431 OHOS::Ace::RefPtr<OHOS::Ace::TextFieldComponent>& textFieldComponent)
432 {
433 Border boxBorder;
434
435 auto boxComponent = ViewStackProcessor::GetInstance()->GetBoxComponent();
436
437 boxComponent->SetMouseAnimationType(HoverAnimationType::BOARD);
438 if (boxComponent->GetBackDecoration()) {
439 boxBorder = boxComponent->GetBackDecoration()->GetBorder();
440 }
441 UpdateDecorationStyle(boxComponent, textFieldComponent, boxBorder, false);
442 if (GreatOrEqual(boxComponent->GetHeightDimension().Value(), 0.0)) {
443 textFieldComponent->SetHeight(boxComponent->GetHeightDimension());
444 }
445 if (isPaddingChanged) {
446 auto padding = textFieldComponent->GetDecoration()->GetPadding();
447 if (searchComponent->GetTextDirection() == TextDirection::RTL) {
448 padding.SetLeft(padding.Left() + searchComponent->GetCloseIconHotZoneHorizontal());
449 } else {
450 padding.SetRight(padding.Right() + searchComponent->GetCloseIconHotZoneHorizontal());
451 }
452 textFieldComponent->GetDecoration()->SetPadding(padding);
453 searchComponent->SetDecoration(textFieldComponent->GetDecoration());
454 isPaddingChanged = false;
455 }
456 }
457
458 } // namespace OHOS::Ace::Framework
459