1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/select_overlay/select_overlay_pattern.h"
17
18 #include <algorithm>
19
20 #include "base/geometry/dimension.h"
21 #include "base/geometry/dimension_rect.h"
22 #include "base/geometry/ng/offset_t.h"
23 #include "base/geometry/ng/point_t.h"
24 #include "base/geometry/ng/rect_t.h"
25 #include "base/geometry/offset.h"
26 #include "base/utils/utils.h"
27 #include "core/components/menu/menu_component.h"
28 #include "core/components/text_overlay/text_overlay_theme.h"
29 #include "core/components_ng/base/ui_node.h"
30 #include "core/components_ng/pattern/menu/menu_layout_property.h"
31 #include "core/components_ng/pattern/select_overlay/select_overlay_node.h"
32 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
33 #include "core/components_ng/property/property.h"
34 #include "core/components_ng/property/safe_area_insets.h"
35 #include "core/pipeline/base/constants.h"
36 #include "core/pipeline_ng/pipeline_context.h"
37
38 namespace OHOS::Ace::NG {
39 namespace {
40 constexpr uint32_t HIDDEN_HANDLE_TIMER_MS = 4000; // 4000ms
41 } // namespace
42
OnAttachToFrameNode()43 void SelectOverlayPattern::OnAttachToFrameNode()
44 {
45 auto host = GetHost();
46 CHECK_NULL_VOID(host);
47 host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
48 host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
49
50 UpdateHandleHotZone();
51 auto gesture = host->GetOrCreateGestureEventHub();
52 gesture->SetHitTestMode(info_->hitTestMode);
53
54 clickEvent_ = MakeRefPtr<ClickEvent>([weak = WeakClaim(this)](GestureEvent& info) {
55 auto pattern = weak.Upgrade();
56 CHECK_NULL_VOID(pattern);
57 pattern->HandleOnClick(info);
58 });
59 if (info_->isSingleHandle) {
60 gesture->AddClickEvent(clickEvent_);
61 }
62 auto panStart = [weak = WeakClaim(this)](GestureEvent& info) {
63 auto pattern = weak.Upgrade();
64 CHECK_NULL_VOID(pattern);
65 pattern->HandlePanStart(info);
66 };
67 auto panUpdate = [weak = WeakClaim(this)](GestureEvent& info) {
68 auto pattern = weak.Upgrade();
69 CHECK_NULL_VOID(pattern);
70 pattern->HandlePanMove(info);
71 };
72 auto panEnd = [weak = WeakClaim(this)](GestureEvent& info) {
73 auto pattern = weak.Upgrade();
74 CHECK_NULL_VOID(pattern);
75 pattern->HandlePanEnd(info);
76 };
77 auto panCancel = [weak = WeakClaim(this)]() {
78 auto pattern = weak.Upgrade();
79 CHECK_NULL_VOID(pattern);
80 pattern->HandlePanCancel();
81 };
82 panEvent_ =
83 MakeRefPtr<PanEvent>(std::move(panStart), std::move(panUpdate), std::move(panEnd), std::move(panCancel));
84 gesture->AddPanEvent(panEvent_, { PanDirection::ALL }, 1, DEFAULT_PAN_DISTANCE);
85
86 auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
87 auto pattern = weak.Upgrade();
88 if (pattern) {
89 pattern->HandleTouchEvent(info);
90 }
91 };
92 touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
93 gesture->AddTouchEvent(touchEvent_);
94
95 if (info_->isSingleHandle && !info_->isHandleLineShow) {
96 StartHiddenHandleTask();
97 }
98 }
99
OnDetachFromFrameNode(FrameNode *)100 void SelectOverlayPattern::OnDetachFromFrameNode(FrameNode* /*frameNode*/)
101 {
102 if (info_->onClose) {
103 info_->onClose(closedByGlobalTouchEvent_);
104 closedByGlobalTouchEvent_ = false;
105 }
106 }
107
AddMenuResponseRegion(std::vector<DimensionRect> & responseRegion)108 void SelectOverlayPattern::AddMenuResponseRegion(std::vector<DimensionRect>& responseRegion)
109 {
110 auto layoutProps = GetLayoutProperty<LayoutProperty>();
111 CHECK_NULL_VOID(layoutProps);
112 float safeAreaInsetsLeft = 0.0f;
113 float safeAreaInsetsTop = 0.0f;
114 auto&& safeAreaInsets = layoutProps->GetSafeAreaInsets();
115 if (safeAreaInsets) {
116 safeAreaInsetsLeft = static_cast<float>(safeAreaInsets->left_.end);
117 safeAreaInsetsTop = static_cast<float>(safeAreaInsets->top_.end);
118 }
119 const auto& children = GetHost()->GetChildren();
120 for (const auto& it : children) {
121 auto child = DynamicCast<FrameNode>(it);
122 if (child == nullptr) {
123 continue;
124 }
125 auto frameRect = child->GetGeometryNode()->GetFrameRect();
126 // rect is relative to window
127 auto rect = Rect(frameRect.GetX() + safeAreaInsetsLeft, frameRect.GetY() + safeAreaInsetsTop, frameRect.Width(),
128 frameRect.Height());
129
130 DimensionRect region;
131 region.SetSize({ Dimension(rect.GetSize().Width()), Dimension(rect.GetSize().Height()) });
132 region.SetOffset(DimensionOffset(Offset(rect.GetOffset().GetX(), rect.GetOffset().GetY())));
133
134 responseRegion.emplace_back(region);
135 }
136 }
137
UpdateHandleHotZone()138 void SelectOverlayPattern::UpdateHandleHotZone()
139 {
140 auto host = GetHost();
141 CHECK_NULL_VOID(host);
142 auto pipeline = PipelineContext::GetCurrentContext();
143 CHECK_NULL_VOID(pipeline);
144 auto firstHandle = info_->firstHandle.paintRect;
145 auto secondHandle = info_->secondHandle.paintRect;
146
147 auto theme = pipeline->GetTheme<TextOverlayTheme>();
148 CHECK_NULL_VOID(theme);
149 auto hotZone = theme->GetHandleHotZoneRadius().ConvertToPx();
150 firstHandleRegion_.SetSize({ hotZone * 2, hotZone * 2 });
151 auto firstHandleOffsetX = (firstHandle.Left() + firstHandle.Right()) / 2;
152 secondHandleRegion_.SetSize({ hotZone * 2, hotZone * 2 });
153 auto secondHandleOffsetX = (secondHandle.Left() + secondHandle.Right()) / 2;
154 std::vector<DimensionRect> responseRegion;
155 if (info_->isSingleHandle) {
156 if (!info_->firstHandle.isShow && info_->secondHandle.isShow) {
157 // Use the second handle to make a single handle.
158 auto secondHandleOffsetY = secondHandle.Bottom();
159 secondHandleRegion_.SetOffset({ secondHandleOffsetX - hotZone, secondHandleOffsetY });
160 DimensionRect secondHandleRegion;
161 secondHandleRegion.SetSize({ Dimension(secondHandleRegion_.GetSize().Width()),
162 Dimension(secondHandleRegion_.GetSize().Height()) });
163 secondHandleRegion.SetOffset(DimensionOffset(
164 Offset(secondHandleRegion_.GetOffset().GetX(), secondHandleRegion_.GetOffset().GetY())));
165 responseRegion.emplace_back(secondHandleRegion);
166 host->GetOrCreateGestureEventHub()->SetResponseRegion(responseRegion);
167 } else {
168 // Use the first handle to make a single handle.
169 auto firstHandleOffsetY = firstHandle.Bottom();
170 firstHandleRegion_.SetOffset({ firstHandleOffsetX - hotZone, firstHandleOffsetY });
171 DimensionRect firstHandleRegion;
172 firstHandleRegion.SetSize(
173 { Dimension(firstHandleRegion_.GetSize().Width()), Dimension(firstHandleRegion_.GetSize().Height()) });
174 firstHandleRegion.SetOffset(
175 DimensionOffset(Offset(firstHandleRegion_.GetOffset().GetX(), firstHandleRegion_.GetOffset().GetY())));
176 responseRegion.emplace_back(firstHandleRegion);
177 host->GetOrCreateGestureEventHub()->SetResponseRegion(responseRegion);
178 }
179 return;
180 }
181 if (info_->handleReverse) {
182 auto firstHandleOffsetY = firstHandle.Bottom();
183 firstHandleRegion_.SetOffset({ firstHandleOffsetX - hotZone, firstHandleOffsetY });
184 auto secondHandleOffsetY = secondHandle.Top();
185 secondHandleRegion_.SetOffset({ secondHandleOffsetX - hotZone, secondHandleOffsetY - hotZone * 2 });
186 } else {
187 auto firstHandleOffsetY = firstHandle.Top();
188 firstHandleRegion_.SetOffset({ firstHandleOffsetX - hotZone, firstHandleOffsetY - hotZone * 2 });
189 auto secondHandleOffsetY = secondHandle.Bottom();
190 secondHandleRegion_.SetOffset({ secondHandleOffsetX - hotZone, secondHandleOffsetY });
191 }
192 DimensionRect firstHandleRegion;
193 firstHandleRegion.SetSize(
194 { Dimension(firstHandleRegion_.GetSize().Width()), Dimension(firstHandleRegion_.GetSize().Height()) });
195 firstHandleRegion.SetOffset(
196 DimensionOffset(Offset(firstHandleRegion_.GetOffset().GetX(), firstHandleRegion_.GetOffset().GetY())));
197 responseRegion.emplace_back(firstHandleRegion);
198 DimensionRect secondHandleRegion;
199 secondHandleRegion.SetSize(
200 { Dimension(secondHandleRegion_.GetSize().Width()), Dimension(secondHandleRegion_.GetSize().Height()) });
201 secondHandleRegion.SetOffset(
202 DimensionOffset(Offset(secondHandleRegion_.GetOffset().GetX(), secondHandleRegion_.GetOffset().GetY())));
203 responseRegion.emplace_back(secondHandleRegion);
204 if (IsCustomMenu()) {
205 AddMenuResponseRegion(responseRegion);
206 }
207
208 host->GetOrCreateGestureEventHub()->SetResponseRegion(responseRegion);
209 }
210
HandleOnClick(GestureEvent &)211 void SelectOverlayPattern::HandleOnClick(GestureEvent& /*info*/)
212 {
213 if (!info_->isSingleHandle) {
214 return;
215 }
216 auto host = DynamicCast<SelectOverlayNode>(GetHost());
217 CHECK_NULL_VOID(host);
218 if (!info_->menuInfo.menuDisable) {
219 if (!info_->isHandleLineShow) {
220 info_->menuInfo.menuIsShow = !info_->menuInfo.menuIsShow;
221 host->UpdateToolBar(false);
222
223 StopHiddenHandleTask();
224 StartHiddenHandleTask();
225 } else if (!info_->menuInfo.menuIsShow) {
226 info_->menuInfo.menuIsShow = true;
227 host->UpdateToolBar(false);
228 }
229 info_->menuInfo.singleHandleMenuIsShow = info_->menuInfo.menuIsShow;
230 }
231 }
232
HandleTouchEvent(const TouchEventInfo & info)233 void SelectOverlayPattern::HandleTouchEvent(const TouchEventInfo& info)
234 {
235 const auto& changedPoint = info.GetChangedTouches().front();
236 if (info_->onTouchDown && changedPoint.GetTouchType() == TouchType::DOWN) {
237 info_->onTouchDown(info);
238 } else if (info_->onTouchDown && changedPoint.GetTouchType() == TouchType::UP) {
239 info_->onTouchUp(info);
240 } else if (info_->onTouchMove && changedPoint.GetTouchType() == TouchType::MOVE) {
241 info_->onTouchMove(info);
242 }
243 if (IsCustomMenu()) {
244 MenuWrapperPattern::OnTouchEvent(info);
245 }
246 }
247
HandlePanStart(GestureEvent & info)248 void SelectOverlayPattern::HandlePanStart(GestureEvent& info)
249 {
250 PointF point = { info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY() };
251 if (firstHandleRegion_.IsInRegion(point) && info.GetSourceDevice() != SourceType::MOUSE) {
252 firstHandleDrag_ = true;
253 secondHandleDrag_ = false;
254 if (info_->onHandleMoveStart) {
255 info_->onHandleMoveStart(firstHandleDrag_);
256 }
257 } else if (secondHandleRegion_.IsInRegion(point) && info.GetSourceDevice() != SourceType::MOUSE) {
258 firstHandleDrag_ = false;
259 secondHandleDrag_ = true;
260 if (info_->onHandleMoveStart) {
261 info_->onHandleMoveStart(firstHandleDrag_);
262 }
263 } else {
264 LOGW("the point is not in drag area");
265 return;
266 }
267
268 auto host = DynamicCast<SelectOverlayNode>(GetHost());
269 CHECK_NULL_VOID(host);
270 orignMenuIsShow_ = info_->menuInfo.menuIsShow;
271 if (info_->menuInfo.menuIsShow) {
272 info_->menuInfo.menuIsShow = false;
273 host->UpdateToolBar(false);
274 }
275 if (info_->isSingleHandle && !info_->isHandleLineShow) {
276 StopHiddenHandleTask();
277 }
278 }
279
HandlePanMove(GestureEvent & info)280 void SelectOverlayPattern::HandlePanMove(GestureEvent& info)
281 {
282 auto host = DynamicCast<SelectOverlayNode>(GetHost());
283 CHECK_NULL_VOID(host);
284 const auto& offset = OffsetF(info.GetDelta().GetX(), info.GetDelta().GetY());
285 if (firstHandleDrag_) {
286 firstHandleRegion_ += offset;
287 info_->firstHandle.paintRect += offset;
288 CheckHandleReverse();
289 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
290 if (info_->onHandleMove) {
291 info_->onHandleMove(info_->firstHandle.paintRect, true);
292 }
293 } else if (secondHandleDrag_) {
294 secondHandleRegion_ += offset;
295 info_->secondHandle.paintRect += offset;
296 CheckHandleReverse();
297 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
298 if (info_->onHandleMove) {
299 info_->onHandleMove(info_->secondHandle.paintRect, false);
300 }
301 } else {
302 LOGW("the move point is not in drag area");
303 }
304 auto context = PipelineContext::GetCurrentContext();
305 CHECK_NULL_VOID(context);
306 if (host->IsLayoutDirtyMarked()) {
307 context->AddDirtyLayoutNode(host);
308 }
309 }
310
HandlePanEnd(GestureEvent &)311 void SelectOverlayPattern::HandlePanEnd(GestureEvent& /*info*/)
312 {
313 auto host = DynamicCast<SelectOverlayNode>(GetHost());
314 CHECK_NULL_VOID(host);
315 if (!info_->menuInfo.menuIsShow) {
316 info_->menuInfo.menuIsShow = orignMenuIsShow_;
317 host->UpdateToolBar(false);
318 }
319 if (firstHandleDrag_) {
320 if (info_->onHandleMoveDone) {
321 info_->onHandleMoveDone(info_->firstHandle.paintRect, true);
322 }
323 firstHandleDrag_ = false;
324 } else if (secondHandleDrag_) {
325 if (info_->onHandleMoveDone) {
326 info_->onHandleMoveDone(info_->secondHandle.paintRect, false);
327 }
328 secondHandleDrag_ = false;
329 }
330 if (info_->isSingleHandle && !info_->isHandleLineShow) {
331 StartHiddenHandleTask();
332 }
333 }
334
HandlePanCancel()335 void SelectOverlayPattern::HandlePanCancel()
336 {
337 GestureEvent info;
338 HandlePanEnd(info);
339 }
340
CheckHandleReverse()341 void SelectOverlayPattern::CheckHandleReverse()
342 {
343 bool handleReverseChanged = false;
344 if (IsHandlesInSameLine()) {
345 if (info_->firstHandle.paintRect.Left() > info_->secondHandle.paintRect.Left()) {
346 if (!info_->handleReverse) {
347 info_->handleReverse = true;
348 handleReverseChanged = true;
349 }
350 } else {
351 if (info_->handleReverse) {
352 info_->handleReverse = false;
353 handleReverseChanged = true;
354 }
355 }
356 } else if (GreatNotEqual(info_->firstHandle.paintRect.Top(), info_->secondHandle.paintRect.Top())) {
357 if (!info_->handleReverse) {
358 info_->handleReverse = true;
359 handleReverseChanged = true;
360 }
361 } else {
362 if (info_->handleReverse) {
363 info_->handleReverse = false;
364 handleReverseChanged = true;
365 }
366 }
367 if (handleReverseChanged && info_->onHandleReverse) {
368 info_->onHandleReverse(info_->handleReverse);
369 }
370 }
371
IsHandlesInSameLine()372 bool SelectOverlayPattern::IsHandlesInSameLine()
373 {
374 float lowerHandleTop = 0.0f;
375 RectF heigherHandleRect;
376 if (GreatNotEqual(info_->firstHandle.paintRect.Top(), info_->secondHandle.paintRect.Top())) {
377 lowerHandleTop = info_->firstHandle.paintRect.Top() + 0.5f;
378 heigherHandleRect = info_->secondHandle.paintRect;
379 } else {
380 lowerHandleTop = info_->secondHandle.paintRect.Top() + 0.5f;
381 heigherHandleRect = info_->firstHandle.paintRect;
382 }
383 return GreatNotEqual(lowerHandleTop, heigherHandleRect.Top())
384 && LessNotEqual(lowerHandleTop, heigherHandleRect.Bottom());
385 }
386
SetHandleReverse(bool reverse)387 void SelectOverlayPattern::SetHandleReverse(bool reverse)
388 {
389 info_->handleReverse = reverse;
390 UpdateHandleHotZone();
391 auto host = DynamicCast<SelectOverlayNode>(GetHost());
392 CHECK_NULL_VOID(host);
393 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
394 }
395
SetSelectRegionVisible(bool isSelectRegionVisible)396 void SelectOverlayPattern::SetSelectRegionVisible(bool isSelectRegionVisible)
397 {
398 if (info_->isSelectRegionVisible != isSelectRegionVisible) {
399 info_->isSelectRegionVisible = isSelectRegionVisible;
400 auto host = DynamicCast<SelectOverlayNode>(GetHost());
401 CHECK_NULL_VOID(host);
402 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
403 }
404 }
405
UpdateFirstSelectHandleInfo(const SelectHandleInfo & info)406 void SelectOverlayPattern::UpdateFirstSelectHandleInfo(const SelectHandleInfo& info)
407 {
408 if (info_->firstHandle == info) {
409 return;
410 }
411 info_->firstHandle = info;
412 CheckHandleReverse();
413 UpdateHandleHotZone();
414 auto host = DynamicCast<SelectOverlayNode>(GetHost());
415 CHECK_NULL_VOID(host);
416 if (info.needLayout) {
417 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
418 } else {
419 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
420 }
421 }
422
UpdateSecondSelectHandleInfo(const SelectHandleInfo & info)423 void SelectOverlayPattern::UpdateSecondSelectHandleInfo(const SelectHandleInfo& info)
424 {
425 if (info_->secondHandle == info) {
426 return;
427 }
428 info_->secondHandle = info;
429 CheckHandleReverse();
430 UpdateHandleHotZone();
431 auto host = DynamicCast<SelectOverlayNode>(GetHost());
432 CHECK_NULL_VOID(host);
433 if (info.needLayout) {
434 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
435 } else {
436 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
437 }
438 }
439
UpdateFirstAndSecondHandleInfo(const SelectHandleInfo & firstInfo,const SelectHandleInfo & secondInfo)440 void SelectOverlayPattern::UpdateFirstAndSecondHandleInfo(
441 const SelectHandleInfo& firstInfo, const SelectHandleInfo& secondInfo)
442 {
443 if (info_->firstHandle == firstInfo && info_->secondHandle == secondInfo) {
444 return;
445 }
446 if (info_->firstHandle != firstInfo) {
447 info_->firstHandle = firstInfo;
448 }
449 if (info_->secondHandle != secondInfo) {
450 info_->secondHandle = secondInfo;
451 }
452 CheckHandleReverse();
453 UpdateHandleHotZone();
454 auto host = DynamicCast<SelectOverlayNode>(GetHost());
455 CHECK_NULL_VOID(host);
456 host->UpdateToolBar(false);
457 }
458
UpdateSelectMenuInfo(const SelectMenuInfo & info)459 void SelectOverlayPattern::UpdateSelectMenuInfo(const SelectMenuInfo& info)
460 {
461 auto host = DynamicCast<SelectOverlayNode>(GetHost());
462 CHECK_NULL_VOID(host);
463 auto itemChanged = info_->menuInfo.IsIconChanged(info);
464 info_->menuInfo = info;
465 host->UpdateToolBar(itemChanged);
466 }
467
UpdateShowArea(const RectF & area)468 void SelectOverlayPattern::UpdateShowArea(const RectF& area)
469 {
470 if (info_->showArea != area) {
471 info_->showArea = area;
472 }
473 auto host = GetHost();
474 CHECK_NULL_VOID(host);
475 host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
476 }
477
UpdateSelectMenuInfo(std::function<void (SelectMenuInfo & menuInfo)> updateAction)478 void SelectOverlayPattern::UpdateSelectMenuInfo(std::function<void(SelectMenuInfo& menuInfo)> updateAction)
479 {
480 if (updateAction) {
481 SelectMenuInfo shadowMenuInfo = info_->menuInfo;
482 updateAction(shadowMenuInfo);
483 UpdateSelectMenuInfo(shadowMenuInfo);
484 }
485 }
486
ShowOrHiddenMenu(bool isHidden,bool noAnimation)487 void SelectOverlayPattern::ShowOrHiddenMenu(bool isHidden, bool noAnimation)
488 {
489 auto host = DynamicCast<SelectOverlayNode>(GetHost());
490 CHECK_NULL_VOID(host);
491 if (info_->menuInfo.menuIsShow && isHidden) {
492 info_->menuInfo.menuIsShow = false;
493 host->UpdateToolBar(false, noAnimation);
494 } else if (!info_->menuInfo.menuIsShow && !isHidden &&
495 (info_->firstHandle.isShow || info_->secondHandle.isShow || info_->isSelectRegionVisible ||
496 (info_->isNewAvoid && !info_->isSingleHandle))) {
497 info_->menuInfo.menuIsShow = true;
498 host->UpdateToolBar(false, noAnimation);
499 }
500 }
501
DisableMenu(bool isDisabled)502 void SelectOverlayPattern::DisableMenu(bool isDisabled)
503 {
504 info_->menuInfo.menuDisable = isDisabled;
505 auto host = DynamicCast<SelectOverlayNode>(GetHost());
506 CHECK_NULL_VOID(host);
507 host->UpdateToolBar(false);
508 }
509
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)510 bool SelectOverlayPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
511 {
512 UpdateHandleHotZone();
513 if (config.skipMeasure || dirty->SkipMeasureContent()) {
514 return false;
515 }
516 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
517 CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
518 auto selectOverlayLayoutAlgorithm =
519 DynamicCast<SelectOverlayLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
520 CHECK_NULL_RETURN(selectOverlayLayoutAlgorithm, false);
521 defaultMenuEndOffset_ = selectOverlayLayoutAlgorithm->GetDefaultMenuEndOffset();
522 menuWidth_ = selectOverlayLayoutAlgorithm->GetMenuWidth();
523 menuHeight_ = selectOverlayLayoutAlgorithm->GetMenuHeight();
524 hasExtensionMenu_ = selectOverlayLayoutAlgorithm->GetHasExtensionMenu();
525 if (IsCustomMenu()) {
526 MenuWrapperPattern::CheckAndShowAnimation();
527 }
528 return true;
529 }
530
IsMenuShow()531 bool SelectOverlayPattern::IsMenuShow()
532 {
533 CHECK_NULL_RETURN(info_, false);
534 return info_->menuInfo.menuIsShow;
535 }
536
IsSingleHandleMenuShow()537 bool SelectOverlayPattern::IsSingleHandleMenuShow()
538 {
539 CHECK_NULL_RETURN(info_, false);
540 return info_->menuInfo.singleHandleMenuIsShow;
541 }
542
IsHandleShow()543 bool SelectOverlayPattern::IsHandleShow()
544 {
545 CHECK_NULL_RETURN(info_, false);
546 return info_->firstHandle.isShow || info_->secondHandle.isShow;
547 }
548
IsSingleHandle()549 bool SelectOverlayPattern::IsSingleHandle()
550 {
551 CHECK_NULL_RETURN(info_, false);
552 return info_->isSingleHandle;
553 }
554
StartHiddenHandleTask(bool isDelay)555 void SelectOverlayPattern::StartHiddenHandleTask(bool isDelay)
556 {
557 auto host = GetHost();
558 CHECK_NULL_VOID(host);
559 auto context = host->GetContext();
560 CHECK_NULL_VOID(context);
561 auto taskExecutor = context->GetTaskExecutor();
562 CHECK_NULL_VOID(taskExecutor);
563 auto weak = WeakClaim(this);
564 hiddenHandleTask_.Reset([weak] {
565 auto client = weak.Upgrade();
566 CHECK_NULL_VOID(client);
567 client->HiddenHandle();
568 });
569 if (isDelay) {
570 taskExecutor->PostDelayedTask(hiddenHandleTask_, TaskExecutor::TaskType::UI, HIDDEN_HANDLE_TIMER_MS);
571 } else {
572 taskExecutor->PostTask(hiddenHandleTask_, TaskExecutor::TaskType::UI);
573 }
574 }
575
HiddenHandle()576 void SelectOverlayPattern::HiddenHandle()
577 {
578 hiddenHandleTask_.Cancel();
579 isHiddenHandle_ = true;
580 auto host = DynamicCast<SelectOverlayNode>(GetHost());
581 CHECK_NULL_VOID(host);
582 host->GetOrCreateGestureEventHub()->RemoveClickEvent(clickEvent_);
583 host->GetOrCreateGestureEventHub()->RemovePanEvent(panEvent_);
584 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
585 }
586
StopHiddenHandleTask()587 void SelectOverlayPattern::StopHiddenHandleTask()
588 {
589 hiddenHandleTask_.Cancel();
590 }
591
UpdateSelectArea(const RectF & selectArea)592 void SelectOverlayPattern::UpdateSelectArea(const RectF& selectArea)
593 {
594 info_->selectArea = selectArea;
595 }
596 } // namespace OHOS::Ace::NG
597