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