• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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