• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_ng/pattern/search/search_pattern.h"
17 
18 #include <cstdint>
19 
20 #include "base/geometry/rect.h"
21 #include "base/utils/system_properties.h"
22 #include "base/utils/utils.h"
23 #include "core/common/recorder/node_data_cache.h"
24 #include "core/components/search/search_theme.h"
25 #include "core/components_ng/base/view_stack_processor.h"
26 #include "core/components_ng/pattern/button/button_pattern.h"
27 #include "core/components_ng/pattern/image/image_pattern.h"
28 #include "core/components_ng/pattern/search/search_model.h"
29 #include "core/components_ng/pattern/text/text_layout_property.h"
30 #include "core/components_ng/pattern/text/text_pattern.h"
31 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
32 
33 namespace OHOS::Ace::NG {
34 
35 namespace {
36 constexpr int32_t TEXTFIELD_INDEX = 0;
37 constexpr int32_t IMAGE_INDEX = 1;
38 constexpr int32_t CANCEL_IMAGE_INDEX = 2;
39 constexpr int32_t CANCEL_BUTTON_INDEX = 3;
40 constexpr int32_t BUTTON_INDEX = 4;
41 constexpr int32_t DOUBLE = 2;
42 constexpr int32_t ERROR = -1;
43 
44 // The focus state requires an 2vp inner stroke, which should be indented by 1vp when drawn.
45 constexpr Dimension FOCUS_OFFSET = 1.0_vp;
46 constexpr Dimension UP_AND_DOWN_PADDING = 8.0_vp;
47 constexpr float HOVER_OPACITY = 0.05f;
48 constexpr float TOUCH_OPACITY = 0.1f;
49 constexpr int32_t HOVER_TO_TOUCH_DURATION = 100;
50 constexpr int32_t HOVER_DURATION = 250;
51 constexpr int32_t TOUCH_DURATION = 250;
52 } // namespace
53 
UpdateChangeEvent(const std::string & value)54 void SearchPattern::UpdateChangeEvent(const std::string& value)
55 {
56     auto frameNode = GetHost();
57     CHECK_NULL_VOID(frameNode);
58     auto buttonHost = AceType::DynamicCast<FrameNode>(frameNode->GetChildAtIndex(CANCEL_BUTTON_INDEX));
59     CHECK_NULL_VOID(buttonHost);
60     auto imageHost = AceType::DynamicCast<FrameNode>(frameNode->GetChildAtIndex(CANCEL_IMAGE_INDEX));
61     CHECK_NULL_VOID(imageHost);
62     auto cancelButtonRenderContext = buttonHost->GetRenderContext();
63     CHECK_NULL_VOID(cancelButtonRenderContext);
64     auto cancelImageRenderContext = imageHost->GetRenderContext();
65     CHECK_NULL_VOID(cancelImageRenderContext);
66     auto layoutProperty = frameNode->GetLayoutProperty<SearchLayoutProperty>();
67     CHECK_NULL_VOID(layoutProperty);
68     auto cancelButtonEvent = buttonHost->GetEventHub<ButtonEventHub>();
69     CHECK_NULL_VOID(cancelButtonEvent);
70     auto imageEvent = imageHost->GetEventHub<ImageEventHub>();
71     CHECK_NULL_VOID(imageEvent);
72 
73     auto style = layoutProperty->GetCancelButtonStyle().value_or(CancelButtonStyle::INPUT);
74     if ((style == CancelButtonStyle::CONSTANT) || ((style == CancelButtonStyle::INPUT) && !value.empty())) {
75         cancelButtonRenderContext->UpdateOpacity(1.0);
76         cancelImageRenderContext->UpdateOpacity(1.0);
77         cancelButtonEvent->SetEnabled(true);
78         imageEvent->SetEnabled(true);
79     } else {
80         cancelButtonRenderContext->UpdateOpacity(0.0);
81         cancelImageRenderContext->UpdateOpacity(0.0);
82         cancelButtonEvent->SetEnabled(false);
83         imageEvent->SetEnabled(false);
84     }
85     buttonHost->MarkModifyDone();
86     imageHost->MarkModifyDone();
87     buttonHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
88     imageHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
89 }
90 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig &)91 bool SearchPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& /*config*/)
92 {
93     auto geometryNode = dirty->GetGeometryNode();
94     CHECK_NULL_RETURN(geometryNode, true);
95     searchSize_ = geometryNode->GetContentSize();
96     searchOffset_ = geometryNode->GetContentOffset();
97 
98     auto textFieldLayoutWrapper = dirty->GetOrCreateChildByIndex(TEXTFIELD_INDEX);
99     CHECK_NULL_RETURN(textFieldLayoutWrapper, true);
100     auto textFieldGeometryNode = textFieldLayoutWrapper->GetGeometryNode();
101     CHECK_NULL_RETURN(textFieldGeometryNode, true);
102     textFieldOffset_ = textFieldGeometryNode->GetFrameOffset();
103     textFieldSize_ = textFieldGeometryNode->GetFrameSize();
104 
105     auto buttonLayoutWrapper = dirty->GetOrCreateChildByIndex(BUTTON_INDEX);
106     CHECK_NULL_RETURN(buttonLayoutWrapper, true);
107     auto buttonGeometryNode = buttonLayoutWrapper->GetGeometryNode();
108     CHECK_NULL_RETURN(buttonGeometryNode, true);
109     buttonOffset_ = buttonGeometryNode->GetFrameOffset();
110 
111     auto buttonNode = buttonLayoutWrapper->GetHostNode();
112     CHECK_NULL_RETURN(buttonNode, true);
113     auto searchButtonEvent = buttonNode->GetEventHub<ButtonEventHub>();
114     CHECK_NULL_RETURN(searchButtonEvent, true);
115 
116     if (!searchButtonEvent->IsEnabled()) {
117         buttonSize_.Reset();
118     } else {
119         buttonSize_ = buttonGeometryNode->GetFrameSize();
120     }
121 
122     auto cancelButtonLayoutWrapper = dirty->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
123     CHECK_NULL_RETURN(cancelButtonLayoutWrapper, true);
124     auto cancelButtonGeometryNode = cancelButtonLayoutWrapper->GetGeometryNode();
125     CHECK_NULL_RETURN(cancelButtonGeometryNode, true);
126 
127     auto cancelButtonNode = cancelButtonLayoutWrapper->GetHostNode();
128     CHECK_NULL_RETURN(cancelButtonNode, true);
129     auto cancelButtonEvent = cancelButtonNode->GetEventHub<ButtonEventHub>();
130     CHECK_NULL_RETURN(cancelButtonEvent, true);
131     cancelButtonOffset_ = cancelButtonGeometryNode->GetFrameOffset();
132     if (!cancelButtonEvent->IsEnabled()) {
133         cancelButtonSize_.Reset();
134     } else {
135         cancelButtonSize_ = cancelButtonGeometryNode->GetFrameSize();
136     }
137 
138     return true;
139 }
140 
OnModifyDone()141 void SearchPattern::OnModifyDone()
142 {
143     Pattern::OnModifyDone();
144     auto host = GetHost();
145     CHECK_NULL_VOID(host);
146     auto layoutProperty = host->GetLayoutProperty<SearchLayoutProperty>();
147     CHECK_NULL_VOID(layoutProperty);
148     if (!layoutProperty->GetMarginProperty()) {
149         MarginProperty margin;
150         margin.top = CalcLength(UP_AND_DOWN_PADDING.ConvertToPx());
151         margin.bottom = CalcLength(UP_AND_DOWN_PADDING.ConvertToPx());
152         layoutProperty->UpdateMargin(margin);
153     }
154 
155     HandleBackgroundColor();
156 
157     auto searchButton = layoutProperty->GetSearchButton();
158     searchButton_ = searchButton.has_value() ? searchButton->value() : "";
159     InitSearchController();
160     auto imageFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(IMAGE_INDEX));
161     CHECK_NULL_VOID(imageFrameNode);
162     imageFrameNode->MarkModifyDone();
163     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(BUTTON_INDEX));
164     CHECK_NULL_VOID(buttonFrameNode);
165     auto buttonLayoutProperty = buttonFrameNode->GetLayoutProperty<ButtonLayoutProperty>();
166     CHECK_NULL_VOID(buttonLayoutProperty);
167     buttonLayoutProperty->UpdateLabel(searchButton_);
168     buttonLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
169     buttonFrameNode->MarkModifyDone();
170 
171     auto searchButtonEvent = buttonFrameNode->GetEventHub<ButtonEventHub>();
172     isSearchButtonEnabled_ = searchButtonEvent->IsEnabled();
173 
174     auto cancelButtonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(CANCEL_BUTTON_INDEX));
175     CHECK_NULL_VOID(cancelButtonFrameNode);
176     auto cancelButtonLayoutProperty = cancelButtonFrameNode->GetLayoutProperty<ButtonLayoutProperty>();
177     CHECK_NULL_VOID(cancelButtonLayoutProperty);
178     cancelButtonLayoutProperty->UpdateLabel("");
179     cancelButtonFrameNode->MarkModifyDone();
180     InitButtonAndImageClickEvent();
181     InitCancelButtonClickEvent();
182     InitTextFieldValueChangeEvent();
183     InitTextFieldDragEvent();
184     InitTextFieldClickEvent();
185     InitButtonMouseAndTouchEvent();
186     HandleTouchableAndHitTestMode();
187     auto focusHub = host->GetFocusHub();
188     CHECK_NULL_VOID(focusHub);
189     InitOnKeyEvent(focusHub);
190     InitFocusEvent(focusHub);
191     InitClickEvent();
192     HandleEnabled();
193 }
194 
HandleBackgroundColor()195 void SearchPattern::HandleBackgroundColor()
196 {
197     auto host = GetHost();
198     CHECK_NULL_VOID(host);
199     auto renderContext = host->GetRenderContext();
200     CHECK_NULL_VOID(renderContext);
201     auto textFieldTheme = PipelineBase::GetCurrentContext()->GetTheme<TextFieldTheme>();
202     CHECK_NULL_VOID(textFieldTheme);
203     if (!renderContext->HasBackgroundColor()) {
204         renderContext->UpdateBackgroundColor(textFieldTheme->GetBgColor());
205     }
206 }
207 
HandleEnabled()208 void SearchPattern::HandleEnabled()
209 {
210     auto host = GetHost();
211     CHECK_NULL_VOID(host);
212     auto searchEventHub = host->GetEventHub<EventHub>();
213     CHECK_NULL_VOID(searchEventHub);
214     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
215     CHECK_NULL_VOID(textFieldFrameNode);
216     auto eventHub = textFieldFrameNode->GetEventHub<TextFieldEventHub>();
217     eventHub->SetEnabled(searchEventHub->IsEnabled()? true : false);
218     textFieldFrameNode->MarkModifyDone();
219 }
220 
HandleTouchableAndHitTestMode()221 void SearchPattern::HandleTouchableAndHitTestMode()
222 {
223     auto host = GetHost();
224     CHECK_NULL_VOID(host);
225     auto searchEventHub = host->GetEventHub<EventHub>();
226     CHECK_NULL_VOID(searchEventHub);
227     auto searchGestureHub = searchEventHub->GetGestureEventHub();
228     CHECK_NULL_VOID(searchGestureHub);
229     bool searchTouchable = true;
230     HitTestMode searchHitTestMode = HitTestMode::HTMDEFAULT;
231     if (searchGestureHub) {
232         searchTouchable = searchGestureHub->GetTouchable();
233         searchHitTestMode = searchGestureHub->GetHitTestMode();
234     }
235     for (int32_t childIndex = TEXTFIELD_INDEX; childIndex <= BUTTON_INDEX; childIndex++) {
236         auto childFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(childIndex));
237         CHECK_NULL_VOID(childFrameNode);
238         auto childEventHub = childFrameNode->GetEventHub<EventHub>();
239         auto childGestureHub = childEventHub->GetGestureEventHub();
240         CHECK_NULL_VOID(childGestureHub);
241         childGestureHub->SetTouchable(searchTouchable);
242         childGestureHub->SetHitTestMode(searchHitTestMode);
243         childFrameNode->MarkModifyDone();
244     }
245 }
246 
InitButtonMouseAndTouchEvent()247 void SearchPattern::InitButtonMouseAndTouchEvent()
248 {
249     InitButtonMouseEvent(searchButtonMouseEvent_, BUTTON_INDEX);
250     InitButtonMouseEvent(cancelButtonMouseEvent_, CANCEL_BUTTON_INDEX);
251     InitButtonTouchEvent(searchButtonTouchListener_, BUTTON_INDEX);
252     InitButtonTouchEvent(cancelButtonTouchListener_, CANCEL_BUTTON_INDEX);
253 }
254 
InitTextFieldValueChangeEvent()255 void SearchPattern::InitTextFieldValueChangeEvent()
256 {
257     auto host = GetHost();
258     CHECK_NULL_VOID(host);
259     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
260     CHECK_NULL_VOID(textFieldFrameNode);
261     auto eventHub = textFieldFrameNode->GetEventHub<TextFieldEventHub>();
262     CHECK_NULL_VOID(eventHub);
263     if (!eventHub->GetOnChange()) {
264         auto searchChangeFunc = [weak = AceType::WeakClaim(this)](const std::string& value) {
265             auto searchPattern = weak.Upgrade();
266             searchPattern->UpdateChangeEvent(value);
267         };
268         eventHub->SetOnChange(std::move(searchChangeFunc));
269     }
270 }
271 
InitTextFieldDragEvent()272 void SearchPattern::InitTextFieldDragEvent()
273 {
274     auto host = GetHost();
275     CHECK_NULL_VOID(host);
276     auto searchEventHub = host->GetEventHub<EventHub>();
277     CHECK_NULL_VOID(searchEventHub);
278     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
279     CHECK_NULL_VOID(textFieldFrameNode);
280     auto textFieldEventHub = textFieldFrameNode->GetEventHub<EventHub>();
281     CHECK_NULL_VOID(textFieldEventHub);
282 
283     textFieldFrameNode->SetDragPreview(host->GetDragPreview());
284 
285     auto dragStart = searchEventHub->GetOnDragStart();
286     if (dragStart != nullptr) {
287         textFieldEventHub->SetOnDragStart(std::move(dragStart));
288     }
289 
290     auto customerDragEnter = searchEventHub->GetCustomerOnDragFunc(DragFuncType::DRAG_ENTER);
291     if (customerDragEnter != nullptr) {
292         textFieldEventHub->SetCustomerOnDragFunc(DragFuncType::DRAG_ENTER, std::move(customerDragEnter));
293     }
294 
295     auto customerDragLeave = searchEventHub->GetCustomerOnDragFunc(DragFuncType::DRAG_LEAVE);
296     if (customerDragLeave != nullptr) {
297         textFieldEventHub->SetCustomerOnDragFunc(DragFuncType::DRAG_LEAVE, std::move(customerDragLeave));
298     }
299 
300     auto customerDragMove = searchEventHub->GetCustomerOnDragFunc(DragFuncType::DRAG_MOVE);
301     if (customerDragMove != nullptr) {
302         textFieldEventHub->SetCustomerOnDragFunc(DragFuncType::DRAG_MOVE, std::move(customerDragMove));
303     }
304 
305     auto customerDragDrop = searchEventHub->GetCustomerOnDragFunc(DragFuncType::DRAG_DROP);
306     if (customerDragDrop != nullptr) {
307         textFieldEventHub->SetCustomerOnDragFunc(DragFuncType::DRAG_DROP, std::move(customerDragDrop));
308     }
309 
310     auto customerDragEnd = searchEventHub->GetCustomerOnDragEndFunc();
311     if (customerDragEnd != nullptr) {
312         textFieldEventHub->SetCustomerOnDragFunc(DragFuncType::DRAG_END, std::move(customerDragEnd));
313     }
314 
315     searchEventHub->ClearCustomerOnDragFunc();
316     RemoveDragFrameNodeFromManager();
317 }
318 
RemoveDragFrameNodeFromManager()319 void SearchPattern::RemoveDragFrameNodeFromManager()
320 {
321     auto frameNode = GetHost();
322     CHECK_NULL_VOID(frameNode);
323     auto context = PipelineContext::GetCurrentContext();
324     CHECK_NULL_VOID(context);
325     auto dragDropManager = context->GetDragDropManager();
326     CHECK_NULL_VOID(dragDropManager);
327     dragDropManager->RemoveDragFrameNode(frameNode->GetId());
328 }
329 
OnAfterModifyDone()330 void SearchPattern::OnAfterModifyDone()
331 {
332     auto host = GetHost();
333     CHECK_NULL_VOID(host);
334     auto inspectorId = host->GetInspectorId().value_or("");
335     if (!inspectorId.empty()) {
336         auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
337         CHECK_NULL_VOID(textFieldFrameNode);
338         auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
339         CHECK_NULL_VOID(textFieldPattern);
340         auto text = textFieldPattern->GetTextValue();
341         Recorder::NodeDataCache::Get().PutString(inspectorId, text);
342     }
343 }
344 
InitButtonAndImageClickEvent()345 void SearchPattern::InitButtonAndImageClickEvent()
346 {
347     // Image click event
348     if (imageClickListener_) {
349         return;
350     }
351     auto host = GetHost();
352     CHECK_NULL_VOID(host);
353     auto imageFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(IMAGE_INDEX));
354     CHECK_NULL_VOID(imageFrameNode);
355     CHECK_NULL_VOID(!imageClickListener_);
356     auto imageGesture = imageFrameNode->GetOrCreateGestureEventHub();
357     CHECK_NULL_VOID(imageGesture);
358     auto imageClickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
359         auto searchPattern = weak.Upgrade();
360         CHECK_NULL_VOID(searchPattern);
361         searchPattern->OnClickButtonAndImage();
362     };
363     imageClickListener_ = MakeRefPtr<ClickEvent>(std::move(imageClickCallback));
364     imageGesture->AddClickEvent(imageClickListener_);
365     // Button click event
366     if (buttonClickListener_) {
367         return;
368     }
369     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(BUTTON_INDEX));
370     CHECK_NULL_VOID(buttonFrameNode);
371     CHECK_NULL_VOID(!buttonClickListener_);
372     auto buttonGesture = buttonFrameNode->GetOrCreateGestureEventHub();
373     CHECK_NULL_VOID(buttonGesture);
374     auto buttonClickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
375         auto searchPattern = weak.Upgrade();
376         CHECK_NULL_VOID(searchPattern);
377         searchPattern->OnClickButtonAndImage();
378     };
379     buttonClickListener_ = MakeRefPtr<ClickEvent>(std::move(buttonClickCallback));
380     buttonGesture->AddClickEvent(buttonClickListener_);
381 }
382 
InitCancelButtonClickEvent()383 void SearchPattern::InitCancelButtonClickEvent()
384 {
385     // CancelButton click event
386     if (cancelButtonClickListener_) {
387         return;
388     }
389     auto host = GetHost();
390     CHECK_NULL_VOID(host);
391     auto cancelButtonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(CANCEL_BUTTON_INDEX));
392     CHECK_NULL_VOID(cancelButtonFrameNode);
393     auto cancelButtonGesture = cancelButtonFrameNode->GetOrCreateGestureEventHub();
394     CHECK_NULL_VOID(cancelButtonGesture);
395     auto cancelButtonClickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
396         auto searchPattern = weak.Upgrade();
397         CHECK_NULL_VOID(searchPattern);
398         searchPattern->OnClickCancelButton();
399     };
400     cancelButtonClickListener_ = MakeRefPtr<ClickEvent>(std::move(cancelButtonClickCallback));
401     cancelButtonGesture->AddClickEvent(cancelButtonClickListener_);
402 }
403 
InitTextFieldClickEvent()404 void SearchPattern::InitTextFieldClickEvent()
405 {
406     if (textFieldClickListener_) {
407         return;
408     }
409     auto host = GetHost();
410     CHECK_NULL_VOID(host);
411     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
412     CHECK_NULL_VOID(textFieldFrameNode);
413     auto textFieldGesture = textFieldFrameNode->GetOrCreateGestureEventHub();
414     CHECK_NULL_VOID(textFieldGesture);
415     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
416         auto searchPattern = weak.Upgrade();
417         CHECK_NULL_VOID(searchPattern);
418         searchPattern->OnClickTextField();
419     };
420     textFieldClickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
421     textFieldGesture->AddClickEvent(textFieldClickListener_);
422 }
423 
InitSearchController()424 void SearchPattern::InitSearchController()
425 {
426     searchController_->SetCaretPosition([weak = WeakClaim(this)](int32_t caretPosition) {
427         auto search = weak.Upgrade();
428         CHECK_NULL_VOID(search);
429         search->HandleCaretPosition(caretPosition);
430     });
431 
432     searchController_->SetGetTextContentRect([weak = WeakClaim(this)]() {
433         auto search = weak.Upgrade();
434         CHECK_NULL_RETURN(search, Rect(0, 0, 0, 0));
435         auto rect = search->searchController_->GetTextContentRect();
436         search->HandleTextContentRect(rect);
437         return rect;
438     });
439 
440     searchController_->SetGetTextContentLinesNum([weak = WeakClaim(this)]() {
441         auto search = weak.Upgrade();
442         CHECK_NULL_RETURN(search, 0);
443         return search->HandleTextContentLines();
444     });
445 
446     searchController_->SetGetCaretIndex([weak = WeakClaim(this)]() {
447         auto search = weak.Upgrade();
448         CHECK_NULL_RETURN(search, ERROR);
449         return search->HandleGetCaretIndex();
450     });
451 
452     searchController_->SetGetCaretPosition([weak = WeakClaim(this)]() {
453         auto search = weak.Upgrade();
454         CHECK_NULL_RETURN(search, NG::OffsetF(ERROR, ERROR));
455         return search->HandleGetCaretPosition();
456     });
457 
458     searchController_->SetStopEditing([weak = WeakClaim(this)]() {
459         auto search = weak.Upgrade();
460         CHECK_NULL_VOID(search);
461         search->StopEditing();
462     });
463 }
464 
HandleGetCaretIndex()465 int32_t SearchPattern::HandleGetCaretIndex()
466 {
467     auto host = GetHost();
468     CHECK_NULL_RETURN(host, ERROR);
469     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
470     CHECK_NULL_RETURN(textFieldFrameNode, ERROR);
471     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
472     CHECK_NULL_RETURN(textFieldPattern, ERROR);
473     return textFieldPattern->GetCaretIndex();
474 }
475 
HandleGetCaretPosition()476 NG::OffsetF SearchPattern::HandleGetCaretPosition()
477 {
478     auto host = GetHost();
479     CHECK_NULL_RETURN(host, NG::OffsetF(ERROR, ERROR));
480     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
481     CHECK_NULL_RETURN(textFieldFrameNode, NG::OffsetF(ERROR, ERROR));
482     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
483     CHECK_NULL_RETURN(textFieldPattern, NG::OffsetF(ERROR, ERROR));
484     return textFieldPattern->GetCaretOffset();
485 }
486 
HandleCaretPosition(int32_t caretPosition)487 void SearchPattern::HandleCaretPosition(int32_t caretPosition)
488 {
489     auto host = GetHost();
490     CHECK_NULL_VOID(host);
491     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
492     CHECK_NULL_VOID(textFieldFrameNode);
493     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
494     CHECK_NULL_VOID(textFieldPattern);
495     textFieldPattern->SetCaretPosition(caretPosition);
496 }
497 
HandleTextContentRect(Rect & rect)498 void SearchPattern::HandleTextContentRect(Rect& rect)
499 {
500     auto host = GetHost();
501     CHECK_NULL_VOID(host);
502     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
503     CHECK_NULL_VOID(textFieldFrameNode);
504     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
505     CHECK_NULL_VOID(textFieldPattern);
506     RectF frameRect = textFieldPattern->GetFrameRect();
507     rect.SetLeft(rect.Left() + frameRect.Left());
508     rect.SetTop(rect.Top() + frameRect.Top());
509 }
510 
HandleTextContentLines()511 int32_t SearchPattern::HandleTextContentLines()
512 {
513     int lines = 0;
514     auto host = GetHost();
515     CHECK_NULL_RETURN(host, lines);
516     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
517     CHECK_NULL_RETURN(textFieldFrameNode, lines);
518     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
519     CHECK_NULL_RETURN(textFieldPattern, lines);
520     if (!textFieldPattern->IsOperation()) {
521         return lines;
522     }
523     RectF textRect = textFieldPattern->GetTextRect();
524 
525     if ((int32_t)textFieldPattern->GetLineHeight() == 0) {
526         return lines;
527     }
528     lines = (int32_t)textRect.Height() / (int32_t)textFieldPattern->GetLineHeight();
529     return lines;
530 }
531 
StopEditing()532 void SearchPattern::StopEditing()
533 {
534     auto host = GetHost();
535     CHECK_NULL_VOID(host);
536     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
537     CHECK_NULL_VOID(textFieldFrameNode);
538     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
539     CHECK_NULL_VOID(textFieldPattern);
540     textFieldPattern->StopEditing();
541 }
542 
OnClickButtonAndImage()543 void SearchPattern::OnClickButtonAndImage()
544 {
545     auto host = GetHost();
546     CHECK_NULL_VOID(host);
547     auto searchEventHub = host->GetEventHub<SearchEventHub>();
548     CHECK_NULL_VOID(searchEventHub);
549     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
550     CHECK_NULL_VOID(textFieldFrameNode);
551     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
552     CHECK_NULL_VOID(textFieldPattern);
553     auto text = textFieldPattern->GetTextValue();
554     searchEventHub->UpdateSubmitEvent(text);
555     textFieldPattern->CloseKeyboard(true);
556 }
557 
OnClickCancelButton()558 void SearchPattern::OnClickCancelButton()
559 {
560     auto host = GetHost();
561     CHECK_NULL_VOID(host);
562     auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
563     CHECK_NULL_VOID(textFieldFrameNode);
564     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
565     CHECK_NULL_VOID(textFieldPattern);
566     CHECK_NULL_VOID(!textFieldPattern->IsDragging());
567     focusChoice_ = FocusChoice::SEARCH;
568     textFieldPattern->InitEditingValueText("");
569     auto textRect = textFieldPattern->GetTextRect();
570     textRect.SetLeft(0.0f);
571     textFieldPattern->SetTextRect(textRect);
572     auto textFieldLayoutProperty = textFieldFrameNode->GetLayoutProperty<TextFieldLayoutProperty>();
573     CHECK_NULL_VOID(textFieldLayoutProperty);
574     textFieldLayoutProperty->UpdateValue("");
575     auto eventHub = textFieldFrameNode->GetEventHub<TextFieldEventHub>();
576     eventHub->FireOnChange("");
577     auto focusHub = host->GetOrCreateFocusHub();
578     CHECK_NULL_VOID(focusHub);
579     focusHub->RequestFocusImmediately();
580     textFieldPattern->HandleFocusEvent();
581     host->MarkModifyDone();
582     textFieldFrameNode->MarkModifyDone();
583 }
584 
OnClickTextField()585 void SearchPattern::OnClickTextField()
586 {
587     focusChoice_ = FocusChoice::SEARCH;
588     auto host = GetHost();
589     CHECK_NULL_VOID(host);
590     RoundRect focusRect;
591     GetInnerFocusPaintRect(focusRect);
592     auto focusHub = host->GetFocusHub();
593     CHECK_NULL_VOID(focusHub);
594     focusHub->PaintInnerFocusState(focusRect);
595     host->MarkModifyDone();
596 }
597 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)598 void SearchPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
599 {
600     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
601         auto pattern = wp.Upgrade();
602         CHECK_NULL_RETURN(pattern, false);
603         return pattern->OnKeyEvent(event);
604     };
605     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
606 
607     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
608         auto pattern = wp.Upgrade();
609         if (pattern) {
610             pattern->GetInnerFocusPaintRect(paintRect);
611         }
612     };
613     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
614 }
615 
OnKeyEvent(const KeyEvent & event)616 bool SearchPattern::OnKeyEvent(const KeyEvent& event)
617 {
618     auto host = GetHost();
619     CHECK_NULL_RETURN(host, false);
620     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
621     CHECK_NULL_RETURN(textFieldFrameNode, false);
622     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
623     CHECK_NULL_RETURN(textFieldPattern, false);
624 
625     bool isAllTextSelected = textFieldPattern->IsSelectAll();
626     bool isCaretVisible = textFieldPattern->GetCursorVisible();
627     bool isTextEmpty = textFieldPattern->GetTextValue().empty();
628     bool isOnlyTabPressed = event.pressedCodes.size() == 1 && event.code == KeyCode::KEY_TAB;
629 
630     auto parentHub = host->GetOrCreateFocusHub()->GetParentFocusHub();
631     auto getMaxFocusableCount = [](auto self, const RefPtr<FocusHub>& focusHub) -> size_t {
632         CHECK_NULL_RETURN(focusHub, 0);
633         auto parentHub = focusHub->GetParentFocusHub();
634         return std::max(focusHub->GetFocusableCount(), self(self, parentHub));
635     };
636     constexpr int ONE = 1; // Only one focusable component on scene
637     bool isOnlyOneFocusableComponent = getMaxFocusableCount(getMaxFocusableCount, parentHub) == ONE;
638 
639     if (event.action == KeyAction::UP && event.code == KeyCode::KEY_TAB &&
640         focusChoice_ != FocusChoice::SEARCH) {
641         textFieldPattern->HandleSetSelection(0, 0, false); // Clear selection and caret when tab pressed
642     }
643 
644     if (event.action != KeyAction::DOWN) {
645         if (event.code == KeyCode::KEY_TAB && focusChoice_ == FocusChoice::SEARCH) {
646             textFieldPattern->OnKeyEvent(event);
647         }
648         return false;
649     }
650 
651     // If the focus is on the search, press Enter to request keyboard.
652     if (event.code == KeyCode::KEY_ENTER && focusChoice_ == FocusChoice::SEARCH) {
653         RequestKeyboard();
654         return true;
655     }
656     // If the focus is on the search button, press Enter to submit the content.
657     if (event.code == KeyCode::KEY_ENTER && focusChoice_ == FocusChoice::SEARCH_BUTTON) {
658         OnClickButtonAndImage();
659         return true;
660     }
661     // If the focus is on the Delete button, press Enter to delete the content.
662     if (event.code == KeyCode::KEY_ENTER && focusChoice_ == FocusChoice::CANCEL_BUTTON) {
663         OnClickCancelButton();
664         PaintFocusState();
665         return true;
666     }
667     // When press '->' or '<-', focus delete button or search button according to whether there is text in the search.
668     if (event.code == KeyCode::KEY_DPAD_LEFT || event.IsShiftWith(KeyCode::KEY_TAB)) {
669         if (focusChoice_ == FocusChoice::CANCEL_BUTTON) {
670             focusChoice_ = FocusChoice::SEARCH;
671             PaintFocusState();
672             return true;
673         }
674         if (focusChoice_ == FocusChoice::SEARCH_BUTTON) {
675             if (NearZero(cancelButtonSize_.Height())) {
676                 focusChoice_ = FocusChoice::SEARCH;
677             } else {
678                 focusChoice_ = FocusChoice::CANCEL_BUTTON;
679             }
680             PaintFocusState();
681             return true;
682         }
683         if (focusChoice_ == FocusChoice::SEARCH && isOnlyOneFocusableComponent && event.IsShiftWith(KeyCode::KEY_TAB)) {
684             if (isSearchButtonEnabled_) {
685                 focusChoice_ = FocusChoice::SEARCH_BUTTON;
686             } else if (!isTextEmpty) {
687                 focusChoice_ = FocusChoice::CANCEL_BUTTON;
688             }
689             PaintFocusState();
690             return true;
691         }
692         if (focusChoice_ == FocusChoice::SEARCH && event.IsShiftWith(KeyCode::KEY_TAB)) {
693             textFieldPattern->CloseKeyboard(true);
694             return false;
695         }
696         if (focusChoice_ == FocusChoice::SEARCH && !isAllTextSelected && !isTextEmpty) {
697             return textFieldPattern->OnKeyEvent(event);
698         }
699         if (focusChoice_ == FocusChoice::SEARCH && isAllTextSelected && !isCaretVisible &&
700             event.code == KeyCode::KEY_DPAD_LEFT) {
701             return true; // no action
702         }
703     }
704     if (event.code == KeyCode::KEY_DPAD_RIGHT || (event.pressedCodes.size() == 1 && event.code == KeyCode::KEY_TAB)) {
705         if (focusChoice_ == FocusChoice::SEARCH && (isAllTextSelected || isTextEmpty || isOnlyTabPressed)) {
706             if (NearZero(cancelButtonSize_.Height()) && !isSearchButtonEnabled_ &&
707                 event.code == KeyCode::KEY_DPAD_RIGHT) {
708                 return true;
709             } else if (NearZero(cancelButtonSize_.Height()) && !isSearchButtonEnabled_) {
710                 textFieldPattern->CloseKeyboard(true);
711                 return false;
712             }
713             if (NearZero(cancelButtonSize_.Height())) {
714                 focusChoice_ = FocusChoice::SEARCH_BUTTON;
715             } else {
716                 focusChoice_ = FocusChoice::CANCEL_BUTTON;
717             }
718             PaintFocusState();
719             return true;
720         } else if (focusChoice_ == FocusChoice::SEARCH && event.code == KeyCode::KEY_DPAD_RIGHT) {
721             textFieldPattern->OnKeyEvent(event);
722             return true;
723         }
724         if (focusChoice_ == FocusChoice::CANCEL_BUTTON) {
725             if (!NearZero(cancelButtonSize_.Height()) && (!isSearchButtonEnabled_) &&
726                 (event.code == KeyCode::KEY_DPAD_RIGHT)) {
727                 return false; // Go out of Search
728             }
729             if (isOnlyOneFocusableComponent && isOnlyTabPressed && !isSearchButtonEnabled_) {
730                 focusChoice_ = FocusChoice::SEARCH;
731                 PaintFocusState();
732                 return true;
733             }
734             if (!isSearchButtonEnabled_) {
735                 return !isOnlyTabPressed; // go outside if Tab pressed, or no action if arrow pressed
736             }
737             focusChoice_ = FocusChoice::SEARCH_BUTTON;
738             PaintFocusState();
739             return true;
740         }
741         if (focusChoice_ == FocusChoice::SEARCH_BUTTON && isOnlyOneFocusableComponent && isOnlyTabPressed) {
742             focusChoice_ = FocusChoice::SEARCH;
743             PaintFocusState();
744             return true;
745         }
746         if (focusChoice_ == FocusChoice::SEARCH_BUTTON &&
747             (event.pressedCodes.size() == 1 && event.code == KeyCode::KEY_TAB)) {
748             textFieldPattern->CloseKeyboard(true);
749             return false;
750         }
751         if (focusChoice_ == FocusChoice::SEARCH_BUTTON && isSearchButtonEnabled_ &&
752             (event.code == KeyCode::KEY_DPAD_RIGHT)) {
753             return false; // Go out of Search
754         }
755     }
756 
757     if (focusChoice_ == FocusChoice::SEARCH) {
758         return textFieldPattern->OnKeyEvent(event);
759     } else {
760         return true;
761     }
762 }
763 
PaintFocusState(bool recoverFlag)764 void SearchPattern::PaintFocusState(bool recoverFlag)
765 {
766     auto host = GetHost();
767     CHECK_NULL_VOID(host);
768     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
769     CHECK_NULL_VOID(textFieldFrameNode);
770     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
771     CHECK_NULL_VOID(textFieldPattern);
772 
773     if (focusChoice_ == FocusChoice::SEARCH) {
774         if (!recoverFlag) {
775             if (!textFieldPattern->GetTextValue().empty()) {
776                 textFieldPattern->NeedRequestKeyboard();
777                 textFieldPattern->HandleOnSelectAll(true); // Select all text
778                 textFieldPattern->StopTwinkling();         // Hide caret
779             } else {
780                 textFieldPattern->HandleFocusEvent(); // Show caret
781             }
782         } else {
783             textFieldPattern->HandleFocusEvent();
784         }
785     } else {
786         if (textFieldPattern->IsSelected() || textFieldPattern->GetCursorVisible()) {
787             textFieldPattern->HandleSetSelection(0, 0, false); // Clear text selection & caret if focus has gone
788         }
789         textFieldPattern->CloseKeyboard(true);
790     }
791 
792     auto context = PipelineContext::GetCurrentContext();
793     CHECK_NULL_VOID(context);
794     RoundRect focusRect;
795     GetInnerFocusPaintRect(focusRect);
796     auto focusHub = host->GetFocusHub();
797     CHECK_NULL_VOID(focusHub);
798     focusHub->PaintInnerFocusState(focusRect, true);
799     host->MarkModifyDone();
800 }
801 
GetInnerFocusPaintRect(RoundRect & paintRect)802 void SearchPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
803 {
804     float originX = 0.0f;
805     float originY = 0.0f;
806     float endX = 0.0f;
807     float endY = 0.0f;
808     float radiusTopLeft = 0.0f;
809     float radiusTopRight = 0.0f;
810     float radiusBottomLeft = 0.0f;
811     float radiusBottomRight = 0.0f;
812     float focusOffset = FOCUS_OFFSET.ConvertToPx();
813     if (focusChoice_ == FocusChoice::SEARCH) {
814         return;
815     }
816     if (focusChoice_ == FocusChoice::CANCEL_BUTTON) {
817         originX = cancelButtonOffset_.GetX() + focusOffset;
818         originY = cancelButtonOffset_.GetY() + focusOffset;
819         endX = cancelButtonSize_.Width() + originX - DOUBLE * focusOffset;
820         endY = cancelButtonSize_.Height() + originY - DOUBLE * focusOffset;
821         radiusTopLeft = cancelButtonSize_.Height() / DOUBLE - focusOffset;
822         radiusTopRight = cancelButtonSize_.Height() / DOUBLE - focusOffset;
823         radiusBottomLeft = cancelButtonSize_.Height() / DOUBLE - focusOffset;
824         radiusBottomRight = cancelButtonSize_.Height() / DOUBLE - focusOffset;
825     }
826     if (focusChoice_ == FocusChoice::SEARCH_BUTTON) {
827         originX = buttonOffset_.GetX() + focusOffset;
828         originY = buttonOffset_.GetY() + focusOffset;
829         endX = buttonSize_.Width() + originX - DOUBLE * focusOffset;
830         endY = buttonSize_.Height() + originY - DOUBLE * focusOffset;
831         radiusTopLeft = buttonSize_.Height() / DOUBLE - focusOffset;
832         radiusTopRight = buttonSize_.Height() / DOUBLE - focusOffset;
833         radiusBottomLeft = buttonSize_.Height() / DOUBLE - focusOffset;
834         radiusBottomRight = buttonSize_.Height() / DOUBLE - focusOffset;
835     }
836 
837     paintRect.SetRect({ originX, originY, endX - originX, endY - originY });
838     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, radiusTopLeft, radiusTopLeft);
839     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, radiusTopRight, radiusTopRight);
840     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, radiusBottomLeft, radiusBottomLeft);
841     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, radiusBottomRight, radiusBottomRight);
842 }
843 
GetFocusPattern() const844 FocusPattern SearchPattern::GetFocusPattern() const
845 {
846     FocusPattern focusPattern = { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION };
847     focusPattern.SetIsFocusActiveWhenFocused(true);
848     return focusPattern;
849 }
850 
RequestKeyboard()851 void SearchPattern::RequestKeyboard()
852 {
853     auto host = GetHost();
854     CHECK_NULL_VOID(host);
855     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
856     CHECK_NULL_VOID(textFieldFrameNode);
857     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
858     textFieldPattern->SearchRequestKeyboard();
859 }
860 
InitButtonTouchEvent(RefPtr<TouchEventImpl> & touchEvent,int32_t childId)861 void SearchPattern::InitButtonTouchEvent(RefPtr<TouchEventImpl>& touchEvent, int32_t childId)
862 {
863     if (touchEvent) {
864         return;
865     }
866     auto host = GetHost();
867     CHECK_NULL_VOID(host);
868     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(childId));
869     CHECK_NULL_VOID(buttonFrameNode);
870     auto gesture = buttonFrameNode->GetOrCreateGestureEventHub();
871     CHECK_NULL_VOID(gesture);
872     auto eventHub = buttonFrameNode->GetEventHub<ButtonEventHub>();
873     CHECK_NULL_VOID(eventHub);
874     eventHub->SetStateEffect(false);
875     auto touchTask = [weak = WeakClaim(this), childId](const TouchEventInfo& info) {
876         auto pattern = weak.Upgrade();
877         CHECK_NULL_VOID(pattern);
878         auto touchType = info.GetTouches().front().GetTouchType();
879         if (touchType == TouchType::DOWN) {
880             pattern->OnButtonTouchDown(childId);
881         }
882         if (touchType == TouchType::UP) {
883             pattern->OnButtonTouchUp(childId);
884         }
885     };
886     touchEvent = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
887     gesture->AddTouchEvent(touchEvent);
888 }
889 
InitButtonMouseEvent(RefPtr<InputEvent> & inputEvent,int32_t childId)890 void SearchPattern::InitButtonMouseEvent(RefPtr<InputEvent>& inputEvent, int32_t childId)
891 {
892     if (inputEvent) {
893         return;
894     }
895     auto host = GetHost();
896     CHECK_NULL_VOID(host);
897     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(childId));
898     CHECK_NULL_VOID(buttonFrameNode);
899     auto eventHub = buttonFrameNode->GetEventHub<ButtonEventHub>();
900     auto inputHub = eventHub->GetOrCreateInputEventHub();
901     auto buttonPattern = buttonFrameNode->GetPattern<ButtonPattern>();
902     CHECK_NULL_VOID(buttonPattern);
903     auto buttonHoverListener = buttonPattern->GetHoverListener();
904     inputHub->RemoveOnHoverEvent(buttonHoverListener);
905     auto mouseTask = [weak = WeakClaim(this), childId](bool isHover) {
906         auto pattern = weak.Upgrade();
907         if (pattern) {
908             pattern->HandleButtonMouseEvent(isHover, childId);
909         }
910     };
911     inputEvent = MakeRefPtr<InputEvent>(std::move(mouseTask));
912     inputHub->AddOnHoverEvent(inputEvent);
913 }
914 
OnButtonTouchDown(int32_t childId)915 void SearchPattern::OnButtonTouchDown(int32_t childId)
916 {
917     auto host = GetHost();
918     CHECK_NULL_VOID(host);
919     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(childId));
920     CHECK_NULL_VOID(buttonFrameNode);
921     auto renderContext = buttonFrameNode->GetRenderContext();
922     CHECK_NULL_VOID(renderContext);
923     if (childId == CANCEL_BUTTON_INDEX ? isCancelButtonHover_ : isSearchButtonHover_) {
924         AnimateTouchAndHover(renderContext, HOVER_OPACITY, TOUCH_OPACITY, HOVER_TO_TOUCH_DURATION, Curves::SHARP);
925     } else {
926         AnimateTouchAndHover(renderContext, 0.0f, TOUCH_OPACITY, TOUCH_DURATION, Curves::FRICTION);
927     }
928 }
929 
OnButtonTouchUp(int32_t childId)930 void SearchPattern::OnButtonTouchUp(int32_t childId)
931 {
932     auto host = GetHost();
933     CHECK_NULL_VOID(host);
934     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(childId));
935     CHECK_NULL_VOID(buttonFrameNode);
936     auto renderContext = buttonFrameNode->GetRenderContext();
937     CHECK_NULL_VOID(renderContext);
938     if (childId == CANCEL_BUTTON_INDEX ? isCancelButtonHover_ : isSearchButtonHover_) {
939         AnimateTouchAndHover(renderContext, TOUCH_OPACITY, HOVER_OPACITY, HOVER_TO_TOUCH_DURATION, Curves::SHARP);
940     } else {
941         AnimateTouchAndHover(renderContext, TOUCH_OPACITY, 0.0f, TOUCH_DURATION, Curves::FRICTION);
942     }
943 }
944 
SetMouseStyle(MouseFormat format)945 void SearchPattern::SetMouseStyle(MouseFormat format)
946 {
947     auto pipeline = PipelineContext::GetCurrentContext();
948     CHECK_NULL_VOID(pipeline);
949     auto windowId = pipeline->GetWindowId();
950     auto mouseStyle = MouseStyle::CreateMouseStyle();
951     CHECK_NULL_VOID(mouseStyle);
952 
953     int32_t currentPointerStyle = 0;
954     mouseStyle->GetPointerStyle(windowId, currentPointerStyle);
955     if (currentPointerStyle != static_cast<int32_t>(format)) {
956         mouseStyle->SetPointerStyle(windowId, format);
957     }
958 }
959 
HandleButtonMouseEvent(bool isHover,int32_t childId)960 void SearchPattern::HandleButtonMouseEvent(bool isHover, int32_t childId)
961 {
962     if (childId == CANCEL_BUTTON_INDEX) {
963         isCancelButtonHover_ = isHover;
964     } else {
965         isSearchButtonHover_ = isHover;
966     }
967     auto host = GetHost();
968     CHECK_NULL_VOID(host);
969     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(childId));
970     CHECK_NULL_VOID(buttonFrameNode);
971     auto renderContext = buttonFrameNode->GetRenderContext();
972     CHECK_NULL_VOID(renderContext);
973     if (isHover) {
974         AnimateTouchAndHover(renderContext, 0.0f, HOVER_OPACITY, HOVER_DURATION, Curves::FRICTION);
975     } else {
976         AnimateTouchAndHover(renderContext, HOVER_OPACITY, 0.0f, HOVER_DURATION, Curves::FRICTION);
977     }
978 }
979 
AnimateTouchAndHover(RefPtr<RenderContext> & renderContext,float startOpacity,float endOpacity,int32_t duration,const RefPtr<Curve> & curve)980 void SearchPattern::AnimateTouchAndHover(RefPtr<RenderContext>& renderContext, float startOpacity, float endOpacity,
981     int32_t duration, const RefPtr<Curve>& curve)
982 {
983     auto colorMode = SystemProperties::GetColorMode();
984     Color touchColorFrom = Color::FromRGBO(0, 0, 0, startOpacity);
985     Color touchColorTo = Color::FromRGBO(0, 0, 0, endOpacity);
986     if (colorMode == ColorMode::DARK) {
987         touchColorFrom = Color::FromRGBO(255, 255, 255, startOpacity);
988         touchColorTo = Color::FromRGBO(255, 255, 255, endOpacity);
989     }
990     Color highlightStart = renderContext->GetBackgroundColor().value_or(Color::TRANSPARENT).BlendColor(touchColorFrom);
991     Color highlightEnd = renderContext->GetBackgroundColor().value_or(Color::TRANSPARENT).BlendColor(touchColorTo);
992     renderContext->OnBackgroundColorUpdate(highlightStart);
993     AnimationOption option = AnimationOption();
994     option.SetDuration(duration);
995     option.SetCurve(curve);
996     AnimationUtils::Animate(
997         option, [renderContext, highlightEnd]() { renderContext->OnBackgroundColorUpdate(highlightEnd); });
998 }
999 
ResetDragOption()1000 void SearchPattern::ResetDragOption()
1001 {
1002     ClearButtonStyle(BUTTON_INDEX);
1003     ClearButtonStyle(CANCEL_BUTTON_INDEX);
1004 }
1005 
ClearButtonStyle(int32_t childId)1006 void SearchPattern::ClearButtonStyle(int32_t childId)
1007 {
1008     auto host = GetHost();
1009     CHECK_NULL_VOID(host);
1010     auto buttonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(childId));
1011     CHECK_NULL_VOID(buttonFrameNode);
1012     auto renderContext = buttonFrameNode->GetRenderContext();
1013     CHECK_NULL_VOID(renderContext);
1014     AnimateTouchAndHover(renderContext, TOUCH_OPACITY, 0.0f, HOVER_TO_TOUCH_DURATION, Curves::SHARP);
1015 }
1016 
InitFocusEvent(const RefPtr<FocusHub> & focusHub)1017 void SearchPattern::InitFocusEvent(const RefPtr<FocusHub>& focusHub)
1018 {
1019     auto focusTask = [weak = WeakClaim(this)]() {
1020         auto pattern = weak.Upgrade();
1021         if (!pattern) {
1022             return;
1023         }
1024         bool backwardFocusMovement = false;
1025         bool forwardFocusMovement = false;
1026         auto host = pattern->GetHost();
1027         if (host) {
1028             auto rootHub = host->GetOrCreateFocusHub()->GetRootFocusHub();
1029             backwardFocusMovement = rootHub && rootHub->HasBackwardFocusMovementInChildren();
1030             forwardFocusMovement = rootHub && rootHub->HasForwardFocusMovementInChildren();
1031             if (rootHub) {
1032                 rootHub->ClearFocusMovementFlagsInChildren();
1033             }
1034         }
1035         pattern->HandleFocusEvent(forwardFocusMovement, backwardFocusMovement);
1036     };
1037     focusHub->SetOnFocusInternal(focusTask);
1038     auto blurTask = [weak = WeakClaim(this)]() {
1039         auto pattern = weak.Upgrade();
1040         CHECK_NULL_VOID(pattern);
1041         pattern->HandleBlurEvent();
1042     };
1043     focusHub->SetOnBlurInternal(blurTask);
1044 }
1045 
HandleFocusEvent(bool forwardFocusMovement,bool backwardFocusMovement)1046 void SearchPattern::HandleFocusEvent(bool forwardFocusMovement, bool backwardFocusMovement)
1047 {
1048     auto host = GetHost();
1049     CHECK_NULL_VOID(host);
1050     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
1051     CHECK_NULL_VOID(textFieldFrameNode);
1052     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
1053     CHECK_NULL_VOID(textFieldPattern);
1054 
1055     if (forwardFocusMovement || backwardFocusMovement) { // Don't update focus if no factical focus movement
1056         focusChoice_ = backwardFocusMovement ? FocusChoice::SEARCH_BUTTON : FocusChoice::SEARCH;
1057         if (focusChoice_ == FocusChoice::SEARCH_BUTTON && !isSearchButtonEnabled_) {
1058             bool isCancelHidden = NearZero(cancelButtonSize_.Height());
1059             focusChoice_ = isCancelHidden ? FocusChoice::SEARCH : FocusChoice::CANCEL_BUTTON;
1060         }
1061     }
1062     PaintFocusState(!(forwardFocusMovement || backwardFocusMovement));
1063 }
1064 
HandleBlurEvent()1065 void SearchPattern::HandleBlurEvent()
1066 {
1067     auto host = GetHost();
1068     CHECK_NULL_VOID(host);
1069     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
1070     CHECK_NULL_VOID(textFieldFrameNode);
1071     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
1072     CHECK_NULL_VOID(textFieldPattern);
1073     textFieldPattern->HandleBlurEvent();
1074 }
1075 
InitClickEvent()1076 void SearchPattern::InitClickEvent()
1077 {
1078     if (clickListener_) {
1079         return;
1080     }
1081     auto host = GetHost();
1082     CHECK_NULL_VOID(host);
1083     auto gesture = host->GetOrCreateGestureEventHub();
1084     CHECK_NULL_VOID(gesture);
1085     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
1086         auto pattern = weak.Upgrade();
1087         CHECK_NULL_VOID(pattern);
1088         pattern->HandleClickEvent(info);
1089     };
1090     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
1091     gesture->AddClickEvent(clickListener_);
1092 }
1093 
HandleClickEvent(GestureEvent & info)1094 void SearchPattern::HandleClickEvent(GestureEvent& info)
1095 {
1096     auto host = GetHost();
1097     CHECK_NULL_VOID(host);
1098     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
1099     CHECK_NULL_VOID(textFieldFrameNode);
1100     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
1101     CHECK_NULL_VOID(textFieldPattern);
1102     textFieldPattern->HandleClickEvent(info);
1103 }
1104 
HandleInputChildOnFocus() const1105 bool SearchPattern::HandleInputChildOnFocus() const
1106 {
1107 #if !defined(PREVIEW)
1108     return false;
1109 #endif
1110     auto focusHub = GetHost()->GetOrCreateFocusHub();
1111     focusHub->RequestFocusImmediately();
1112     return true;
1113 }
1114 
ToJsonValueForTextField(std::unique_ptr<JsonValue> & json) const1115 void SearchPattern::ToJsonValueForTextField(std::unique_ptr<JsonValue>& json) const
1116 {
1117     auto host = GetHost();
1118     CHECK_NULL_VOID(host);
1119     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
1120     CHECK_NULL_VOID(textFieldFrameNode);
1121     auto textFieldLayoutProperty = textFieldFrameNode->GetLayoutProperty<TextFieldLayoutProperty>();
1122     CHECK_NULL_VOID(textFieldLayoutProperty);
1123     auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
1124     CHECK_NULL_VOID(textFieldPattern);
1125 
1126     json->Put("value", textFieldPattern->GetTextValue().c_str());
1127     json->Put("placeholder", textFieldPattern->GetPlaceHolder().c_str());
1128     json->Put("placeholderColor", textFieldPattern->GetPlaceholderColor().c_str());
1129     json->Put("placeholderFont", textFieldPattern->GetPlaceholderFont().c_str());
1130     json->Put("textAlign", V2::ConvertWrapTextAlignToString(textFieldPattern->GetTextAlign()).c_str());
1131     auto textColor = textFieldLayoutProperty->GetTextColor().value_or(Color());
1132     json->Put("fontColor", textColor.ColorToString().c_str());
1133     auto textFontJson = JsonUtil::Create(true);
1134     textFontJson->Put("fontSize", textFieldPattern->GetFontSize().c_str());
1135     textFontJson->Put("fontStyle",
1136         textFieldPattern->GetItalicFontStyle() == Ace::FontStyle::NORMAL ? "FontStyle.Normal" : "FontStyle.Italic");
1137     textFontJson->Put("fontWeight", V2::ConvertWrapFontWeightToStirng(textFieldPattern->GetFontWeight()).c_str());
1138     textFontJson->Put("fontFamily", textFieldPattern->GetFontFamily().c_str());
1139     json->Put("textFont", textFontJson->ToString().c_str());
1140     json->Put("copyOption",
1141         ConvertCopyOptionsToString(textFieldLayoutProperty->GetCopyOptionsValue(CopyOptions::None)).c_str());
1142     auto maxLength = GetMaxLength();
1143     json->Put("maxLength", GreatOrEqual(maxLength, Infinity<uint32_t>()) ? "INF" : std::to_string(maxLength).c_str());
1144     json->Put("type", textFieldPattern->TextInputTypeToString().c_str());
1145     textFieldLayoutProperty->HasCopyOptions();
1146 }
1147 
ToJsonValueForSearchIcon(std::unique_ptr<JsonValue> & json) const1148 void SearchPattern::ToJsonValueForSearchIcon(std::unique_ptr<JsonValue>& json) const
1149 {
1150     auto host = GetHost();
1151     CHECK_NULL_VOID(host);
1152     auto imageFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(IMAGE_INDEX));
1153     CHECK_NULL_VOID(imageFrameNode);
1154     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
1155     CHECK_NULL_VOID(imageLayoutProperty);
1156     auto searchIconJson = JsonUtil::Create(true);
1157 
1158     // icon size
1159     auto searchIconGeometryNode = imageFrameNode->GetGeometryNode();
1160     CHECK_NULL_VOID(searchIconGeometryNode);
1161     auto searchIconFrameSize = searchIconGeometryNode->GetFrameSize().Width();
1162     auto searchLayoutProperty = host->GetLayoutProperty<SearchLayoutProperty>();
1163     CHECK_NULL_VOID(searchLayoutProperty);
1164     auto searchIconSize = searchLayoutProperty->GetSearchIconUDSizeValue(Dimension(searchIconFrameSize)).ConvertToPx();
1165     searchIconJson->Put("size", Dimension(searchIconSize, DimensionUnit::PX).ToString().c_str());
1166 
1167     // icon color
1168     auto searchIconColor = imageLayoutProperty->GetImageSourceInfo()->GetFillColor().value_or(Color());
1169     searchIconJson->Put("color", searchIconColor.ColorToString().c_str());
1170 
1171     // icon path
1172     auto searchIconPath = imageLayoutProperty->GetImageSourceInfo()->GetSrc();
1173     searchIconJson->Put("src", searchIconPath.c_str());
1174     json->Put("icon", searchIconPath.c_str());
1175     json->Put("searchIcon", searchIconJson);
1176 }
1177 
ToJsonValueForCancelButton(std::unique_ptr<JsonValue> & json) const1178 void SearchPattern::ToJsonValueForCancelButton(std::unique_ptr<JsonValue>& json) const
1179 {
1180     auto host = GetHost();
1181     CHECK_NULL_VOID(host);
1182     auto layoutProperty = host->GetLayoutProperty<SearchLayoutProperty>();
1183     CHECK_NULL_VOID(layoutProperty);
1184     auto cancelImageFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(CANCEL_IMAGE_INDEX));
1185     CHECK_NULL_VOID(cancelImageFrameNode);
1186     auto cancelImageLayoutProperty = cancelImageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
1187     CHECK_NULL_VOID(cancelImageLayoutProperty);
1188     auto cancelButtonJson = JsonUtil::Create(true);
1189 
1190     // style
1191     if (layoutProperty->GetCancelButtonStyle() == CancelButtonStyle::CONSTANT) {
1192         cancelButtonJson->Put("style", "CancelButtonStyle.CONSTANT");
1193     } else if (layoutProperty->GetCancelButtonStyle() == CancelButtonStyle::INVISIBLE) {
1194         cancelButtonJson->Put("style", "CancelButtonStyle.INVISIBLE");
1195     } else {
1196         cancelButtonJson->Put("style", "CancelButtonStyle.INPUT");
1197     }
1198 
1199     auto cancelIconJson = JsonUtil::Create(true);
1200 
1201     // icon size
1202     auto cancelIconGeometryNode = cancelImageFrameNode->GetGeometryNode();
1203     CHECK_NULL_VOID(cancelIconGeometryNode);
1204     auto cancelIconFrameSize = cancelIconGeometryNode->GetFrameSize().Width();
1205     auto searchLayoutProperty = host->GetLayoutProperty<SearchLayoutProperty>();
1206     CHECK_NULL_VOID(searchLayoutProperty);
1207     auto cancelIconSize =
1208         searchLayoutProperty->GetCancelButtonUDSizeValue(Dimension(cancelIconFrameSize)).ConvertToPx();
1209     cancelIconJson->Put("size", Dimension(cancelIconSize, DimensionUnit::PX).ToString().c_str());
1210 
1211     // icon color
1212     auto cancelImageRenderProperty = cancelImageFrameNode->GetPaintProperty<ImageRenderProperty>();
1213     CHECK_NULL_VOID(cancelImageRenderProperty);
1214     auto cancelIconColor = cancelImageRenderProperty->GetSvgFillColor().value_or(Color());
1215     cancelIconJson->Put("color", cancelIconColor.ColorToString().c_str());
1216 
1217     // right icon src path
1218     auto cancelImageSrc = cancelImageLayoutProperty->GetImageSourceInfo()->GetSrc();
1219     cancelIconJson->Put("src", cancelImageSrc.c_str());
1220     cancelButtonJson->Put("icon", cancelIconJson);
1221     json->Put("cancelButton", cancelButtonJson);
1222 }
1223 
ToJsonValueForSearchButtonOption(std::unique_ptr<JsonValue> & json) const1224 void SearchPattern::ToJsonValueForSearchButtonOption(std::unique_ptr<JsonValue>& json) const
1225 {
1226     auto host = GetHost();
1227     CHECK_NULL_VOID(host);
1228     auto searchButtonFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(BUTTON_INDEX));
1229     CHECK_NULL_VOID(searchButtonFrameNode);
1230     auto searchButtonLayoutProperty = searchButtonFrameNode->GetLayoutProperty<ButtonLayoutProperty>();
1231     CHECK_NULL_VOID(searchButtonLayoutProperty);
1232     auto searchButtonJson = JsonUtil::Create(true);
1233 
1234     // font size
1235     auto searchButtonFontSize = searchButtonLayoutProperty->GetFontSize().value_or(Dimension(0, DimensionUnit::VP));
1236     searchButtonJson->Put("fontSize", searchButtonFontSize.ToString().c_str());
1237 
1238     // font color
1239     auto searchButtonFontColor = searchButtonLayoutProperty->GetFontColor().value_or(Color());
1240     searchButtonJson->Put("fontColor", searchButtonFontColor.ColorToString().c_str());
1241     json->Put("searchButtonOption", searchButtonJson);
1242 }
1243 
ToJsonValueForCursor(std::unique_ptr<JsonValue> & json) const1244 void SearchPattern::ToJsonValueForCursor(std::unique_ptr<JsonValue>& json) const
1245 {
1246     auto host = GetHost();
1247     CHECK_NULL_VOID(host);
1248     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
1249     CHECK_NULL_VOID(textFieldFrameNode);
1250     auto textFieldPaintProperty = textFieldFrameNode->GetPaintProperty<TextFieldPaintProperty>();
1251     CHECK_NULL_VOID(textFieldPaintProperty);
1252     auto cursorJson = JsonUtil::Create(true);
1253 
1254     // color
1255     auto caretColor = textFieldPaintProperty->GetCursorColor().value_or(Color());
1256     cursorJson->Put("color", caretColor.ColorToString().c_str());
1257     auto caretWidth = textFieldPaintProperty->GetCursorWidth().value_or(Dimension(0, DimensionUnit::VP));
1258     cursorJson->Put("width", caretWidth.ToString().c_str());
1259     json->Put("caretStyle", cursorJson);
1260 }
1261 
ToJsonValue(std::unique_ptr<JsonValue> & json) const1262 void SearchPattern::ToJsonValue(std::unique_ptr<JsonValue>& json) const
1263 {
1264     Pattern::ToJsonValue(json);
1265 
1266     ToJsonValueForTextField(json);
1267     ToJsonValueForSearchIcon(json);
1268     ToJsonValueForCancelButton(json);
1269     ToJsonValueForCursor(json);
1270     ToJsonValueForSearchButtonOption(json);
1271 }
1272 
OnColorConfigurationUpdate()1273 void SearchPattern::OnColorConfigurationUpdate()
1274 {
1275     auto host = GetHost();
1276     CHECK_NULL_VOID(host);
1277     host->SetNeedCallChildrenUpdate(false);
1278     auto pipeline = PipelineBase::GetCurrentContext();
1279     CHECK_NULL_VOID(pipeline);
1280     auto textFieldTheme = pipeline->GetTheme<TextFieldTheme>();
1281     CHECK_NULL_VOID(textFieldTheme);
1282     auto renderContext = host->GetRenderContext();
1283     CHECK_NULL_VOID(renderContext);
1284     renderContext->UpdateBackgroundColor(textFieldTheme->GetBgColor());
1285     CHECK_NULL_VOID(pipeline);
1286     auto searchTheme = pipeline->GetTheme<SearchTheme>();
1287     CHECK_NULL_VOID(searchTheme);
1288     if (cancelButtonNode_) {
1289         auto cancelButtonRenderContext = cancelButtonNode_->GetRenderContext();
1290         CHECK_NULL_VOID(cancelButtonRenderContext);
1291         cancelButtonRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
1292         auto textFrameNode = AceType::DynamicCast<FrameNode>(cancelButtonNode_->GetChildren().front());
1293         CHECK_NULL_VOID(textFrameNode);
1294         auto textLayoutProperty = textFrameNode->GetLayoutProperty<TextLayoutProperty>();
1295         CHECK_NULL_VOID(textLayoutProperty);
1296         textLayoutProperty->UpdateTextColor(searchTheme->GetSearchButtonTextColor());
1297         cancelButtonNode_->MarkModifyDone();
1298         cancelButtonNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1299     }
1300     if (buttonNode_) {
1301         auto buttonRenderContext = buttonNode_->GetRenderContext();
1302         CHECK_NULL_VOID(buttonRenderContext);
1303         buttonRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
1304         auto textFrameNode = AceType::DynamicCast<FrameNode>(buttonNode_->GetChildren().front());
1305         CHECK_NULL_VOID(textFrameNode);
1306         auto textLayoutProperty = textFrameNode->GetLayoutProperty<TextLayoutProperty>();
1307         CHECK_NULL_VOID(textLayoutProperty);
1308         textLayoutProperty->UpdateTextColor(searchTheme->GetSearchButtonTextColor());
1309         buttonNode_->MarkModifyDone();
1310         buttonNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1311     }
1312     if (textField_) {
1313         auto textFieldLayoutProperty = textField_->GetLayoutProperty<TextFieldLayoutProperty>();
1314         CHECK_NULL_VOID(textFieldLayoutProperty);
1315         textFieldLayoutProperty->UpdateTextColor(searchTheme->GetTextColor());
1316         textFieldLayoutProperty->UpdatePlaceholderTextColor(searchTheme->GetPlaceholderColor());
1317         textField_->MarkModifyDone();
1318         textField_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1319     }
1320 }
1321 
GetMaxLength() const1322 uint32_t SearchPattern::GetMaxLength() const
1323 {
1324     auto host = GetHost();
1325     CHECK_NULL_RETURN(host, Infinity<uint32_t>());
1326     auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
1327     CHECK_NULL_RETURN(textFieldFrameNode, Infinity<uint32_t>());
1328     auto textFieldLayoutProperty = textFieldFrameNode->GetLayoutProperty<TextFieldLayoutProperty>();
1329     CHECK_NULL_RETURN(textFieldLayoutProperty, Infinity<uint32_t>());
1330     return textFieldLayoutProperty->HasMaxLength() ? textFieldLayoutProperty->GetMaxLengthValue(Infinity<uint32_t>())
1331                                                    : Infinity<uint32_t>();
1332 }
1333 
1334 } // namespace OHOS::Ace::NG
1335