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