1 /*
2 * Copyright (c) 2021-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 "core/components/search/render_search.h"
17
18 #include "base/json/json_util.h"
19 #include "base/log/log_wrapper.h"
20 #include "base/mousestyle/mouse_style.h"
21 #include "base/utils/system_properties.h"
22 #include "core/components/box/box_component.h"
23 #include "core/components/button/button_component.h"
24 #include "core/components/common/properties/alignment.h"
25 #include "core/components/divider/divider_component.h"
26 #include "core/components/divider/render_divider.h"
27 #include "core/components/padding/padding_component.h"
28 #include "core/components/text/render_text.h"
29 #include "core/components/text/text_component.h"
30 #include "core/components/text_field/text_field_component.h"
31 #include "core/event/ace_event_helper.h"
32
33 namespace OHOS::Ace {
34 namespace {
35
36 constexpr Dimension SEARCH_SPACING = 2.0_vp;
37 constexpr Dimension DIVIDER_WIDTH = 1.0_px;
38 constexpr Dimension TEXT_PADDING = 14.0_vp;
39 constexpr Dimension SEARCH_TEXT_HEIGHT = 36.0_vp;
40 constexpr Dimension SEARCH_BUTTON_TEXT_FONT_SIZE = 14.0_fp;
41 const Color SEARCH_BUTTON_TEXT_COLOR = Color(0xFF254FF7);
42
43 } // namespace
44
Update(const RefPtr<Component> & component)45 void RenderSearch::Update(const RefPtr<Component>& component)
46 {
47 searchComponent_ = AceType::DynamicCast<SearchComponent>(component);
48 if (!searchComponent_) {
49 LOGW("component is null");
50 return;
51 }
52 needReverse_ = (searchComponent_->GetTextDirection() == TextDirection::RTL);
53 closeIconSize_ = searchComponent_->GetCloseIconSize();
54 placeHoldStyle_ = searchComponent_->GetPlaceHoldStyle();
55 editingStyle_ = searchComponent_->GetEditingStyle();
56 closeIconHotZoneHorizontal_ = searchComponent_->GetCloseIconHotZoneHorizontal();
57
58 decoration_ = searchComponent_->GetDecoration();
59 if (searchComponent_->GetTextEditController() && textEditController_ != searchComponent_->GetTextEditController()) {
60 if (textEditController_) {
61 textEditController_->RemoveObserver(WeakClaim(this));
62 }
63 textEditController_ = searchComponent_->GetTextEditController();
64 textEditController_->AddObserver(WeakClaim(this));
65 }
66
67 hoverColor_ = searchComponent_->GetHoverColor();
68 pressColor_ = searchComponent_->GetPressColor();
69 CreateRenderImage(searchComponent_);
70 CreateRenderButton(searchComponent_);
71
72 auto context = context_.Upgrade();
73 if (context && context->GetIsDeclarative()) {
74 if (searchComponent_->GetOnChange()) {
75 changeEvent_ = *searchComponent_->GetOnChange();
76 } else {
77 changeEvent_ = nullptr;
78 }
79
80 if (searchComponent_->GetOnSubmit()) {
81 submitEvent_ = *searchComponent_->GetOnSubmit();
82 } else {
83 submitEvent_ = nullptr;
84 }
85 } else {
86 changeEvent_ = AceAsyncEvent<void(const std::string)>::Create(searchComponent_->GetChangeEventId(), context_);
87 submitEvent_ = AceAsyncEvent<void(const std::string)>::Create(searchComponent_->GetSubmitEventId(), context_);
88 }
89
90 MarkNeedLayout();
91 }
92
FireSubmitEvent(const std::string & searchKey)93 void RenderSearch::FireSubmitEvent(const std::string& searchKey)
94 {
95 if (submitEvent_) {
96 auto context = context_.Upgrade();
97 if (context && context->GetIsDeclarative()) {
98 submitEvent_(searchKey);
99 } else {
100 auto submitResult = JsonUtil::Create(true);
101 submitResult->Put("text", searchKey.c_str());
102 submitEvent_(std::string(R"("submit",)").append(submitResult->ToString()));
103 }
104 }
105 }
106
PerformLayout()107 void RenderSearch::PerformLayout()
108 {
109 const auto& renderTextField = AceType::DynamicCast<RenderTextField>(GetChildren().front());
110 if (!renderTextField) {
111 return;
112 }
113 renderTextField->Layout(GetLayoutParam());
114 SetLayoutSize(renderTextField->GetLayoutSize());
115 renderTextField->SetSubmitEvent([weak = WeakClaim(this)](const std::string& searchKey) {
116 auto renderSearch = weak.Upgrade();
117 if (renderSearch) {
118 renderSearch->FireSubmitEvent(searchKey);
119 }
120 });
121
122 auto context = context_.Upgrade();
123 if (context && context->GetIsDeclarative()) {
124 renderTextField->SetOnValueChangeEvent(changeEvent_);
125 } else {
126 renderTextField->SetOnTextChangeEvent(changeEvent_);
127 }
128
129 Size deflateSize = Size(NormalizeToPx(SEARCH_SPACING), NormalizeToPx(SEARCH_SPACING)) * 2.0;
130 if (context && decoration_) {
131 deflateSize += decoration_->GetBorder().GetLayoutSize(context->GetDipScale());
132 }
133 LayoutParam layoutParam = LayoutParam(GetLayoutSize() - deflateSize, Size());
134 if (renderCloseIcon_) {
135 renderCloseIcon_->Layout(layoutParam);
136 }
137 if (renderSearchBox_) {
138 renderSearchBox_->Layout(layoutParam);
139 }
140
141 InitRect(renderTextField);
142 }
143
InitRect(const RefPtr<RenderTextField> & renderTextField)144 void RenderSearch::InitRect(const RefPtr<RenderTextField>& renderTextField)
145 {
146 auto pipelineContext = context_.Upgrade();
147 if (!pipelineContext) {
148 return;
149 }
150 Border border;
151 if (decoration_) {
152 border = decoration_->GetBorder();
153 }
154 double leftBorderWidth = NormalizeToPx(border.Left().GetWidth());
155 double topBorderWidth = NormalizeToPx(border.Top().GetWidth());
156 double rightBorderWidth = NormalizeToPx(border.Right().GetWidth());
157 double bottomBorderWidth = NormalizeToPx(border.Bottom().GetWidth());
158
159 double searchHeight = GetLayoutSize().Height();
160 double searchInnerHeight = searchHeight - topBorderWidth - bottomBorderWidth;
161
162 // Compute rect of search text.
163 double searchBoxSpacing = NormalizeToPx(SEARCH_SPACING) * 2.0 + NormalizeToPx(DIVIDER_WIDTH);
164 if (renderSearchBox_) {
165 double searchBoxVerticalOffset =
166 topBorderWidth + (searchInnerHeight - renderSearchBox_->GetLayoutSize().Height()) / 2.0;
167 double searchBoxWidth = renderSearchBox_->GetLayoutSize().Width();
168 Offset searchTextOffset = Offset(
169 GetLayoutSize().Width() - rightBorderWidth - searchBoxWidth - searchBoxSpacing, searchBoxVerticalOffset);
170 Offset searchReactOffset =
171 Offset(GetLayoutSize().Width() - rightBorderWidth - searchBoxWidth - searchBoxSpacing, topBorderWidth);
172 if (needReverse_) {
173 searchTextOffset = Offset(leftBorderWidth, searchBoxVerticalOffset);
174 searchReactOffset = Offset(leftBorderWidth, topBorderWidth);
175 }
176 Size searchBoxSize(renderSearchBox_->GetLayoutSize().Width() + searchBoxSpacing, GetLayoutSize().Height());
177 searchReactRect_ = Rect(searchReactOffset, searchBoxSize);
178 searchTextRect_ = Rect(searchTextOffset, renderSearchBox_->GetLayoutSize() + Size(searchBoxSpacing, 0.0));
179 } else {
180 searchTextRect_ = Rect();
181 searchReactRect_ = Rect();
182 }
183
184 auto context = context_.Upgrade();
185 if (context && context->GetIsDeclarative()) {
186 double padding = searchTextRect_.Width() + rightBorderWidth + NormalizeToPx(closeIconHotZoneHorizontal_) -
187 (NormalizeToPx(closeIconSize_) / 2.0);
188 renderTextField->SetPaddingHorizonForSearch(padding);
189 } else {
190 renderTextField->SetPaddingHorizonForSearch(searchTextRect_.Width());
191 }
192
193 renderTextField->MarkNeedLayout();
194
195 // Compute rect of close icon.
196 if (renderCloseIcon_) {
197 double iconVerticalOffset =
198 topBorderWidth + (searchInnerHeight - renderCloseIcon_->GetLayoutSize().Height()) / 2.0;
199 double iconHotzonOffset = (NormalizeToPx(closeIconHotZoneHorizontal_) - NormalizeToPx(closeIconSize_)) / 2.0;
200 Offset closeIconOffset = Offset(GetLayoutSize().Width() - rightBorderWidth - searchTextRect_.Width() -
201 renderCloseIcon_->GetLayoutSize().Width() - iconHotzonOffset,
202 iconVerticalOffset);
203 if (needReverse_) {
204 closeIconOffset = Offset(leftBorderWidth + searchTextRect_.Width() + iconHotzonOffset, iconVerticalOffset);
205 }
206 closeIconRect_ = Rect(closeIconOffset, renderCloseIcon_->GetLayoutSize());
207
208 // Compute rect of hot zone of close icon.
209 double searchSpacing = NormalizeToPx(SEARCH_SPACING);
210 double horizonSpacing = iconHotzonOffset - searchSpacing;
211 double verticalSpacing =
212 std::min(iconHotzonOffset, (searchInnerHeight - renderCloseIcon_->GetLayoutSize().Height()) / 2.0) -
213 searchSpacing;
214 closeIconHotZoneRect_ =
215 closeIconRect_ - Offset(horizonSpacing, verticalSpacing) + Size(horizonSpacing, verticalSpacing) * 2.0;
216 } else {
217 closeIconRect_ = Rect();
218 closeIconHotZoneRect_ = Rect();
219 }
220 }
221
OnValueChanged(bool needFireChangeEvent,bool needFireSelectChangeEvent)222 void RenderSearch::OnValueChanged(bool needFireChangeEvent, bool needFireSelectChangeEvent)
223 {
224 if (textEditController_) {
225 const auto& currentText = textEditController_->GetValue().text;
226 showCloseIcon_ = !currentText.empty();
227 auto context = context_.Upgrade();
228 if (context && context->GetIsDeclarative()) {
229 auto renderTextField = AceType::DynamicCast<RenderTextField>(GetChildren().front());
230 if (showCloseIcon_) {
231 renderTextField->SetTextStyle(editingStyle_);
232 } else {
233 renderTextField->SetTextStyle(placeHoldStyle_);
234 }
235 }
236 }
237 }
238
CreateRenderImage(const RefPtr<SearchComponent> & searchComponent)239 void RenderSearch::CreateRenderImage(const RefPtr<SearchComponent>& searchComponent)
240 {
241 if (!searchComponent) {
242 return;
243 }
244 if (!renderCloseIcon_ && (SystemProperties::GetDeviceType() != DeviceType::TV)) {
245 const auto& closeIconSrc = searchComponent->GetCloseIconSrc();
246 RefPtr<ImageComponent> imageComponent;
247 if (closeIconSrc.empty()) {
248 imageComponent = AceType::MakeRefPtr<ImageComponent>(InternalResource::ResourceId::CLOSE_SVG);
249 } else {
250 imageComponent = AceType::MakeRefPtr<ImageComponent>(closeIconSrc);
251 }
252 imageComponent->SetWidth(searchComponent->GetCloseIconSize());
253 imageComponent->SetHeight(searchComponent->GetCloseIconSize());
254
255 renderCloseIcon_ = AceType::DynamicCast<RenderImage>(imageComponent->CreateRenderNode());
256 if (!renderCloseIcon_) {
257 return;
258 }
259 renderCloseIcon_->Attach(GetContext());
260 renderCloseIcon_->Update(imageComponent);
261 }
262 }
263
CreateRenderButton(const RefPtr<SearchComponent> & searchComponent)264 void RenderSearch::CreateRenderButton(const RefPtr<SearchComponent>& searchComponent)
265 {
266 if (!searchComponent) {
267 return;
268 }
269 if (searchComponent->GetSearchText().empty()) {
270 searchText_ = "";
271 renderSearchBox_.Reset();
272 return;
273 }
274 if (searchText_ != searchComponent->GetSearchText()) {
275 searchText_ = searchComponent->GetSearchText();
276 renderSearchBox_.Reset();
277 }
278 if (!renderSearchBox_ && (SystemProperties::GetDeviceType() != DeviceType::TV)) {
279 const auto& searchText = searchComponent->GetSearchText();
280 const auto& textComponent = AceType::MakeRefPtr<TextComponent>(searchText);
281 TextStyle textStyle;
282 textStyle.SetMaxLines(1);
283 textStyle.SetTextColor(SEARCH_BUTTON_TEXT_COLOR);
284 textStyle.SetFontSize(SEARCH_BUTTON_TEXT_FONT_SIZE);
285 textStyle.SetFontWeight(FontWeight::W500);
286 textComponent->SetTextStyle(textStyle);
287 auto renderText = AceType::DynamicCast<RenderText>(textComponent->CreateRenderNode());
288 if (!renderText) {
289 return;
290 }
291 renderText->Attach(GetContext());
292 renderText->Update(textComponent);
293
294 auto boxComponent = AceType::MakeRefPtr<BoxComponent>();
295 Edge edge = Edge(TEXT_PADDING, 0.0_vp, TEXT_PADDING, 0.0_vp);
296 boxComponent->SetPadding(edge);
297 boxComponent->SetHeight(SEARCH_TEXT_HEIGHT.Value(), SEARCH_TEXT_HEIGHT.Unit());
298 renderSearchBox_ = AceType::DynamicCast<RenderBox>(boxComponent->CreateRenderNode());
299 if (!renderSearchBox_) {
300 return;
301 }
302 renderSearchBox_->Attach(GetContext());
303 renderSearchBox_->Update(boxComponent);
304 renderSearchBox_->AddChild(renderText);
305 renderSearchBox_->SyncRSNode(nullptr);
306 renderText->SyncRSNode(nullptr);
307 }
308 }
309
HandleEnterEvent()310 bool RenderSearch::HandleEnterEvent()
311 {
312 auto renderTextField = AceType::DynamicCast<RenderTextField>(GetChildren().front());
313 if (!renderTextField || !textEditController_) {
314 return false;
315 }
316
317 if (focusRender_ == SearchNodeType::IMAGE) {
318 renderTextField->SetNeedNotifyChangeEvent(true);
319 textEditController_->Clear();
320 focusRender_ = SearchNodeType::NONE;
321 MarkNeedRender();
322 return true;
323 }
324 if (focusRender_ == SearchNodeType::BUTTON) {
325 std::string searchKey = textEditController_->GetText();
326 FireSubmitEvent(searchKey);
327 focusRender_ = SearchNodeType::NONE;
328 MarkNeedRender();
329 return true;
330 }
331 return false;
332 }
333
HandleFocusEvent(bool vertical,bool reverse)334 bool RenderSearch::HandleFocusEvent(bool vertical, bool reverse)
335 {
336 if (vertical) {
337 focusRender_ = SearchNodeType::NONE;
338 return false;
339 }
340 if (!(showCloseIcon_ && renderCloseIcon_) && !renderSearchBox_) {
341 focusRender_ = SearchNodeType::NONE;
342 return false;
343 }
344
345 auto renderTextField = AceType::DynamicCast<RenderTextField>(GetChildren().front());
346 if (!renderTextField) {
347 focusRender_ = SearchNodeType::NONE;
348 return false;
349 }
350 bool result = false;
351 if ((showCloseIcon_ && renderCloseIcon_) && renderSearchBox_) {
352 if (focusRender_ == SearchNodeType::NONE) {
353 if (!reverse) {
354 focusRender_ = SearchNodeType::IMAGE;
355 result = true;
356 }
357 } else if (focusRender_ == SearchNodeType::IMAGE) {
358 if (!reverse) {
359 focusRender_ = SearchNodeType::BUTTON;
360 result = true;
361 } else {
362 focusRender_ = SearchNodeType::NONE;
363 renderTextField->UpdateFocusAnimation();
364 result = true;
365 }
366 } else if (focusRender_ == SearchNodeType::BUTTON) {
367 if (reverse) {
368 focusRender_ = SearchNodeType::IMAGE;
369 result = true;
370 }
371 }
372 } else {
373 if (focusRender_ == SearchNodeType::NONE) {
374 if (!reverse) {
375 focusRender_ = renderSearchBox_ ? SearchNodeType::BUTTON : SearchNodeType::IMAGE;
376 result = true;
377 }
378 } else {
379 if (reverse) {
380 focusRender_ = SearchNodeType::NONE;
381 renderTextField->UpdateFocusAnimation();
382 result = true;
383 }
384 }
385 }
386 if (result) {
387 MarkNeedRender();
388 }
389 return result;
390 }
391
TouchTest(const Point & globalPoint,const Point & parentLocalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result)392 bool RenderSearch::TouchTest(const Point& globalPoint, const Point& parentLocalPoint,
393 const TouchRestrict& touchRestrict, TouchTestResult& result)
394 {
395 LOGD("OnTouchTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
396 GetTypeName(), GetTouchRect().Left(), GetTouchRect().Top(), GetTouchRect().Width(), GetTouchRect().Height());
397 LOGD("OnTouchTest: the local point refer to parent is %{public}lf, %{public}lf, ", parentLocalPoint.GetX(),
398 parentLocalPoint.GetY());
399 auto pointWithoutMargin = parentLocalPoint - GetPosition();
400 if (GetDisableTouchEvent() || disabled_) {
401 return false;
402 }
403 if (showCloseIcon_ && closeIconHotZoneRect_.IsInRegion(pointWithoutMargin)) {
404 hoverOrPressRender_ = SearchNodeType::IMAGE;
405 } else if (searchReactRect_.IsInRegion(pointWithoutMargin)) {
406 hoverOrPressRender_ = SearchNodeType::BUTTON;
407 } else {
408 hoverOrPressRender_ = SearchNodeType::NONE;
409 }
410 // Since the paintRect is relative to parent, use parent local point to perform touch test.
411 if (closeIconHotZoneRect_.IsInRegion(pointWithoutMargin) || searchReactRect_.IsInRegion(pointWithoutMargin)) {
412 // Calculates the coordinate offset in this node.
413 const auto localPoint = pointWithoutMargin - GetPaintRect().GetOffset();
414 const auto coordinateOffset = globalPoint - localPoint;
415 globalPoint_ = globalPoint;
416 OnTouchTestHit(coordinateOffset, touchRestrict, result);
417 return true;
418 }
419 if (GetPaintRect().IsInRegion(parentLocalPoint)) {
420 // Calculates the local point location in this node.
421 const auto localPoint = parentLocalPoint - GetPaintRect().GetOffset();
422 bool dispatchSuccess = false;
423 for (auto iter = GetChildren().rbegin(); iter != GetChildren().rend(); ++iter) {
424 auto& child = *iter;
425 if (child->TouchTest(globalPoint, localPoint, touchRestrict, result)) {
426 dispatchSuccess = true;
427 break;
428 }
429 if (child->InterceptTouchEvent()) {
430 break;
431 }
432 }
433 return dispatchSuccess;
434 }
435 return false;
436 }
437
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)438 void RenderSearch::OnTouchTestHit(
439 const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
440 {
441 if (!rawRecognizer_) {
442 rawRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
443 auto weak = WeakClaim(this);
444 rawRecognizer_->SetOnTouchDown([weak = WeakClaim(this)](const TouchEventInfo& info) {
445 auto search = weak.Upgrade();
446 if (search) {
447 search->overlayColor_ = search->pressColor_;
448 search->MarkNeedRender();
449 }
450 });
451
452 rawRecognizer_->SetOnTouchUp([weak = WeakClaim(this)](const TouchEventInfo& info) {
453 auto search = weak.Upgrade();
454 if (search) {
455 search->overlayColor_ = Color::TRANSPARENT;
456 search->MarkNeedRender();
457 }
458 });
459
460 rawRecognizer_->SetOnTouchCancel([weak = WeakClaim(this)](const TouchEventInfo& info) {
461 auto search = weak.Upgrade();
462 if (search) {
463 search->overlayColor_ = Color::TRANSPARENT;
464 search->MarkNeedRender();
465 }
466 });
467 }
468 rawRecognizer_->SetTouchRestrict(touchRestrict);
469 rawRecognizer_->SetCoordinateOffset(coordinateOffset);
470 result.emplace_back(rawRecognizer_);
471
472 if (!clickRecognizer_) {
473 clickRecognizer_ = AceType::MakeRefPtr<ClickRecognizer>();
474 clickRecognizer_->SetOnClick([weak = WeakClaim(this)](const ClickInfo& info) {
475 auto search = weak.Upgrade();
476 if (search) {
477 search->HandleClick();
478 }
479 });
480 }
481 clickRecognizer_->SetTouchRestrict(touchRestrict);
482 clickRecognizer_->SetCoordinateOffset(coordinateOffset);
483 result.emplace_back(clickRecognizer_);
484 }
485
HandleClick()486 void RenderSearch::HandleClick()
487 {
488 auto renderTextField = AceType::DynamicCast<RenderTextField>(GetChildren().front());
489 if (!renderTextField || !textEditController_) {
490 return;
491 }
492 std::string accessibilityEventType = "click";
493 SendAccessibilityEvent(accessibilityEventType);
494 if (hoverOrPressRender_ == SearchNodeType::IMAGE) {
495 renderTextField->SetNeedNotifyChangeEvent(true);
496 textEditController_->Clear();
497 auto onValueChange = renderTextField->GetOnValueChange();
498 if (onValueChange) {
499 onValueChange();
500 }
501 } else if (hoverOrPressRender_ == SearchNodeType::BUTTON) {
502 std::string searchKey = textEditController_->GetText();
503 renderTextField->CloseKeyboard(true);
504 FireSubmitEvent(searchKey);
505 }
506 }
507
MouseHoverTest(const Point & parentLocalPoint)508 bool RenderSearch::MouseHoverTest(const Point& parentLocalPoint)
509 {
510 auto context = context_.Upgrade();
511 if (!context) {
512 hoverOrPressRender_ = SearchNodeType::NONE;
513 return false;
514 }
515 if (!InTouchRectList(parentLocalPoint, GetTouchRectList())) {
516 if (mouseState_ == MouseState::HOVER) {
517 mouseState_ = MouseState::NONE;
518 hoverOrPressRender_ = SearchNodeType::NONE;
519 }
520 CancelTextFieldHover();
521 return false;
522 }
523 context->AddToHoverList(AceType::WeakClaim(this).Upgrade());
524
525 if (showCloseIcon_ && closeIconHotZoneRect_.IsInRegion(parentLocalPoint)) {
526 if (mouseState_ == MouseState::NONE || hoverOrPressRender_ == SearchNodeType::BUTTON) {
527 mouseState_ = MouseState::HOVER;
528 hoverOrPressRender_ = SearchNodeType::IMAGE;
529 CancelTextFieldHover();
530 return true;
531 }
532 }
533
534 if (searchTextRect_.IsInRegion(parentLocalPoint)) {
535 if (mouseState_ == MouseState::NONE || hoverOrPressRender_ == SearchNodeType::IMAGE) {
536 mouseState_ = MouseState::HOVER;
537 hoverOrPressRender_ = SearchNodeType::BUTTON;
538 CancelTextFieldHover();
539 return true;
540 }
541 }
542
543 bool hoverInSearch = !searchTextRect_.IsInRegion(parentLocalPoint);
544 if (showCloseIcon_ && hoverInSearch) {
545 hoverInSearch = !closeIconHotZoneRect_.IsInRegion(parentLocalPoint);
546 }
547 if (hoverInSearch) {
548 hoverOrPressRender_ = SearchNodeType::NONE;
549 mouseState_ = MouseState::NONE;
550
551 // Change textfield to hover.
552 auto renderTextField = AceType::DynamicCast<RenderTextField>(GetChildren().front());
553 if (renderTextField) {
554 renderTextField->SetOverlayColor(hoverColor_);
555 renderTextField->MarkNeedRender();
556 }
557 }
558 return true;
559 }
560
CancelTextFieldHover()561 void RenderSearch::CancelTextFieldHover()
562 {
563 auto renderTextField = AceType::DynamicCast<RenderTextField>(GetChildren().front());
564 if (renderTextField) {
565 renderTextField->SetOverlayColor(Color::TRANSPARENT);
566 renderTextField->MarkNeedRender();
567 }
568 }
569
HandleMouseEvent(const MouseEvent & event)570 bool RenderSearch::HandleMouseEvent(const MouseEvent& event)
571 {
572 MouseInfo info;
573 info.SetButton(event.button);
574 info.SetAction(event.action);
575 info.SetGlobalLocation(event.GetOffset());
576 info.SetLocalLocation(event.GetOffset() - Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY()));
577 info.SetScreenLocation(event.GetScreenOffset());
578 info.SetTimeStamp(event.time);
579 auto lowBound = searchReactRect_.GetOffset().GetX();
580 auto upBound = searchReactRect_.GetOffset().GetX() + searchReactRect_.GetSize().Width();
581 RefPtr mouseStyle = MouseStyle::CreateMouseStyle();
582 auto context = GetContext().Upgrade();
583 auto windowId = context->GetWindowId();
584 int32_t curPointerStyle = 0;
585
586 if (info.GetLocalLocation().GetX() >= lowBound && info.GetLocalLocation().GetX() <= upBound) {
587 isInSearchButton_ = true;
588 } else {
589 isInSearchButton_ = false;
590 }
591 if (preIsInSearchButton_ != isInSearchButton_) {
592 preIsInSearchButton_ = isInSearchButton_;
593 if (isInSearchButton_) {
594 MouseFormat defaultStyle = MouseFormat::DEFAULT;
595 mouseStyle->SetPointerStyle(windowId, defaultStyle);
596 } else {
597 MouseFormat textCursorStyle = MouseFormat::TEXT_CURSOR;
598 mouseStyle->SetPointerStyle(windowId, textCursorStyle);
599 }
600 }
601 MouseFormat hopenPointStyle = isInSearchButton_ ? MouseFormat::DEFAULT : MouseFormat::TEXT_CURSOR;
602 if (mouseStyle->GetPointerStyle(windowId, curPointerStyle) != -1 && (int32_t)hopenPointStyle != curPointerStyle) {
603 mouseStyle->SetPointerStyle(windowId, hopenPointStyle);
604 isInSearchButton_ = hopenPointStyle == MouseFormat::DEFAULT ? true : false;
605 }
606 return true;
607 }
608
HandleMouseHoverEvent(MouseState mouseState)609 void RenderSearch::HandleMouseHoverEvent(MouseState mouseState) {}
610
611 } // namespace OHOS::Ace
612