• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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/overlay/sheet_presentation_pattern.h"
17 #include "overlay_manager.h"
18 
19 #include "base/geometry/dimension.h"
20 #include "base/log/dump_log.h"
21 #include "base/memory/referenced.h"
22 #include "base/utils/utils.h"
23 #include "base/window/foldable_window.h"
24 #include "core/animation/animation_pub.h"
25 #include "core/animation/curve.h"
26 #include "core/common/ace_engine.h"
27 #include "core/common/container.h"
28 #include "core/common/resource/resource_parse_utils.h"
29 #include "core/components/drag_bar/drag_bar_theme.h"
30 #include "core/components_ng/base/frame_node.h"
31 #include "core/components_ng/event/event_hub.h"
32 #include "core/components_ng/event/gesture_event_hub.h"
33 #include "core/components_ng/event/touch_event.h"
34 #include "core/components_ng/pattern/container_modal/enhance/container_modal_view_enhance.h"
35 #include "core/components_ng/pattern/image/image_pattern.h"
36 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
37 #include "core/components_ng/pattern/overlay/overlay_manager.h"
38 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
39 #include "core/components_ng/pattern/overlay/sheet_manager.h"
40 #include "core/components_ng/pattern/overlay/sheet_style.h"
41 #include "core/components_ng/pattern/overlay/sheet_view.h"
42 #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h"
43 #include "core/components_ng/pattern/scroll/scroll_layout_algorithm.h"
44 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
45 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
46 #include "core/components_ng/pattern/stage/page_pattern.h"
47 #include "core/components_ng/pattern/text/text_layout_property.h"
48 #include "core/components_ng/pattern/text_field/text_field_manager.h"
49 #include "core/components_ng/property/accessibility_property_helper.h"
50 #ifdef WINDOW_SCENE_SUPPORTED
51 #include "core/components_ng/pattern/window_scene/scene/system_window_scene.h"
52 #endif
53 #include "core/components_ng/property/property.h"
54 #ifdef ENABLE_ROSEN_BACKEND
55 #include "core/components_ng/render/adapter/rosen_render_context.h"
56 #endif
57 #include "core/components/theme/shadow_theme.h"
58 #include "core/components_v2/inspector/inspector_constants.h"
59 #include "core/event/touch_event.h"
60 #include "core/pipeline_ng/pipeline_context.h"
61 
62 namespace OHOS::Ace::NG {
63 namespace {
64 constexpr int32_t SHEET_DETENTS_ZERO = 0;
65 constexpr int32_t SHEET_DETENTS_ONE = 1;
66 constexpr int32_t SHEET_DETENTS_TWO = 2;
67 constexpr int32_t SHEET_DETENTS_THREE = 3;
68 constexpr float SHEET_VISIABLE_ALPHA = 1.0f;
69 constexpr float SHEET_INVISIABLE_ALPHA = 0.0f;
70 constexpr int32_t SHEET_ENTRY_ANIMATION_DURATION = 250;
71 constexpr int32_t SHEET_EXIT_ANIMATION_DURATION = 100;
72 constexpr float SHEET_INVISIABLE_OFFSET = 8.0f;
73 constexpr float BOTTOM_STYLE_RATIO = 1.25f;
74 constexpr int32_t SHEET_HALF_HEIGHT = 2;
75 constexpr Dimension ARROW_VERTICAL_P1_OFFSET_X = 8.0_vp;
76 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_X = 1.5_vp;
77 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_Y = 7.32_vp;
78 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_X = 1.5_vp;
79 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_Y = 7.32_vp;
80 constexpr Dimension ARROW_VERTICAL_P5_OFFSET_X = 8.0_vp;
81 constexpr Dimension ARROW_CORNER_P2_OFFSET_X = 12.8_vp;
82 constexpr Dimension ARROW_CORNER_P2_OFFSET_Y = 7.6_vp;
83 constexpr Dimension ARROW_CORNER_P4_OFFSET_Y = 6.0_vp;
84 constexpr Dimension ARROW_RADIUS = 2.0_vp;
85 constexpr Dimension SUBWINDOW_SHEET_TRANSLATION = 80.0_vp;
86 } // namespace
87 
88 // MarkModifyDone must be called after UpdateSheetObject. InitSheetMode depends on SheetObject.
OnModifyDone()89 void SheetPresentationPattern::OnModifyDone()
90 {
91     Pattern::CheckLocalized();
92     auto host = GetHost();
93     CHECK_NULL_VOID(host);
94     auto renderContext = host->GetRenderContext();
95     if (renderContext) {
96         auto pipeline = host->GetContext();
97         CHECK_NULL_VOID(pipeline);
98         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
99         CHECK_NULL_VOID(sheetTheme);
100         auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
101         CHECK_NULL_VOID(layoutProperty);
102         auto sheetStyle = layoutProperty->GetSheetStyleValue();
103         BlurStyle blurStyle = static_cast<BlurStyle>(sheetTheme->GetSheetBackgroundBlurStyle());
104         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)
105             && blurStyle != BlurStyle::NO_MATERIAL) {
106             BlurStyleOption options;
107             options.blurStyle = blurStyle;
108             renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
109             renderContext->UpdateBackBlurStyle(sheetStyle.backgroundBlurStyle.value_or(options));
110         } else {
111             renderContext->UpdateBackgroundColor(
112                 sheetStyle.backgroundColor.value_or(sheetTheme->GetSheetBackgoundColor()));
113         }
114     }
115     InitPanEvent();
116     InitPageHeight();
117     InitSheetMode();
118     sheetObject_->InitScrollProps();
119     InitFoldCreaseRegion();
120 }
121 
122 // check device is phone, fold status, and device in landscape
IsPhoneInLandScape()123 bool SheetPresentationPattern::IsPhoneInLandScape()
124 {
125     auto host = GetHost();
126     CHECK_NULL_RETURN(host, false);
127     auto pipelineContext = host->GetContext();
128     CHECK_NULL_RETURN(pipelineContext, false);
129     auto containerId = Container::CurrentId();
130     auto foldWindow = FoldableWindow::CreateFoldableWindow(containerId);
131     CHECK_NULL_RETURN(foldWindow, false);
132     auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
133     CHECK_NULL_RETURN(sheetTheme, false);
134     auto sheetThemeType = sheetTheme->GetSheetType();
135     if (sheetThemeType == "auto" && !foldWindow->IsFoldExpand() &&
136         SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE) {
137         return true;
138     }
139     return false;
140 }
141 
GetSheetTopSafeArea()142 float SheetPresentationPattern::GetSheetTopSafeArea()
143 {
144     auto host = GetHost();
145     CHECK_NULL_RETURN(host, 0.0f);
146     auto pipelineContext = host->GetContext();
147     CHECK_NULL_RETURN(pipelineContext, 0.0f);
148     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
149     auto sheetTopSafeArea = safeAreaInsets.top_.Length();
150     auto windowManager = pipelineContext->GetWindowManager();
151     auto sheetType = sheetType_;
152     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
153     double deviceHeight = static_cast<double>(SystemProperties::GetDeviceHeight());
154 
155     // full screen subwindow sheet is also WINDOW_MODE_FLOATING, can not enter
156     if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING &&
157         !NearEqual(windowGlobalRect.Height(), deviceHeight)) {
158         sheetTopSafeArea = SHEET_BLANK_FLOATING_STATUS_BAR.ConvertToPx();
159     } else if ((sheetType == SheetType::SHEET_BOTTOMLANDSPACE || sheetType == SheetType::SHEET_BOTTOM ||
160                 sheetType == SheetType::SHEET_BOTTOM_OFFSET) &&
161                Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
162         sheetTopSafeArea = GetBottomSafeArea();
163     } else if (sheetType == SheetType::SHEET_BOTTOMLANDSPACE &&
164                AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
165         sheetTopSafeArea = 0.0f;
166     }
167     // before API14,ignore safeArea height when in landscape
168     if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
169         auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
170         CHECK_NULL_RETURN(layoutProperty, 0.0f);
171         auto sheetStyle = layoutProperty->GetSheetStyleValue();
172         if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
173             IsPhoneInLandScape()) {
174             sheetTopSafeArea = 0.0f;
175         }
176     }
177     // if window titleBar hidden, avoid button area.
178     NG::RectF floatButtons;
179     if (GetWindowButtonRect(floatButtons)) {
180         sheetTopSafeArea = floatButtons.Height();
181     }
182     return sheetTopSafeArea;
183 }
184 
InitPageHeight()185 void SheetPresentationPattern::InitPageHeight()
186 {
187     auto host = GetHost();
188     CHECK_NULL_VOID(host);
189     auto pipelineContext = host->GetContext();
190     CHECK_NULL_VOID(pipelineContext);
191     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
192     auto currentTopSafeArea = sheetTopSafeArea_;
193     TAG_LOGD(AceLogTag::ACE_SHEET, "statusBarHeight of sheet by GetSafeAreaWithoutProcess : %{public}u",
194         safeAreaInsets.top_.Length());
195     sheetTopSafeArea_ =
196         sheetType_ != SheetType::SHEET_BOTTOMLANDSPACE ? safeAreaInsets.top_.Length() : .0f;
197     auto showInPage =
198         GetLayoutProperty<SheetPresentationProperty>()->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
199     auto overlay = GetOverlayManager();
200     if (overlay && overlay->IsRootExpansive() && showInPage) {
201         sheetTopSafeArea_ = .0f;
202     }
203     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
204     CHECK_NULL_VOID(layoutProperty);
205     auto sheetStyle = layoutProperty->GetSheetStyleValue();
206     if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
207         IsPhoneInLandScape()) {
208         sheetTopSafeArea_ = 0.0f;
209     }
210     sheetTopSafeArea_ = GetSheetTopSafeArea();
211     TAG_LOGD(AceLogTag::ACE_SHEET, "sheetTopSafeArea of sheet is : %{public}f", sheetTopSafeArea_);
212     if (!NearEqual(currentTopSafeArea, sheetTopSafeArea_)) {
213         topSafeAreaChanged_ = true;
214     }
215 }
216 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)217 bool SheetPresentationPattern::OnDirtyLayoutWrapperSwap(
218     const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
219 {
220     if (config.skipMeasure && config.skipLayout) {
221         return false;
222     }
223     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
224     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
225     InitPageHeight();
226     sheetObject_->DirtyLayoutProcess(layoutAlgorithmWrapper);
227     UpdateFontScaleStatus();
228     UpdateCloseIconStatus();
229     UpdateTitlePadding();
230     UpdateSheetTitle();
231     ClipSheetNode();
232 
233     sheetObject_->AvoidKeyboardInDirtyLayoutProcess();
234 
235     if (sheetType_ == SheetType::SHEET_POPUP) {
236         MarkSheetPageNeedRender();
237     }
238     return true;
239 }
240 
SetBottomStyleHotAreaInSubwindow()241 void SheetPresentationPattern::SetBottomStyleHotAreaInSubwindow()
242 {
243     if (IsShowInSubWindow() && IsSheetBottom()) {
244         auto host = GetHost();
245         auto paintRect = host->GetPaintRectWithTransform();
246         std::vector<Rect> rects;
247         auto rect =
248             Rect(paintRect.GetOffset().GetX(), paintRect.GetOffset().GetY(), paintRect.Width(), paintRect.Height());
249         rects.emplace_back(rect);
250         SubwindowManager::GetInstance()->SetHotAreas(rects, SubwindowType::TYPE_SHEET, host->GetId(), GetSubWindowId());
251     }
252 }
253 
CheckBuilderChange()254 void SheetPresentationPattern::CheckBuilderChange()
255 {
256     auto host = GetHost();
257     CHECK_NULL_VOID(host);
258     auto builderNode = GetFirstFrameNodeOfBuilder();
259     CHECK_NULL_VOID(builderNode);
260     auto eventHub = builderNode->GetOrCreateEventHub<EventHub>();
261     CHECK_NULL_VOID(eventHub);
262     OnAreaChangedFunc onBuilderAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
263                                                      const OffsetF& /* oldOrigin */, const RectF& /* rect */,
264                                                      const OffsetF& /* origin */) {
265         auto sheetNode = sheetNodeWk.Upgrade();
266         CHECK_NULL_VOID(sheetNode);
267         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
268         CHECK_NULL_VOID(sheetPattern);
269         auto layoutProperty = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
270         CHECK_NULL_VOID(layoutProperty);
271         auto sheetStyle = layoutProperty->GetSheetStyleValue();
272         if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
273             auto sheetWrapper = sheetNode->GetParent();
274             CHECK_NULL_VOID(sheetWrapper);
275             sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
276         }
277     };
278     eventHub->AddInnerOnAreaChangedCallback(builderNode->GetId(), std::move(onBuilderAreaChangedFunc));
279 }
280 
AvoidAiBar()281 void SheetPresentationPattern::AvoidAiBar()
282 {
283     CHECK_NULL_VOID(Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN));
284     if (!IsTypeNeedAvoidAiBar()) {
285         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet need not avoid AiBar.");
286         return;
287     }
288     auto host = GetHost();
289     CHECK_NULL_VOID(host);
290     auto scrollNode = GetSheetScrollNode();
291     CHECK_NULL_VOID(scrollNode);
292     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
293     CHECK_NULL_VOID(scrollPattern);
294     if (NonPositive(scrollPattern->GetScrollableDistance()) || isScrolling_) {
295         return;
296     }
297     auto pipeline = PipelineContext::GetCurrentContext();
298     CHECK_NULL_VOID(pipeline);
299     auto inset = pipeline->GetSafeArea();
300     auto layoutProperty = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
301     layoutProperty->UpdateScrollContentEndOffset(inset.bottom_.Length());
302     TAG_LOGD(AceLogTag::ACE_SHEET, "AvoidAiBar function execution completed");
303     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
304 }
305 
IsScrollable() const306 bool SheetPresentationPattern::IsScrollable() const
307 {
308     auto scrollNode = GetSheetScrollNode();
309     CHECK_NULL_RETURN(scrollNode, false);
310     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
311     CHECK_NULL_RETURN(scrollPattern, false);
312     return Positive(scrollPattern->GetScrollableDistance());
313 }
314 
OnAttachToFrameNode()315 void SheetPresentationPattern::OnAttachToFrameNode()
316 {
317     auto host = GetHost();
318     CHECK_NULL_VOID(host);
319     InitFoldState();
320     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
321     host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
322     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
323     CHECK_NULL_VOID(targetNode);
324     auto targetNodeContext = targetNode->GetContext();
325     CHECK_NULL_VOID(targetNodeContext);
326     auto sheetTheme = targetNodeContext->GetTheme<SheetTheme>();
327     CHECK_NULL_VOID(sheetTheme);
328     sheetThemeType_ = sheetTheme->GetSheetType();
329     scale_ = targetNodeContext->GetFontScale();
330     if (IsShowInSubWindow()) {
331         targetNodeContext->AddWindowSizeChangeCallback(host->GetId());
332         targetNodeContext->AddOnAreaChangeNode(targetNode->GetId());
333     } else {
334         auto currentPipeline = host->GetContext();
335         CHECK_NULL_VOID(currentPipeline);
336         currentPipeline->AddWindowSizeChangeCallback(host->GetId());
337         currentPipeline->AddOnAreaChangeNode(targetNode->GetId());
338     }
339     OnAreaChangedFunc onAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
340                                               const OffsetF& /* oldOrigin */, const RectF& /* rect */,
341                                               const OffsetF& /* origin */) {
342         auto sheetNode = sheetNodeWk.Upgrade();
343         CHECK_NULL_VOID(sheetNode);
344         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
345         CHECK_NULL_VOID(sheetPattern);
346         if (sheetPattern->GetSheetTypeNoProcess() == SheetType::SHEET_POPUP) {
347             auto sheetWrapper = sheetNode->GetParent();
348             CHECK_NULL_VOID(sheetWrapper);
349             sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
350         }
351     };
352     auto eventHub = targetNode->GetOrCreateEventHub<EventHub>();
353     CHECK_NULL_VOID(eventHub);
354     eventHub->AddInnerOnAreaChangedCallback(host->GetId(), std::move(onAreaChangedFunc));
355 
356     auto gesture = host->GetOrCreateGestureEventHub();
357     CHECK_NULL_VOID(gesture);
358     auto touchTask = [](TouchEventInfo& info) {
359         info.SetStopPropagation(true);
360         TAG_LOGD(AceLogTag::ACE_SHEET, "The sheet hits the touch event.");
361     };
362     gesture->AddTouchEvent(MakeRefPtr<TouchEventImpl>(std::move(touchTask)));
363     RegisterHoverModeChangeCallback();
364     RegisterAvoidInfoChangeListener(host);
365 }
366 
OnDetachFromFrameNode(FrameNode * sheetNode)367 void SheetPresentationPattern::OnDetachFromFrameNode(FrameNode* sheetNode)
368 {
369     CHECK_NULL_VOID(sheetNode);
370     auto pipeline = sheetNode->GetContext();
371     CHECK_NULL_VOID(pipeline);
372     pipeline->RemoveWindowSizeChangeCallback(sheetNode->GetId());
373     if (HasHoverModeChangedCallbackId()) {
374         pipeline->UnRegisterHalfFoldHoverChangedCallback(hoverModeChangedCallbackId_.value_or(-1));
375     }
376     UnRegisterAvoidInfoChangeListener(sheetNode);
377     SendMessagesAfterTransitionOut(sheetNode);
378 
379     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
380     CHECK_NULL_VOID(targetNode);
381     auto eventHub = targetNode->GetOrCreateEventHub<EventHub>();
382     CHECK_NULL_VOID(eventHub);
383     eventHub->RemoveInnerOnAreaChangedCallback(sheetNode->GetId());
384 }
385 
RegisterHoverModeChangeCallback()386 void SheetPresentationPattern::RegisterHoverModeChangeCallback()
387 {
388     auto host = GetHost();
389     CHECK_NULL_VOID(host);
390     auto context = host->GetContext();
391     CHECK_NULL_VOID(context);
392     auto hoverModeChangeCallback = [weak = WeakClaim(this)](bool isHalfFoldHover) {
393         auto pattern = weak.Upgrade();
394         CHECK_NULL_VOID(pattern);
395         auto sheetType = pattern->GetSheetTypeNoProcess();
396         if (sheetType != SheetType::SHEET_CENTER) {
397             return;
398         }
399         auto host = pattern->GetHost();
400         CHECK_NULL_VOID(host);
401         auto context = host->GetContext();
402         CHECK_NULL_VOID(context);
403         AnimationOption optionPosition;
404         auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.35f, 1.0f, 0.0f);
405         optionPosition.SetCurve(motion);
406         context->FlushUITasks();
407         context->Animate(
408             optionPosition, motion,
409             [host, context]() {
410                 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
411                 context->FlushUITasks();
412             },
413             [weak]() {
414                 auto pattern = weak.Upgrade();
415                 CHECK_NULL_VOID(pattern);
416                 pattern->FireHoverModeChangeCallback();
417             });
418     };
419     auto hoverModeCallId = context->RegisterHalfFoldHoverChangedCallback(std::move(hoverModeChangeCallback));
420     UpdateHoverModeChangedCallbackId(hoverModeCallId);
421 }
422 
SetSheetBorderWidth(bool isPartialUpdate)423 void SheetPresentationPattern::SetSheetBorderWidth(bool isPartialUpdate)
424 {
425     auto host = GetHost();
426     CHECK_NULL_VOID(host);
427     auto pipeline = host->GetContext();
428     CHECK_NULL_VOID(pipeline);
429     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
430     CHECK_NULL_VOID(sheetTheme);
431     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
432     CHECK_NULL_VOID(layoutProperty);
433     auto sheetStyle = layoutProperty->GetSheetStyleValue();
434     auto renderContext = host->GetRenderContext();
435     CHECK_NULL_VOID(renderContext);
436     renderContext->SetClipToBounds(true);
437     if (sheetStyle.borderWidth.has_value()) {
438         auto borderWidth = sheetStyle.borderWidth.value();
439         borderWidth = GetSheetObject()->PostProcessBorderWidth(borderWidth);
440         layoutProperty->UpdateBorderWidth(borderWidth);
441         renderContext->UpdateBorderWidth(borderWidth);
442     } else if (renderContext->GetBorderWidth().has_value() && !isPartialUpdate) {
443         BorderWidthProperty borderWidth;
444         borderWidth.SetBorderWidth(0.0_vp);
445         layoutProperty->UpdateBorderWidth(borderWidth);
446         renderContext->UpdateBorderWidth(borderWidth);
447     }
448 
449     SetSheetOuterBorderWidth(sheetTheme, sheetStyle);
450 }
451 
452 // initial drag gesture event
InitPanEvent()453 void SheetPresentationPattern::InitPanEvent()
454 {
455     auto host = GetHost();
456     CHECK_NULL_VOID(host);
457     auto focusHub = host->GetFocusHub();
458     CHECK_NULL_VOID(focusHub);
459     InitOnkeyEvent(focusHub);
460     if (IsShowInSubWindowTwoInOne()) {
461         return;
462     }
463 
464     auto hub = host->GetOrCreateEventHub<EventHub>();
465     CHECK_NULL_VOID(hub);
466     auto gestureHub = hub->GetOrCreateGestureEventHub();
467     CHECK_NULL_VOID(gestureHub);
468     if (panEvent_) {
469         return;
470     }
471 
472     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& event) {
473         auto pattern = weak.Upgrade();
474         if (pattern) {
475             pattern->HandleDragStart();
476         }
477     };
478 
479     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
480         auto pattern = weak.Upgrade();
481         if (pattern) {
482             pattern->HandleDragUpdate(info);
483         }
484     };
485 
486     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
487         auto pattern = weak.Upgrade();
488         if (pattern) {
489             pattern->HandleDragEnd(info.GetMainVelocity());
490         }
491     };
492     auto actionCancelTask = [weak = WeakClaim(this)]() {
493         auto pattern = weak.Upgrade();
494         if (pattern) {
495             pattern->HandleDragEnd({});
496         }
497     };
498     PanDirection panDirection;
499     panDirection.type = sheetObject_->GetPanDirection();
500     panEvent_ = MakeRefPtr<PanEvent>(
501         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
502     PanDistanceMap distanceMap = { { SourceTool::UNKNOWN, DEFAULT_PAN_DISTANCE.ConvertToPx() },
503         { SourceTool::PEN, DEFAULT_PEN_PAN_DISTANCE.ConvertToPx() } };
504     gestureHub->AddPanEvent(panEvent_, panDirection, 1, distanceMap);
505 }
506 
RemovePanEvent()507 void SheetPresentationPattern::RemovePanEvent()
508 {
509     auto host = GetHost();
510     CHECK_NULL_VOID(host);
511     auto hub = host->GetEventHub<EventHub>();
512     CHECK_NULL_VOID(hub);
513     auto gestureHub = hub->GetOrCreateGestureEventHub();
514     CHECK_NULL_VOID(gestureHub);
515     gestureHub->RemovePanEvent(panEvent_);
516     panEvent_.Reset();
517 }
518 
InitOnkeyEvent(const RefPtr<FocusHub> & focusHub)519 void SheetPresentationPattern::InitOnkeyEvent(const RefPtr<FocusHub>& focusHub)
520 {
521     CHECK_NULL_VOID(focusHub);
522     focusHub->SetOnFocusInternal([weak = WeakClaim(this)](FocusReason reason) {
523         auto pattern = weak.Upgrade();
524         if (pattern) {
525             pattern->HandleFocusEvent();
526         }
527     });
528 
529     focusHub->SetOnBlurInternal([weak = WeakClaim(this)]() {
530         auto pattern = weak.Upgrade();
531         if (pattern) {
532             pattern->HandleBlurEvent();
533         }
534     });
535 }
536 
SetShadowStyle(bool isFocused)537 void SheetPresentationPattern::SetShadowStyle(bool isFocused)
538 {
539     auto host = GetHost();
540     CHECK_NULL_VOID(host);
541     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
542     CHECK_NULL_VOID(layoutProperty);
543     auto sheetStyle = layoutProperty->GetSheetStyleValue();
544     if (sheetStyle.shadow.has_value()) {
545         return;
546     }
547     auto pipeline = host->GetContext();
548     CHECK_NULL_VOID(pipeline);
549     auto renderContext = host->GetRenderContext();
550     CHECK_NULL_VOID(renderContext);
551     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
552     CHECK_NULL_VOID(sheetTheme);
553     auto style = static_cast<ShadowStyle>(sheetTheme->GetSheetShadowConfig());
554     if (!isFocused) {
555         style = static_cast<ShadowStyle>(sheetTheme->GetSheetShadowConfigS());
556     }
557     auto shadow = GetShadowFromTheme(style);
558     renderContext->UpdateBackShadow(shadow);
559 }
560 
HandleFocusEvent()561 void SheetPresentationPattern::HandleFocusEvent()
562 {
563     auto host = GetHost();
564     CHECK_NULL_VOID(host);
565     auto sheetId = host->GetId();
566     TAG_LOGI(AceLogTag::ACE_SHEET, "Sheet get focus, and id is : %{public}d", sheetId);
567     SheetManager::GetInstance().SetFocusSheetId(sheetId);
568     SetShadowStyle(true);
569 }
570 
HandleBlurEvent()571 void SheetPresentationPattern::HandleBlurEvent()
572 {
573     TAG_LOGI(AceLogTag::ACE_SHEET, "Sheet lost focus");
574     SheetManager::GetInstance().SetFocusSheetId(std::nullopt);
575     SetShadowStyle(false);
576 }
577 
HandleDragStart()578 void SheetPresentationPattern::HandleDragStart()
579 {
580     sheetObject_->HandleDragStart();
581 }
582 
HandleDragUpdate(const GestureEvent & info)583 void SheetPresentationPattern::HandleDragUpdate(const GestureEvent& info)
584 {
585     sheetObject_->HandleDragUpdate(info);
586 }
587 
HandleDragEnd(float dragVelocity)588 void SheetPresentationPattern::HandleDragEnd(float dragVelocity)
589 {
590     sheetObject_->HandleDragEnd(dragVelocity);
591 }
592 
SendTextUpdateEvent()593 void SheetPresentationPattern::SendTextUpdateEvent()
594 {
595     auto sheetNode = GetHost();
596     CHECK_NULL_VOID(sheetNode);
597     // Use TEXT_CHANGE to send events.
598     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet sent TEXT_CHANGE event, when follow up.");
599     sheetNode->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, "", "");
600 }
601 
SendSelectedEvent()602 void SheetPresentationPattern::SendSelectedEvent()
603 {
604     auto sheetNode = GetHost();
605     CHECK_NULL_VOID(sheetNode);
606     // Use SELECTED to send events.
607     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet sent SELECTED event, when get out of your hands.");
608     sheetNode->OnAccessibilityEvent(AccessibilityEventType::SELECTED, "", "");
609 }
610 
RegisterElementInfoCallBack()611 void SheetPresentationPattern::RegisterElementInfoCallBack()
612 {
613     auto sheetNode = GetHost();
614     CHECK_NULL_VOID(sheetNode);
615     auto accessibilityProperty = sheetNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
616     CHECK_NULL_VOID(accessibilityProperty);
617     auto callBack = [sheetDetents = std::to_string(static_cast<int32_t>(sheetDetents_))]
618         (Accessibility::ExtraElementInfo& extraElementInfo) {
619         extraElementInfo.SetExtraElementInfo("BindSheet", sheetDetents);
620     };
621     accessibilityProperty->SetRelatedElementInfoCallback(callBack);
622 }
623 
UpdateAccessibilityDetents(float height)624 bool SheetPresentationPattern::UpdateAccessibilityDetents(float height)
625 {
626     auto sheetDetentsSize = sheetDetentHeight_.size();
627     bool invalid = sheetDetentsSize < 2 || !IsSheetBottomStyle();
628     if (invalid) {
629         return false;
630     }
631     for (uint32_t i = 0; i < sheetDetentsSize; i++) {
632         if (NearEqual(height, sheetDetentHeight_[i])) {
633             // size is 2, corresponds to high and low.
634             // size is 3, corresponds to high、medium and low.
635             // The lower of the two detents, corresponds to "LOW".
636             bool lowOfTwoDetents = sheetDetentsSize == 2 && i == 0;
637             sheetDetents_ = lowOfTwoDetents
638                 ? static_cast<SheetAccessibilityDetents>(sheetDetentsSize - i)
639                 : static_cast<SheetAccessibilityDetents>(sheetDetentsSize -1 - i);
640             TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet detents enum value: %{public}d", sheetDetents_);
641             RegisterElementInfoCallBack();
642             return true;
643         }
644     }
645     return false;
646 }
647 
GetCurrentBroadcastDetentsIndex()648 uint32_t SheetPresentationPattern::GetCurrentBroadcastDetentsIndex()
649 {
650     bool invalid = sheetDetentHeight_.size() < 2 || !IsSheetBottomStyle();
651     if (invalid) {
652         return broadcastPreDetentsIndex_;
653     }
654     // get currrent detents index.
655     auto it = std::find(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), height_);
656     if (it != sheetDetentHeight_.end()) {
657         broadcastPreDetentsIndex_ = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), it));
658     }
659     return broadcastPreDetentsIndex_;
660 }
661 
HandleFollowAccessibilityEvent(float currHeight)662 void SheetPresentationPattern::HandleFollowAccessibilityEvent(float currHeight)
663 {
664     auto sheetDetentsSize = sheetDetentHeight_.size();
665     bool invalid = sheetDetentsSize < 2 || !IsSheetBottomStyle();
666     if (invalid) {
667         return;
668     }
669     if (currHeight < sheetDetentHeight_[0] || currHeight > sheetDetentHeight_[sheetDetentsSize - 1]) {
670         return;
671     }
672     float upHeight = 0.0f;
673     float downHeight = 0.0f;
674     float finalHeight = 0.0f;
675 
676     // record current position info.
677     uint32_t detentsLowerPos = 0;
678     uint32_t detentsUpperPos = 0;
679     uint32_t broadcastCurrDetentsIndex = 0;
680     ComputeDetentsPos(currHeight, upHeight, downHeight, detentsLowerPos, detentsUpperPos);
681 
682     if (GreatNotEqual(std::abs(currHeight - upHeight), std::abs(currHeight - downHeight))) {
683         finalHeight = downHeight;
684         broadcastCurrDetentsIndex = detentsLowerPos;
685     } else if (LessNotEqual(std::abs(currHeight - upHeight), std::abs(currHeight - downHeight))) {
686         finalHeight = upHeight;
687         broadcastCurrDetentsIndex = detentsUpperPos;
688     }
689 
690     // Broadcast once when enter other effect area.
691     if (broadcastCurrDetentsIndex != broadcastPreDetentsIndex_) {
692         UpdateAccessibilityDetents(finalHeight);
693         SendTextUpdateEvent();
694         broadcastPreDetentsIndex_ = broadcastCurrDetentsIndex;
695     }
696 }
697 
HandleDragEndAccessibilityEvent()698 void SheetPresentationPattern::HandleDragEndAccessibilityEvent()
699 {
700     if (UpdateAccessibilityDetents(GetSheetHeightBeforeDragUpdate())) {
701         SendSelectedEvent();
702     }
703 }
704 
ComputeDetentsPos(float currentSheetHeight,float & upHeight,float & downHeight,uint32_t & detentsLowerPos,uint32_t & detentsUpperPos)705 void SheetPresentationPattern::ComputeDetentsPos(
706     float currentSheetHeight, float& upHeight, float& downHeight, uint32_t& detentsLowerPos, uint32_t& detentsUpperPos)
707 {
708     // when drag the sheet page, find the lower and upper index range
709     auto lowerIter = std::lower_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
710     auto upperIter = std::upper_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
711     auto sheetDetentsSize = sheetDetentHeight_.size();
712     if (lowerIter == sheetDetentHeight_.end() || upperIter == sheetDetentHeight_.end()) {
713         // when drag over the highest sheet page
714         upHeight = sheetDetentHeight_[sheetDetentsSize - 1];
715         downHeight = sheetDetentHeight_[sheetDetentsSize - 1];
716         detentsLowerPos = sheetDetentsSize - 1;
717         detentsUpperPos = sheetDetentsSize - 1;
718     } else {
719         auto lowerPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), lowerIter));
720         auto upperPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), upperIter));
721         if (lowerPosition == 0) {
722             upHeight = sheetDetentHeight_[lowerPosition];
723             downHeight = 0;
724         } else {
725             // the first largest height greater than the currentsheet height
726             upHeight = sheetDetentHeight_[upperPosition];
727 
728             // the largest height lower than the currentsheet height
729             downHeight = sheetDetentHeight_[lowerPosition - 1];
730             detentsLowerPos = lowerPosition - 1;
731             detentsUpperPos = upperPosition;
732         }
733     }
734 }
735 
ChangeSheetPage(float height)736 void SheetPresentationPattern::ChangeSheetPage(float height)
737 {
738     if (IsAvoidingKeyboard() && keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL) {
739         return;
740     }
741     ChangeScrollHeight(height);
742 }
743 
OnCoordScrollStart()744 void SheetPresentationPattern::OnCoordScrollStart()
745 {
746     if (animation_ && isAnimationProcess_) {
747         AnimationUtils::StopAnimation(animation_);
748         isAnimationBreak_ = true;
749     }
750     currentOffset_ = 0.0f;
751     GetCurrentBroadcastDetentsIndex();
752 }
753 
OnCoordScrollUpdate(float scrollOffset)754 bool SheetPresentationPattern::OnCoordScrollUpdate(float scrollOffset)
755 {
756     if (!GetShowState() || !IsScrollable()) {
757         return false;
758     }
759 
760     auto sheetType = GetSheetType();
761     auto sheetDetentsSize = sheetDetentHeight_.size();
762     if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0)) {
763         return false;
764     }
765     auto height = GetSheetHeightBeforeDragUpdate();
766     if ((NearZero(currentOffset_)) && (LessNotEqual(scrollOffset, 0.0f)) &&
767         (GreatOrEqual(height, GetMaxSheetHeightBeforeDragUpdate()))) {
768         return false;
769     }
770     auto host = GetHost();
771     CHECK_NULL_RETURN(host, false);
772     currentOffset_ = currentOffset_ + scrollOffset;
773     auto pageHeight = GetPageHeightWithoutOffset();
774     auto offset = pageHeight - height + currentOffset_;
775     if (LessOrEqual(offset, pageHeight - sheetMaxHeight_)) {
776         offset = pageHeight - sheetMaxHeight_;
777         currentOffset_ = height - sheetMaxHeight_;
778     }
779     HandleFollowAccessibilityEvent(height - currentOffset_);
780     auto renderContext = host->GetRenderContext();
781     renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
782     return true;
783 }
784 
OnCoordScrollEnd(float dragVelocity)785 void SheetPresentationPattern::OnCoordScrollEnd(float dragVelocity)
786 {
787     HandleDragEnd(dragVelocity);
788 }
789 
InitialLayoutProps()790 void SheetPresentationPattern::InitialLayoutProps()
791 {
792     CheckSheetHeightChange();
793     InitSheetDetents();
794 }
795 
GetWindowButtonRect(NG::RectF & floatButtons)796 bool SheetPresentationPattern::GetWindowButtonRect(NG::RectF& floatButtons)
797 {
798     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_EIGHTEEN)) {
799         return false;
800     }
801     auto host = GetHost();
802     CHECK_NULL_RETURN(host, false);
803     auto pipelineContext = host->GetContext();
804     CHECK_NULL_RETURN(pipelineContext, false);
805     auto avoidInfoMgr = pipelineContext->GetAvoidInfoManager();
806     CHECK_NULL_RETURN(avoidInfoMgr, false);
807     NG::RectF floatContainerModal;
808     if (avoidInfoMgr->NeedAvoidContainerModal() &&
809         avoidInfoMgr->GetContainerModalButtonsRect(floatContainerModal, floatButtons)) {
810         TAG_LOGD(AceLogTag::ACE_SHEET, "When hidden, floatButtons rect is %{public}s", floatButtons.ToString().c_str());
811         return true;
812     };
813     TAG_LOGD(AceLogTag::ACE_SHEET, "Window title builder shown");
814     return false;
815 }
816 
GetWindowButtonRectForAllAPI(NG::RectF & floatButtons)817 bool SheetPresentationPattern::GetWindowButtonRectForAllAPI(NG::RectF& floatButtons)
818 {
819     auto host = GetHost();
820     CHECK_NULL_RETURN(host, false);
821     auto pipelineContext = host->GetContext();
822     CHECK_NULL_RETURN(pipelineContext, false);
823     auto avoidInfoMgr = pipelineContext->GetAvoidInfoManager();
824     CHECK_NULL_RETURN(avoidInfoMgr, false);
825     NG::RectF floatContainerModal;
826     if (avoidInfoMgr->NeedAvoidContainerModal() &&
827         avoidInfoMgr->GetContainerModalButtonsRect(floatContainerModal, floatButtons)) {
828         TAG_LOGD(AceLogTag::ACE_SHEET, "When hidden, floatButtons rect is %{public}s", floatButtons.ToString().c_str());
829         return true;
830     };
831     TAG_LOGD(AceLogTag::ACE_SHEET, "Window title builder shown");
832     return false;
833 }
834 
InitialSingleGearHeight(NG::SheetStyle & sheetStyle)835 float SheetPresentationPattern::InitialSingleGearHeight(NG::SheetStyle& sheetStyle)
836 {
837     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
838     float sheetHeight = largeHeight;
839     auto sheetNode = GetHost();
840     CHECK_NULL_RETURN(sheetNode, sheetHeight);
841     if (sheetStyle.sheetHeight.sheetMode.has_value()) {
842         auto pipelineContext = sheetNode->GetContext();
843         CHECK_NULL_RETURN(pipelineContext, sheetHeight);
844         auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
845         CHECK_NULL_RETURN(sheetTheme, sheetHeight);
846         if (sheetStyle.sheetHeight.sheetMode == SheetMode::MEDIUM) {
847             sheetHeight = pageHeight_ * sheetTheme->GetMediumPercent();
848             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
849                 sheetHeight = pageHeight_ * MEDIUM_SIZE_PRE;
850             }
851         } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::LARGE) {
852             sheetHeight = sheetTheme->GetHeightApplyFullScreen() ? pageHeight_ : largeHeight;
853             sheetHeight *= sheetTheme->GetLargePercent();
854         } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
855             sheetHeight = GetFitContentHeight();
856             if (sheetHeight > largeHeight) {
857                 sheetHeight = largeHeight;
858             }
859             HandleFitContontChange(sheetHeight);
860         }
861     } else {
862         float height = 0.0f;
863         if (sheetStyle.sheetHeight.height->Unit() == DimensionUnit::PERCENT) {
864             height = sheetStyle.sheetHeight.height->ConvertToPxWithSize(sheetMaxHeight_);
865         } else {
866             height = sheetStyle.sheetHeight.height->ConvertToPx();
867         }
868         if (GreatNotEqual(height, largeHeight)) {
869             sheetHeight = largeHeight;
870         } else if (LessNotEqual(height, 0)) {
871             sheetHeight = largeHeight;
872         } else {
873             sheetHeight = height;
874         }
875     }
876     return sheetHeight;
877 }
878 
BeforeCreateLayoutWrapper()879 void SheetPresentationPattern::BeforeCreateLayoutWrapper()
880 {
881     ContentRootPattern::BeforeCreateLayoutWrapper();
882     CHECK_NULL_VOID(sheetObject_);
883     sheetObject_->BeforeCreateLayoutWrapper();
884 }
885 
AvoidSafeArea(bool forceAvoid)886 void SheetPresentationPattern::AvoidSafeArea(bool forceAvoid)
887 {
888     sheetObject_->AvoidKeyboard(forceAvoid);
889 }
890 
AvoidKeyboard(bool forceAvoid)891 void SheetPresentationPattern::AvoidKeyboard(bool forceAvoid)
892 {
893     auto sheetType = sheetType_;
894     if (sheetType == SheetType::SHEET_POPUP || IsCurSheetNeedHalfFoldHover() ||
895         sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
896         return;
897     }
898     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
899         AvoidKeyboardBySheetMode(forceAvoid);
900         return;
901     }
902     auto host = GetHost();
903     CHECK_NULL_VOID(host);
904     auto pipelineContext = PipelineContext::GetCurrentContext();
905     CHECK_NULL_VOID(pipelineContext);
906     auto manager = pipelineContext->GetSafeAreaManager();
907     if (!forceAvoid && keyboardHeight_ == manager->GetKeyboardInset().Length()) {
908         return;
909     }
910     keyboardHeight_ = manager->GetKeyboardInset().Length();
911     CHECK_NULL_VOID(host->GetFocusHub());
912     auto heightUp = host->GetFocusHub()->IsCurrentFocus() ? GetSheetHeightChange() : 0.0f;
913     sheetHeightUp_ = heightUp;
914     if (isDismissProcess_) {
915         TAG_LOGD(AceLogTag::ACE_SHEET,
916             "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
917         return;
918     }
919     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet height increase %{public}f.", heightUp);
920     auto offset = pageHeight_ - height_ - heightUp;
921     auto renderContext = host->GetRenderContext();
922     if (isScrolling_) {
923         // if scrolling and keyboard will down, scroll needs to reset.
924         if (NearZero(heightUp)) {
925             ScrollTo(.0f);
926             renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
927         } else {
928             sheetHeightUp_ = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
929             // Otherwise, sheet is necessary to raise and trigger scroll scrolling
930             // sheet is raised to the top first
931             renderContext->UpdateTransformTranslate(
932                 { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
933             // Then adjust the remaining height(heightUp = h - maxH) difference by scrolling
934             ScrollTo(heightUp);
935         }
936     } else {
937         // offset: translate endpoint, calculated from top
938         renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
939     }
940     if (IsSheetBottomStyle()) {
941         OnHeightDidChange(height_ + sheetHeightUp_);
942     }
943 }
944 
GetSheetHeightChange()945 float SheetPresentationPattern::GetSheetHeightChange()
946 {
947     // TextFieldManagerNG::GetClickPosition: The upper left corner offset of the cursor position relative to rootNode
948     // TextFieldManagerNG::GetHeight: the cursor Height + 24vp
949     auto host = GetHost();
950     CHECK_NULL_RETURN(host, .0f);
951     auto pipelineContext = host->GetContext();
952     CHECK_NULL_RETURN(pipelineContext, .0f);
953     auto manager = pipelineContext->GetSafeAreaManager();
954     auto keyboardInsert = manager->GetKeyboardInset();
955     if (keyboardInsert.Length() == 0) {
956         return 0.f;
957     }
958     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipelineContext->GetTextFieldManager());
959     // inputH : Distance from input component's Caret to bottom of screen
960     // = caret's offset + caret's height + 24vp
961     if (textFieldManager && !textFieldManager->GetOptionalClickPosition().has_value() &&
962         !pipelineContext->UsingCaretAvoidMode()) {
963         TAG_LOGD(AceLogTag::ACE_SHEET, "illegal caret position, don't calc height this time");
964         return .0f;
965     }
966     float inputH = 0.f;
967     if (pipelineContext->UsingCaretAvoidMode()) {
968         // when user scroll after avoiding keyboard, we need to update scroll offset before avoid keyboard twice.
969         GetCurrentScrollHeight();
970         // when avoiding keyboard twice, recover input height before avoiding is needed.
971         inputH = textFieldManager ? pipelineContext->GetRootHeight() -
972             textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight() - sheetHeightUp_ -
973             scrollHeight_ : 0.f;
974     } else {
975         inputH = textFieldManager ? (pipelineContext->GetRootHeight() -
976             textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight()) : 0.f;
977     }
978     // keyboardH : keyboard height + height of the bottom navigation bar
979     auto keyboardH = keyboardInsert.Length() + manager->GetSystemSafeArea().bottom_.Length();
980     // The minimum height of the input component from the bottom of the screen after popping up the soft keyboard
981     auto inputMinH = keyboardH;
982     // the LARGE sheet is 15vp from the status bar, and SHEET_CENTER's Node height not equal to screen height.
983     auto largeHeight = pipelineContext->GetRootHeight() - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - sheetTopSafeArea_;
984     // maxH : height that the sheet can reach the stage = the LARGE sheet - Current sheet height
985     auto maxH = largeHeight - height_;
986     if (inputH >= inputMinH) {
987         // sheet needs not up
988         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet needs not up");
989         return .0f;
990     }
991     // The expected height of the sheet to be lifted
992     auto h = inputMinH - inputH;
993     if (h <= maxH) {
994         RecoverScrollOrResizeAvoidStatus();
995         // sheet is lifted up with h
996         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is lifted up with h = %{public}f", h);
997         return h;
998     }
999     // h > maxH, sheet goes up to the LARGE, then adjust the remaining height(h - maxH) difference by scrolling
1000     if (IsResizeWhenAvoidKeyboard()) {
1001         // remaing height need to update to (keyboardH - bottomDistance) when in resize mode after translate
1002         inputH = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
1003         h = inputMinH - inputH;
1004     }
1005     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is LARGE, and there is [%{public}f] height left to be processed.", h - maxH);
1006     isScrolling_ = true;
1007     return h - maxH;
1008 }
1009 
CreatePropertyCallback()1010 void SheetPresentationPattern::CreatePropertyCallback()
1011 {
1012     sheetObject_->CreatePropertyCallback();
1013 }
1014 
ModifyFireSheetTransition(float dragVelocity)1015 void SheetPresentationPattern::ModifyFireSheetTransition(float dragVelocity)
1016 {
1017     sheetObject_->ModifyFireSheetTransition(dragVelocity);
1018 }
1019 
1020 /**
1021  * @brief Get the max height before drag or nestedScroll.
1022  * the height is relative to the bottom of screen.
1023  */
GetMaxSheetHeightBeforeDragUpdate()1024 float SheetPresentationPattern::GetMaxSheetHeightBeforeDragUpdate()
1025 {
1026     if (IsCurSheetNeedHalfFoldHover() || sheetType_ == SheetType::SHEET_BOTTOM_OFFSET ||
1027         IsNotBottomStyleInSubwindow()) {
1028         return GetPageHeightWithoutOffset() - sheetOffsetY_;
1029     }
1030     auto sheetDetentsSize = sheetDetentHeight_.size();
1031     if (sheetDetentsSize <= 0) {
1032         TAG_LOGW(AceLogTag::ACE_SHEET, "sheetDetentsSize is nonPositive");
1033         return 0.0f;
1034     }
1035     // The value can be returned in other scenarios as follows:
1036     // 1. bottom sheet tyle : maxHeight is maxDetent.
1037     // 2. center and other sheet tyle, except for popup tyle :
1038     // maxHeight is the height of the top left corner of sheet from the bottom of screen
1039     // 3. scene in setting offsetY : add offsetY to the following value
1040     return sheetDetentHeight_[sheetDetentsSize - 1];
1041 }
1042 
1043 /**
1044  * @brief Get the height before drag or nestedScroll.
1045  * the height is relative to the bottom of screen.
1046  */
GetSheetHeightBeforeDragUpdate()1047 float SheetPresentationPattern::GetSheetHeightBeforeDragUpdate()
1048 {
1049     if (IsCurSheetNeedHalfFoldHover() || sheetType_ == SheetType::SHEET_BOTTOM_OFFSET ||
1050         IsNotBottomStyleInSubwindow()) {
1051         return GetPageHeightWithoutOffset() - sheetOffsetY_;
1052     }
1053     // height_ : from the bottom of screen, after the sheet entry action has ended.
1054     // sheetHeightUp_ : increased height to avoid soft keyboard.
1055     // -bottomOffsetY_ : increased height by setting offsetY. bottomOffsetY_ is a negative number.
1056     return height_ + sheetHeightUp_;
1057 }
1058 
UpdateSheetTransitionOffset()1059 float SheetPresentationPattern::UpdateSheetTransitionOffset()
1060 {
1061     // dentets greater than 1 and no rebound
1062     if (!WillSpringBack() && sheetDetentHeight_.size() > 1) {
1063         // When avoiding keyboards
1064         // don't consider the height difference introduced by avoidance after switching detents
1065         sheetHeightUp_ = 0.0f;
1066     }
1067     // apply to springBack scene
1068     // return the offset before drag
1069     auto offset = GetPageHeightWithoutOffset() - GetSheetHeightBeforeDragUpdate();
1070     return offset;
1071 }
1072 
SheetTransition(bool isTransitionIn,float dragVelocity)1073 void SheetPresentationPattern::SheetTransition(bool isTransitionIn, float dragVelocity)
1074 {
1075     if ((HasOnHeightDidChange() && IsSheetBottomStyle() && isTransitionIn && isNeedProcessHeight_)
1076         || (isTransitionIn && IsNeedChangeScrollHeight(height_))) {
1077         // Pass height_ because it was updated by ChangeSheetHeight() before
1078         ModifyFireSheetTransition(dragVelocity);
1079         return;
1080     }
1081     auto host = GetHost();
1082     CHECK_NULL_VOID(host);
1083     AnimationOption option;
1084     const RefPtr<InterpolatingSpring> curve = sheetObject_->GetSheetTransitionCurve(dragVelocity);
1085     option.SetCurve(curve);
1086     sheetObject_->SetSheetAnimationOption(option);
1087     auto offset = UpdateSheetTransitionOffset();
1088     if (!isTransitionIn) {
1089         const auto& overlayManager = GetOverlayManager();
1090         CHECK_NULL_VOID(overlayManager);
1091         auto maskNode = overlayManager->GetSheetMask(host);
1092         if (maskNode) {
1093             overlayManager->PlaySheetMaskTransition(maskNode, host, false);
1094         }
1095     }
1096     option.SetOnFinishEvent(sheetObject_->GetSheetTransitionFinishEvent(isTransitionIn));
1097     StartSheetTransitionAnimation(option, isTransitionIn, offset);
1098 }
1099 
SheetTransitionForOverlay(bool isTransitionIn,bool isFirstTransition)1100 void SheetPresentationPattern::SheetTransitionForOverlay(bool isTransitionIn, bool isFirstTransition)
1101 {
1102     if (GetDismissProcess()) {
1103         return;
1104     }
1105     // get sheet animation option and finishCallback
1106     AnimationOption option = sheetObject_->GetAnimationOptionForOverlay(isTransitionIn, isFirstTransition);
1107     // Init other animation information, includes the starting point of the animation.
1108     sheetObject_->InitAnimationForOverlay(isTransitionIn, isFirstTransition);
1109     StopModifySheetTransition();
1110     auto host = GetHost();
1111     CHECK_NULL_VOID(host);
1112     auto pipeline = host->GetContextRefPtr();
1113     AnimationUtils::Animate(option,
1114         sheetObject_->GetAnimationPropertyCallForOverlay(isTransitionIn), // Moving effect end point
1115         option.GetOnFinishEvent(), nullptr, pipeline);
1116     SetBottomStyleHotAreaInSubwindow();
1117 }
1118 
SheetInteractiveDismiss(BindSheetDismissReason dismissReason,float dragVelocity)1119 void SheetPresentationPattern::SheetInteractiveDismiss(BindSheetDismissReason dismissReason, float dragVelocity)
1120 {
1121     isDirectionUp_ = false;
1122     if (HasShouldDismiss() || HasOnWillDismiss()) {
1123         const auto& overlayManager = GetOverlayManager();
1124         CHECK_NULL_VOID(overlayManager);
1125         overlayManager->SetDismissTarget(DismissTarget(sheetKey_));
1126         auto host = GetHost();
1127         CHECK_NULL_VOID(host);
1128         SheetManager::GetInstance().SetDismissSheet(host->GetId());
1129         if (dismissReason >= BindSheetDismissReason::SLIDE_DOWN) {
1130             isSpringBack_ = true;
1131             if (HasSheetSpringBack()) {
1132                 CallSheetSpringBack();
1133             } else {
1134                 isDismissProcess_ = false;
1135                 SheetTransition(true);
1136             }
1137         }
1138         CallShouldDismiss();
1139         CallOnWillDismiss(static_cast<int32_t>(dismissReason));
1140     } else {
1141         DismissTransition(false, dragVelocity);
1142     }
1143 }
1144 
DismissTransition(bool isTransitionIn,float dragVelocity)1145 void SheetPresentationPattern::DismissTransition(bool isTransitionIn, float dragVelocity)
1146 {
1147     isDismissProcess_ = true;
1148     const auto& overlayManager = GetOverlayManager();
1149     CHECK_NULL_VOID(overlayManager);
1150     overlayManager->ModalPageLostFocus(GetHost());
1151     if (!isTransitionIn) {
1152         OnWillDisappear();
1153     }
1154     auto sheetType = GetSheetTypeNoProcess();
1155     if (sheetType == SheetType::SHEET_POPUP) {
1156         BubbleStyleSheetTransition(isTransitionIn);
1157     } else {
1158         SheetTransition(isTransitionIn, dragVelocity);
1159     }
1160 }
1161 
ChangeScrollHeight(float height)1162 void SheetPresentationPattern::ChangeScrollHeight(float height)
1163 {
1164     auto host = GetHost();
1165     CHECK_NULL_VOID(host);
1166     auto geometryNode = host->GetGeometryNode();
1167     CHECK_NULL_VOID(geometryNode);
1168     auto scrollNode = GetSheetScrollNode();
1169     CHECK_NULL_VOID(scrollNode);
1170     auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
1171     CHECK_NULL_VOID(scrollProps);
1172     auto scrollHeight = height - GetTitleBuilderHeight() - resizeDecreasedHeight_;
1173     auto sheetType = GetSheetTypeNoProcess();
1174     if (sheetType == SheetType::SHEET_POPUP || sheetType == SheetType::SHEET_CENTER ||
1175         sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
1176         auto sheetHeight = geometryNode->GetFrameSize().Height();
1177         scrollHeight = sheetHeight - GetTitleBuilderHeight() - resizeDecreasedHeight_;
1178     }
1179     scrollProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(scrollHeight)));
1180     scrollNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1181 }
1182 
IsSingleDetents(const NG::SheetStyle & sheetStyle)1183 bool SheetPresentationPattern::IsSingleDetents(const NG::SheetStyle& sheetStyle)
1184 {
1185     bool isSingle = true;
1186     bool isFitContent = false;
1187     for (const auto& detent : sheetStyle.detents) {
1188         if (!detent.sheetMode.has_value()) {
1189             continue;
1190         }
1191         if (detent.sheetMode.value() == SheetMode::AUTO) {
1192             isFitContent = true;
1193         }
1194     }
1195     if (unSortedSheetDentents_.size() == SHEET_DETENTS_TWO) {
1196         isSingle = unSortedSheetDentents_[SHEET_DETENTS_ZERO] == unSortedSheetDentents_[SHEET_DETENTS_ONE];
1197     } else if (unSortedSheetDentents_.size() == SHEET_DETENTS_THREE) {
1198         isSingle = unSortedSheetDentents_[SHEET_DETENTS_ZERO] == unSortedSheetDentents_[SHEET_DETENTS_ONE] &&
1199                    unSortedSheetDentents_[SHEET_DETENTS_ONE] == unSortedSheetDentents_[SHEET_DETENTS_TWO];
1200     }
1201     if (sheetStyle.detents.size() > SHEET_DETENTS_ONE && isFitContent) {
1202         isSingle = false;
1203     }
1204     return isSingle;
1205 }
1206 
UpdateDragBarStatus()1207 void SheetPresentationPattern::UpdateDragBarStatus()
1208 {
1209     auto host = GetHost();
1210     CHECK_NULL_VOID(host);
1211     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1212     CHECK_NULL_VOID(layoutProperty);
1213     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
1214     auto showDragIndicator = sheetStyle.showDragBar.value_or(true);
1215 
1216     auto sheetDragBar = GetDragBarNode();
1217     CHECK_NULL_VOID(sheetDragBar);
1218     auto dragBarLayoutProperty = sheetDragBar->GetLayoutProperty();
1219     CHECK_NULL_VOID(dragBarLayoutProperty);
1220     if (!host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) {
1221         dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1222         sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1223         return;
1224     }
1225     if (IsSheetBottomStyle() && !IsSingleDetents(sheetStyle)) {
1226         if (sheetStyle.isTitleBuilder.has_value()) {
1227             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1228         } else {
1229             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1230         }
1231     } else {
1232         if (sheetStyle.isTitleBuilder.has_value()) {
1233             dragBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1234         } else {
1235             dragBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
1236         }
1237     }
1238     int32_t zIndex = sheetStyle.enableFloatingDragBar.value_or(false) ? INT32_MAX : 0;
1239     auto dragBarRenderContext = sheetDragBar->GetRenderContext();
1240     CHECK_NULL_VOID(dragBarRenderContext);
1241     dragBarRenderContext->UpdateZIndex(zIndex);
1242     sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1243 }
1244 
UpdateTitleColumnSize()1245 void SheetPresentationPattern::UpdateTitleColumnSize()
1246 {
1247     auto host = GetHost();
1248     CHECK_NULL_VOID(host);
1249     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1250     CHECK_NULL_VOID(layoutProperty);
1251     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1252     auto operationColumn = GetTitleBuilderNode();
1253     auto pipeline = host->GetContext();
1254     CHECK_NULL_VOID(pipeline);
1255     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1256     CHECK_NULL_VOID(sheetTheme);
1257 
1258     if (operationColumn && sheetStyle.sheetTitle.has_value() &&
1259         NearEqual(pipeline->GetFontScale(), sheetTheme->GetSheetNormalScale())) {
1260         auto layoutProps = operationColumn->GetLayoutProperty<LinearLayoutProperty>();
1261         CHECK_NULL_VOID(layoutProps);
1262         layoutProps->UpdateUserDefinedIdealSize(CalcSize(
1263             std::nullopt, CalcLength(sheetTheme->GetOperationAreaHeight() - sheetTheme->GetSheetTitleAreaMargin() -
1264                                      GetDragBarHeight(GetDragBarNode()))));
1265         if (sheetStyle.sheetSubtitle.has_value()) {
1266             layoutProps->UpdateUserDefinedIdealSize(CalcSize(
1267                 std::nullopt, CalcLength(sheetTheme->GetOperationAreaHeightDouble() -
1268                                          sheetTheme->GetSheetTitleAreaMargin() - GetDragBarHeight(GetDragBarNode()))));
1269         }
1270     }
1271 }
1272 
GetCloseIconPosX(const SizeF & sheetSize,const RefPtr<SheetTheme> & sheetTheme)1273 float SheetPresentationPattern::GetCloseIconPosX(const SizeF& sheetSize, const RefPtr<SheetTheme>& sheetTheme)
1274 {
1275     auto closeIconX = sheetSize.Width() - static_cast<float>(sheetTheme->GetCloseIconButtonWidth().ConvertToPx()) -
1276                       static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1277     if (AceApplicationInfo::GetInstance().IsRightToLeft() &&
1278         AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1279         closeIconX = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1280     }
1281     return closeIconX;
1282 }
1283 
IsShowCloseIcon()1284 bool SheetPresentationPattern::IsShowCloseIcon()
1285 {
1286     auto host = GetHost();
1287     CHECK_NULL_RETURN(host, false);
1288     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1289     CHECK_NULL_RETURN(layoutProperty, false);
1290     return layoutProperty->GetSheetStyleValue().showCloseIcon.value_or(true);
1291 }
1292 
GetTitleNode()1293 RefPtr<FrameNode> SheetPresentationPattern::GetTitleNode()
1294 {
1295     auto operationNode = GetTitleBuilderNode();
1296     CHECK_NULL_RETURN(operationNode, nullptr);
1297     return DynamicCast<FrameNode>(operationNode->GetChildAtIndex(0));
1298 }
1299 
UpdateTitleTextColor()1300 void SheetPresentationPattern::UpdateTitleTextColor()
1301 {
1302     auto host = GetHost();
1303     CHECK_NULL_VOID(host);
1304     auto pipeline = host->GetContext();
1305     CHECK_NULL_VOID(pipeline);
1306     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1307     CHECK_NULL_VOID(sheetTheme);
1308     auto firstChild = GetTitleBuilderNode();
1309     CHECK_NULL_VOID(firstChild);
1310     auto sheetTitleColumn = firstChild->GetChildAtIndex(0);
1311     CHECK_NULL_VOID(sheetTitleColumn);
1312     auto mainRow = sheetTitleColumn->GetChildAtIndex(0);
1313     CHECK_NULL_VOID(mainRow);
1314     auto mainTitleText = DynamicCast<FrameNode>(mainRow->GetChildAtIndex(0));
1315     CHECK_NULL_VOID(mainTitleText);
1316     auto mainTitleProp = mainTitleText->GetLayoutProperty<TextLayoutProperty>();
1317     CHECK_NULL_VOID(mainTitleProp);
1318     mainTitleProp->UpdateTextColor(sheetTheme->GetTitleTextFontColor());
1319     mainTitleText->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1320 
1321     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1322     CHECK_NULL_VOID(layoutProperty);
1323     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1324     if (sheetStyle.sheetSubtitle.has_value()) {
1325         auto subRow = sheetTitleColumn->GetChildAtIndex(1);
1326         CHECK_NULL_VOID(subRow);
1327         auto subTitleText = DynamicCast<FrameNode>(subRow->GetChildAtIndex(0));
1328         CHECK_NULL_VOID(subTitleText);
1329         auto subTitleProp = subTitleText->GetLayoutProperty<TextLayoutProperty>();
1330         CHECK_NULL_VOID(subTitleProp);
1331         subTitleProp->UpdateTextColor(sheetTheme->GetSubtitleTextFontColor());
1332         subTitleText->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1333     }
1334 }
1335 
UpdateTitlePadding()1336 void SheetPresentationPattern::UpdateTitlePadding()
1337 {
1338     auto host = GetHost();
1339     CHECK_NULL_VOID(host);
1340     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1341     CHECK_NULL_VOID(layoutProperty);
1342     if (!layoutProperty->GetSheetStyleValue().isTitleBuilder.has_value()) {
1343         return;
1344     }
1345 
1346     auto titleNode = GetTitleNode();
1347     CHECK_NULL_VOID(titleNode);
1348     auto titleLayoutProperty = DynamicCast<LinearLayoutProperty>(titleNode->GetLayoutProperty());
1349     CHECK_NULL_VOID(titleLayoutProperty);
1350     auto pipeline = host->GetContext();
1351     CHECK_NULL_VOID(pipeline);
1352     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1353     CHECK_NULL_VOID(sheetTheme);
1354     auto showCloseIcon = true;
1355     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN)) {
1356         showCloseIcon = IsShowCloseIcon();
1357     }
1358     PaddingProperty padding;
1359 
1360     // The title bar area is reserved for the close button area size by default.
1361     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1362         auto sheetCloseIconTitleSpace = sheetTheme->GetSheetCloseIconTitleSpaceNew();
1363         padding.end =
1364             CalcLength(showCloseIcon ? sheetCloseIconTitleSpace + sheetTheme->GetCloseIconButtonWidth() : 0.0_vp);
1365     } else {
1366         padding.right = CalcLength(SHEET_CLOSE_ICON_TITLE_SPACE + SHEET_CLOSE_ICON_WIDTH);
1367     }
1368     titleLayoutProperty->UpdatePadding(padding);
1369     auto titleColumnPattern = titleNode->GetPattern<LinearLayoutPattern>();
1370     CHECK_NULL_VOID(titleColumnPattern);
1371     titleColumnPattern->CheckLocalized();
1372     titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1373 }
1374 
UpdateCloseIconStatus()1375 void SheetPresentationPattern::UpdateCloseIconStatus()
1376 {
1377     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1378         TAG_LOGI(AceLogTag::ACE_SHEET, "PlatformVersion less or equal to version 10");
1379         return;
1380     }
1381     auto showCloseIcon = IsShowCloseIcon();
1382     auto sheetCloseIcon = GetSheetCloseIcon();
1383     CHECK_NULL_VOID(sheetCloseIcon);
1384     auto iconLayoutProperty = sheetCloseIcon->GetLayoutProperty();
1385     CHECK_NULL_VOID(iconLayoutProperty);
1386     iconLayoutProperty->UpdateVisibility(showCloseIcon ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1387     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1388 }
1389 
UpdateSheetTitle()1390 void SheetPresentationPattern::UpdateSheetTitle()
1391 {
1392     auto host = GetHost();
1393     CHECK_NULL_VOID(host);
1394     auto pipeline = PipelineContext::GetCurrentContext();
1395     CHECK_NULL_VOID(pipeline);
1396     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1397     CHECK_NULL_VOID(layoutProperty);
1398     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1399     if (sheetStyle.sheetTitle.has_value()) {
1400         auto titleId = GetTitleId();
1401         auto titleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(titleId));
1402         CHECK_NULL_VOID(titleNode);
1403         auto titleProp = titleNode->GetLayoutProperty<TextLayoutProperty>();
1404         CHECK_NULL_VOID(titleProp);
1405         titleProp->UpdateContent(sheetStyle.sheetTitle.value());
1406         if (pipeline->GetFontScale() != scale_) {
1407             titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1408         }
1409         titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1410         if (sheetStyle.sheetSubtitle.has_value()) {
1411             auto subtitleId = GetSubtitleId();
1412             auto subtitleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(subtitleId));
1413             CHECK_NULL_VOID(subtitleNode);
1414             auto subtitleProp = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
1415             CHECK_NULL_VOID(subtitleProp);
1416             subtitleProp->UpdateContent(sheetStyle.sheetSubtitle.value());
1417             subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1418         }
1419     }
1420 }
1421 
GetDragBarHeight(const RefPtr<FrameNode> & dragBarNode)1422 Dimension SheetPresentationPattern::GetDragBarHeight(const RefPtr<FrameNode>& dragBarNode)
1423 {
1424     CHECK_NULL_RETURN(dragBarNode, 0.0_vp);
1425     auto dragBarLayoutProperty = dragBarNode->GetLayoutProperty();
1426     CHECK_NULL_RETURN(dragBarLayoutProperty, 0.0_vp);
1427     if (!dragBarLayoutProperty->HasVisibility()) {
1428         return 0.0_vp;
1429     }
1430     return (dragBarLayoutProperty->GetVisibility() == VisibleType::GONE) ? 0.0_vp : SHEET_DRAG_BAR_HEIGHT;
1431 }
1432 
UpdateFontScaleStatus()1433 void SheetPresentationPattern::UpdateFontScaleStatus()
1434 {
1435     auto host = GetHost();
1436     CHECK_NULL_VOID(host);
1437     auto pipeline = PipelineContext::GetCurrentContext();
1438     CHECK_NULL_VOID(pipeline);
1439     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1440     CHECK_NULL_VOID(layoutProperty);
1441     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1442     if (pipeline->GetFontScale() != scale_) {
1443         auto operationNode = GetTitleBuilderNode();
1444         CHECK_NULL_VOID(operationNode);
1445         auto titleColumnNode = DynamicCast<FrameNode>(operationNode->GetChildAtIndex(0));
1446         CHECK_NULL_VOID(titleColumnNode);
1447         auto layoutProps = operationNode->GetLayoutProperty<LinearLayoutProperty>();
1448         CHECK_NULL_VOID(layoutProps);
1449         auto titleLayoutProps = titleColumnNode->GetLayoutProperty<LinearLayoutProperty>();
1450         CHECK_NULL_VOID(titleLayoutProps);
1451         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1452         CHECK_NULL_VOID(sheetTheme);
1453         bool isSheetHasNoTitle = !sheetStyle.isTitleBuilder.has_value();
1454         bool isFontScaledInSystemTitle = sheetStyle.isTitleBuilder.has_value() && !sheetStyle.isTitleBuilder.value() &&
1455                                          GreatNotEqual(pipeline->GetFontScale(), sheetTheme->GetSheetNormalScale());
1456         if (isSheetHasNoTitle || isFontScaledInSystemTitle) {
1457             layoutProps->ClearUserDefinedIdealSize(false, true);
1458             titleLayoutProps->ClearUserDefinedIdealSize(false, true);
1459         } else if (sheetStyle.isTitleBuilder.has_value()) {
1460             auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1461             CHECK_NULL_VOID(sheetTheme);
1462             auto operationAreaHeight = sheetTheme->GetOperationAreaHeight();
1463             layoutProps->UpdateUserDefinedIdealSize(
1464                 CalcSize(std::nullopt, CalcLength(operationAreaHeight - sheetTheme->GetSheetTitleAreaMargin() -
1465                                                   GetDragBarHeight(GetDragBarNode()))));
1466             titleLayoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(operationAreaHeight)));
1467             if (sheetStyle.sheetSubtitle.has_value()) {
1468                 layoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
1469                     CalcLength(sheetTheme->GetOperationAreaHeightDouble() - sheetTheme->GetSheetTitleAreaMargin() -
1470                                GetDragBarHeight(GetDragBarNode()))));
1471                 titleLayoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
1472                     CalcLength(sheetTheme->GetOperationAreaHeightDouble() - SHEET_DOUBLE_TITLE_BOTTON_MARGIN)));
1473             }
1474         }
1475         UpdateSheetTitle();
1476         scale_ = pipeline->GetFontScale();
1477         auto sheetWrapper = host->GetParent();
1478         CHECK_NULL_VOID(sheetWrapper);
1479         sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1480     }
1481 }
1482 
UpdateSheetCloseIcon()1483 void SheetPresentationPattern::UpdateSheetCloseIcon()
1484 {
1485     auto host = GetHost();
1486     CHECK_NULL_VOID(host);
1487     auto pipeline = host->GetContext();
1488     CHECK_NULL_VOID(pipeline);
1489     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1490     CHECK_NULL_VOID(sheetTheme);
1491     auto sheetCloseIcon = DynamicCast<FrameNode>(host->GetChildAtIndex(2));
1492     CHECK_NULL_VOID(sheetCloseIcon);
1493     auto renderContext = sheetCloseIcon->GetRenderContext();
1494     CHECK_NULL_VOID(renderContext);
1495     renderContext->UpdateBackgroundColor(sheetTheme->GetCloseIconColor());
1496     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1497     auto iconNode = DynamicCast<FrameNode>(sheetCloseIcon->GetChildAtIndex(0));
1498     CHECK_NULL_VOID(iconNode);
1499     // when api >= 12, use symbol format image, else use image format.
1500     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
1501         SystemProperties::IsNeedSymbol()) {
1502         auto symbolLayoutProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
1503         CHECK_NULL_VOID(symbolLayoutProperty);
1504         symbolLayoutProperty->UpdateSymbolColorList({sheetTheme->GetCloseIconSymbolColor()});
1505     } else {
1506         auto imagePaintProperty = iconNode->GetPaintProperty<ImageRenderProperty>();
1507         CHECK_NULL_VOID(imagePaintProperty);
1508         imagePaintProperty->UpdateSvgFillColor(sheetTheme->GetCloseIconImageColor());
1509     }
1510     iconNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1511 }
1512 
UpdateSheetBackgroundColor()1513 void SheetPresentationPattern::UpdateSheetBackgroundColor()
1514 {
1515     auto host = GetHost();
1516     CHECK_NULL_VOID(host);
1517     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1518     CHECK_NULL_VOID(layoutProperty);
1519     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1520     if (sheetStyle.backgroundColor.has_value()) {
1521         return;
1522     }
1523     auto pipeline = host->GetContext();
1524     CHECK_NULL_VOID(pipeline);
1525     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1526     CHECK_NULL_VOID(sheetTheme);
1527     auto renderContext = host->GetRenderContext();
1528     CHECK_NULL_VOID(renderContext);
1529     renderContext->UpdateBackgroundColor(sheetTheme->GetSheetBackgoundColor());
1530     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1531 }
1532 
OnColorConfigurationUpdate()1533 void SheetPresentationPattern::OnColorConfigurationUpdate()
1534 {
1535     UpdateTitleTextColor();
1536     UpdateSheetCloseIcon();
1537     UpdateSheetBackgroundColor();
1538 }
1539 
GetWrapperHeight()1540 float SheetPresentationPattern::GetWrapperHeight()
1541 {
1542     auto host = GetHost();
1543     CHECK_NULL_RETURN(host, 0.0f);
1544     auto sheetWrapper = host->GetParent();
1545     CHECK_NULL_RETURN(sheetWrapper, 0.0f);
1546     auto sheetWrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper);
1547     CHECK_NULL_RETURN(sheetWrapperNode, 0.0f);
1548     auto sheetWrapperGeometryNode = sheetWrapperNode->GetGeometryNode();
1549     CHECK_NULL_RETURN(sheetWrapperGeometryNode, 0.0f);
1550     return sheetWrapperGeometryNode->GetFrameSize().Height();
1551 }
1552 
GetWrapperWidth()1553 float SheetPresentationPattern::GetWrapperWidth()
1554 {
1555     auto host = GetHost();
1556     CHECK_NULL_RETURN(host, 0.0f);
1557     auto sheetWrapper = host->GetParent();
1558     CHECK_NULL_RETURN(sheetWrapper, 0.0f);
1559     auto sheetWrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper);
1560     CHECK_NULL_RETURN(sheetWrapperNode, 0.0f);
1561     auto sheetWrapperGeometryNode = sheetWrapperNode->GetGeometryNode();
1562     CHECK_NULL_RETURN(sheetWrapperGeometryNode, 0.0f);
1563     return sheetWrapperGeometryNode->GetFrameSize().Width();
1564 }
1565 
SheetHeightNeedChanged()1566 bool SheetPresentationPattern::SheetHeightNeedChanged()
1567 {
1568     auto host = GetHost();
1569     CHECK_NULL_RETURN(host, false);
1570     auto sheetGeometryNode = host->GetGeometryNode();
1571     CHECK_NULL_RETURN(sheetGeometryNode, false);
1572     if (!NearEqual(sheetGeometryNode->GetFrameSize().Height(), sheetObject_->GetSheetHeight()) ||
1573         !NearEqual(GetWrapperHeight(), wrapperHeight_)) {
1574         return true;
1575     }
1576     return false;
1577 }
1578 
SheetWidthNeedChanged()1579 bool SheetPresentationPattern::SheetWidthNeedChanged()
1580 {
1581     auto host = GetHost();
1582     CHECK_NULL_RETURN(host, false);
1583     auto sheetGeometryNode = host->GetGeometryNode();
1584     CHECK_NULL_RETURN(sheetGeometryNode, false);
1585     if (!NearEqual(sheetGeometryNode->GetFrameSize().Width(), sheetWidth_) ||
1586         !NearEqual(GetWrapperWidth(), wrapperWidth_)) {
1587         return true;
1588     }
1589     return false;
1590 }
1591 
UpdateMaskBackgroundColor()1592 void SheetPresentationPattern::UpdateMaskBackgroundColor()
1593 {
1594     auto host = GetHost();
1595     CHECK_NULL_VOID(host);
1596     auto pipeline = host->GetContext();
1597     CHECK_NULL_VOID(pipeline);
1598     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1599     CHECK_NULL_VOID(sheetTheme);
1600     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1601     CHECK_NULL_VOID(layoutProperty);
1602     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1603     sheetMaskColor_ = sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor());
1604     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1605         if (sheetStyle.maskColor.has_value()) {
1606             sheetMaskColor_ = sheetStyle.maskColor.value();
1607         } else {
1608             sheetMaskColor_ = Color::TRANSPARENT;
1609         }
1610     } else {
1611         if ((!sheetStyle.interactive.has_value() && GetSheetTypeNoProcess() == SheetType::SHEET_POPUP) ||
1612             sheetStyle.interactive.value_or(false)) {
1613             sheetMaskColor_ = Color::TRANSPARENT;
1614         }
1615     }
1616 }
1617 
UpdateMaskBackgroundColorRender()1618 void SheetPresentationPattern::UpdateMaskBackgroundColorRender()
1619 {
1620     if (GetDismissProcess()) {
1621         return;
1622     }
1623     auto host = GetHost();
1624     CHECK_NULL_VOID(host);
1625     UpdateMaskBackgroundColor();
1626     const auto& overlayManager = GetOverlayManager();
1627     CHECK_NULL_VOID(overlayManager);
1628     auto maskNode = overlayManager->GetSheetMask(host);
1629     CHECK_NULL_VOID(maskNode);
1630     auto maskRenderContext = maskNode->GetRenderContext();
1631     CHECK_NULL_VOID(maskRenderContext);
1632     maskRenderContext->UpdateBackgroundColor(sheetMaskColor_);
1633 }
1634 
FireCommonCallback()1635 void SheetPresentationPattern::FireCommonCallback()
1636 {
1637     FireOnTypeDidChange();
1638     FireOnWidthDidChange();
1639     FireOnHeightDidChange();
1640 }
1641 
PopupSheetChanged()1642 void SheetPresentationPattern::PopupSheetChanged()
1643 {
1644     // when sheet height and width not change, but sheetOffsetY changed because of avoiding keyboard, update offsetY.
1645     if (SheetHeightNeedChanged() || SheetWidthNeedChanged() || typeChanged_ || sheetOffsetYChanged_) {
1646         FireCommonCallback();
1647         auto renderContext = GetRenderContext();
1648         CHECK_NULL_VOID(renderContext);
1649         renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_), 0.0f });
1650         typeChanged_ = false;
1651         sheetOffsetYChanged_ = false;
1652     }
1653 }
1654 
CheckSheetHeightChange()1655 void SheetPresentationPattern::CheckSheetHeightChange()
1656 {
1657     auto host = GetHost();
1658     CHECK_NULL_VOID(host);
1659     auto sheetGeometryNode = host->GetGeometryNode();
1660     CHECK_NULL_VOID(sheetGeometryNode);
1661     if (!isFirstInit_) {
1662         if (typeChanged_) {
1663             if (sheetType_ == SheetType::SHEET_POPUP) {
1664                 MarkSheetPageNeedRender();
1665             }
1666             SetSheetBorderWidth();
1667         }
1668         if (sheetType_ == SheetType::SHEET_POPUP) {
1669             PopupSheetChanged();
1670         } else if (SheetHeightNeedChanged() || typeChanged_ || windowChanged_ || topSafeAreaChanged_) {
1671             const auto& overlayManager = GetOverlayManager();
1672             CHECK_NULL_VOID(overlayManager);
1673             auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1674             CHECK_NULL_VOID(layoutProperty);
1675             auto sheetStyle = layoutProperty->GetSheetStyleValue();
1676             overlayManager->ComputeSheetOffset(sheetStyle, host);
1677             overlayManager->PlaySheetTransition(host, true, false);
1678             auto maskNode = overlayManager->GetSheetMask(host);
1679             if (maskNode) {
1680                 UpdateMaskBackgroundColorRender();
1681             }
1682             windowChanged_ = false;
1683             topSafeAreaChanged_ = false;
1684             typeChanged_ = false;
1685         }
1686     }
1687     sheetObject_->SetSheetHeight(sheetGeometryNode->GetFrameSize().Height());
1688     sheetWidth_ = sheetGeometryNode->GetFrameSize().Width();
1689     wrapperHeight_ = GetWrapperHeight();
1690     wrapperWidth_ = GetWrapperWidth();
1691     isFirstInit_ = false;
1692     GetBuilderInitHeight();
1693 }
1694 
IsCustomDetentsChanged(SheetStyle sheetStyle)1695 void SheetPresentationPattern::IsCustomDetentsChanged(SheetStyle sheetStyle)
1696 {
1697     unsigned int preDetentsSize = preDetents_.size();
1698     unsigned int userSetDetentsSize = sheetStyle.detents.size();
1699     // if preview detents size is not equal to the new one, set detents index to zero
1700     if (preDetentsSize != userSetDetentsSize) {
1701         detentsFinalIndex_ = 0;
1702         return;
1703     }
1704 
1705     // check whether the new coming one's content is equal to the last time input
1706     unsigned int length = std::min(preDetentsSize, userSetDetentsSize);
1707     for (unsigned int index = 0; index < length; index++) {
1708         if (sheetStyle.detents[index] != preDetents_[index]) {
1709             // if detents has been changed, set detents index to zero
1710             detentsFinalIndex_ = 0;
1711             break;
1712         }
1713     }
1714 }
1715 
InitSheetDetents()1716 void SheetPresentationPattern::InitSheetDetents()
1717 {
1718     // record input detents
1719     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1720     CHECK_NULL_VOID(layoutProperty);
1721     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1722     IsCustomDetentsChanged(sheetStyle);
1723     preDetents_.clear();
1724     sheetDetentHeight_.clear();
1725     unSortedSheetDentents_.clear();
1726     float height = 0.0f;
1727     auto sheetNode = GetHost();
1728     CHECK_NULL_VOID(sheetNode);
1729     auto geometryNode = sheetNode->GetGeometryNode();
1730     CHECK_NULL_VOID(geometryNode);
1731     auto pipelineContext = sheetNode->GetContext();
1732     CHECK_NULL_VOID(pipelineContext);
1733     auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
1734     CHECK_NULL_VOID(sheetTheme);
1735     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1736     auto sheetType = GetSheetTypeNoProcess();
1737     auto sheetFrameHeight = geometryNode->GetFrameSize().Height();
1738     auto mediumSize = sheetTheme->GetMediumPercent();
1739     float largeHeightOfTheme = sheetTheme->GetHeightApplyFullScreen() ? pageHeight_ : largeHeight;
1740     largeHeightOfTheme *= sheetTheme->GetLargePercent();
1741     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1742         mediumSize = MEDIUM_SIZE_PRE;
1743     }
1744     switch (sheetType) {
1745         case SheetType::SHEET_BOTTOMLANDSPACE:
1746             if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1747                 height = sheetFrameHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1748                 sheetDetentHeight_.emplace_back(height);
1749                 break;
1750             }
1751             [[fallthrough]];
1752         case SheetType::SHEET_BOTTOM:
1753             [[fallthrough]];
1754         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
1755             if (sheetStyle.detents.size() <= 0) {
1756                 height = InitialSingleGearHeight(sheetStyle);
1757                 sheetDetentHeight_.emplace_back(height);
1758                 break;
1759             }
1760             InitDetents(sheetStyle, height, mediumSize, largeHeightOfTheme, largeHeight);
1761             std::sort(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), std::less<float>());
1762             sheetDetentHeight_.erase(
1763                 std::unique(sheetDetentHeight_.begin(), sheetDetentHeight_.end()), sheetDetentHeight_.end());
1764             break;
1765         case SheetType::SHEET_CENTER:
1766             height = (centerHeight_ + pageHeight_) / SHEET_HALF_HEIGHT;
1767             sheetDetentHeight_.emplace_back(height);
1768             break;
1769         case SheetType::SHEET_BOTTOM_OFFSET:
1770             height = InitialSingleGearHeight(sheetStyle);
1771             sheetDetentHeight_.emplace_back(height);
1772             break;
1773         default:
1774             break;
1775     }
1776 }
1777 
InitDetents(SheetStyle sheetStyle,float height,double mediumSize,float largeHeightOfTheme,double largeHeight)1778 void SheetPresentationPattern::InitDetents(
1779     SheetStyle sheetStyle, float height, double mediumSize, float largeHeightOfTheme, double largeHeight)
1780 {
1781     for (auto iter : sheetStyle.detents) {
1782         preDetents_.emplace_back(iter);
1783         if (iter.sheetMode.has_value()) {
1784             if (iter.sheetMode == SheetMode::MEDIUM) {
1785                 height = pageHeight_ * mediumSize;
1786             } else if (iter.sheetMode == SheetMode::LARGE) {
1787                 height = largeHeightOfTheme;
1788             } else if (iter.sheetMode == SheetMode::AUTO) {
1789                 height = GetFitContentHeight();
1790                 height = GreatNotEqual(height, largeHeight) ? largeHeight : height;
1791                 HandleFitContontChange(height);
1792             }
1793         } else {
1794             if (iter.height->Unit() == DimensionUnit::PERCENT) {
1795                 height = iter.height->ConvertToPxWithSize(sheetMaxHeight_);
1796             } else {
1797                 height = iter.height->ConvertToPx();
1798             }
1799             if (GreatNotEqual(height, largeHeight)) {
1800                 height = largeHeight;
1801             } else if (LessNotEqual(height, 0)) {
1802                 height = largeHeight;
1803             }
1804         }
1805         sheetDetentHeight_.emplace_back(height);
1806         unSortedSheetDentents_.emplace_back(height);
1807     }
1808 }
1809 
HandleFitContontChange(float height)1810 void SheetPresentationPattern::HandleFitContontChange(float height)
1811 {
1812     if ((NearEqual(height_, sheetFitContentHeight_)) && (!NearEqual(height, sheetFitContentHeight_))) {
1813         ChangeSheetHeight(height);
1814         ChangeSheetPage(height_);
1815         SheetTransition(true);
1816     }
1817     sheetFitContentHeight_ = height;
1818 }
1819 
ComputeTransitionOffset(float sheetHeight)1820 float SheetPresentationPattern::ComputeTransitionOffset(float sheetHeight)
1821 {
1822     float offset = 0.0f;
1823     auto sheetType = GetSheetTypeNoProcess();
1824     if (sheetType == SheetType::SHEET_POPUP ||
1825         sheetType == SheetType::SHEET_BOTTOM_OFFSET || IsCurSheetNeedHalfFoldHover()
1826         || IsNotBottomStyleInSubwindow()) {
1827         offset = GetSheetOffset();
1828     } else {
1829         offset = GetPageHeightWithoutOffset() - sheetHeight;
1830     }
1831     return offset;
1832 }
1833 
GetSubWindowId() const1834 int32_t SheetPresentationPattern::GetSubWindowId() const
1835 {
1836     auto host = GetHost();
1837     CHECK_NULL_RETURN(host, INVALID_SUBWINDOW_ID);
1838     auto sheetWrapper = host->GetParent();
1839     CHECK_NULL_RETURN(sheetWrapper, INVALID_SUBWINDOW_ID);
1840     auto wrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper);
1841     auto sheetWrapperPattern = wrapperNode->GetPattern<SheetWrapperPattern>();
1842     CHECK_NULL_RETURN(sheetWrapperPattern, INVALID_SUBWINDOW_ID);
1843     return sheetWrapperPattern->GetSubWindowId();
1844 }
1845 
ComputeSheetTypeInSubWindow() const1846 SheetType SheetPresentationPattern::ComputeSheetTypeInSubWindow() const
1847 {
1848     auto instanceId = SubwindowManager::GetInstance()->GetParentContainerId(GetSubWindowId());
1849     auto container = AceEngine::Get().GetContainer(instanceId);
1850     CHECK_NULL_RETURN(container, SheetType::SHEET_CENTER);
1851     auto mainWindowContext = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1852     CHECK_NULL_RETURN(mainWindowContext, SheetType::SHEET_CENTER);
1853     auto windowWidth = mainWindowContext->GetDisplayWindowRectInfo().Width();
1854     auto windowHeight = mainWindowContext->GetDisplayWindowRectInfo().Height();
1855     auto manager = mainWindowContext->GetWindowManager();
1856     if (container->IsUIExtensionWindow()) {
1857         auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(GetSubWindowId(),
1858             SubwindowType::TYPE_SHEET);
1859         CHECK_NULL_RETURN(subwindow, SheetType::SHEET_CENTER);
1860         windowWidth = subwindow->GetUIExtensionHostWindowRect().Width();
1861         windowHeight = subwindow->GetUIExtensionHostWindowRect().Height();
1862     }
1863     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1864     CHECK_NULL_RETURN(layoutProperty, SheetType::SHEET_CENTER);
1865     auto sheetStyle = layoutProperty->GetSheetStyleValue();
1866     auto sheetType =  SheetType::SHEET_CENTER;
1867     if (manager && manager->IsPcOrPadFreeMultiWindowMode()) {
1868         // Two in one or pad free-window mode
1869         if (sheetStyle.sheetType.has_value() &&
1870             sheetStyle.sheetType.value() == SheetType::SHEET_POPUP && sheetKey_.hasValidTargetNode) {
1871             return SheetType::SHEET_POPUP;
1872         }
1873         return sheetType;
1874     }
1875     if (LessOrEqual(windowWidth, SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
1876         return SheetType::SHEET_BOTTOM;
1877     }
1878     if (LessOrEqual(windowWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) &&
1879         GreatOrEqual(windowWidth, SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) &&
1880         LessOrEqual(windowWidth, BOTTOM_STYLE_RATIO * windowHeight)) {
1881         // phone in landsapce
1882         if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM) {
1883             return SheetType::SHEET_BOTTOM;
1884         }
1885         return SheetType::SHEET_BOTTOMLANDSPACE;
1886     }
1887     if (sheetStyle.sheetType.has_value()) {
1888         sheetType = sheetStyle.sheetType.value();
1889     }
1890     if (sheetStyle.sheetType.value() == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
1891         sheetType = SheetType::SHEET_CENTER;
1892     }
1893     return sheetType;
1894 }
1895 
InitSheetTransitionAction(float offset)1896 void SheetPresentationPattern::InitSheetTransitionAction(float offset)
1897 {
1898     auto sheetNode = GetHost();
1899     CHECK_NULL_VOID(sheetNode);
1900     auto context = sheetNode->GetRenderContext();
1901     CHECK_NULL_VOID(context);
1902     if (IsShowInSubWindowTwoInOne()) {
1903         context->UpdateOpacity(0.0);
1904         context->UpdateTransformTranslate({ 0.0f, SUBWINDOW_SHEET_TRANSLATION.ConvertToPx() + offset, 0.0f });
1905     } else {
1906         context->UpdateTransformTranslate({ 0.0f, pageHeight_, 0.0f });
1907     }
1908 }
1909 
SheetTransitionAction(float offset,bool isFirstTransition,bool isTransitionIn)1910 void SheetPresentationPattern::SheetTransitionAction(float offset, bool isFirstTransition, bool isTransitionIn)
1911 {
1912     auto sheetNode = GetHost();
1913     CHECK_NULL_VOID(sheetNode);
1914     auto context = sheetNode->GetRenderContext();
1915     CHECK_NULL_VOID(context);
1916     if (!isTransitionIn) {
1917         // play sheet dismiss transition and move sheet down to out of screen
1918         InitSheetTransitionAction(offset);
1919         return;
1920     }
1921     // play sheet enter transition
1922     if (isFirstTransition) {
1923         // move sheet down to out of screen
1924         InitSheetTransitionAction(offset);
1925     } else {
1926         // move sheet up
1927         if (IsShowInSubWindowTwoInOne()) {
1928             context->UpdateOpacity(1.0);
1929         }
1930         context->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1931     }
1932 }
1933 
GetSheetTypeFromSheetManager() const1934 SheetType SheetPresentationPattern::GetSheetTypeFromSheetManager() const
1935 {
1936     SheetType sheetType = SheetType::SHEET_BOTTOM;
1937     auto host = GetHost();
1938     CHECK_NULL_RETURN(host, sheetType);
1939     if (!host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) {
1940         return SHEET_BOTTOM;
1941     }
1942 #ifdef PREVIEW
1943     sheetType = GetSheetType();
1944 #else
1945     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1946     CHECK_NULL_RETURN(layoutProperty, sheetType);
1947     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
1948     if (sheetStyle.instanceId.has_value()) {
1949         return GetSheetType();
1950     }
1951     if (sheetStyle.showInSubWindow.value_or(false)) {
1952         return ComputeSheetTypeInSubWindow();
1953     }
1954     DeviceType deviceType = SystemProperties::GetDeviceType();
1955     if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM) {
1956         return sheetStyle.bottomOffset.has_value() && deviceType == DeviceType::TWO_IN_ONE ?
1957             SheetType::SHEET_BOTTOM_OFFSET : SheetType::SHEET_BOTTOM;
1958     }
1959     auto pipeline = host->GetContext();
1960     CHECK_NULL_RETURN(pipeline, sheetType);
1961     auto windowManager = pipeline->GetWindowManager();
1962     CHECK_NULL_RETURN(windowManager, sheetType);
1963     auto widthBreakpoints = windowManager->GetWidthBreakpointCallback();
1964     auto heightBreakpoints = windowManager->GetHeightBreakpointCallback();
1965     auto state =
1966         SheetManager::GetInstance().CreateBreakPointState(widthBreakpoints, heightBreakpoints);
1967     sheetType = state->HandleType(sheetStyle);
1968     // When hasValidTargetNode is false, meaning the target node has not been provided,
1969     // set popup style actually takes effect as the center style.
1970     if (sheetType == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
1971         sheetType = SheetType::SHEET_CENTER;
1972     }
1973 #endif
1974     return sheetType;
1975 }
1976 
GetSheetType() const1977 SheetType SheetPresentationPattern::GetSheetType() const
1978 {
1979     SheetType sheetType = SheetType::SHEET_BOTTOM;
1980     auto host = GetHost();
1981     CHECK_NULL_RETURN(host, sheetType);
1982     if (!host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) {
1983         return SHEET_BOTTOM;
1984     }
1985     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1986     CHECK_NULL_RETURN(layoutProperty, sheetType);
1987     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
1988     if (sheetStyle.showInSubWindow.value_or(false)) {
1989         return ComputeSheetTypeInSubWindow();
1990     }
1991     auto pipelineContext = host->GetContext();
1992     CHECK_NULL_RETURN(pipelineContext, sheetType);
1993     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
1994     TAG_LOGD(AceLogTag::ACE_SHEET, "GetSheetType displayWindowRect info is : %{public}s",
1995         windowGlobalRect.ToString().c_str());
1996     // first check SHEET_CONTENT_COVER, then check SHEET_BOTTOM
1997     if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_CONTENT_COVER) {
1998         return SheetType::SHEET_CONTENT_COVER;
1999     }
2000     DeviceType deviceType = SystemProperties::GetDeviceType();
2001     // only bottom when width is less than 600vp
2002     if ((windowGlobalRect.Width() < SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) ||
2003         (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM)) {
2004         return sheetStyle.bottomOffset.has_value() && deviceType == DeviceType::TWO_IN_ONE ?
2005             SheetType::SHEET_BOTTOM_OFFSET : SheetType::SHEET_BOTTOM;
2006     }
2007     if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_SIDE) {
2008         return SheetType::SHEET_SIDE;
2009     }
2010     if (sheetThemeType_ == "auto") {
2011         GetSheetTypeWithAuto(sheetType);
2012     } else if (sheetThemeType_ == "popup") {
2013         GetSheetTypeWithPopup(sheetType);
2014     } else if (sheetThemeType_ == "center") {
2015         GetSheetTypeWithCenter(sheetType);
2016     }
2017     return sheetType;
2018 }
2019 
InitSheetMode()2020 void SheetPresentationPattern::InitSheetMode()
2021 {
2022     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2023     CHECK_NULL_VOID(layoutProperty);
2024     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2025     scrollSizeMode_ = sheetStyle.scrollSizeMode.value_or(ScrollSizeMode::FOLLOW_DETENT);
2026     keyboardAvoidMode_ = sheetStyle.sheetKeyboardAvoidMode.value_or(sheetObject_->GetAvoidKeyboardModeByDefault());
2027     sheetEffectEdge_ = sheetStyle.sheetEffectEdge.value_or(SheetEffectEdge::ALL);
2028 }
2029 
GetSheetTypeWithAuto(SheetType & sheetType) const2030 void SheetPresentationPattern::GetSheetTypeWithAuto(SheetType& sheetType) const
2031 {
2032     double rootWidth = 0.0;
2033     double rootHeight = 0.0;
2034     auto host = GetHost();
2035     CHECK_NULL_VOID(host);
2036     auto pipeline = host->GetContext();
2037     CHECK_NULL_VOID(pipeline);
2038     if (windowSize_.has_value()) {
2039         rootWidth = windowSize_.value().Width();
2040         rootHeight = windowSize_.value().Height();
2041     } else {
2042         rootWidth = pipeline->GetRootWidth();
2043         rootHeight = pipeline->GetRootHeight();
2044     }
2045     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
2046     CHECK_NULL_VOID(sheetTheme);
2047 #ifdef PREVIEW
2048     auto container = Container::Current();
2049     CHECK_NULL_VOID(container);
2050     if (container->IsFoldable() && container->GetCurrentFoldStatus() == FoldStatus::EXPAND) {
2051 #else
2052     // when big fold expand
2053     if (IsFoldExpand() && !sheetTheme->IsOnlyBottom()) {
2054 #endif
2055         sheetType = SheetType::SHEET_CENTER;
2056         auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2057         CHECK_NULL_VOID(layoutProperty);
2058         auto sheetStyle = layoutProperty->GetSheetStyleValue();
2059         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN) &&
2060             sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_POPUP) {
2061             sheetType = SheetType::SHEET_POPUP;
2062         }
2063     } else {
2064         if (LessNotEqual(rootHeight, rootWidth)) {
2065             sheetType = SheetType::SHEET_BOTTOMLANDSPACE;
2066         } else {
2067             sheetType = SheetType::SHEET_BOTTOM;
2068         }
2069     }
2070 }
2071 
2072 void SheetPresentationPattern::GetSheetTypeWithPopup(SheetType& sheetType) const
2073 {
2074     auto pipelineContext = PipelineContext::GetCurrentContext();
2075     double rootWidth = 0.0;
2076     if (windowSize_.has_value()) {
2077         rootWidth = windowSize_.value().Width();
2078     } else {
2079         rootWidth = PipelineContext::GetCurrentRootWidth();
2080     }
2081     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2082     CHECK_NULL_VOID(layoutProperty);
2083     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2084 #ifdef PREVIEW
2085     rootWidth = pipelineContext->GetDisplayWindowRectInfo().Width();
2086 #endif
2087     if (GreatOrEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
2088         if (sheetStyle.sheetType.has_value()) {
2089             sheetType = sheetStyle.sheetType.value();
2090         } else {
2091             sheetType = SheetType::SHEET_POPUP;
2092         }
2093     } else if (GreatOrEqual(rootWidth, SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) &&
2094                LessNotEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
2095         if (sheetStyle.sheetType.has_value()) {
2096             sheetType = sheetStyle.sheetType.value();
2097         } else {
2098             sheetType = SheetType::SHEET_CENTER;
2099         }
2100     } else {
2101         sheetType = SheetType::SHEET_BOTTOM_FREE_WINDOW;
2102     }
2103     if (sheetType == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
2104         sheetType = SheetType::SHEET_CENTER;
2105     }
2106 }
2107 
2108 void SheetPresentationPattern::GetSheetTypeWithCenter(SheetType& sheetType) const
2109 {
2110     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2111     CHECK_NULL_VOID(layoutProperty);
2112     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2113     if (sheetStyle.sheetType.has_value()) {
2114         sheetType = sheetStyle.sheetType.value();
2115         return;
2116     }
2117     double rootWidth = 0.0;
2118     if (windowSize_.has_value()) {
2119         rootWidth = windowSize_.value().Width();
2120     } else {
2121         rootWidth = PipelineContext::GetCurrentRootWidth();
2122     }
2123     if (GreatOrEqual(rootWidth, SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
2124         sheetType = SheetType::SHEET_CENTER;
2125     } else {
2126         // SHEET_BOTTOMLANDSPACE need to adapt
2127         sheetType = SheetType::SHEET_BOTTOM;
2128     }
2129 }
2130 
2131 void SheetPresentationPattern::SetUIFirstSwitch(bool isFirstTransition, bool isNone)
2132 {
2133 #ifdef ENABLE_ROSEN_BACKEND
2134     if (!isFirstTransition) {
2135         return;
2136     }
2137     auto host = GetHost();
2138     CHECK_NULL_VOID(host);
2139     auto rosenContext = DynamicCast<RosenRenderContext>(host->GetRenderContext());
2140     CHECK_NULL_VOID(rosenContext);
2141     rosenContext->SetUIFirstSwitch(
2142         isNone ? OHOS::Rosen::RSUIFirstSwitch::NONE : OHOS::Rosen::RSUIFirstSwitch::MODAL_WINDOW_CLOSE);
2143 #endif
2144 }
2145 
2146 void SheetPresentationPattern::SetWindowUseImplicitAnimation(FrameNode* sheetNode, bool useImplicit)
2147 {
2148     CHECK_NULL_VOID(sheetNode);
2149     auto layoutProperty = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
2150     CHECK_NULL_VOID(layoutProperty);
2151     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2152     if (sheetStyle.showInSubWindow.value_or(false)) {
2153         TAG_LOGD(AceLogTag::ACE_SHEET, "UseImplicitAnimation ShowInSubWindow");
2154         return;
2155     }
2156     auto pipelineContext = sheetNode->GetContext();
2157     CHECK_NULL_VOID(pipelineContext);
2158     auto windowManager = pipelineContext->GetWindowManager();
2159     CHECK_NULL_VOID(windowManager);
2160     TAG_LOGI(AceLogTag::ACE_SHEET, "WindowUseImplicitAnimation: %{public}d", useImplicit);
2161     windowManager->SetWindowUseImplicitAnimation(useImplicit);
2162 }
2163 
2164 void SheetPresentationPattern::BubbleStyleSheetTransition(bool isTransitionIn)
2165 {
2166     auto host = this->GetHost();
2167     CHECK_NULL_VOID(host);
2168     if (!isTransitionIn) {
2169         const auto& overlayManager = GetOverlayManager();
2170         CHECK_NULL_VOID(overlayManager);
2171         auto maskNode = overlayManager->GetSheetMask(host);
2172         if (maskNode) {
2173             overlayManager->PlaySheetMaskTransition(maskNode, host, false);
2174         }
2175         StartOffsetExitingAnimation();
2176         StartAlphaExitingAnimation(
2177             [weakNode = AceType::WeakClaim(AceType::RawPtr(host)), weakPattern = AceType::WeakClaim(this)]() {
2178                 auto node = weakNode.Upgrade();
2179                 CHECK_NULL_VOID(node);
2180                 auto pattern = weakPattern.Upgrade();
2181                 CHECK_NULL_VOID(pattern);
2182                 const auto& overlayManager = pattern->GetOverlayManager();
2183                 CHECK_NULL_VOID(overlayManager);
2184                 overlayManager->FireAutoSave(node);
2185                 pattern->OnDisappear();
2186                 overlayManager->RemoveSheet(node);;
2187                 pattern->FireCallback("false");
2188             });
2189         overlayManager->CleanSheet(host, GetSheetKey());
2190     }
2191 }
2192 
2193 void SheetPresentationPattern::StartOffsetEnteringAnimation()
2194 {
2195     AnimationOption optionPosition;
2196     optionPosition.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
2197     optionPosition.SetCurve(Curves::FRICTION);
2198     auto host = GetHost();
2199     CHECK_NULL_VOID(host);
2200     auto pipeline = host->GetContextRefPtr();
2201     AnimationUtils::Animate(
2202         optionPosition,
2203         [weak = WeakClaim(this)]() {
2204             auto pattern = weak.Upgrade();
2205             CHECK_NULL_VOID(pattern);
2206             auto renderContext = pattern->GetRenderContext();
2207             CHECK_NULL_VOID(renderContext);
2208             renderContext->UpdateTransformTranslate({ 0.0f, Dimension(pattern->sheetOffsetY_), 0.0f });
2209         },
2210         nullptr, nullptr, pipeline);
2211 }
2212 
2213 void SheetPresentationPattern::StartAlphaEnteringAnimation(std::function<void()> finish)
2214 {
2215     AnimationOption optionAlpha;
2216     optionAlpha.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
2217     optionAlpha.SetCurve(Curves::SHARP);
2218     auto host = GetHost();
2219     CHECK_NULL_VOID(host);
2220     auto pipeline = host->GetContextRefPtr();
2221     AnimationUtils::Animate(
2222         optionAlpha,
2223         [weak = WeakClaim(this)]() {
2224             auto pattern = weak.Upgrade();
2225             CHECK_NULL_VOID(pattern);
2226             auto renderContext = pattern->GetRenderContext();
2227             CHECK_NULL_VOID(renderContext);
2228             renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
2229         },
2230         finish, nullptr, pipeline);
2231 }
2232 
2233 void SheetPresentationPattern::StartOffsetExitingAnimation()
2234 {
2235     AnimationOption optionPosition;
2236     optionPosition.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
2237     optionPosition.SetCurve(Curves::FRICTION);
2238     auto host = GetHost();
2239     CHECK_NULL_VOID(host);
2240     auto pipeline = host->GetContextRefPtr();
2241     AnimationUtils::Animate(
2242         optionPosition,
2243         [weak = WeakClaim(this)]() {
2244             auto pattern = weak.Upgrade();
2245             CHECK_NULL_VOID(pattern);
2246             auto renderContext = pattern->GetRenderContext();
2247             CHECK_NULL_VOID(renderContext);
2248             renderContext->UpdateTransformTranslate(
2249                 { 0.0f, Dimension(pattern->sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
2250         },
2251         nullptr, nullptr, pipeline);
2252 }
2253 
2254 void SheetPresentationPattern::StartAlphaExitingAnimation(std::function<void()> finish)
2255 {
2256     AnimationOption optionAlpha;
2257     optionAlpha.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
2258     optionAlpha.SetCurve(Curves::SHARP);
2259     auto host = GetHost();
2260     CHECK_NULL_VOID(host);
2261     auto pipeline = host->GetContextRefPtr();
2262     AnimationUtils::Animate(
2263         optionAlpha,
2264         [weak = WeakClaim(this)]() {
2265             auto pattern = weak.Upgrade();
2266             CHECK_NULL_VOID(pattern);
2267             auto renderContext = pattern->GetRenderContext();
2268             CHECK_NULL_VOID(renderContext);
2269             renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
2270         },
2271         finish, nullptr, pipeline);
2272 }
2273 
2274 RefPtr<RenderContext> SheetPresentationPattern::GetRenderContext()
2275 {
2276     auto frameNode = GetHost();
2277     CHECK_NULL_RETURN(frameNode, nullptr);
2278     return frameNode->GetRenderContext();
2279 }
2280 
2281 bool SheetPresentationPattern::PostTask(const TaskExecutor::Task& task, const std::string& name)
2282 {
2283     auto pipeline = PipelineBase::GetCurrentContext();
2284     CHECK_NULL_RETURN(pipeline, false);
2285     auto taskExecutor = pipeline->GetTaskExecutor();
2286     CHECK_NULL_RETURN(taskExecutor, false);
2287     return taskExecutor->PostTask(task, TaskExecutor::TaskType::UI, name);
2288 }
2289 
2290 void SheetPresentationPattern::ResetToInvisible()
2291 {
2292     auto renderContext = GetRenderContext();
2293     CHECK_NULL_VOID(renderContext);
2294     renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
2295     renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
2296 }
2297 
2298 bool SheetPresentationPattern::IsFoldExpand() const
2299 {
2300     bool isExpand = false;
2301     auto container = Container::CurrentSafelyWithCheck();
2302     CHECK_NULL_RETURN(container, false);
2303     auto foldStatus = container->GetCurrentFoldStatus();
2304     isExpand = foldStatus != FoldStatus::FOLDED && foldStatus != FoldStatus::UNKNOWN;
2305     if (isExpand) {
2306         TAG_LOGD(AceLogTag::ACE_SHEET, "Get Fold status IsFoldExpand is true");
2307         return true;
2308     } else {
2309         return false;
2310     }
2311 }
2312 
2313 void SheetPresentationPattern::ChangeSheetHeight(float height)
2314 {
2315     if (!NearEqual(height_, height)) {
2316         isDirectionUp_ = GreatNotEqual(height, height_);
2317         height_ = height;
2318         SetCurrentHeightToOverlay(height_);
2319     }
2320 }
2321 
2322 void SheetPresentationPattern::StartSheetTransitionAnimation(
2323     const AnimationOption& option, bool isTransitionIn, float offset)
2324 {
2325     auto host = GetHost();
2326     CHECK_NULL_VOID(host);
2327     auto context = host->GetRenderContext();
2328     CHECK_NULL_VOID(context);
2329     isAnimationProcess_ = true;
2330     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
2331     CHECK_NULL_VOID(sheetPattern);
2332     auto pipeline = host->GetContextRefPtr();
2333     if (isTransitionIn) {
2334         HandleDragEndAccessibilityEvent();
2335         animation_ = AnimationUtils::StartAnimation(option,
2336             sheetObject_->GetSheetAnimationEvent(isTransitionIn, offset), option.GetOnFinishEvent(), nullptr, pipeline);
2337         SetBottomStyleHotAreaInSubwindow();
2338     } else {
2339         StopModifySheetTransition();
2340         animation_ = AnimationUtils::StartAnimation(option,
2341             sheetObject_->GetSheetAnimationEvent(isTransitionIn, offset), option.GetOnFinishEvent(), nullptr, pipeline);
2342         const auto& overlayManager = GetOverlayManager();
2343         CHECK_NULL_VOID(overlayManager);
2344         overlayManager->CleanSheet(host, GetSheetKey());
2345     }
2346 }
2347 
2348 void SheetPresentationPattern::DismissSheetShadow(const RefPtr<RenderContext>& context)
2349 {
2350     auto shadow = context->GetBackShadow();
2351     if (!shadow.has_value()) {
2352         shadow = Shadow::CreateShadow(ShadowStyle::None);
2353     }
2354     auto color = shadow->GetColor();
2355     auto newColor = color.ChangeAlpha(0);
2356     shadow->SetColor(newColor);
2357     context->UpdateBackShadow(shadow.value());
2358 }
2359 
2360 void SheetPresentationPattern::ClipSheetNode()
2361 {
2362     sheetObject_->ClipSheetNode();
2363 }
2364 
2365 bool SheetPresentationPattern::IsWindowSizeChangedWithUndefinedReason(
2366     int32_t width, int32_t height, WindowSizeChangeReason type)
2367 {
2368     bool isWindowChanged = false;
2369     if (windowSize_.has_value()) {
2370         isWindowChanged = (type == WindowSizeChangeReason::UNDEFINED &&
2371                            (windowSize_->Width() != width || windowSize_->Height() != height));
2372     }
2373     return isWindowChanged;
2374 }
2375 
2376 void SheetPresentationPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
2377 {
2378     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet WindowSizeChangeReason type is: %{public}d", type);
2379     ACE_SCOPED_TRACE("Sheet OnWindowSizeChanged: WindowSizeChangeReason type is: %d", type);
2380     if (type == WindowSizeChangeReason::DRAG_START || type == WindowSizeChangeReason::DRAG_END ||
2381         type == WindowSizeChangeReason::DRAG_MOVE) {
2382         return;
2383     }
2384     auto sheetType = GetSheetType();
2385     if ((type == WindowSizeChangeReason::ROTATION) &&
2386         ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOMLANDSPACE) ||
2387          (sheetType == SheetType::SHEET_BOTTOM_OFFSET))) {
2388         windowRotate_ = true;
2389         SetColumnMinSize(true);
2390         // Before rotation, reset to the initial mode sheet ratio of the current vertical or horizontal screen
2391         // It's actually a state where the soft keyboard is not pulled up
2392         if (isScrolling_) {
2393             resizeDecreasedHeight_ = 0.f;
2394             ScrollTo(.0f);
2395         }
2396     }
2397     if (IsWindowSizeChangedWithUndefinedReason(width, height, type)) {
2398         windowChanged_ = true;
2399     }
2400     windowSize_ = SizeT<int32_t>(width, height);
2401     if (type == WindowSizeChangeReason::ROTATION || type == WindowSizeChangeReason::DRAG ||
2402         type == WindowSizeChangeReason::RESIZE) {
2403         windowChanged_ = true;
2404     }
2405 
2406     if (type == WindowSizeChangeReason::ROTATION && sheetType == SheetType::SHEET_CENTER) {
2407         auto recoverTask = [weak = WeakClaim(this), id = Container::CurrentId()] () {
2408             ContainerScope scope(id);
2409             auto pattern = weak.Upgrade();
2410             CHECK_NULL_VOID(pattern);
2411             pattern->RecoverHalfFoldOrAvoidStatus();
2412         };
2413         PostTask(recoverTask, "ArkUISheetHalfFoldStatusSwitch");
2414     }
2415 
2416     auto host = GetHost();
2417     CHECK_NULL_VOID(host);
2418     auto pipelineContext = host->GetContext();
2419     CHECK_NULL_VOID(pipelineContext);
2420     UpdateSheetWhenSheetTypeChanged();
2421     auto windowManager = pipelineContext->GetWindowManager();
2422     if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
2423         host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2424     }
2425 }
2426 
2427 void SheetPresentationPattern::TranslateTo(float height)
2428 {
2429     auto host = GetHost();
2430     CHECK_NULL_VOID(host);
2431     auto context = host->GetRenderContext();
2432     CHECK_NULL_VOID(context);
2433     context->UpdateTransformTranslate({ 0.0f, height, 0.0f });
2434 }
2435 
2436 void SheetPresentationPattern::ScrollTo(float height)
2437 {
2438     // height = 0 or height > 0
2439     auto host = GetHost();
2440     CHECK_NULL_VOID(host);
2441     auto scroll = GetSheetScrollNode();
2442     CHECK_NULL_VOID(scroll);
2443     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2444     CHECK_NULL_VOID(scrollPattern);
2445     auto layoutProp = scrollPattern->GetLayoutProperty<ScrollLayoutProperty>();
2446     CHECK_NULL_VOID(layoutProp);
2447     auto geometryNode = scroll->GetGeometryNode();
2448     CHECK_NULL_VOID(geometryNode);
2449     // height > 0, Scroll will reduce height, and become scrolling.
2450     isScrolling_ = height > 0;
2451     SetColumnMinSize(!isScrolling_);
2452     if (!AdditionalScrollTo(scroll, height)) {
2453         scrollHeight_ = height;
2454         float maxScrollDecreaseHeight = scrollHeight_;
2455         float maxAvoidSize = keyboardHeight_ - (sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.f);
2456         auto pipelineContext = host->GetContext();
2457         CHECK_NULL_VOID(pipelineContext);
2458         auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2459         /*
2460          * when the screen rotates from portrait to landscape, and the sheet needs to avoid caret twice,
2461          * there is a condition that, the caret position that does not exceed the height of sheet in portrait mode,
2462          * may be exceed the height of sheet in landscape mode. In that case,
2463          * the distance to avoid caret may exceed as well. To keep bindSheet display normally,
2464          * we need to obtain the minimum content height and then the avoidance is made.
2465          */
2466         if (useCaretAvoidMode && NonNegative(maxAvoidSize) && NonNegative(maxAvoidSize - sheetHeightUp_) &&
2467             maxScrollDecreaseHeight > maxAvoidSize - sheetHeightUp_) {
2468             maxScrollDecreaseHeight = maxAvoidSize - sheetHeightUp_;
2469         }
2470         layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
2471             CalcLength(GetScrollHeight() - maxScrollDecreaseHeight)));
2472         auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2473         scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2474     }
2475     scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2476 }
2477 
2478 bool SheetPresentationPattern::AdditionalScrollTo(const RefPtr<FrameNode>& scroll, float height)
2479 {
2480     if (NonPositive(height)) {
2481         return false;
2482     }
2483     // If ScrollHeight is larger than childHeight
2484     // there will be a scene that is still larger than childHeight after reducing Scrollheight to moving sheet up
2485     // At this point, even if JumpToPosition is negative, the Scroll will still not to scroll
2486     auto buildContent = GetFirstFrameNodeOfBuilder();
2487     CHECK_NULL_RETURN(buildContent, false);
2488     auto scrollHeight = scroll->GetGeometryNode() ? scroll->GetGeometryNode()->GetFrameSize().Height() : .0f;
2489     auto host = GetHost();
2490     CHECK_NULL_RETURN(host, false);
2491     auto pipelineContext = host->GetContext();
2492     CHECK_NULL_RETURN(pipelineContext, false);
2493     auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2494     if (useCaretAvoidMode) {
2495         scrollHeight = GetScrollHeight();
2496     }
2497     auto childHeight = buildContent->GetGeometryNode() ? buildContent->GetGeometryNode()->GetFrameSize().Height() : .0f;
2498     if (scrollHeight <= childHeight) {
2499         return false;
2500     }
2501     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
2502     CHECK_NULL_RETURN(layoutProp, false);
2503     auto geometryNode = scroll->GetGeometryNode();
2504     CHECK_NULL_RETURN(geometryNode, false);
2505     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2506     CHECK_NULL_RETURN(scrollPattern, false);
2507     // Scroll first shrinks to the same size as childHeight, then reduces the height to allow it to scroll
2508     scrollHeight_ = scrollHeight - childHeight + height;
2509     layoutProp->UpdateUserDefinedIdealSize(
2510         CalcSize(std::nullopt, CalcLength(GetScrollHeight() - (scrollHeight - childHeight + height))));
2511     // And then scroll move the content with '-height' offset
2512     auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2513     scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2514     return true;
2515 }
2516 
2517 void SheetPresentationPattern::SetColumnMinSize(bool reset)
2518 {
2519     auto buildContent = GetFirstFrameNodeOfBuilder();
2520     CHECK_NULL_VOID(buildContent);
2521     auto geometryNode = buildContent->GetGeometryNode();
2522     CHECK_NULL_VOID(geometryNode);
2523     auto props = buildContent->GetLayoutProperty<LayoutProperty>();
2524     CHECK_NULL_VOID(props);
2525     if (reset) {
2526         props->ResetCalcMinSize();
2527         return;
2528     }
2529     props->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(builderHeight_)));
2530 }
2531 
2532 void SheetPresentationPattern::CalculateSheetRadius(BorderRadiusProperty& sheetRadius)
2533 {
2534     auto host = GetHost();
2535     CHECK_NULL_VOID(host);
2536     auto geometryNode = host->GetGeometryNode();
2537     CHECK_NULL_VOID(geometryNode);
2538     auto sheetSize = geometryNode->GetFrameSize();
2539     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
2540     CHECK_NULL_VOID(layoutProperty);
2541     auto sheetStyle = layoutProperty->GetSheetStyleValue();
2542     if (sheetSize.IsPositive()) {
2543         CalculateAloneSheetRadius(sheetRadius.radiusTopLeft, sheetStyle.radius->radiusTopLeft);
2544         CalculateAloneSheetRadius(sheetRadius.radiusTopRight, sheetStyle.radius->radiusTopRight);
2545         CalculateAloneSheetRadius(sheetRadius.radiusBottomLeft, sheetStyle.radius->radiusBottomLeft);
2546         CalculateAloneSheetRadius(sheetRadius.radiusBottomRight, sheetStyle.radius->radiusBottomRight);
2547     }
2548 }
2549 
2550 void SheetPresentationPattern::CalculateAloneSheetRadius(
2551     std::optional<Dimension>& sheetRadius, const std::optional<Dimension>& sheetStyleRadius)
2552 {
2553     auto host = GetHost();
2554     CHECK_NULL_VOID(host);
2555     auto geometryNode = host->GetGeometryNode();
2556     CHECK_NULL_VOID(geometryNode);
2557     auto sheetSize = geometryNode->GetFrameSize();
2558     float half = 0.5f;
2559     if (sheetStyleRadius.has_value() && GreatOrEqual(sheetStyleRadius->Value(), 0.0f)) {
2560         if (sheetStyleRadius->Unit() == DimensionUnit::PERCENT) {
2561             sheetRadius = Dimension(sheetStyleRadius->Value() * sheetSize.Width());
2562         } else {
2563             sheetRadius = sheetStyleRadius;
2564         }
2565     }
2566     // The maximum value of radius is half the width of the page.
2567     if (sheetSize.Width() * half < sheetRadius->ConvertToPx()) {
2568         sheetRadius = Dimension(sheetSize.Width() * half);
2569     }
2570 }
2571 
2572 std::string SheetPresentationPattern::GetPopupStyleSheetClipPath(
2573     const SizeF& sheetSize, const BorderRadiusProperty& sheetRadius)
2574 {
2575     auto host = GetHost();
2576     CHECK_NULL_RETURN(host, "");
2577     if (host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
2578         return GetPopupStyleSheetClipPathNew(sheetSize, sheetRadius);
2579     }
2580     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
2581     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
2582     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
2583     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
2584     std::string path = MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopLeft);
2585     path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, SHEET_ARROW_HEIGHT.ConvertToPx());
2586     path +=
2587         LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
2588     path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
2589         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P2_OFFSET_Y.ConvertToPx()); // P2
2590     path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
2591         arrowOffset_.GetX() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
2592         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P4_OFFSET_Y.ConvertToPx()); // P4
2593     path +=
2594         LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
2595     path += LineTo(sheetSize.Width() - radiusTopRight, SHEET_ARROW_HEIGHT.ConvertToPx());
2596     path += ArcTo(
2597         radiusTopRight, radiusTopRight, 0.0f, 0, sheetSize.Width(), SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopRight);
2598     path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
2599     path +=
2600         ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0, sheetSize.Width() - radiusBottomRight, sheetSize.Height());
2601     path += LineTo(radiusBottomLeft, sheetSize.Height());
2602     path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0, 0.0f, sheetSize.Height() - radiusBottomLeft);
2603     return path + "Z";
2604 }
2605 
2606 std::string SheetPresentationPattern::GetCenterStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2607 {
2608     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2609     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2610     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2611     path += ArcTo(
2612         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2613     path += LineTo(sheetSize.Width(), sheetSize.Height() - sheetRadius.ConvertToPx());
2614     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0,
2615         sheetSize.Width() - sheetRadius.ConvertToPx(), sheetSize.Height());
2616     path += LineTo(sheetRadius.ConvertToPx(), sheetSize.Height());
2617     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, 0.0f,
2618         sheetSize.Height() - sheetRadius.ConvertToPx());
2619     return path + "Z";
2620 }
2621 
2622 std::string SheetPresentationPattern::GetBottomStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2623 {
2624     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2625     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2626     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2627     path += ArcTo(
2628         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2629     path += LineTo(sheetSize.Width(), sheetSize.Height());
2630     path += LineTo(0.0f, sheetSize.Height());
2631     return path + "Z";
2632 }
2633 
2634 std::string SheetPresentationPattern::MoveTo(double x, double y)
2635 {
2636     return "M" + std::to_string(x) + " " + std::to_string(y) + " ";
2637 }
2638 
2639 std::string SheetPresentationPattern::LineTo(double x, double y)
2640 {
2641     return "L" + std::to_string(x) + " " + std::to_string(y) + " ";
2642 }
2643 
2644 std::string SheetPresentationPattern::ArcTo(double rx, double ry, double rotation, int32_t arc_flag, double x, double y)
2645 {
2646     int32_t sweep_flag = 1;
2647     return "A" + std::to_string(rx) + " " + std::to_string(ry) + " " + std::to_string(rotation) + " " +
2648            std::to_string(arc_flag) + " " + std::to_string(sweep_flag) + " " + std::to_string(x) + " " +
2649            std::to_string(y) + " ";
2650 }
2651 
2652 float SheetPresentationPattern::GetFitContentHeight()
2653 {
2654     auto builderNode = GetFirstFrameNodeOfBuilder();
2655     CHECK_NULL_RETURN(builderNode, 0.0f);
2656     auto builderGeometryNode = builderNode->GetGeometryNode();
2657     return builderGeometryNode->GetMarginFrameSize().Height() + GetTitleBuilderHeight();
2658 }
2659 
2660 float SheetPresentationPattern::GetTitleBuilderHeight() const
2661 {
2662     auto titleColumn = GetTitleBuilderNode();
2663     CHECK_NULL_RETURN(titleColumn, 0.0f);
2664     auto titleGeometryNode = titleColumn->GetGeometryNode();
2665     CHECK_NULL_RETURN(titleGeometryNode, 0.0f);
2666     OffsetF titleOffset = titleGeometryNode->GetMarginFrameOffset();
2667     float titleOffsetY = titleOffset.GetY();
2668     float titleHeight = Positive(
2669         titleGeometryNode->GetFrameSize().Height()) ? titleGeometryNode->GetFrameSize().Height() : 0.0f;
2670     float titleBottomY = titleOffsetY + titleHeight;
2671     return titleBottomY;
2672 }
2673 
2674 RefPtr<OverlayManager> SheetPresentationPattern::GetOverlayManager()
2675 {
2676     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2677     CHECK_NULL_RETURN(layoutProp, nullptr);
2678     auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2679 
2680     if (layoutProp->GetSheetStyleValue(SheetStyle()).showInSubWindow.value_or(false)) {
2681         auto aceContainer = AceEngine::Get().GetContainer(GetSubWindowId());
2682         CHECK_NULL_RETURN(aceContainer, nullptr);
2683         auto context = DynamicCast<NG::PipelineContext>(aceContainer->GetPipelineContext());
2684         CHECK_NULL_RETURN(context, nullptr);
2685         auto overlayManager = context->GetOverlayManager();
2686         return overlayManager;
2687     }
2688     if (!showInPage) {
2689         auto host = GetHost();
2690         CHECK_NULL_RETURN(host, nullptr);
2691         auto pipeline = host->GetContext();
2692         CHECK_NULL_RETURN(pipeline, nullptr);
2693         return pipeline->GetOverlayManager();
2694     }
2695     auto host = GetHost();
2696     CHECK_NULL_RETURN(host, nullptr);
2697     auto sheetWrapper = host->GetParent();
2698     CHECK_NULL_RETURN(sheetWrapper, nullptr);
2699     auto node = AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2700     CHECK_NULL_RETURN(node, nullptr);
2701     RefPtr<OverlayManager> overlay;
2702     if (node->GetTag() == V2::PAGE_ETS_TAG) {
2703         auto pattern = node->GetPattern<PagePattern>();
2704         CHECK_NULL_RETURN(pattern, nullptr);
2705         overlay = pattern->GetOverlayManager();
2706     } else if (node->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
2707         auto pattern = node->GetPattern<NavDestinationPattern>();
2708         CHECK_NULL_RETURN(pattern, nullptr);
2709         overlay = pattern->GetOverlayManager();
2710     }
2711     if (!overlay) {
2712         auto overlayManager = overlayManager_.Upgrade();
2713         overlay = overlayManager;
2714     }
2715     return overlay;
2716 }
2717 
2718 RefPtr<FrameNode> SheetPresentationPattern::GetFirstFrameNodeOfBuilder() const
2719 {
2720     auto scrollNode = GetSheetScrollNode();
2721     CHECK_NULL_RETURN(scrollNode, nullptr);
2722     auto buildNode = scrollNode->GetChildAtIndex(0);
2723     CHECK_NULL_RETURN(buildNode, nullptr);
2724     return AceType::DynamicCast<FrameNode>(buildNode->GetFrameChildByIndex(0, true));
2725 }
2726 
2727 void SheetPresentationPattern::GetBuilderInitHeight()
2728 {
2729     auto buildContent = GetFirstFrameNodeOfBuilder();
2730     CHECK_NULL_VOID(buildContent);
2731     auto geometryNode = buildContent->GetGeometryNode();
2732     CHECK_NULL_VOID(geometryNode);
2733     builderHeight_ = geometryNode->GetFrameSize().Height();
2734 }
2735 
2736 RefPtr<FrameNode> SheetPresentationPattern::GetOverlayRoot()
2737 {
2738     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2739     CHECK_NULL_RETURN(layoutProp, nullptr);
2740     auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2741     auto host = GetHost();
2742     CHECK_NULL_RETURN(host, nullptr);
2743     if (!showInPage) {
2744         auto pipelineContext = host->GetContext();
2745         CHECK_NULL_RETURN(pipelineContext, nullptr);
2746         auto overlay = pipelineContext->GetOverlayManager();
2747         CHECK_NULL_RETURN(overlay, nullptr);
2748         return AceType::DynamicCast<FrameNode>(overlay->GetRootNode().Upgrade());
2749     }
2750     auto sheetWrapper = host->GetParent();
2751     CHECK_NULL_RETURN(sheetWrapper, nullptr);
2752     return AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2753 }
2754 
2755 float SheetPresentationPattern::GetRootOffsetYToWindow()
2756 {
2757     const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2758     CHECK_NULL_RETURN(layoutProp, .0f);
2759     const auto& showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2760     CHECK_NULL_RETURN(showInPage, .0f);
2761     const auto& overlayNode = GetOverlayRoot();
2762     CHECK_NULL_RETURN(overlayNode, .0f);
2763     auto parertOffset = overlayNode->GetOffsetRelativeToWindow();
2764     TAG_LOGD(AceLogTag::ACE_OVERLAY, "PageLevel Node's offset to window: %{public}s", parertOffset.ToString().c_str());
2765     return parertOffset.GetY();
2766 }
2767 
2768 void SheetPresentationPattern::DumpAdvanceInfo()
2769 {
2770     DumpLog::GetInstance().AddDesc("------------------------------------------");
2771     DumpLog::GetInstance().AddDesc(
2772         "TargetId: " + std::to_string(static_cast<int32_t>(targetId_)) + " , TargetTag : " + targetTag_);
2773     DumpLog::GetInstance().AddDesc("------------ SheetPage Pattern : ");
2774     DumpLog::GetInstance().AddDesc(
2775         std::string("SheetType: ").append(std::to_string(static_cast<int32_t>(GetSheetTypeNoProcess()))));
2776     DumpLog::GetInstance().AddDesc(std::string("SheetPage Node Height: ").append(std::to_string(centerHeight_)));
2777     DumpLog::GetInstance().AddDesc(
2778         std::string("Sheet Height [start from the bottom, KeyboardHeight = 0]: ").append(std::to_string(height_)));
2779     DumpLog::GetInstance().AddDesc(
2780         std::string("SheetMaxHeight [start from the bottom, pageHeight - sheetTopSafeArea]: ")
2781             .append(std::to_string(sheetMaxHeight_)));
2782     DumpLog::GetInstance().AddDesc(std::string("Page Height: ").append(std::to_string(pageHeight_)));
2783     DumpLog::GetInstance().AddDesc(
2784         std::string("StatusBar Height [current sheetType needed]: ").append(std::to_string(sheetTopSafeArea_)));
2785     DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetX: ").append(std::to_string(sheetOffsetX_)));
2786     DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetY: ").append(std::to_string(sheetOffsetY_)));
2787     DumpLog::GetInstance().AddDesc(std::string("SheetMaxWidth: ").append(std::to_string(sheetMaxWidth_)));
2788     DumpLog::GetInstance().AddDesc(std::string("FitContent Height: ").append(std::to_string(sheetFitContentHeight_)));
2789     DumpLog::GetInstance().AddDesc("SheetThemeType: " + sheetThemeType_);
2790     DumpLog::GetInstance().AddDesc(std::string("currentOffset: ").append(std::to_string(currentOffset_)));
2791     DumpLog::GetInstance().AddDesc("------------");
2792     DumpLog::GetInstance().AddDesc(
2793         std::string("Height ScrollTo [KeyboardHeight > 0, and is scrolling]: ").append(std::to_string(-scrollHeight_)));
2794     DumpLog::GetInstance().AddDesc(std::string("KeyboardHeight: ").append(std::to_string(keyboardHeight_)));
2795     DumpLog::GetInstance().AddDesc(std::string("is scrolling: ").append(isScrolling_ ? "true" : "false"));
2796     DumpLog::GetInstance().AddDesc(std::string("SheetHeightUp[sheet offset to move up when avoiding keyboard]: ")
2797                                        .append(std::to_string(sheetHeightUp_)));
2798     DumpLog::GetInstance().AddDesc("------------");
2799     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2800     CHECK_NULL_VOID(layoutProperty);
2801     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2802     DumpLog::GetInstance().AddDesc(
2803         std::string("height: ").append(sheetStyle.sheetHeight.height.has_value() ?
2804         sheetStyle.sheetHeight.height->ToString() : "None"));
2805     DumpLog::GetInstance().AddDesc(
2806         ("sheetMode: ") + (sheetStyle.sheetHeight.sheetMode.has_value()
2807                                   ? std::to_string(static_cast<int32_t>(sheetStyle.sheetHeight.sheetMode.value()))
2808                                   : "None"));
2809     DumpLog::GetInstance().AddDesc(std::string("detents' Size: ").append(std::to_string(sheetStyle.detents.size())));
2810     DumpLog::GetInstance().AddDesc(std::string("IsShouldDismiss: ").append(shouldDismiss_ ? "true" : "false"));
2811 }
2812 
2813 void SheetPresentationPattern::FireOnHeightDidChange()
2814 {
2815     auto height = 0.0f;
2816     if (!IsSheetBottomStyle()) {
2817         height = centerHeight_;
2818     } else {
2819         height = height_;
2820     }
2821     if (NearEqual(preDidHeight_, height)) {
2822         return;
2823     }
2824     OnHeightDidChange(height);
2825     preDidHeight_ = height;
2826 }
2827 
2828 void SheetPresentationPattern::FireOnDetentsDidChange(float height)
2829 {
2830     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2831     CHECK_NULL_VOID(layoutProperty);
2832     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2833     if (!IsSheetBottomStyle() || NearEqual(preDetentsHeight_, height) ||
2834         LessOrEqual(sheetStyle.detents.size(), 0)) {
2835         return;
2836     }
2837     OnDetentsDidChange(height);
2838     preDetentsHeight_ = height;
2839 }
2840 
2841 void SheetPresentationPattern::FireOnWidthDidChange()
2842 {
2843     auto host = GetHost();
2844     CHECK_NULL_VOID(host);
2845     auto sheetGeo = host->GetGeometryNode();
2846     CHECK_NULL_VOID(sheetGeo);
2847     auto width = sheetGeo->GetFrameSize().Width();
2848     if (NearEqual(preWidth_, width)) {
2849         return;
2850     }
2851     onWidthDidChange(width);
2852     preWidth_ = width;
2853 }
2854 
2855 void SheetPresentationPattern::FireOnTypeDidChange()
2856 {
2857     auto sheetType = sheetType_;
2858     if (IsSheetBottomStyle() || sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
2859         sheetType = SheetType::SHEET_BOTTOM;
2860     }
2861     if (preType_ == sheetType) {
2862         return;
2863     }
2864     onTypeDidChange(sheetType);
2865     preType_ = sheetType;
2866 }
2867 
2868 bool SheetPresentationPattern::IsScrollOutOfBoundary()
2869 {
2870     auto scrollNode = GetSheetScrollNode();
2871     CHECK_NULL_RETURN(scrollNode, false);
2872     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
2873     CHECK_NULL_RETURN(scrollPattern, false);
2874     return scrollPattern->OutBoundaryCallback();
2875 }
2876 
2877 void SheetPresentationPattern::OnScrollStartRecursive(
2878     WeakPtr<NestableScrollContainer> child, float position, float velocity)
2879 {
2880     return sheetObject_->OnScrollStartRecursive(position, velocity);
2881 }
2882 
2883 ScrollResult SheetPresentationPattern::HandleScroll(float scrollOffset, int32_t source, NestedState state,
2884     float velocity)
2885 {
2886     return sheetObject_->HandleScroll(scrollOffset, source, state, velocity);
2887 }
2888 
2889 void SheetPresentationPattern::OnScrollEndRecursive(const std::optional<float>& velocity)
2890 {
2891     sheetObject_->OnScrollEndRecursive(velocity);
2892 }
2893 
2894 bool SheetPresentationPattern::HandleScrollVelocity(float velocity, const RefPtr<NestableScrollContainer>& child)
2895 {
2896     return sheetObject_->HandleScrollVelocity(velocity);
2897 }
2898 
2899 bool SheetPresentationPattern::IsTypeNeedAvoidAiBar()
2900 {
2901     auto overlay = GetOverlayManager();
2902     auto layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2903     if (overlay && overlay->IsRootExpansive() &&
2904         layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false)) {
2905         return false;
2906     }
2907     return sheetType_ == SheetType::SHEET_BOTTOM || sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE ||
2908            sheetType_ == SheetType::SHEET_BOTTOM_OFFSET || sheetType_ == SheetType::SHEET_SIDE;
2909 }
2910 
2911 void SheetPresentationPattern::IsNeedPlayTransition(const SheetStyle& inputStyle)
2912 {
2913     isPlayTransition_ = false;
2914     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2915     CHECK_NULL_VOID(layoutProperty);
2916     auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2917     if (preStyle.sheetHeight.height != inputStyle.sheetHeight.height) {
2918         isPlayTransition_ = true;
2919         return;
2920     }
2921     if (preStyle.detents != inputStyle.detents) {
2922         isPlayTransition_ = true;
2923         return;
2924     }
2925     if (preStyle.sheetHeight.sheetMode != inputStyle.sheetHeight.sheetMode) {
2926         isPlayTransition_ = true;
2927         return;
2928     }
2929     isPlayTransition_ = UpdateIndexByDetentSelection(inputStyle, false) || isPlayTransition_;
2930 }
2931 
2932 bool SheetPresentationPattern::UpdateIndexByDetentSelection(const SheetStyle& inputStyle, bool isFirstTransition)
2933 {
2934     if (!inputStyle.detentSelection.has_value() || inputStyle.detents.size() == 0) {
2935         // when input detentSelection or detent selection is invalid
2936         return false;
2937     }
2938     auto selection = inputStyle.detentSelection.value();
2939     if ((selection.sheetMode.has_value() && selection.sheetMode.value() == NG::SheetMode::AUTO) ||
2940         (selection.height.has_value() && selection.height.value().IsNegative())) {
2941         return false;
2942     }
2943     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2944     CHECK_NULL_RETURN(layoutProperty, false);
2945     auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2946     if (!isFirstTransition && preStyle.detentSelection == inputStyle.detentSelection) {
2947         // only when sheet is first pulled up or pre-detents equal to current detents, otherwise false
2948         return false;
2949     }
2950     for (uint32_t index = 0; index < inputStyle.detents.size(); index++) {
2951         if (inputStyle.detents[index] == inputStyle.detentSelection.value()) {
2952             detentsFinalIndex_ = index;
2953             TAG_LOGI(AceLogTag::ACE_SHEET, "find detent selection is %u", index);
2954             return true;
2955         }
2956     }
2957     return false;
2958 }
2959 
2960 void SheetPresentationPattern::OverlayDismissSheet()
2961 {
2962     auto overlayManager = GetOverlayManager();
2963     CHECK_NULL_VOID(overlayManager);
2964     overlayManager->DismissSheet();
2965 }
2966 
2967 void SheetPresentationPattern::OverlaySheetSpringBack()
2968 {
2969     auto overlayManager = GetOverlayManager();
2970     CHECK_NULL_VOID(overlayManager);
2971     overlayManager->SheetSpringBack();
2972 }
2973 
2974 PipelineContext* SheetPresentationPattern::GetSheetMainPipeline() const
2975 {
2976     auto host = GetHost();
2977     CHECK_NULL_RETURN(host, nullptr);
2978     auto pipelineContext = host->GetContext();
2979     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2980     CHECK_NULL_RETURN(layoutProperty, nullptr);
2981     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2982 
2983     if (sheetStyle.instanceId.has_value()) {
2984         // need to get mainWindow's pipeline, and get mainWindow's cutoutSafeArea
2985         auto container = Container::GetContainer(sheetStyle.instanceId.value());
2986         CHECK_NULL_RETURN(container, nullptr);
2987         auto parentId = container->GetParentId();
2988         TAG_LOGI(AceLogTag::ACE_SHEET, "mainWindow id : %{public}d", parentId);
2989         auto parentContainer = Container::GetContainer(parentId);
2990         CHECK_NULL_RETURN(parentContainer, nullptr);
2991         auto parentPipelineBase = parentContainer->GetPipelineContext();
2992         CHECK_NULL_RETURN(parentPipelineBase, nullptr);
2993         auto parentPipelineContext = AceType::DynamicCast<PipelineContext>(parentPipelineBase);
2994         pipelineContext = RawPtr(parentPipelineContext);
2995     }
2996     return pipelineContext;
2997 }
2998 
2999 float SheetPresentationPattern::GetBottomSafeArea()
3000 {
3001     auto pipelineContext = GetSheetMainPipeline();
3002     CHECK_NULL_RETURN(pipelineContext, .0f);
3003     auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
3004     auto manager = pipelineContext->GetSafeAreaManager();
3005     CHECK_NULL_RETURN(manager, .0f);
3006     auto cutoutSafeArea = manager->GetCutoutSafeAreaWithoutProcess();
3007     if (cutoutSafeArea.top_.IsValid()) {
3008         auto topAreaInWindow = GetTopAreaInWindow();
3009         TAG_LOGD(AceLogTag::ACE_SHEET, "rosen window sheetTopSafeArea of sheet is : %{public}f", topAreaInWindow);
3010         return topAreaInWindow;
3011     } else {
3012         return safeAreaInsets.top_.Length();
3013     }
3014 }
3015 
3016 // Height of status bar
3017 float SheetPresentationPattern::GetTopAreaInWindow() const
3018 {
3019     auto host = GetHost();
3020     CHECK_NULL_RETURN(host, 0.0f);
3021     auto pipelineContext = host->GetContext();
3022     CHECK_NULL_RETURN(pipelineContext, 0.0f);
3023     auto window = pipelineContext->GetWindow();
3024     CHECK_NULL_RETURN(window, 0.0f);
3025     return window->GetStatusBarHeight();
3026 }
3027 
3028 void SheetPresentationPattern::MarkSheetPageNeedRender()
3029 {
3030     auto parentHost = GetHost()->GetParent();
3031     CHECK_NULL_VOID(parentHost);
3032     auto frameNode = AceType::DynamicCast<FrameNode>(parentHost);
3033     CHECK_NULL_VOID(frameNode);
3034     frameNode->MarkNeedRenderOnly();
3035 }
3036 
3037 void SheetPresentationPattern::SetSheetOuterBorderWidth(
3038     const RefPtr<SheetTheme>& sheetTheme, const NG::SheetStyle& sheetStyle)
3039 {
3040     auto host = GetHost();
3041     CHECK_NULL_VOID(host);
3042     auto renderContext = host->GetRenderContext();
3043     CHECK_NULL_VOID(renderContext);
3044     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
3045     CHECK_NULL_VOID(layoutProperty);
3046     auto sheetType = sheetType_;
3047     if (sheetTheme->IsOuterBorderEnable() && !sheetStyle.borderWidth.has_value()) {
3048         BorderWidthProperty borderWidth;
3049         BorderWidthProperty outBorderWidth;
3050         BorderColorProperty borderColor;
3051         BorderColorProperty outBorderColor;
3052         borderWidth.SetBorderWidth(0.0_vp);
3053         outBorderWidth.SetBorderWidth(0.0_vp);
3054         if (sheetObject_->CheckIfNeedSetOuterBorderProp()) {
3055             borderColor.SetColor(sheetTheme->GetSheetInnerBorderColor());
3056             outBorderColor.SetColor(sheetTheme->GetSheetOuterBorderColor());
3057             renderContext->UpdateOuterBorderColor(outBorderColor);
3058             renderContext->UpdateBorderColor(borderColor);
3059             if (sheetType == SheetType::SHEET_CENTER || sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
3060                 borderWidth.SetBorderWidth(sheetTheme->GetSheetInnerBorderWidth());
3061                 outBorderWidth.SetBorderWidth(sheetTheme->GetSheetOuterBorderWidth());
3062             } else {
3063                 borderWidth.leftDimen = sheetTheme->GetSheetInnerBorderWidth();
3064                 borderWidth.topDimen = sheetTheme->GetSheetInnerBorderWidth();
3065                 borderWidth.rightDimen = sheetTheme->GetSheetInnerBorderWidth();
3066                 outBorderWidth.leftDimen = sheetTheme->GetSheetOuterBorderWidth();
3067                 outBorderWidth.topDimen = sheetTheme->GetSheetOuterBorderWidth();
3068                 outBorderWidth.rightDimen = sheetTheme->GetSheetOuterBorderWidth();
3069             }
3070         }
3071         layoutProperty->UpdateBorderWidth(borderWidth);
3072         renderContext->UpdateBorderWidth(borderWidth);
3073         layoutProperty->UpdateOuterBorderWidth(outBorderWidth);
3074         renderContext->UpdateOuterBorderWidth(outBorderWidth);
3075     }
3076 }
3077 
3078 void SheetPresentationPattern::DumpAdvanceInfo(std::unique_ptr<JsonValue>& json)
3079 {
3080     json->Put("TargetId", static_cast<int32_t>(targetId_));
3081     json->Put("TargetTag", targetTag_.c_str());
3082     std::unique_ptr<JsonValue> children = JsonUtil::Create(true);
3083     children->Put("SheetType", static_cast<int32_t>(GetSheetTypeNoProcess()));
3084     children->Put("SheetPage Node Height", centerHeight_);
3085     children->Put("Sheet Height [start from the bottom, KeyboardHeight = 0]", height_);
3086     children->Put("SheetMaxHeight [start from the bottom, pageHeight - sheetTopSafeArea]", sheetMaxHeight_);
3087     children->Put("Page Height", pageHeight_);
3088     children->Put("StatusBar Height [current sheetType needed]", sheetTopSafeArea_);
3089     children->Put("PopupSheet OffsetX", sheetOffsetX_);
3090     children->Put("PopupSheet OffsetX", sheetOffsetY_);
3091     children->Put("SheetMaxWidth", sheetMaxWidth_);
3092     children->Put("FitContent Height", sheetFitContentHeight_);
3093     children->Put("SheetThemeType", sheetThemeType_.c_str());
3094     children->Put("currentOffset", currentOffset_);
3095     json->Put("SheetPage Pattern", children);
3096 
3097     json->Put("Height ScrollTo [KeyboardHeight > 0, and is scrolling]", -scrollHeight_);
3098     json->Put("KeyboardHeight", static_cast<int32_t>(keyboardHeight_));
3099     json->Put("is scrolling", isScrolling_);
3100     json->Put("SheetHeightUp[sheet offset to move up when avoiding keyboard]", sheetHeightUp_);
3101 
3102     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3103     CHECK_NULL_VOID(layoutProperty);
3104     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3105     json->Put("height", sheetStyle.sheetHeight.height.has_value() ?
3106         sheetStyle.sheetHeight.height->ToString().c_str() : "None");
3107     json->Put("sheetMode", sheetStyle.sheetHeight.sheetMode.has_value()
3108                                ? std::to_string(static_cast<int32_t>(sheetStyle.sheetHeight.sheetMode.value())).c_str()
3109                                : "None");
3110     json->Put("detents Size", static_cast<int32_t>(sheetStyle.detents.size()));
3111     json->Put("IsShouldDismiss", shouldDismiss_ ? "true" : "false");
3112 }
3113 
3114 void SheetPresentationPattern::StopModifySheetTransition()
3115 {
3116     if (isAnimationProcess_ && animation_) {
3117         AnimationUtils::StopAnimation(animation_);
3118     }
3119 }
3120 
3121 void SheetPresentationPattern::AvoidKeyboardBySheetMode(bool forceAvoid)
3122 {
3123     if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::NONE ||
3124         keyboardAvoidMode_ == SheetKeyboardAvoidMode::POPUP_SHEET) {
3125         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet will not avoid keyboard.");
3126         return;
3127     }
3128     auto host = GetHost();
3129     CHECK_NULL_VOID(host);
3130     auto pipelineContext = host->GetContext();
3131     CHECK_NULL_VOID(pipelineContext);
3132     auto manager = pipelineContext->GetSafeAreaManager();
3133     if (keyboardHeight_ == manager->GetKeyboardInset().Length() && !forceAvoid) {
3134         return;
3135     }
3136     keyboardHeight_ = manager->GetKeyboardInset().Length();
3137 
3138     if (isDismissProcess_) {
3139         TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet will disappear, not need to handle canceling keyboard avoidance here.");
3140         return;
3141     }
3142     StopModifySheetTransition();
3143     // 1.handle non upward logic: avoidKeyboardMode::RESIZE_ONLY
3144     if (AvoidKeyboardBeforeTranslate()) {
3145         return;
3146     }
3147 
3148     // 2.handle upward logic
3149     CHECK_NULL_VOID(host->GetFocusHub());
3150     // When bindSheet lift height exceed the max height, hightUp = the remaining height that needs to scroll,
3151     // otherwise, hightUp = the height to be lifted up
3152     auto heightUp = host->GetFocusHub()->IsCurrentFocus() ? GetSheetHeightChange() : 0.0f;
3153     sheetHeightUp_ = heightUp;
3154     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet needs to deal with %{public}f height.", heightUp);
3155     auto offset = pageHeight_ - height_ - heightUp;
3156     auto renderContext = host->GetRenderContext();
3157 
3158     // when bindSheet height exceed the max height, lift it up to the maxHeight,
3159     // otherwise, lift it up to show input area
3160     if (isScrolling_) {
3161         if (NearZero(heightUp)) {
3162             // scroll needs to reset first when keyboard is down.
3163             renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
3164         } else {
3165             auto sheetHeightUp = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
3166             sheetHeightUp_ = LessNotEqual(sheetHeightUp, 0.0f) ? 0.0f : sheetHeightUp;
3167             if (GreatNotEqual(sheetHeightUp_, 0.0f)) {
3168                 // sheet is raised to the top first
3169                 renderContext->UpdateTransformTranslate(
3170                     { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
3171             }
3172         }
3173     } else {
3174         // offset: translate endpoint, calculated from top
3175         renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
3176     }
3177 
3178     // 3.deal with left height, scroll or resize
3179     if (isScrolling_) {
3180         AvoidKeyboardAfterTranslate(heightUp);
3181     }
3182 
3183     if (IsSheetBottomStyle()) {
3184         OnHeightDidChange(height_ + sheetHeightUp_);
3185     }
3186 }
3187 
3188 bool SheetPresentationPattern::AvoidKeyboardBeforeTranslate()
3189 {
3190     if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY) {
3191         // resize bindSheet need to keep safe distance from keyboard
3192         auto distanceFromBottom = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
3193         DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : keyboardHeight_ - distanceFromBottom);
3194         return true;
3195     }
3196     return false;
3197 }
3198 
3199 void SheetPresentationPattern::AvoidKeyboardAfterTranslate(float height)
3200 {
3201     switch (keyboardAvoidMode_) {
3202     case SheetKeyboardAvoidMode::NONE:
3203     case SheetKeyboardAvoidMode::RESIZE_ONLY:
3204         break;
3205     case SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE:
3206         // resize bindSheet need to keep safe distance from keyboard
3207         DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : height);
3208         break;
3209     case SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL:
3210         ScrollTo(height);
3211         break;
3212     default:
3213         TAG_LOGW(AceLogTag::ACE_SHEET, "Invalid keyboard avoid mode %{public}d", keyboardAvoidMode_);
3214         break;
3215     }
3216 }
3217 
3218 void SheetPresentationPattern::DecreaseScrollHeightInSheet(float decreaseHeight)
3219 {
3220     auto scroll = GetSheetScrollNode();
3221     CHECK_NULL_VOID(scroll);
3222     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
3223     CHECK_NULL_VOID(layoutProp);
3224 
3225     // height > 0, Scroll will reduce height, and need to set isScrolling true
3226     isScrolling_ = (decreaseHeight > 0);
3227 
3228     TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, Scroll Height reduces by height %{public}f.", decreaseHeight);
3229     layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight() - decreaseHeight)));
3230     resizeDecreasedHeight_ = decreaseHeight;
3231     scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3232 }
3233 
3234 bool SheetPresentationPattern::IsResizeWhenAvoidKeyboard()
3235 {
3236     return keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE ||
3237         keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY;
3238 }
3239 
3240 void SheetPresentationPattern::ResetClipShape()
3241 {
3242     // need reset clip path,when system clip path change to user defined
3243     auto host = GetHost();
3244     CHECK_NULL_VOID(host);
3245     auto renderContext = host->GetRenderContext();
3246     CHECK_NULL_VOID(renderContext);
3247     renderContext->UpdateClipShape(nullptr);
3248     renderContext->ResetClipShape();
3249 }
3250 
3251 void SheetPresentationPattern::GetCurrentScrollHeight()
3252 {
3253     if (!isScrolling_) {
3254         return;
3255     }
3256     auto host = GetHost();
3257     CHECK_NULL_VOID(host);
3258     auto scrollNode = GetSheetScrollNode();
3259     CHECK_NULL_VOID(scrollNode);
3260     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
3261     CHECK_NULL_VOID(scrollPattern);
3262     auto curOffset = scrollPattern->GetTotalOffset();
3263     if (NearEqual(scrollHeight_, curOffset)) {
3264         return;
3265     }
3266     TAG_LOGD(AceLogTag::ACE_SHEET, "scroll height changed because of user scrolling, %{public}f", curOffset);
3267     scrollHeight_ = curOffset;
3268 }
3269 
3270 void SheetPresentationPattern::UpdateSheetWhenSheetTypeChanged()
3271 {
3272     auto sheetType = GetSheetTypeFromSheetManager();
3273     if (sheetType_ != sheetType) {
3274         // It can only be MarkOuterBorder When the SheetType switches and the sheetType_ was SHEET_POPUP
3275         if (sheetType_ == SheetType::SHEET_POPUP) {
3276             // Clear the current double outline, as it is drawn on the sheetWrapper.
3277             MarkSheetPageNeedRender();
3278         }
3279         sheetType_ = sheetType;
3280         UpdateSheetObject(sheetType_);
3281         typeChanged_ = true;
3282         SetSheetBorderWidth();
3283     }
3284 }
3285 
3286 bool SheetPresentationPattern::IsWaterfallWindowMode()
3287 {
3288     if (!SystemProperties::IsSuperFoldDisplayDevice()) {
3289         return false;
3290     }
3291 
3292     auto container = Container::Current();
3293     if (!container) {
3294         TAG_LOGW(AceLogTag::ACE_DIALOG, "container is null");
3295         return false;
3296     }
3297 
3298     if (container->IsSubContainer()) {
3299         auto instanceId = SubwindowManager::GetInstance()->GetParentContainerId(GetSubWindowId());
3300         container = AceEngine::Get().GetContainer(instanceId);
3301         if (!container) {
3302             TAG_LOGW(AceLogTag::ACE_DIALOG, "parent container is null");
3303             return false;
3304         }
3305     }
3306 
3307     auto halfFoldStatus = container->GetCurrentFoldStatus() == FoldStatus::HALF_FOLD;
3308     auto isWaterfallWindow = container->IsWaterfallWindow();
3309     return halfFoldStatus && isWaterfallWindow;
3310 }
3311 
3312 bool SheetPresentationPattern::IsCurSheetNeedHalfFoldHover()
3313 {
3314     auto host = GetHost();
3315     CHECK_NULL_RETURN(host, false);
3316     auto pipeline = host->GetContext();
3317     CHECK_NULL_RETURN(pipeline, false);
3318     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3319     CHECK_NULL_RETURN(sheetTheme, false);
3320     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3321     CHECK_NULL_RETURN(layoutProperty, false);
3322     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3323     DeviceType deviceType = SystemProperties::GetDeviceType();
3324     auto enableHoverMode = sheetStyle.enableHoverMode.value_or((deviceType == DeviceType::TWO_IN_ONE) ? true : false);
3325     bool isHoverMode = enableHoverMode ? pipeline->IsHalfFoldHoverStatus() : false;
3326     if (deviceType == DeviceType::TWO_IN_ONE) {
3327         TAG_LOGD(AceLogTag::ACE_SHEET, "sheet IsOuterBorderEnable is true.");
3328         isHoverMode = enableHoverMode ? IsWaterfallWindowMode() : false;
3329     }
3330     return isHoverMode && GetSheetTypeNoProcess() == SheetType::SHEET_CENTER;
3331 }
3332 
3333 bool SheetPresentationPattern::IsShowInSubWindowTwoInOne()
3334 {
3335     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3336     CHECK_NULL_RETURN(layoutProperty, false);
3337     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3338     if (!sheetStyle.showInSubWindow.value_or(false)) {
3339         return false;
3340     }
3341     auto host = GetHost();
3342     CHECK_NULL_RETURN(host, false);
3343     auto pipeline = host->GetContext();
3344     CHECK_NULL_RETURN(pipeline, false);
3345     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3346     CHECK_NULL_RETURN(sheetTheme, false);
3347     return sheetTheme->IsOuterBorderEnable();
3348 }
3349 
3350 bool SheetPresentationPattern::IsShowInSubWindow() const
3351 {
3352     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3353     CHECK_NULL_RETURN(layoutProperty, false);
3354     auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3355     return sheetStyle.showInSubWindow.value_or(false);
3356 }
3357 
3358 void SheetPresentationPattern::InitFoldCreaseRegion()
3359 {
3360     if (!currentFoldCreaseRegion_.empty()) {
3361         return;
3362     }
3363     auto container = Container::Current();
3364     CHECK_NULL_VOID(container);
3365     if (container->IsSubContainer()) {
3366         auto instanceId = SubwindowManager::GetInstance()->GetParentContainerId(container->GetInstanceId());
3367         container = AceEngine::Get().GetContainer(instanceId);
3368     }
3369     CHECK_NULL_VOID(container);
3370     auto displayInfo = container->GetDisplayInfo();
3371     CHECK_NULL_VOID(displayInfo);
3372     currentFoldCreaseRegion_ = displayInfo->GetCurrentFoldCreaseRegion();
3373 }
3374 
3375 Rect SheetPresentationPattern::GetFoldScreenRect() const
3376 {
3377     if (currentFoldCreaseRegion_.empty()) {
3378         TAG_LOGW(AceLogTag::ACE_SHEET, "FoldCreaseRegion is invalid.");
3379         return Rect();
3380     }
3381     return currentFoldCreaseRegion_.front();
3382 }
3383 
3384 Shadow SheetPresentationPattern::GetShadowFromTheme(ShadowStyle shadowStyle)
3385 {
3386     if (shadowStyle == ShadowStyle::None || !sheetObject_->CheckIfNeedShadowByDefault()) {
3387         return Shadow();
3388     }
3389     auto host = GetHost();
3390     CHECK_NULL_RETURN(host, Shadow());
3391     auto pipelineContext = host->GetContext();
3392     CHECK_NULL_RETURN(pipelineContext, Shadow());
3393     auto colorMode = pipelineContext->GetColorMode();
3394     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
3395     CHECK_NULL_RETURN(shadowTheme, Shadow());
3396     auto shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
3397     return shadow;
3398 }
3399 
3400 void SheetPresentationPattern::FireHoverModeChangeCallback()
3401 {
3402     auto host = GetHost();
3403     CHECK_NULL_VOID(host);
3404     auto pipeline = host->GetContext();
3405     CHECK_NULL_VOID(pipeline);
3406     if (!IsCurSheetNeedHalfFoldHover()) {
3407         TAG_LOGD(AceLogTag::ACE_SHEET, "halfFoldHoverStatus: %{public}d, Sheet is not half folded.",
3408             pipeline->IsHalfFoldHoverStatus());
3409         return;
3410     }
3411     OnHeightDidChange(centerHeight_);
3412 }
3413 
3414 void SheetPresentationPattern::GetArrowOffsetByPlacement(
3415     const RefPtr<SheetPresentationLayoutAlgorithm>& layoutAlgorithm)
3416 {
3417     CHECK_NULL_VOID(layoutAlgorithm);
3418     auto host = GetHost();
3419     CHECK_NULL_VOID(host);
3420     if (!host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
3421         return;
3422     }
3423     finalPlacement_ = sheetPopupInfo_.finalPlacement;
3424     showArrow_ = sheetPopupInfo_.showArrow;
3425     arrowPosition_ = sheetPopupInfo_.arrowPosition;
3426     if (!showArrow_ || finalPlacement_ == Placement::NONE) {
3427         arrowOffset_ = OffsetF(0.f, 0.f);
3428         return;
3429     }
3430 
3431     switch (finalPlacement_) {
3432         case Placement::BOTTOM_LEFT:
3433             [[fallthrough]];
3434         case Placement::BOTTOM_RIGHT:
3435             [[fallthrough]];
3436         case Placement::BOTTOM:
3437             [[fallthrough]];
3438         case Placement::TOP_LEFT:
3439             [[fallthrough]];
3440         case Placement::TOP_RIGHT:
3441             [[fallthrough]];
3442         case Placement::TOP: {
3443             arrowOffset_ = OffsetF(sheetPopupInfo_.arrowOffsetX, 0.f);
3444             break;
3445         }
3446         case Placement::RIGHT_TOP:
3447             [[fallthrough]];
3448         case Placement::RIGHT_BOTTOM:
3449             [[fallthrough]];
3450         case Placement::RIGHT:
3451             [[fallthrough]];
3452         case Placement::LEFT_TOP:
3453             [[fallthrough]];
3454         case Placement::LEFT_BOTTOM:
3455             [[fallthrough]];
3456         case Placement::LEFT: {
3457             arrowOffset_ = OffsetF(0.f, sheetPopupInfo_.arrowOffsetY);
3458             break;
3459         }
3460         default:
3461             break;
3462     }
3463 }
3464 
3465 std::string SheetPresentationPattern::GetPopupStyleSheetClipPathNew(
3466     const SizeF& sheetSize, const BorderRadiusProperty& sheetRadius)
3467 {
3468     std::string drawPath;
3469     switch (finalPlacement_) {
3470         case Placement::BOTTOM_LEFT:
3471             [[fallthrough]];
3472         case Placement::BOTTOM_RIGHT:
3473             [[fallthrough]];
3474         case Placement::BOTTOM: {
3475             drawPath = DrawClipPathBottom(sheetSize, sheetRadius);
3476             break;
3477         }
3478         case Placement::TOP_LEFT:
3479             [[fallthrough]];
3480         case Placement::TOP_RIGHT:
3481             [[fallthrough]];
3482         case Placement::TOP: {
3483             drawPath = DrawClipPathTop(sheetSize, sheetRadius);
3484             break;
3485         }
3486         case Placement::RIGHT_TOP:
3487             [[fallthrough]];
3488         case Placement::RIGHT_BOTTOM:
3489             [[fallthrough]];
3490         case Placement::RIGHT: {
3491             drawPath = DrawClipPathRight(sheetSize, sheetRadius);
3492             break;
3493         }
3494         case Placement::LEFT_TOP:
3495             [[fallthrough]];
3496         case Placement::LEFT_BOTTOM:
3497             [[fallthrough]];
3498         case Placement::LEFT: {
3499             drawPath = DrawClipPathLeft(sheetSize, sheetRadius);
3500             break;
3501         }
3502         default:
3503             break;
3504     }
3505     return drawPath;
3506 }
3507 
3508 std::string SheetPresentationPattern::DrawClipPathBottom(const SizeF& sheetSize,
3509     const BorderRadiusProperty& sheetRadius)
3510 {
3511     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3512     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3513     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3514     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3515     // clip path start from TopLeft, and draw Right-angled arrow first if needed
3516     std::string path;
3517     if (arrowPosition_ == SheetArrowPosition::BOTTOM_LEFT) {
3518         path += MoveTo(0.f, SHEET_ARROW_HEIGHT.ConvertToPx());  // P5
3519         path += LineTo(0.f, (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx()); // P4
3520         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3521             (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3522             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3523         path += LineTo(SHEET_ARROW_WIDTH.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx());  // P1
3524     } else {
3525         path += MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopLeft);
3526         path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft,
3527             SHEET_ARROW_HEIGHT.ConvertToPx());
3528     }
3529     if (arrowPosition_ == SheetArrowPosition::NONE) {
3530         path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(),
3531             SHEET_ARROW_HEIGHT.ConvertToPx());  // P1
3532         path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
3533             (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx());   // P2
3534         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3535             arrowOffset_.GetX() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
3536             (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx());   // P4
3537         path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(),
3538             SHEET_ARROW_HEIGHT.ConvertToPx());  // P5
3539     }
3540     if (arrowPosition_ == SheetArrowPosition::BOTTOM_RIGHT) {
3541         path += LineTo(sheetSize.Width() -
3542             SHEET_ARROW_WIDTH.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx());  // P1
3543         path += LineTo(sheetSize.Width() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3544             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3545         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3546             sheetSize.Width(), (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx());  // P4
3547         path += LineTo(sheetSize.Width(), SHEET_ARROW_HEIGHT.ConvertToPx());    // P5
3548     } else {
3549         path += LineTo(sheetSize.Width() - radiusTopRight, SHEET_ARROW_HEIGHT.ConvertToPx());
3550         path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0, sheetSize.Width(),
3551             SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopRight);
3552     }
3553     path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
3554     path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3555         sheetSize.Width() - radiusBottomRight, sheetSize.Height());
3556     path += LineTo(radiusBottomLeft, sheetSize.Height());
3557     path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0, 0.0f,
3558         sheetSize.Height() - radiusBottomLeft);
3559     return path + "Z";
3560 }
3561 
3562 std::string SheetPresentationPattern::DrawClipPathTop(const SizeF& sheetSize,
3563     const BorderRadiusProperty& sheetRadius)
3564 {
3565     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3566     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3567     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3568     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3569     // clip path start from TopLeft, and draw sheet radius first
3570     std::string path;
3571     path += MoveTo(0.f, radiusTopLeft);
3572     path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, 0.f);
3573     path += LineTo(sheetSize.Width() - radiusTopRight, 0.f);
3574     path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3575         sheetSize.Width(), radiusTopRight);
3576     if (arrowPosition_ == SheetArrowPosition::TOP_RIGHT) {
3577         path += LineTo(sheetSize.Width(),
3578             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx());    // P4
3579         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3580             sheetSize.Width() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3581             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx());    // P2
3582         path += LineTo(sheetSize.Width() - SHEET_ARROW_WIDTH.ConvertToPx(),
3583             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3584     } else {
3585         path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight - SHEET_ARROW_HEIGHT.ConvertToPx());
3586         path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3587             sheetSize.Width() - radiusBottomRight, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx());
3588     }
3589     if (arrowPosition_ == SheetArrowPosition::NONE) {
3590         path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(),
3591             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3592         path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
3593             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx());  // P2
3594         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3595             arrowOffset_.GetX() - ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
3596             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx());  // P4
3597         path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(),
3598             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3599     }
3600     if (arrowPosition_ == SheetArrowPosition::TOP_LEFT) {
3601         path += LineTo(SHEET_ARROW_WIDTH.ConvertToPx(),
3602             sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3603         path += LineTo((SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3604             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx());    // P2
3605         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0, 0.f,
3606             sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx());    // P4
3607         path += LineTo(0.f, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3608     } else {
3609         path += LineTo(radiusBottomLeft, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx());
3610         path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3611             0.f, sheetSize.Height() - radiusBottomLeft - SHEET_ARROW_HEIGHT.ConvertToPx());
3612     }
3613     return path + "Z";
3614 }
3615 
3616 std::string SheetPresentationPattern::DrawClipPathLeft(const SizeF& sheetSize,
3617     const BorderRadiusProperty& sheetRadius)
3618 {
3619     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3620     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3621     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3622     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3623     // clip path start from TopLeft, and draw sheet radius first
3624     std::string path;
3625     path += MoveTo(0.f, radiusTopLeft);
3626     path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, 0.f);
3627     if (arrowPosition_ == SheetArrowPosition::LEFT_TOP) {
3628         path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), 0.f); // P4
3629         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3630             sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3631             (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx());  // P2
3632         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3633             SHEET_ARROW_WIDTH.ConvertToPx());  // P1
3634     } else {
3635         path += LineTo(sheetSize.Width() - radiusTopRight - SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
3636         path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3637             sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(), radiusTopRight);
3638     }
3639     if (arrowPosition_ == SheetArrowPosition::NONE) {
3640         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3641             arrowOffset_.GetY() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx());    // P1
3642         path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx(),
3643             arrowOffset_.GetY() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx());    // P2
3644         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3645             sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx(),
3646             arrowOffset_.GetY() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx());    // P4
3647         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3648             arrowOffset_.GetY() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx());    // P5
3649     }
3650     if (arrowPosition_ == SheetArrowPosition::LEFT_BOTTOM) {
3651         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3652             sheetSize.Height() - SHEET_ARROW_WIDTH.ConvertToPx());  // P1
3653         path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3654             sheetSize.Height() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3655         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0, sheetSize.Width() -
3656             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), sheetSize.Height()); // P4
3657         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());   // P5
3658     } else {
3659         path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3660             sheetSize.Height() - radiusBottomRight);
3661         path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3662             sheetSize.Width() - radiusBottomRight - SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());
3663     }
3664     path += LineTo(radiusBottomLeft, sheetSize.Height());
3665     path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3666         0.f, sheetSize.Height() - radiusBottomLeft);
3667     return path + "Z";
3668 }
3669 
3670 std::string SheetPresentationPattern::DrawClipPathRight(const SizeF& sheetSize,
3671     const BorderRadiusProperty& sheetRadius)
3672 {
3673     auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3674     auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3675     auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3676     auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3677     // clip path start from TopLeft, and if left side need draw left top Right-angled arrow, draw it first
3678     std::string path;
3679     if (arrowPosition_ == SheetArrowPosition::RIGHT_TOP) {
3680         path += MoveTo(SHEET_ARROW_HEIGHT.ConvertToPx(), SHEET_ARROW_WIDTH.ConvertToPx());  // P1
3681         path += LineTo((SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3682             (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx());  // P2
3683         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3684             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), 0.f);    // P4
3685         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);  // P5
3686     } else {
3687         path += MoveTo(SHEET_ARROW_HEIGHT.ConvertToPx(), radiusTopLeft);
3688         path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0,
3689             radiusTopLeft + SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
3690     }
3691     path += LineTo(sheetSize.Width() - radiusTopRight, 0.f);
3692     path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3693         sheetSize.Width(), radiusTopRight);
3694     path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
3695     path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3696         sheetSize.Width() - radiusBottomRight, sheetSize.Height());
3697     if (arrowPosition_ == SheetArrowPosition::RIGHT_BOTTOM) {
3698         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());   // P5
3699         path += LineTo((SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), sheetSize.Height());  // P4
3700         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3701             (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3702             sheetSize.Height() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3703         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3704             sheetSize.Height() - SHEET_ARROW_WIDTH.ConvertToPx()); // P1
3705     } else {
3706         path += LineTo(radiusBottomLeft + SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());
3707         path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3708             SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height() - radiusBottomLeft);
3709     }
3710     if (arrowPosition_ == SheetArrowPosition::NONE) {
3711         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3712             arrowOffset_.GetY() + ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx());    // P1
3713         path += LineTo((SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx(),
3714             arrowOffset_.GetY() + ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx());    // P2
3715         path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3716             (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx(),
3717             arrowOffset_.GetY() - ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx());    // P4
3718         path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3719             arrowOffset_.GetY() - ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx());    // P5
3720     }
3721     return path + "Z";
3722 }
3723 
3724 void SheetPresentationPattern::RecoverHalfFoldOrAvoidStatus()
3725 {
3726     TAG_LOGD(AceLogTag::ACE_SHEET, "recover half fold status because of window rotate");
3727     auto host = GetHost();
3728     CHECK_NULL_VOID(host);
3729     auto pipeline = host->GetContext();
3730     CHECK_NULL_VOID(pipeline);
3731     if (IsCurSheetNeedHalfFoldHover()) {
3732         RecoverAvoidKeyboardStatus();
3733     } else {
3734         AvoidSafeArea(true);
3735     }
3736 }
3737 
3738 void SheetPresentationPattern::RecoverAvoidKeyboardStatus()
3739 {
3740     RecoverScrollOrResizeAvoidStatus();
3741     sheetHeightUp_ = 0.f;
3742     OnHeightDidChange(centerHeight_);
3743 }
3744 
3745 void SheetPresentationPattern::RecoverScrollOrResizeAvoidStatus()
3746 {
3747     auto scroll = GetSheetScrollNode();
3748     CHECK_NULL_VOID(scroll);
3749     auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
3750     CHECK_NULL_VOID(layoutProp);
3751     layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight())));
3752     resizeDecreasedHeight_ = 0.f;
3753     scrollHeight_ = 0.f;
3754     ScrollTo(0.f);
3755     isScrolling_ = false;
3756 }
3757 
3758 void SheetPresentationPattern::OnWillAppear()
3759 {
3760     isOnAppearing_ = true;
3761     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet lifecycle change to onWillAppear state.");
3762     if (onWillAppear_) {
3763         onWillAppear_();
3764     }
3765     // "SendMessagesBeforeXX" and "SendMessagesAfterXX" need to be called in conjunction.
3766     // Currently, this is ensured through the lifecycle, and it is not recommended to call them separately.
3767     SendMessagesBeforeFirstTransitionIn(true);
3768 }
3769 
3770 void SheetPresentationPattern::OnAppear()
3771 {
3772     isOnAppearing_ = false;
3773     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet lifecycle change to onAppear state.");
3774     if (onAppear_) {
3775         onAppear_();
3776     }
3777     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
3778         SendMessagesAfterFirstTransitionIn(true);
3779     }
3780 }
3781 
3782 bool SheetPresentationPattern::IsNeedChangeScrollHeight(float height)
3783 {
3784     auto it = std::min_element(sheetDetentHeight_.begin(), sheetDetentHeight_.end());
3785     if (it == sheetDetentHeight_.end()) {
3786         return false;
3787     }
3788     if (IsAvoidingKeyboard()) {
3789         return false;
3790     }
3791     float lowestDetentHeight = *it;
3792     bool isNeedChangeScrollHeight =
3793         scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && GreatOrEqual(height, lowestDetentHeight);
3794     return isNeedChangeScrollHeight;
3795 }
3796 
3797 void SheetPresentationPattern::OnWillDisappear()
3798 {
3799     isOnDisappearing_ = true;
3800     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet lifecycle change to onWillDisappear state.");
3801     if (onWillDisappear_) {
3802         onWillDisappear_();
3803     }
3804     SendMessagesBeforeTransitionOut();
3805     auto hostNode = GetHost();
3806     CHECK_NULL_VOID(hostNode);
3807     auto pipelineContext = hostNode->GetContextRefPtr();
3808     CHECK_NULL_VOID(pipelineContext);
3809     auto navigationManager = pipelineContext->GetNavigationManager();
3810     CHECK_NULL_VOID(navigationManager);
3811     navigationManager->FireOverlayLifecycle(hostNode, static_cast<int32_t>(NavDestinationLifecycle::ON_INACTIVE),
3812         static_cast<int32_t>(NavDestinationActiveReason::SHEET));
3813 }
3814 
3815 void SheetPresentationPattern::OnDisappear()
3816 {
3817     isOnDisappearing_ = false;
3818     TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet lifecycle change to onDisappear state.");
3819     if (onDisappear_) {
3820         isExecuteOnDisappear_ = true;
3821         onDisappear_();
3822     }
3823     isDismissProcess_ = false;
3824 }
3825 
3826 void SheetPresentationPattern::OnFontScaleConfigurationUpdate()
3827 {
3828     auto hostNode = GetHost();
3829     CHECK_NULL_VOID(hostNode);
3830     auto pipeline = hostNode->GetContext();
3831     CHECK_NULL_VOID(pipeline);
3832     pipeline->AddAfterReloadAnimationTask([weak = WeakClaim(this)]() {
3833         auto pattern = weak.Upgrade();
3834         CHECK_NULL_VOID(pattern);
3835         pattern->AvoidSafeArea(true);
3836     });
3837 }
3838 
3839 void SheetPresentationPattern::OnAvoidInfoChange(const ContainerModalAvoidInfo& info)
3840 {
3841     auto host = GetHost();
3842     CHECK_NULL_VOID(host);
3843     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3844 }
3845 
3846 void SheetPresentationPattern::RegisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
3847 {
3848     CHECK_NULL_VOID(hostNode);
3849     auto pipeline = hostNode->GetContext();
3850     CHECK_NULL_VOID(pipeline);
3851     auto mgr = pipeline->GetAvoidInfoManager();
3852     CHECK_NULL_VOID(mgr);
3853     mgr->AddAvoidInfoListener(WeakClaim(this));
3854 }
3855 
3856 void SheetPresentationPattern::UnRegisterAvoidInfoChangeListener(FrameNode* hostNode)
3857 {
3858     CHECK_NULL_VOID(hostNode);
3859     auto pipeline = hostNode->GetContext();
3860     CHECK_NULL_VOID(pipeline);
3861     auto mgr = pipeline->GetAvoidInfoManager();
3862     CHECK_NULL_VOID(mgr);
3863     mgr->RemoveAvoidInfoListener(WeakClaim(this));
3864 }
3865 
3866 /**
3867  * @brief Update and Send messages in other fields before the sheet entrance animation starts.
3868  * Its timing is equivalent to the callback "onWillAppear".
3869  * "SendMessagesBeforeXX" and "SendMessagesAfterXX" need to be called in conjunction.
3870  * Currently, this is ensured through the lifecycle, and it is not recommended to call them separately.
3871  */
3872 void SheetPresentationPattern::SendMessagesBeforeFirstTransitionIn(bool isFirstTransition)
3873 {
3874     if (!isFirstTransition) {
3875         return;
3876     }
3877     auto host = GetHost();
3878     CHECK_NULL_VOID(host);
3879     // Close UIFirst
3880     SetUIFirstSwitch(isFirstTransition, false);
3881     // WindowMaximize
3882     SetWindowUseImplicitAnimation(RawPtr(host), true);
3883     auto context = host->GetRenderContext();
3884     CHECK_NULL_VOID(context);
3885     context->UpdateRenderGroup(true, false, true);
3886     TAG_LOGD(AceLogTag::ACE_SHEET, "UpdateRenderGroup start");
3887     const auto& overlayManager = GetOverlayManager();
3888     CHECK_NULL_VOID(overlayManager);
3889     UpdateAccessibilityDetents(overlayManager->GetSheetHeight());
3890     auto sheetParent = DynamicCast<FrameNode>(host->GetParent());
3891     CHECK_NULL_VOID(sheetParent);
3892     auto levelOrder = overlayManager->GetLevelOrder(sheetParent);
3893     if (overlayManager->IsTopOrder(levelOrder)) {
3894         host->OnAccessibilityEvent(AccessibilityEventType::PAGE_OPEN,
3895             WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
3896     }
3897     ACE_SCOPED_TRACE("Sheet BeforeFirstTransitionIn end");
3898     host->AddToOcclusionMap(true);
3899 }
3900 
3901 /**
3902  * @brief Update and Send messages in other fields after the sheet entrance animation ends.
3903  * Its timing is equivalent to the callback "onAppear".
3904  */
3905 void SheetPresentationPattern::SendMessagesAfterFirstTransitionIn(bool isFirstTransition)
3906 {
3907     if (!isFirstTransition) {
3908         return;
3909     }
3910     SetUIFirstSwitch(isFirstTransition, true);
3911     auto host = GetHost();
3912     CHECK_NULL_VOID(host);
3913     auto context = host->GetRenderContext();
3914     CHECK_NULL_VOID(context);
3915     context->UpdateRenderGroup(false, false, true);
3916     TAG_LOGD(AceLogTag::ACE_SHEET, "UpdateRenderGroup finished");
3917     ACE_SCOPED_TRACE("Sheet AfterFirstTransitionIn end");
3918 }
3919 
3920 /**
3921  * @brief Update and Send messages in other fields before the sheet exit animation starts.
3922  * Its timing is equivalent to the callback "onWillDisappear".
3923  */
3924 void SheetPresentationPattern::SendMessagesBeforeTransitionOut()
3925 {
3926     auto host = GetHost();
3927     CHECK_NULL_VOID(host);
3928     host->OnAccessibilityEvent(
3929         AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
3930     // supports Gesture durring transition
3931     auto sheetParent = DynamicCast<FrameNode>(host->GetParent());
3932     CHECK_NULL_VOID(sheetParent);
3933     auto hub = sheetParent->GetEventHub<EventHub>();
3934     CHECK_NULL_VOID(hub);
3935     hub->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMTRANSPARENT);
3936     ACE_SCOPED_TRACE("Sheet BeforeTransitionOut end");
3937 }
3938 
3939 /**
3940  * @brief Update and Send messages in other fields after the sheet exit animation ends.
3941  * Its timing is equivalent to the callback "onDisappear".
3942  */
3943 void SheetPresentationPattern::SendMessagesAfterTransitionOut(FrameNode* sheetNode)
3944 {
3945     CHECK_NULL_VOID(sheetNode);
3946     // WindowMaximize
3947     SetWindowUseImplicitAnimation(sheetNode, false);
3948     ACE_SCOPED_TRACE("Sheet AfterTransitionOut end");
3949     sheetNode->AddToOcclusionMap(false);
3950 }
3951 
3952 void SheetPresentationPattern::UpdateSheetType()
3953 {
3954     auto sheetType = GetSheetTypeFromSheetManager();
3955     if (sheetType_ != sheetType) {
3956         // It can only be MarkOuterBorder When the SheetType switches and the sheetType_ was SHEET_POPUP
3957         if (sheetType_ == SheetType::SHEET_POPUP) {
3958             // Clear the current double outline, as it is drawn on the sheetWrapper.
3959             MarkSheetPageNeedRender();
3960         }
3961         sheetType_ = sheetType;
3962         typeChanged_ = true;
3963     }
3964 }
3965 
3966 void SheetPresentationPattern::InitSheetObject()
3967 {
3968     // The first CreateObject must be later than UpdateSheetStyle, must be earlier than MarkModifyDone.
3969     // And must be earlier than the entry animation.
3970     if (sheetType_ == SheetType::SHEET_SIDE) {
3971         sheetObject_ = AceType::MakeRefPtr<SheetSideObject>(sheetType_);
3972     } else if (sheetType_ == SheetType::SHEET_CONTENT_COVER) {
3973         sheetObject_ = AceType::MakeRefPtr<SheetContentCoverObject>(sheetType_);
3974     } else {
3975         sheetObject_ = AceType::MakeRefPtr<SheetObject>(sheetType_);
3976     }
3977     sheetObject_->BindPattern(WeakClaim(this));
3978     // Don't process information here, such as events, etc
3979     // Because here only the SheetStyle is updated to the layoutProperty, but the properties are not parsed,
3980     // and the data is not updated to the pattern.
3981 }
3982 
3983 /**
3984  * @brief Update SheetObject according to the new SheetType
3985  *
3986  * UpdateSheetObject must be called after Update sheetType.
3987  *
3988  * UpdateSheetRender is a function which can handle the differentiating capabilities of 2in1.
3989  * The capabilities are include about default shadow, double border.
3990  * UpdateSheetObject must be called before UpdateSheetRender.
3991  * Default shadow and double border depend on new SheetObject.
3992  *
3993  * MarkModifyDone will be called after UpdateSheetRender.
3994  *
3995  * UpdateSheetType -> UpdateSheetObject -> UpdateSheetRender -> MarkModifyDone
3996  *
3997  * @param newType new SheetType
3998  */
3999 void SheetPresentationPattern::UpdateSheetObject(SheetType newType)
4000 {
4001     CHECK_NULL_VOID(sheetObject_);
4002     RefPtr<SheetObject> sheetObject = sheetObject_;
4003     if (sheetObject->GetSheetType() == newType) {
4004         return;
4005     }
4006     if (!sheetObject->CheckIfUpdateObject(newType)) {
4007         sheetObject->UpdateSheetType(newType);
4008         return;
4009     }
4010     if (newType == SheetType::SHEET_SIDE) {
4011         sheetObject = AceType::MakeRefPtr<SheetSideObject>(newType);
4012     } else if (newType == SheetType::SHEET_CONTENT_COVER) {
4013         sheetObject = AceType::MakeRefPtr<SheetContentCoverObject>(newType);
4014     } else {
4015         sheetObject = AceType::MakeRefPtr<SheetObject>(newType);
4016     }
4017     sheetObject->CopyData(sheetObject_);
4018     // start clear old sheet data
4019     RemovePanEvent();
4020     ResetScrollUserDefinedIdealSize(sheetObject_, sheetObject);
4021     ResetLayoutInfo();
4022 
4023     SetSheetObject(sheetObject);
4024     sheetObject_->BindPattern(WeakClaim(this));
4025     FireOnTypeDidChange();
4026     // start init new sheet data
4027     InitPanEvent();
4028     InitSheetMode();
4029     isFirstInit_ = false;
4030     AvoidAiBar();
4031 }
4032 
4033 void SheetPresentationPattern::UpdateBgColor(const RefPtr<ResourceObject>& resObj,
4034     const WeakPtr<FrameNode>& sheetNodeWK)
4035 {
4036     auto sheetNode = sheetNodeWK.Upgrade();
4037     CHECK_NULL_VOID(sheetNode);
4038     // Parse the background olor using the resource object.
4039     Color backgroundColor;
4040     bool result = ResourceParseUtils::ParseResColor(resObj, backgroundColor);
4041     if (!result) {
4042         auto pipelineContext = sheetNode->GetContext();
4043         CHECK_NULL_VOID(pipelineContext);
4044         auto sheetTheme = pipelineContext->GetTheme<OHOS::Ace::NG::SheetTheme>();
4045         backgroundColor = (sheetTheme != nullptr) ? sheetTheme->GetSheetBackgoundColor() : backgroundColor;
4046     }
4047 
4048     // Update sheetStyle.
4049     auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4050     CHECK_NULL_VOID(layoutProperty);
4051     auto sheetStyle = layoutProperty->GetSheetStyleValue();
4052     NG::SheetStyle currSheetStyle = sheetStyle;
4053     currSheetStyle.backgroundColor = backgroundColor;
4054     layoutProperty->UpdateSheetStyle(currSheetStyle);
4055 
4056     // Update sheet mask background color.
4057     auto renderContext = sheetNode->GetRenderContext();
4058     renderContext->UpdateBackgroundColor(backgroundColor);
4059     sheetNode->MarkModifyDone();
4060 }
4061 
4062 void SheetPresentationPattern::RegisterBgColorRes(
4063     const RefPtr<FrameNode>& sheetNode, RefPtr<ResourceObject>& colorResObj)
4064 {
4065     CHECK_NULL_VOID(sheetNode);
4066     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4067     CHECK_NULL_VOID(pattern);
4068     if (colorResObj) {
4069         auto&& updateFunc = [sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode)), weak = WeakClaim(this)]
4070             (const RefPtr<ResourceObject>& colorResObj) {
4071             auto pattern = weak.Upgrade();
4072             CHECK_NULL_VOID(pattern);
4073             pattern->UpdateBgColor(colorResObj, sheetNodeWK);
4074         };
4075         pattern->AddResObj("sheetPage.backgroundColor", colorResObj, std::move(updateFunc));
4076     } else {
4077         pattern->RemoveResObj("sheetPage.backgroundColor");
4078     }
4079 }
4080 
4081 void SheetPresentationPattern::RegisterRadiusRes(const RefPtr<FrameNode>& sheetNode)
4082 {
4083     CHECK_NULL_VOID(sheetNode);
4084     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4085     CHECK_NULL_VOID(pattern);
4086     auto sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode));
4087     auto&& updateFunc = [sheetNodeWK](const RefPtr<ResourceObject>& resObj) {
4088         auto sheetNode = sheetNodeWK.Upgrade();
4089         CHECK_NULL_VOID(sheetNode);
4090         auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4091         CHECK_NULL_VOID(layoutProperty);
4092         auto sheetStyle = layoutProperty->GetSheetStyleValue();
4093         NG::SheetStyle currSheetStyle = sheetStyle;
4094         NG::BorderRadiusProperty radius;
4095         radius.multiValued = false;
4096         auto radiusResObj = sheetStyle.GetRadiusResObj();
4097         // Return directly when the developer does not set the resource type.
4098         if (!sheetStyle.radius->multiValued && !radiusResObj) {
4099             return;
4100         }
4101         if (sheetStyle.radius->multiValued) {
4102             // When multiValued is true, the value is set in multiple directions.
4103             // In this case, invoke ReloadResources to re-parse.
4104             radius = sheetStyle.radius.value();
4105             radius.ReloadResources();
4106         } else if (radiusResObj) {
4107             // When multiValued is false and resource object is not empty, same value in all directions.
4108             // In this case, parse the sheet radius using the resource object.
4109             CalcDimension radiusSingle;
4110             ResourceParseUtils::ParseResDimensionVpNG(radiusResObj, radiusSingle);
4111             radius.SetRadius(radiusSingle);
4112         }
4113         currSheetStyle.radius = radius;
4114         // Update sheet style and radius when radius changes.
4115         layoutProperty->UpdateSheetStyle(currSheetStyle);
4116         auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4117         CHECK_NULL_VOID(pattern);
4118         pattern->ClipSheetNode();
4119         sheetNode->MarkModifyDone();
4120     };
4121     auto resObj = AceType::MakeRefPtr<ResourceObject>();
4122     pattern->AddResObj("sheetPage.radius", resObj, std::move(updateFunc));
4123 }
4124 
4125 void SheetPresentationPattern::UpdateBorderWidth(const RefPtr<FrameNode>& sheetNode)
4126 {
4127     auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4128     CHECK_NULL_VOID(layoutProperty);
4129     auto sheetStyle = layoutProperty->GetSheetStyleValue();
4130     NG::BorderWidthProperty borderWidth;
4131     auto widthResObj = sheetStyle.GetBorderWidthResObj();
4132     // Return directly when the developer does not set the resource type.
4133     if (!sheetStyle.borderWidth->multiValued && !widthResObj) {
4134         return;
4135     }
4136     if (sheetStyle.borderWidth->multiValued) {
4137         // When multiValued is true, the value is set in multiple directions.
4138         // In this case, invoke ReloadResources of border width to re-parse.
4139         borderWidth = sheetStyle.borderWidth.value();
4140         borderWidth.ReloadResources();
4141     } else if (widthResObj) {
4142         // When multiValued is false and resource object is not empty, same value in all directions.
4143         // In this case, parse the sheet border width using the resource object.
4144         CalcDimension borderWidthSingle;
4145         ResourceParseUtils::ParseResDimensionVpNG(widthResObj, borderWidthSingle);
4146         borderWidth = NG::BorderWidthProperty({ borderWidthSingle, borderWidthSingle,
4147             borderWidthSingle, borderWidthSingle, std::nullopt, std::nullopt});
4148     }
4149     // Update sheet style and border width when border width changes.
4150     NG::SheetStyle currSheetStyle = sheetStyle;
4151     currSheetStyle.borderWidth = borderWidth;
4152     layoutProperty->UpdateSheetStyle(currSheetStyle);
4153     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4154     CHECK_NULL_VOID(pattern);
4155     borderWidth = pattern->GetSheetObject()->PostProcessBorderWidth(borderWidth);
4156     layoutProperty->UpdateBorderWidth(borderWidth);
4157     auto renderContext = sheetNode->GetRenderContext();
4158     CHECK_NULL_VOID(renderContext);
4159     renderContext->UpdateBorderWidth(borderWidth);
4160     sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4161 }
4162 
4163 void SheetPresentationPattern::UpdateBorderColor(const RefPtr<FrameNode>& sheetNode)
4164 {
4165     auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4166     CHECK_NULL_VOID(layoutProperty);
4167     auto sheetStyle = layoutProperty->GetSheetStyleValue();
4168     auto colorResObj = sheetStyle.GetBorderColorResObj();
4169     if (!sheetStyle.borderColor.has_value() || (!sheetStyle.borderColor->multiValued && !colorResObj)) {
4170         return;
4171     }
4172     // re-parse border color when needed
4173     NG::BorderColorProperty borderColor;
4174     if (sheetStyle.borderColor->multiValued) {
4175         // When multiValued is true, the value is set in multiple directions.
4176         // In this case, invoke ReloadResources of border Color to re-parse.
4177         borderColor = sheetStyle.borderColor.value();
4178         borderColor.ReloadResources();
4179     } else if (colorResObj) {
4180         // When multiValued is false and resource object is not empty, same value in all directions.
4181         // In this case, parse the sheet border color using the resource object.
4182         Color borderColorSingle;
4183         ResourceParseUtils::ParseResColor(colorResObj, borderColorSingle);
4184         borderColor.SetColor(borderColorSingle);
4185     }
4186     // Update sheet style and border color when border color changes.
4187     NG::SheetStyle currSheetStyle = sheetStyle;
4188     currSheetStyle.borderColor = borderColor;
4189     layoutProperty->UpdateSheetStyle(currSheetStyle);
4190     auto renderContext = sheetNode->GetRenderContext();
4191     CHECK_NULL_VOID(renderContext);
4192     renderContext->UpdateBorderColor(borderColor);
4193     sheetNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4194 }
4195 
4196 void SheetPresentationPattern::RegisterBorderWidthOrColorRes(const RefPtr<FrameNode>& sheetNode)
4197 {
4198     CHECK_NULL_VOID(sheetNode);
4199     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4200     CHECK_NULL_VOID(pattern);
4201     auto&& updateFunc = [sheetNodeWK= AceType::WeakClaim(AceType::RawPtr(sheetNode)), weak = WeakClaim(this)]
4202         (const RefPtr<ResourceObject>& resObjWidth) {
4203         auto pattern = weak.Upgrade();
4204         CHECK_NULL_VOID(pattern);
4205         auto sheetNode = sheetNodeWK.Upgrade();
4206         CHECK_NULL_VOID(sheetNode);
4207         pattern->UpdateBorderWidth(sheetNode);
4208         pattern->UpdateBorderColor(sheetNode);
4209         sheetNode->MarkModifyDone();
4210     };
4211     auto resObj = AceType::MakeRefPtr<ResourceObject>();
4212     pattern->AddResObj("sheetPage.border", resObj, std::move(updateFunc));
4213 }
4214 
4215 void SheetPresentationPattern::HandleMultiDetentKeyboardAvoid()
4216 {
4217     // This function is used to handle the scenario where the semi-modal multi-detent sheet switches to a higher detent
4218     // when avoiding the keyboard.
4219     // height_: Target height of the displacement
4220     // preDetentsHeight_: Height of the previous detent
4221     if (IsAvoidingKeyboard() && GreatNotEqual(height_, preDetentsHeight_)) {
4222         isScrolling_ = true;
4223     }
4224 }
4225 
4226 void SheetPresentationPattern::RegisterTitleRes(const RefPtr<FrameNode>& sheetNode,
4227     RefPtr<ResourceObject>& mainTitleResObj)
4228 {
4229     CHECK_NULL_VOID(sheetNode);
4230     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4231     CHECK_NULL_VOID(pattern);
4232     if (!mainTitleResObj) {
4233         pattern->RemoveResObj("sheetPage.title");
4234     }
4235     auto&& updateFunc =
4236         [sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode)),
4237             weak = WeakClaim(this)](const RefPtr<ResourceObject>& mainTitleResObj) {
4238         // Parse the sheet main title using the resource object.
4239         // Return when parse failed.
4240         std::string mainTitle;
4241         bool result = ResourceParseUtils::ParseResString(mainTitleResObj, mainTitle);
4242         CHECK_NULL_VOID(result);
4243         // Update sheetStyle.
4244         auto sheetNode = sheetNodeWK.Upgrade();
4245         CHECK_NULL_VOID(sheetNode);
4246         auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4247         CHECK_NULL_VOID(layoutProperty);
4248         auto sheetStyle = layoutProperty->GetSheetStyleValue();
4249         NG::SheetStyle currSheetStyle = sheetStyle;
4250         currSheetStyle.sheetTitle = mainTitle;
4251         layoutProperty->UpdateSheetStyle(currSheetStyle);
4252         // Update sheet main title content.
4253         auto pattern = weak.Upgrade();
4254         CHECK_NULL_VOID(pattern);
4255         auto titleNode =
4256             AceType::DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(pattern->GetTitleId()));
4257         CHECK_NULL_VOID(titleNode);
4258         auto titleProp = titleNode->GetLayoutProperty<TextLayoutProperty>();
4259         CHECK_NULL_VOID(titleProp);
4260         titleProp->UpdateContent(mainTitle);
4261         titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4262         sheetNode->MarkModifyDone();
4263 
4264         auto subTitleResObj = sheetStyle.GetSubTitleResObj();
4265         if (sheetStyle.sheetSubtitle.has_value() && subTitleResObj) {
4266             // Parse the sheet subtitle using the resource object.
4267             // Return when parse failed.
4268             std::string subTitle;
4269             bool result = ResourceParseUtils::ParseResString(subTitleResObj, subTitle);
4270             CHECK_NULL_VOID(result);
4271             // Update sheetStyle.
4272             currSheetStyle.sheetSubtitle = subTitle;
4273             layoutProperty->UpdateSheetStyle(currSheetStyle);
4274             // Update sheet subtitle content.
4275             auto subtitleNode =
4276                 DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(pattern->GetSubtitleId()));
4277             CHECK_NULL_VOID(subtitleNode);
4278             auto subtitleProp = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
4279             CHECK_NULL_VOID(subtitleProp);
4280             subtitleProp->UpdateContent(subTitle);
4281             subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4282             sheetNode->MarkModifyDone();
4283         }
4284     };
4285     pattern->AddResObj("sheetPage.title", mainTitleResObj, std::move(updateFunc));
4286 }
4287 
4288 void SheetPresentationPattern::RegisterDetentSelectionRes(const RefPtr<FrameNode>& sheetNode,
4289     RefPtr<ResourceObject>& resObj)
4290 {
4291     CHECK_NULL_VOID(sheetNode);
4292     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4293     CHECK_NULL_VOID(pattern);
4294     if (resObj) {
4295         auto sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode));
4296         auto overlayWk = pattern->GetOverlay();
4297         auto&& updateFunc = [overlayWk, sheetNodeWK](const RefPtr<ResourceObject>& resObj) {
4298             auto sheetNode = sheetNodeWK.Upgrade();
4299             CHECK_NULL_VOID(sheetNode);
4300             auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4301             CHECK_NULL_VOID(layoutProperty);
4302             auto sheetStyle = layoutProperty->GetSheetStyleValue();
4303             NG::SheetStyle currSheetStyle = sheetStyle;
4304             CalcDimension detentSelection;
4305             currSheetStyle.detentSelection->height.reset();
4306             currSheetStyle.detentSelection->sheetMode.reset();
4307             // Parse the sheet detentSelection using the resource object.
4308             bool result = ResourceParseUtils::ParseResDimensionVpNG(resObj, detentSelection);
4309             if (result) {
4310                 currSheetStyle.detentSelection->height = detentSelection;
4311             } else {
4312                 // Use the default detentSelection in sheetTheme for parse failed.
4313                 auto pipelineContext = sheetNode->GetContext();
4314                 CHECK_NULL_VOID(pipelineContext);
4315                 auto sheetTheme = pipelineContext->GetTheme<OHOS::Ace::NG::SheetTheme>();
4316                 CHECK_NULL_VOID(sheetTheme);
4317                 currSheetStyle.detentSelection->sheetMode =
4318                     static_cast<NG::SheetMode>(sheetTheme->GetSheetHeightDefaultMode());
4319             }
4320             auto overlayManager = overlayWk.Upgrade();
4321             if (overlayManager) {
4322                 // Update sheetpage when detentSelection changes.
4323                 overlayManager->UpdateSheetPage(sheetNode, currSheetStyle);
4324             }
4325         };
4326         pattern->AddResObj("sheetPage.detentSelection", resObj, std::move(updateFunc));
4327     } else {
4328         pattern->RemoveResObj("sheetPage.detentSelection");
4329     }
4330 }
4331 
4332 void SheetPresentationPattern::RegisterShowCloseRes(const RefPtr<FrameNode>& sheetNode,
4333     RefPtr<ResourceObject>& showCloseResObj)
4334 {
4335     CHECK_NULL_VOID(sheetNode);
4336     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4337     CHECK_NULL_VOID(pattern);
4338     if (showCloseResObj) {
4339         auto sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode));
4340         auto&& updateFunc = [sheetNodeWK, weak = WeakClaim(this)](const RefPtr<ResourceObject>& showCloseResObj) {
4341             bool showCloseIcon = true;
4342             bool result = ResourceParseUtils::ParseResBool(showCloseResObj, showCloseIcon);
4343             auto sheetNode = sheetNodeWK.Upgrade();
4344             CHECK_NULL_VOID(sheetNode);
4345             if (!result) {
4346                 // Use the default showCloseIcon in sheetTheme for parse failed.
4347                 auto pipelineContext = sheetNode->GetContext();
4348                 CHECK_NULL_VOID(pipelineContext);
4349                 auto sheetTheme = pipelineContext->GetTheme<OHOS::Ace::NG::SheetTheme>();
4350                 showCloseIcon = (sheetTheme != nullptr) ? sheetTheme->GetShowCloseIcon() : showCloseIcon;
4351             }
4352 
4353             // Update sheetStyle.
4354             auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4355             CHECK_NULL_VOID(layoutProperty);
4356             auto sheetStyle = layoutProperty->GetSheetStyleValue();
4357             NG::SheetStyle currSheetStyle = sheetStyle;
4358             currSheetStyle.showCloseIcon = showCloseIcon;
4359             layoutProperty->UpdateSheetStyle(currSheetStyle);
4360 
4361             // Update sheet close icom visible status.
4362             auto pattern = weak.Upgrade();
4363             CHECK_NULL_VOID(pattern);
4364             auto sheetCloseIcon = pattern->GetSheetCloseIcon();
4365             CHECK_NULL_VOID(sheetCloseIcon);
4366             auto iconLayoutProperty = sheetCloseIcon->GetLayoutProperty();
4367             CHECK_NULL_VOID(iconLayoutProperty);
4368             iconLayoutProperty->UpdateVisibility(showCloseIcon ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
4369             sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4370             sheetNode->MarkModifyDone();
4371         };
4372         pattern->AddResObj("sheetPage.showClose", showCloseResObj, std::move(updateFunc));
4373     } else {
4374         pattern->RemoveResObj("sheetPage.showClose");
4375     }
4376 }
4377 
4378 void SheetPresentationPattern::RegisterHeightRes(const RefPtr<FrameNode>& sheetNode,
4379     RefPtr<ResourceObject>& resObj)
4380 {
4381     CHECK_NULL_VOID(sheetNode);
4382     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4383     CHECK_NULL_VOID(pattern);
4384     if (resObj) {
4385         auto sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode));
4386         auto overlayWk = pattern->GetOverlay();
4387         auto&& updateFunc = [overlayWk, sheetNodeWK](const RefPtr<ResourceObject>& resObj) {
4388             auto sheetNode = sheetNodeWK.Upgrade();
4389             CHECK_NULL_VOID(sheetNode);
4390             auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4391             CHECK_NULL_VOID(layoutProperty);
4392             auto sheetStyle = layoutProperty->GetSheetStyleValue();
4393             NG::SheetStyle currSheetStyle = sheetStyle;
4394             CalcDimension sheetHeightValue;
4395             // Parse the sheet height using the resource object.
4396             bool result = ResourceParseUtils::ParseResDimensionVpNG(resObj, sheetHeightValue);
4397             currSheetStyle.sheetHeight.height.reset();
4398             currSheetStyle.sheetHeight.sheetMode.reset();
4399             if (result) {
4400                 currSheetStyle.sheetHeight.height = sheetHeightValue;
4401             } else {
4402                 // Use the default sheetMode in sheetTheme for parse failed.
4403                 auto pipelineContext = sheetNode->GetContext();
4404                 CHECK_NULL_VOID(pipelineContext);
4405                 auto sheetTheme = pipelineContext->GetTheme<OHOS::Ace::NG::SheetTheme>();
4406                 CHECK_NULL_VOID(sheetTheme);
4407                 currSheetStyle.sheetHeight.sheetMode =
4408                     static_cast<NG::SheetMode>(sheetTheme->GetSheetHeightDefaultMode());
4409             }
4410             auto overlayManager = overlayWk.Upgrade();
4411             if (overlayManager) {
4412                 // Update sheetpage when height changes.
4413                 overlayManager->UpdateSheetPage(sheetNode, currSheetStyle);
4414             }
4415         };
4416         pattern->AddResObj("sheetPage.sheetHeight", resObj, std::move(updateFunc));
4417     } else {
4418         pattern->RemoveResObj("sheetPage.sheetHeight");
4419     }
4420 }
4421 
4422 void SheetPresentationPattern::RegisterWidthRes(const RefPtr<FrameNode>& sheetNode,
4423     RefPtr<ResourceObject>& resObj)
4424 {
4425     CHECK_NULL_VOID(sheetNode);
4426     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4427     CHECK_NULL_VOID(pattern);
4428     if (resObj) {
4429         auto sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode));
4430         auto overlayWk = pattern->GetOverlay();
4431         auto&& updateFunc = [overlayWk, weak = WeakClaim(this), sheetNodeWK](const RefPtr<ResourceObject>& resObj) {
4432             auto sheetNode = sheetNodeWK.Upgrade();
4433             CHECK_NULL_VOID(sheetNode);
4434             auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4435             CHECK_NULL_VOID(layoutProperty);
4436             auto sheetStyle = layoutProperty->GetSheetStyleValue();
4437             NG::SheetStyle currSheetStyle = sheetStyle;
4438             CalcDimension width;
4439             // Parse the sheet width using the resource object.
4440             bool result = ResourceParseUtils::ParseResDimensionVpNG(resObj, width);
4441             if (result) {
4442                 currSheetStyle.width = width;
4443             } else {
4444                 // Use the default width in sheetTheme for parse failed,
4445                 // when sheet type is SHEET_CENTER.
4446                 auto pipeline = sheetNode->GetContext();
4447                 CHECK_NULL_VOID(pipeline);
4448                 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
4449                 auto pattern = weak.Upgrade();
4450                 CHECK_NULL_VOID(pattern);
4451                 currSheetStyle.width = ((sheetTheme != nullptr) && pattern->GetSheetTypeNoProcess() == SHEET_CENTER)
4452                     ? sheetTheme->GetCenterDefaultWidth()
4453                     : width;
4454             }
4455             auto overlayManager = overlayWk.Upgrade();
4456             if (overlayManager) {
4457                 // Update sheetpage when width changes.
4458                 overlayManager->UpdateSheetPage(sheetNode, currSheetStyle);
4459             }
4460         };
4461         pattern->AddResObj("sheetPage.width", resObj, std::move(updateFunc));
4462     } else {
4463         pattern->RemoveResObj("sheetPage.width");
4464     }
4465 }
4466 
4467 void SheetPresentationPattern::UpdateSheetDetents(const RefPtr<ResourceObject>& resObj,
4468     const WeakPtr<FrameNode>& sheetNodeWK, const WeakPtr<OverlayManager>& overlayWk)
4469 {
4470     auto sheetNode = sheetNodeWK.Upgrade();
4471     CHECK_NULL_VOID(sheetNode);
4472     auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4473     CHECK_NULL_VOID(layoutProperty);
4474     auto sheetStyle = layoutProperty->GetSheetStyleValue();
4475     NG::SheetStyle sheetStyleValue = sheetStyle;
4476     std::vector<RefPtr<ResourceObject>> resObjVector = sheetStyle.GetDetentsResObjs();
4477     std::vector<NG::SheetHeight> sheetDetents;
4478     for (const auto& resObj : resObjVector) {
4479         // Traverse resObjVector and parse each detents height resource.
4480         if (resObj == nullptr) {
4481             continue;
4482         }
4483         NG::SheetHeight sheetDetent;
4484         CalcDimension sheetHeightValue;
4485         bool result = ResourceParseUtils::ParseResDimensionVpNG(resObj, sheetHeightValue);
4486         if (result) {
4487             sheetDetent.height = sheetHeightValue;
4488         } else {
4489             // Use the default sheetMode in sheetTheme for parse failed.
4490             auto pipelineContext = sheetNode->GetContext();
4491             CHECK_NULL_VOID(pipelineContext);
4492             auto sheetTheme = pipelineContext->GetTheme<OHOS::Ace::NG::SheetTheme>();
4493             CHECK_NULL_VOID(sheetTheme);
4494             sheetDetent.sheetMode = static_cast<NG::SheetMode>(sheetTheme->GetSheetHeightDefaultMode());
4495         }
4496         sheetDetents.emplace_back(sheetDetent);
4497     }
4498     sheetStyleValue.detents = sheetDetents;
4499     auto overlayManager = overlayWk.Upgrade();
4500     if (overlayManager) {
4501         // Update sheetpage when detents changes.
4502         overlayManager->UpdateSheetPage(sheetNode, sheetStyleValue);
4503     }
4504 }
4505 
4506 void SheetPresentationPattern::RegisterDetentsRes(const RefPtr<FrameNode>& sheetNode,
4507     std::vector<RefPtr<ResourceObject>>& resObjVec)
4508 {
4509     CHECK_NULL_VOID(sheetNode);
4510     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4511     CHECK_NULL_VOID(pattern);
4512     bool isNeedRegisterRes =
4513         !resObjVec.empty() &&
4514             std::any_of(resObjVec.begin(), resObjVec.end(), [](const RefPtr<ResourceObject>& resObj) {
4515         return resObj != nullptr;
4516     });
4517     if (isNeedRegisterRes) {
4518         RefPtr<ResourceObject> resObject = AceType::MakeRefPtr<ResourceObject>();
4519         auto sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode));
4520         auto overlayWk = pattern->GetOverlay();
4521         auto&& updateFunc = [overlayWk, sheetNodeWK, weak = WeakClaim(this)]
4522             (const RefPtr<ResourceObject>& resObject) {
4523             auto pattern = weak.Upgrade();
4524             CHECK_NULL_VOID(pattern);
4525             pattern->UpdateSheetDetents(resObject, sheetNodeWK, overlayWk);
4526         };
4527         pattern->AddResObj("sheetPage.sheetDetents", resObject, std::move(updateFunc));
4528     } else {
4529         pattern->RemoveResObj("sheetPage.sheetDetents");
4530     }
4531 }
4532 
4533 void SheetPresentationPattern::RegisterShadowRes(const RefPtr<FrameNode>& sheetNode)
4534 {
4535     CHECK_NULL_VOID(sheetNode);
4536     auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4537     CHECK_NULL_VOID(pattern);
4538     auto sheetNodeWK = AceType::WeakClaim(AceType::RawPtr(sheetNode));
4539     auto&& updateFunc = [sheetNodeWK](const RefPtr<ResourceObject>& resObj) {
4540         auto sheetNode = sheetNodeWK.Upgrade();
4541         CHECK_NULL_VOID(sheetNode);
4542         auto layoutProperty = DynamicCast<SheetPresentationProperty>(sheetNode->GetLayoutProperty());
4543         CHECK_NULL_VOID(layoutProperty);
4544         auto sheetStyle = layoutProperty->GetSheetStyleValue();
4545         NG::SheetStyle currSheetStyle = sheetStyle;
4546         std::optional<Shadow> shadow;
4547         if (sheetStyle.shadow.has_value()) {
4548             // If the shadow in the sheetstyle is not empty,
4549             // reload the shadow to update its value.
4550             shadow = sheetStyle.shadow.value();
4551             shadow->ReloadResources();
4552             currSheetStyle.shadow = shadow;
4553             layoutProperty->UpdateSheetStyle(currSheetStyle);
4554             auto renderContext = sheetNode->GetRenderContext();
4555             CHECK_NULL_VOID(renderContext);
4556             renderContext->UpdateBackShadow(shadow.value());
4557             sheetNode->MarkModifyDone();
4558         }
4559     };
4560     RefPtr<ResourceObject> resObj = AceType::MakeRefPtr<ResourceObject>();
4561     pattern->AddResObj("sheetPage.shadow", resObj, std::move(updateFunc));
4562 }
4563 
4564 void SheetPresentationPattern::UpdateSheetParamResource(const RefPtr<FrameNode>& sheetNode,
4565     NG::SheetStyle& sheetStyle)
4566 {
4567     if (sheetStyle.sheetHeight.height.has_value()) {
4568         auto resObj = sheetStyle.GetSheetHeightResObj();
4569         RegisterHeightRes(sheetNode, resObj);
4570     }
4571     if (!sheetStyle.detents.empty()) {
4572         auto resObjVec = sheetStyle.GetDetentsResObjs();
4573         RegisterDetentsRes(sheetNode, resObjVec);
4574     }
4575     if (sheetStyle.detentSelection.has_value()) {
4576         auto resObj = sheetStyle.GetDetentSelectionResObj();
4577         RegisterDetentSelectionRes(sheetNode, resObj);
4578     }
4579     if (sheetStyle.showCloseIcon.has_value()) {
4580         auto resObj = sheetStyle.GetShowCloseResObj();
4581         RegisterShowCloseRes(sheetNode, resObj);
4582     }
4583     if (sheetStyle.sheetTitle.has_value()) {
4584         auto mainTitleResObj = sheetStyle.GetMainTitleResObj();
4585         RegisterTitleRes(sheetNode, mainTitleResObj);
4586     }
4587     if (sheetStyle.width.has_value()) {
4588         auto resObj = sheetStyle.GetSheetWidthResObj();
4589         RegisterWidthRes(sheetNode, resObj);
4590     }
4591     if (sheetStyle.backgroundColor.has_value()) {
4592         auto resObj = sheetStyle.GetBackgroundColorResObj();
4593         RegisterBgColorRes(sheetNode, resObj);
4594     }
4595     if (sheetStyle.borderWidth.has_value()) {
4596         RegisterBorderWidthOrColorRes(sheetNode);
4597     }
4598     if (sheetStyle.radius.has_value()) {
4599         RegisterRadiusRes(sheetNode);
4600     }
4601     if (sheetStyle.shadow.has_value()) {
4602         RegisterShadowRes(sheetNode);
4603     }
4604 }
4605 
4606 void SheetPresentationPattern::ResetLayoutInfo()
4607 {
4608     height_ = 0.0f;
4609     property_.Reset();
4610     animation_.reset();
4611 }
4612 
4613 void SheetPresentationPattern::ResetScrollUserDefinedIdealSize(
4614     const RefPtr<SheetObject>& oldObject, const RefPtr<SheetObject>& newObject)
4615 {
4616     CHECK_NULL_VOID(oldObject);
4617     CHECK_NULL_VOID(newObject);
4618     if (newObject->GetSheetType() != SheetType::SHEET_SIDE) {
4619         return;
4620     }
4621     auto scrollNode = GetSheetScrollNode();
4622     CHECK_NULL_VOID(scrollNode);
4623     auto props = scrollNode->GetLayoutProperty();
4624     CHECK_NULL_VOID(props);
4625     props->ClearUserDefinedIdealSize(true, true);
4626 }
4627 
4628 void SheetPresentationPattern::OnLanguageConfigurationUpdate()
4629 {
4630     sheetObject_->OnLanguageConfigurationUpdate();
4631 }
4632 } // namespace OHOS::Ace::NG
4633