• 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/gestures/gesture_info.h"
36 #include "core/pipeline/base/constants.h"
37 #include "core/pipeline_ng/pipeline_context.h"
38 
39 namespace OHOS::Ace::NG {
40 namespace {
41 constexpr uint32_t HIDDEN_HANDLE_TIMER_MS = 4000; // 4000ms
42 } // namespace
43 
OnAttachToFrameNode()44 void SelectOverlayPattern::OnAttachToFrameNode()
45 {
46     auto host = GetHost();
47     CHECK_NULL_VOID(host);
48     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
49     host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
50 
51     UpdateHandleHotZone();
52     auto gesture = host->GetOrCreateGestureEventHub();
53     gesture->SetHitTestMode(info_->hitTestMode);
54 
55     clickEvent_ = MakeRefPtr<ClickEvent>([weak = WeakClaim(this)](GestureEvent& info) {
56         auto pattern = weak.Upgrade();
57         CHECK_NULL_VOID(pattern);
58         pattern->HandleOnClick(info);
59     });
60     if (info_->isSingleHandle) {
61         gesture->AddClickEvent(clickEvent_);
62     }
63     auto panStart = [weak = WeakClaim(this)](GestureEvent& info) {
64         auto pattern = weak.Upgrade();
65         CHECK_NULL_VOID(pattern);
66         pattern->HandlePanStart(info);
67     };
68     auto panUpdate = [weak = WeakClaim(this)](GestureEvent& info) {
69         auto pattern = weak.Upgrade();
70         CHECK_NULL_VOID(pattern);
71         pattern->HandlePanMove(info);
72     };
73     auto panEnd = [weak = WeakClaim(this)](GestureEvent& info) {
74         auto pattern = weak.Upgrade();
75         CHECK_NULL_VOID(pattern);
76         pattern->HandlePanEnd(info);
77     };
78     auto panCancel = [weak = WeakClaim(this)]() {
79         auto pattern = weak.Upgrade();
80         CHECK_NULL_VOID(pattern);
81         pattern->HandlePanCancel();
82     };
83     panEvent_ =
84         MakeRefPtr<PanEvent>(std::move(panStart), std::move(panUpdate), std::move(panEnd), std::move(panCancel));
85     gesture->SetPanEvent(panEvent_, { PanDirection::ALL }, 1, DEFAULT_PAN_DISTANCE);
86 
87     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
88         auto pattern = weak.Upgrade();
89         if (pattern) {
90             pattern->HandleTouchEvent(info);
91         }
92     };
93     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
94     gesture->AddTouchEvent(touchEvent_);
95 
96     if (info_->isSingleHandle && !info_->isHandleLineShow) {
97         StartHiddenHandleTask();
98     }
99 }
100 
OnDetachFromFrameNode(FrameNode *)101 void SelectOverlayPattern::OnDetachFromFrameNode(FrameNode* /*frameNode*/)
102 {
103     if (info_->onClose) {
104         info_->onClose(closedByGlobalTouchEvent_);
105         closedByGlobalTouchEvent_ = false;
106     }
107 }
108 
BeforeCreateLayoutWrapper()109 void SelectOverlayPattern::BeforeCreateLayoutWrapper()
110 {
111     if (!IsCustomMenu()) {
112         return;
113     }
114     auto menu = DynamicCast<FrameNode>(GetHost()->GetFirstChild());
115     CHECK_NULL_VOID(menu);
116     auto layoutProperty = menu->GetLayoutProperty<MenuLayoutProperty>();
117     CHECK_NULL_VOID(layoutProperty);
118 
119     auto pipeline = PipelineContext::GetCurrentContext();
120     CHECK_NULL_VOID(pipeline);
121     auto theme = pipeline->GetTheme<TextOverlayTheme>();
122     CHECK_NULL_VOID(theme);
123 
124     // Calculate the spacing with text and handle, menu is fixed up the handle and text.
125     double menuSpacing = theme->GetMenuSpacingWithText().ConvertToPx() + theme->GetHandleDiameter().ConvertToPx();
126     // Get bound rect of handles
127     RectF handleBound = info_->firstHandle.paintRect.CombineRectT(info_->secondHandle.paintRect);
128     // Bound rect plus top and bottom padding
129     RectF safeArea(handleBound.GetX(), handleBound.GetY() - menuSpacing, handleBound.Width(),
130         handleBound.Height() + menuSpacing * 2);
131 
132     layoutProperty->UpdateTargetSize(safeArea.GetSize());
133     OffsetF offset(safeArea.GetX(), safeArea.Bottom());
134     layoutProperty->UpdateMenuOffset(offset);
135 }
136 
AddMenuResponseRegion(std::vector<DimensionRect> & responseRegion)137 void SelectOverlayPattern::AddMenuResponseRegion(std::vector<DimensionRect>& responseRegion)
138 {
139     auto layoutProps = GetLayoutProperty<LayoutProperty>();
140     CHECK_NULL_VOID(layoutProps);
141     float safeAreaInsetsLeft = 0.0f;
142     float safeAreaInsetsTop = 0.0f;
143     auto&& safeAreaInsets = layoutProps->GetSafeAreaInsets();
144     if (safeAreaInsets) {
145         safeAreaInsetsLeft = static_cast<float>(safeAreaInsets->left_.end);
146         safeAreaInsetsTop = static_cast<float>(safeAreaInsets->top_.end);
147     }
148     const auto& children = GetHost()->GetChildren();
149     for (const auto& it : children) {
150         auto child = DynamicCast<FrameNode>(it);
151         if (child == nullptr) {
152             continue;
153         }
154         auto frameRect = child->GetGeometryNode()->GetFrameRect();
155         // rect is relative to window
156         auto rect = Rect(frameRect.GetX() + safeAreaInsetsLeft, frameRect.GetY() + safeAreaInsetsTop, frameRect.Width(),
157             frameRect.Height());
158 
159         DimensionRect region;
160         region.SetSize({ Dimension(rect.GetSize().Width()), Dimension(rect.GetSize().Height()) });
161         region.SetOffset(DimensionOffset(Offset(rect.GetOffset().GetX(), rect.GetOffset().GetY())));
162 
163         responseRegion.emplace_back(region);
164     }
165 }
166 
UpdateHandleHotZone()167 void SelectOverlayPattern::UpdateHandleHotZone()
168 {
169     auto host = GetHost();
170     CHECK_NULL_VOID(host);
171     auto pipeline = PipelineContext::GetCurrentContext();
172     CHECK_NULL_VOID(pipeline);
173     auto firstHandle = info_->firstHandle.paintRect;
174     auto secondHandle = info_->secondHandle.paintRect;
175 
176     auto theme = pipeline->GetTheme<TextOverlayTheme>();
177     CHECK_NULL_VOID(theme);
178     auto hotZone = theme->GetHandleHotZoneRadius().ConvertToPx();
179     firstHandleRegion_.SetSize({ hotZone * 2, hotZone * 2 });
180     auto firstHandleOffsetX = (firstHandle.Left() + firstHandle.Right()) / 2;
181     secondHandleRegion_.SetSize({ hotZone * 2, hotZone * 2 });
182     auto secondHandleOffsetX = (secondHandle.Left() + secondHandle.Right()) / 2;
183     std::vector<DimensionRect> responseRegion;
184     if (info_->isSingleHandle) {
185         if (!info_->firstHandle.isShow && info_->secondHandle.isShow) {
186             // Use the second handle to make a single handle.
187             auto secondHandleOffsetY = secondHandle.Bottom();
188             secondHandleRegion_.SetOffset({ secondHandleOffsetX - hotZone, secondHandleOffsetY });
189             DimensionRect secondHandleRegion;
190             secondHandleRegion.SetSize({ Dimension(secondHandleRegion_.GetSize().Width()),
191                 Dimension(secondHandleRegion_.GetSize().Height()) });
192             secondHandleRegion.SetOffset(DimensionOffset(
193                 Offset(secondHandleRegion_.GetOffset().GetX(), secondHandleRegion_.GetOffset().GetY())));
194             responseRegion.emplace_back(secondHandleRegion);
195             host->GetOrCreateGestureEventHub()->SetResponseRegion(responseRegion);
196         } else {
197             // Use the first handle to make a single handle.
198             auto firstHandleOffsetY = firstHandle.Bottom();
199             firstHandleRegion_.SetOffset({ firstHandleOffsetX - hotZone, firstHandleOffsetY });
200             DimensionRect firstHandleRegion;
201             firstHandleRegion.SetSize(
202                 { Dimension(firstHandleRegion_.GetSize().Width()), Dimension(firstHandleRegion_.GetSize().Height()) });
203             firstHandleRegion.SetOffset(
204                 DimensionOffset(Offset(firstHandleRegion_.GetOffset().GetX(), firstHandleRegion_.GetOffset().GetY())));
205             responseRegion.emplace_back(firstHandleRegion);
206             host->GetOrCreateGestureEventHub()->SetResponseRegion(responseRegion);
207         }
208         return;
209     }
210     if (info_->handleReverse) {
211         auto firstHandleOffsetY = firstHandle.Bottom();
212         firstHandleRegion_.SetOffset({ firstHandleOffsetX - hotZone, firstHandleOffsetY });
213         auto secondHandleOffsetY = secondHandle.Top();
214         secondHandleRegion_.SetOffset({ secondHandleOffsetX - hotZone, secondHandleOffsetY - hotZone * 2 });
215     } else {
216         auto firstHandleOffsetY = firstHandle.Top();
217         firstHandleRegion_.SetOffset({ firstHandleOffsetX - hotZone, firstHandleOffsetY - hotZone * 2 });
218         auto secondHandleOffsetY = secondHandle.Bottom();
219         secondHandleRegion_.SetOffset({ secondHandleOffsetX - hotZone, secondHandleOffsetY });
220     }
221     DimensionRect firstHandleRegion;
222     firstHandleRegion.SetSize(
223         { Dimension(firstHandleRegion_.GetSize().Width()), Dimension(firstHandleRegion_.GetSize().Height()) });
224     firstHandleRegion.SetOffset(
225         DimensionOffset(Offset(firstHandleRegion_.GetOffset().GetX(), firstHandleRegion_.GetOffset().GetY())));
226     responseRegion.emplace_back(firstHandleRegion);
227     DimensionRect secondHandleRegion;
228     secondHandleRegion.SetSize(
229         { Dimension(secondHandleRegion_.GetSize().Width()), Dimension(secondHandleRegion_.GetSize().Height()) });
230     secondHandleRegion.SetOffset(
231         DimensionOffset(Offset(secondHandleRegion_.GetOffset().GetX(), secondHandleRegion_.GetOffset().GetY())));
232     responseRegion.emplace_back(secondHandleRegion);
233     if (IsCustomMenu()) {
234         AddMenuResponseRegion(responseRegion);
235     }
236 
237     host->GetOrCreateGestureEventHub()->SetResponseRegion(responseRegion);
238 }
239 
HandleOnClick(GestureEvent &)240 void SelectOverlayPattern::HandleOnClick(GestureEvent& /*info*/)
241 {
242     if (!info_->isSingleHandle) {
243         return;
244     }
245     auto host = DynamicCast<SelectOverlayNode>(GetHost());
246     CHECK_NULL_VOID(host);
247     if (!info_->menuInfo.menuDisable) {
248         if (!info_->isHandleLineShow) {
249             info_->menuInfo.menuIsShow = !info_->menuInfo.menuIsShow;
250             host->UpdateToolBar(false);
251 
252             StopHiddenHandleTask();
253             StartHiddenHandleTask();
254         } else if (!info_->menuInfo.menuIsShow) {
255             info_->menuInfo.menuIsShow = true;
256             host->UpdateToolBar(false);
257         }
258     }
259 }
260 
HandleTouchEvent(const TouchEventInfo & info)261 void SelectOverlayPattern::HandleTouchEvent(const TouchEventInfo& info)
262 {
263     const auto& changedPoint = info.GetChangedTouches().front();
264     if (info_->onTouchDown && changedPoint.GetTouchType() == TouchType::DOWN) {
265         info_->onTouchDown(info);
266     } else if (info_->onTouchDown && changedPoint.GetTouchType() == TouchType::UP) {
267         info_->onTouchUp(info);
268     } else if (info_->onTouchMove && changedPoint.GetTouchType() == TouchType::MOVE) {
269         info_->onTouchMove(info);
270     }
271     if (IsCustomMenu()) {
272         MenuWrapperPattern::OnTouchEvent(info);
273     }
274 }
275 
HandlePanStart(GestureEvent & info)276 void SelectOverlayPattern::HandlePanStart(GestureEvent& info)
277 {
278     PointF point = { info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY() };
279     if (firstHandleRegion_.IsInRegion(point)) {
280         firstHandleDrag_ = true;
281         secondHandleDrag_ = false;
282         if (info_->onHandleMoveStart) {
283             info_->onHandleMoveStart(firstHandleDrag_);
284         }
285     } else if (secondHandleRegion_.IsInRegion(point)) {
286         firstHandleDrag_ = false;
287         secondHandleDrag_ = true;
288         if (info_->onHandleMoveStart) {
289             info_->onHandleMoveStart(firstHandleDrag_);
290         }
291     } else {
292         LOGW("the point is not in drag area");
293         return;
294     }
295 
296     auto host = DynamicCast<SelectOverlayNode>(GetHost());
297     CHECK_NULL_VOID(host);
298     orignMenuIsShow_ = info_->menuInfo.menuIsShow;
299     if (info_->menuInfo.menuIsShow) {
300         info_->menuInfo.menuIsShow = false;
301         host->UpdateToolBar(false);
302     }
303     if (info_->isSingleHandle && !info_->isHandleLineShow) {
304         StopHiddenHandleTask();
305     }
306 }
307 
HandlePanMove(GestureEvent & info)308 void SelectOverlayPattern::HandlePanMove(GestureEvent& info)
309 {
310     auto host = DynamicCast<SelectOverlayNode>(GetHost());
311     CHECK_NULL_VOID(host);
312     const auto& offset = OffsetF(info.GetDelta().GetX(), info.GetDelta().GetY());
313     if (firstHandleDrag_) {
314         firstHandleRegion_ += offset;
315         info_->firstHandle.paintRect += offset;
316         CheckHandleReverse();
317         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
318         if (info_->onHandleMove) {
319             info_->onHandleMove(info_->firstHandle.paintRect, true);
320         }
321     } else if (secondHandleDrag_) {
322         secondHandleRegion_ += offset;
323         info_->secondHandle.paintRect += offset;
324         CheckHandleReverse();
325         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
326         if (info_->onHandleMove) {
327             info_->onHandleMove(info_->secondHandle.paintRect, false);
328         }
329     } else {
330         LOGW("the move point is not in drag area");
331     }
332 }
333 
HandlePanEnd(GestureEvent &)334 void SelectOverlayPattern::HandlePanEnd(GestureEvent& /*info*/)
335 {
336     auto host = DynamicCast<SelectOverlayNode>(GetHost());
337     CHECK_NULL_VOID(host);
338     if (!info_->menuInfo.menuIsShow) {
339         info_->menuInfo.menuIsShow = orignMenuIsShow_;
340         host->UpdateToolBar(false);
341     }
342     if (firstHandleDrag_) {
343         if (info_->onHandleMoveDone) {
344             info_->onHandleMoveDone(info_->firstHandle.paintRect, true);
345         }
346         firstHandleDrag_ = false;
347     } else if (secondHandleDrag_) {
348         if (info_->onHandleMoveDone) {
349             info_->onHandleMoveDone(info_->secondHandle.paintRect, false);
350         }
351         secondHandleDrag_ = false;
352     }
353     if (info_->isSingleHandle && !info_->isHandleLineShow) {
354         StartHiddenHandleTask();
355     }
356 }
357 
HandlePanCancel()358 void SelectOverlayPattern::HandlePanCancel()
359 {
360     GestureEvent info;
361     HandlePanEnd(info);
362 }
363 
CheckHandleReverse()364 void SelectOverlayPattern::CheckHandleReverse()
365 {
366     bool handleReverseChanged = false;
367     double epsilon = std::max(info_->firstHandle.paintRect.Height(), info_->secondHandle.paintRect.Height());
368     epsilon = std::max(static_cast<double>(info_->singleLineHeight), epsilon);
369     if (NearEqual(info_->firstHandle.paintRect.Top(), info_->secondHandle.paintRect.Top(), epsilon)) {
370         if (info_->firstHandle.paintRect.Left() > info_->secondHandle.paintRect.Left()) {
371             if (!info_->handleReverse) {
372                 info_->handleReverse = true;
373                 handleReverseChanged = true;
374             }
375         } else {
376             if (info_->handleReverse) {
377                 info_->handleReverse = false;
378                 handleReverseChanged = true;
379             }
380         }
381     } else if (GreatNotEqual(info_->firstHandle.paintRect.Top(), info_->secondHandle.paintRect.Top())) {
382         if (!info_->handleReverse) {
383             info_->handleReverse = true;
384             handleReverseChanged = true;
385         }
386     } else {
387         if (info_->handleReverse) {
388             info_->handleReverse = false;
389             handleReverseChanged = true;
390         }
391     }
392     if (handleReverseChanged && info_->onHandleReverse) {
393         info_->onHandleReverse(info_->handleReverse);
394     }
395 }
396 
SetHandleReverse(bool reverse)397 void SelectOverlayPattern::SetHandleReverse(bool reverse)
398 {
399     info_->handleReverse = reverse;
400     UpdateHandleHotZone();
401     auto host = DynamicCast<SelectOverlayNode>(GetHost());
402     CHECK_NULL_VOID(host);
403     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
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 
ShowOrHiddenMenu(bool isHidden)478 void SelectOverlayPattern::ShowOrHiddenMenu(bool isHidden)
479 {
480     auto host = DynamicCast<SelectOverlayNode>(GetHost());
481     CHECK_NULL_VOID(host);
482     if (info_->menuInfo.menuIsShow && isHidden) {
483         info_->menuInfo.menuIsShow = false;
484         host->UpdateToolBar(false);
485     } else if (!info_->menuInfo.menuIsShow && !isHidden && (info_->firstHandle.isShow || info_->secondHandle.isShow)) {
486         info_->menuInfo.menuIsShow = true;
487         host->UpdateToolBar(false);
488     }
489 }
490 
DisableMenu(bool isDisabled)491 void SelectOverlayPattern::DisableMenu(bool isDisabled)
492 {
493     info_->menuInfo.menuDisable = isDisabled;
494     auto host = DynamicCast<SelectOverlayNode>(GetHost());
495     CHECK_NULL_VOID(host);
496     host->UpdateToolBar(false);
497 }
498 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)499 bool SelectOverlayPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
500 {
501     UpdateHandleHotZone();
502     if (config.skipMeasure || dirty->SkipMeasureContent()) {
503         return false;
504     }
505     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
506     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
507     auto selectOverlayLayoutAlgorithm =
508         DynamicCast<SelectOverlayLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
509     CHECK_NULL_RETURN(selectOverlayLayoutAlgorithm, false);
510     defaultMenuEndOffset_ = selectOverlayLayoutAlgorithm->GetDefaultMenuEndOffset();
511     menuWidth_ = selectOverlayLayoutAlgorithm->GetMenuWidth();
512     menuHeight_ = selectOverlayLayoutAlgorithm->GetMenuHeight();
513     hasExtensionMenu_ = selectOverlayLayoutAlgorithm->GetHasExtensionMenu();
514     if (IsCustomMenu()) {
515         MenuWrapperPattern::CheckAndShowAnimation();
516     }
517     return true;
518 }
519 
IsMenuShow()520 bool SelectOverlayPattern::IsMenuShow()
521 {
522     CHECK_NULL_RETURN(info_, false);
523     return info_->menuInfo.menuIsShow;
524 }
525 
IsHandleShow()526 bool SelectOverlayPattern::IsHandleShow()
527 {
528     CHECK_NULL_RETURN(info_, false);
529     return info_->firstHandle.isShow || info_->secondHandle.isShow;
530 }
531 
StartHiddenHandleTask()532 void SelectOverlayPattern::StartHiddenHandleTask()
533 {
534     auto host = GetHost();
535     CHECK_NULL_VOID(host);
536     auto context = host->GetContext();
537     CHECK_NULL_VOID(context);
538     auto taskExecutor = context->GetTaskExecutor();
539     CHECK_NULL_VOID(taskExecutor);
540     auto weak = WeakClaim(this);
541     hiddenHandleTask_.Reset([weak] {
542         auto client = weak.Upgrade();
543         CHECK_NULL_VOID_NOLOG(client);
544         client->HiddenHandle();
545     });
546     taskExecutor->PostDelayedTask(hiddenHandleTask_, TaskExecutor::TaskType::UI, HIDDEN_HANDLE_TIMER_MS);
547 }
548 
HiddenHandle()549 void SelectOverlayPattern::HiddenHandle()
550 {
551     hiddenHandleTask_.Cancel();
552     isHiddenHandle_ = true;
553     auto host = DynamicCast<SelectOverlayNode>(GetHost());
554     CHECK_NULL_VOID(host);
555     host->GetOrCreateGestureEventHub()->RemoveClickEvent(clickEvent_);
556     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
557 }
558 
StopHiddenHandleTask()559 void SelectOverlayPattern::StopHiddenHandleTask()
560 {
561     hiddenHandleTask_.Cancel();
562 }
563 } // namespace OHOS::Ace::NG
564