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
18 #include "base/geometry/dimension.h"
19 #include "base/log/dump_log.h"
20 #include "base/memory/referenced.h"
21 #include "base/utils/utils.h"
22 #include "base/window/foldable_window.h"
23 #include "core/animation/animation_pub.h"
24 #include "core/animation/curve.h"
25 #include "core/common/ace_engine.h"
26 #include "core/common/container.h"
27 #include "core/components/drag_bar/drag_bar_theme.h"
28 #include "core/components_ng/base/frame_node.h"
29 #include "core/components_ng/event/event_hub.h"
30 #include "core/components_ng/event/gesture_event_hub.h"
31 #include "core/components_ng/event/touch_event.h"
32 #include "core/components_ng/pattern/container_modal/enhance/container_modal_view_enhance.h"
33 #include "core/components_ng/pattern/image/image_pattern.h"
34 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
35 #include "core/components_ng/pattern/overlay/overlay_manager.h"
36 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
37 #include "core/components_ng/pattern/overlay/sheet_manager.h"
38 #include "core/components_ng/pattern/overlay/sheet_style.h"
39 #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h"
40 #include "core/components_ng/pattern/scroll/scroll_layout_algorithm.h"
41 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
42 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
43 #include "core/components_ng/pattern/stage/page_pattern.h"
44 #include "core/components_ng/pattern/text/text_layout_property.h"
45 #include "core/components_ng/pattern/text_field/text_field_manager.h"
46 #include "core/components_ng/property/accessibility_property_helper.h"
47 #ifdef WINDOW_SCENE_SUPPORTED
48 #include "core/components_ng/pattern/window_scene/scene/system_window_scene.h"
49 #endif
50 #include "core/components_ng/property/property.h"
51 #ifdef ENABLE_ROSEN_BACKEND
52 #include "core/components_ng/render/adapter/rosen_render_context.h"
53 #endif
54 #include "core/components/theme/shadow_theme.h"
55 #include "core/components_v2/inspector/inspector_constants.h"
56 #include "core/event/touch_event.h"
57 #include "core/pipeline_ng/pipeline_context.h"
58
59 namespace OHOS::Ace::NG {
60 namespace {
61 constexpr float SHEET_VISIABLE_ALPHA = 1.0f;
62 constexpr float SHEET_INVISIABLE_ALPHA = 0.0f;
63 constexpr int32_t SHEET_ENTRY_ANIMATION_DURATION = 250;
64 constexpr int32_t SHEET_EXIT_ANIMATION_DURATION = 100;
65 constexpr float SHEET_INVISIABLE_OFFSET = 8.0;
66 constexpr int32_t SHEET_HALF_HEIGHT = 2;
67 constexpr Dimension ARROW_VERTICAL_P1_OFFSET_X = 8.0_vp;
68 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_X = 1.5_vp;
69 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_Y = 7.32_vp;
70 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_X = 1.5_vp;
71 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_Y = 7.32_vp;
72 constexpr Dimension ARROW_VERTICAL_P5_OFFSET_X = 8.0_vp;
73 constexpr Dimension ARROW_CORNER_P2_OFFSET_X = 12.8_vp;
74 constexpr Dimension ARROW_CORNER_P2_OFFSET_Y = 7.6_vp;
75 constexpr Dimension ARROW_CORNER_P4_OFFSET_Y = 6.0_vp;
76 constexpr Dimension ARROW_RADIUS = 2.0_vp;
77 constexpr Dimension SUBWINDOW_SHEET_TRANSLATION = 80.0_vp;
78 } // namespace
OnModifyDone()79 void SheetPresentationPattern::OnModifyDone()
80 {
81 auto host = GetHost();
82 CHECK_NULL_VOID(host);
83 auto renderContext = host->GetRenderContext();
84 if (renderContext) {
85 auto pipeline = host->GetContext();
86 CHECK_NULL_VOID(pipeline);
87 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
88 CHECK_NULL_VOID(sheetTheme);
89 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
90 CHECK_NULL_VOID(layoutProperty);
91 auto sheetStyle = layoutProperty->GetSheetStyleValue();
92 BlurStyle blurStyle = static_cast<BlurStyle>(sheetTheme->GetSheetBackgroundBlurStyle());
93 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)
94 && blurStyle != BlurStyle::NO_MATERIAL) {
95 BlurStyleOption options;
96 options.blurStyle = blurStyle;
97 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
98 renderContext->UpdateBackBlurStyle(sheetStyle.backgroundBlurStyle.value_or(options));
99 } else {
100 renderContext->UpdateBackgroundColor(
101 sheetStyle.backgroundColor.value_or(sheetTheme->GetSheetBackgoundColor()));
102 }
103 }
104 InitPanEvent();
105 InitPageHeight();
106 InitScrollProps();
107 UpdateSheetType();
108 InitFoldCreaseRegion();
109 }
110
111 // check device is phone, fold status, and device in landscape
IsPhoneInLandScape()112 bool SheetPresentationPattern::IsPhoneInLandScape()
113 {
114 auto host = GetHost();
115 CHECK_NULL_RETURN(host, false);
116 auto pipelineContext = host->GetContext();
117 CHECK_NULL_RETURN(pipelineContext, false);
118 auto containerId = Container::CurrentId();
119 auto foldWindow = FoldableWindow::CreateFoldableWindow(containerId);
120 CHECK_NULL_RETURN(foldWindow, false);
121 auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
122 CHECK_NULL_RETURN(sheetTheme, false);
123 auto sheetThemeType = sheetTheme->GetSheetType();
124 if (sheetThemeType == "auto" && !foldWindow->IsFoldExpand() &&
125 SystemProperties::GetDeviceOrientation() == DeviceOrientation::LANDSCAPE) {
126 return true;
127 }
128 return false;
129 }
130
GetSheetTopSafeArea()131 float SheetPresentationPattern::GetSheetTopSafeArea()
132 {
133 auto host = GetHost();
134 CHECK_NULL_RETURN(host, 0.0f);
135 auto pipelineContext = host->GetContext();
136 CHECK_NULL_RETURN(pipelineContext, 0.0f);
137 auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
138 auto sheetTopSafeArea = safeAreaInsets.top_.Length();
139 auto windowManager = pipelineContext->GetWindowManager();
140 auto sheetType = GetSheetType();
141 auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
142 double deviceHeight = static_cast<double>(SystemProperties::GetDeviceHeight());
143
144 // full screen subwindow sheet is also WINDOW_MODE_FLOATING, can not enter
145 if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING &&
146 !NearEqual(windowGlobalRect.Height(), deviceHeight)) {
147 sheetTopSafeArea = SHEET_BLANK_FLOATING_STATUS_BAR.ConvertToPx();
148 } else if ((sheetType == SheetType::SHEET_BOTTOMLANDSPACE || sheetType == SheetType::SHEET_BOTTOM ||
149 sheetType == SheetType::SHEET_BOTTOM_OFFSET) &&
150 Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
151 sheetTopSafeArea = GetBottomSafeArea();
152 } else if (sheetType == SheetType::SHEET_BOTTOMLANDSPACE &&
153 AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
154 sheetTopSafeArea = 0.0f;
155 }
156 // before API14,ignore safeArea height when in landscape
157 if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
158 auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
159 CHECK_NULL_RETURN(layoutProperty, 0.0f);
160 auto sheetStyle = layoutProperty->GetSheetStyleValue();
161 if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
162 IsPhoneInLandScape()) {
163 sheetTopSafeArea = 0.0f;
164 }
165 }
166 // if window titleBar hidden, avoid button area.
167 NG::RectF floatButtons;
168 if (GetWindowButtonRect(floatButtons)) {
169 sheetTopSafeArea = floatButtons.Height();
170 }
171 return sheetTopSafeArea;
172 }
173
InitPageHeight()174 void SheetPresentationPattern::InitPageHeight()
175 {
176 auto pipelineContext = PipelineContext::GetCurrentContext();
177 CHECK_NULL_VOID(pipelineContext);
178 auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
179 auto currentTopSafeArea = sheetTopSafeArea_;
180 TAG_LOGD(AceLogTag::ACE_SHEET, "statusBarHeight of sheet by GetSafeAreaWithoutProcess : %{public}u",
181 safeAreaInsets.top_.Length());
182 sheetTopSafeArea_ =
183 GetSheetType() != SheetType::SHEET_BOTTOMLANDSPACE ? safeAreaInsets.top_.Length() : .0f;
184 auto showInPage =
185 GetLayoutProperty<SheetPresentationProperty>()->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
186 auto overlay = GetOverlayManager();
187 if (overlay && overlay->IsRootExpansive() && showInPage) {
188 sheetTopSafeArea_ = .0f;
189 }
190 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
191 CHECK_NULL_VOID(layoutProperty);
192 auto sheetStyle = layoutProperty->GetSheetStyleValue();
193 if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
194 IsPhoneInLandScape()) {
195 sheetTopSafeArea_ = 0.0f;
196 }
197 sheetTopSafeArea_ = GetSheetTopSafeArea();
198 TAG_LOGD(AceLogTag::ACE_SHEET, "sheetTopSafeArea of sheet is : %{public}f", sheetTopSafeArea_);
199 if (!NearEqual(currentTopSafeArea, sheetTopSafeArea_)) {
200 topSafeAreaChanged_ = true;
201 }
202 auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
203 CHECK_NULL_VOID(sheetTheme);
204 sheetThemeType_ = sheetTheme->GetSheetType();
205 InitSheetMode();
206 }
207
InitScrollProps()208 void SheetPresentationPattern::InitScrollProps()
209 {
210 auto scrollNode = GetSheetScrollNode();
211 CHECK_NULL_VOID(scrollNode);
212 auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
213 CHECK_NULL_VOID(scrollPattern);
214
215 // When sheet content height is larger than sheet height,
216 // the sheet height should set scroll always enabled.
217 auto edgeEffectAlwaysEnabled = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && IsScrollable();
218 if (sheetEffectEdge_ == SheetEffectEdge::NONE) {
219 scrollPattern->SetEdgeEffect(EdgeEffect::NONE, edgeEffectAlwaysEnabled);
220 } else {
221 scrollPattern->SetEdgeEffect(EdgeEffect::SPRING,
222 edgeEffectAlwaysEnabled, static_cast<EffectEdge>(sheetEffectEdge_));
223 }
224 }
225
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)226 bool SheetPresentationPattern::OnDirtyLayoutWrapperSwap(
227 const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
228 {
229 if (config.skipMeasure && config.skipLayout) {
230 return false;
231 }
232 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
233 CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
234 auto sheetLayoutAlgorithm =
235 DynamicCast<SheetPresentationLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
236 CHECK_NULL_RETURN(sheetLayoutAlgorithm, false);
237 InitPageHeight();
238 if (sheetLayoutAlgorithm->GetSheetMaxHeight() > 0) {
239 pageHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight();
240 sheetMaxHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight() - sheetTopSafeArea_;
241 sheetMaxWidth_ = sheetLayoutAlgorithm->GetSheetMaxWidth();
242 centerHeight_ = sheetLayoutAlgorithm->GetCenterHeight();
243 if (!NearEqual(sheetOffsetX_, sheetLayoutAlgorithm->GetSheetOffsetX()) ||
244 !NearEqual(sheetOffsetY_, sheetLayoutAlgorithm->GetSheetOffsetY())) {
245 sheetOffsetX_ = sheetLayoutAlgorithm->GetSheetOffsetX();
246 sheetOffsetY_ = sheetLayoutAlgorithm->GetSheetOffsetY();
247 arrowOffset_ = OffsetF(sheetPopupInfo_.arrowOffsetX, .0f);
248 windowChanged_ = true;
249 }
250 }
251 GetArrowOffsetByPlacement(sheetLayoutAlgorithm);
252 InitialLayoutProps();
253 UpdateFontScaleStatus();
254 UpdateDragBarStatus();
255 UpdateCloseIconStatus();
256 UpdateTitlePadding();
257 UpdateSheetTitle();
258 ClipSheetNode();
259 CheckBuilderChange();
260 if (GetSheetType() != SheetType::SHEET_POPUP) {
261 if (windowRotate_) {
262 // When rotating the screen,
263 // first switch the sheet to the position corresponding to the proportion before rotation
264 TranslateTo(pageHeight_ - height_);
265 windowRotate_ = false;
266 } else {
267 // After rotation, if need to avoid the keyboard, trigger the avoidance behavior
268 AvoidSafeArea();
269 }
270 }
271 if (GetSheetType() == SheetType::SHEET_POPUP) {
272 MarkSheetPageNeedRender();
273 }
274 return true;
275 }
276
CheckBuilderChange()277 void SheetPresentationPattern::CheckBuilderChange()
278 {
279 auto host = GetHost();
280 CHECK_NULL_VOID(host);
281 auto builderNode = GetFirstFrameNodeOfBuilder();
282 CHECK_NULL_VOID(builderNode);
283 auto eventHub = builderNode->GetEventHub<EventHub>();
284 CHECK_NULL_VOID(eventHub);
285 OnAreaChangedFunc onBuilderAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
286 const OffsetF& /* oldOrigin */, const RectF& /* rect */,
287 const OffsetF& /* origin */) {
288 auto sheetNode = sheetNodeWk.Upgrade();
289 CHECK_NULL_VOID(sheetNode);
290 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
291 CHECK_NULL_VOID(sheetPattern);
292 auto layoutProperty = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
293 CHECK_NULL_VOID(layoutProperty);
294 auto sheetStyle = layoutProperty->GetSheetStyleValue();
295 if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
296 auto sheetWrapper = sheetNode->GetParent();
297 CHECK_NULL_VOID(sheetWrapper);
298 sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
299 }
300 };
301 eventHub->AddInnerOnAreaChangedCallback(builderNode->GetId(), std::move(onBuilderAreaChangedFunc));
302 }
303
AvoidAiBar()304 void SheetPresentationPattern::AvoidAiBar()
305 {
306 CHECK_NULL_VOID(Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN));
307 if (!IsTypeNeedAvoidAiBar()) {
308 TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet need not avoid AiBar.");
309 return;
310 }
311 auto host = GetHost();
312 CHECK_NULL_VOID(host);
313 auto scrollNode = GetSheetScrollNode();
314 CHECK_NULL_VOID(scrollNode);
315 auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
316 CHECK_NULL_VOID(scrollPattern);
317 if (NonPositive(scrollPattern->GetScrollableDistance()) || isScrolling_) {
318 return;
319 }
320 auto pipeline = PipelineContext::GetCurrentContext();
321 CHECK_NULL_VOID(pipeline);
322 auto inset = pipeline->GetSafeArea();
323 auto layoutProperty = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
324 layoutProperty->UpdateScrollContentEndOffset(inset.bottom_.Length());
325 TAG_LOGD(AceLogTag::ACE_SHEET, "AvoidAiBar function execution completed");
326 host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
327 }
328
IsScrollable() const329 bool SheetPresentationPattern::IsScrollable() const
330 {
331 auto scrollNode = GetSheetScrollNode();
332 CHECK_NULL_RETURN(scrollNode, false);
333 auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
334 CHECK_NULL_RETURN(scrollPattern, false);
335 return Positive(scrollPattern->GetScrollableDistance());
336 }
337
OnAttachToFrameNode()338 void SheetPresentationPattern::OnAttachToFrameNode()
339 {
340 auto host = GetHost();
341 CHECK_NULL_VOID(host);
342 auto pipelineContext = host->GetContext();
343 CHECK_NULL_VOID(pipelineContext);
344 scale_ = pipelineContext->GetFontScale();
345 InitFoldState();
346 pipelineContext->AddWindowSizeChangeCallback(host->GetId());
347 host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
348 host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
349 auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
350 CHECK_NULL_VOID(targetNode);
351 pipelineContext->AddOnAreaChangeNode(targetNode->GetId());
352 OnAreaChangedFunc onAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
353 const OffsetF& /* oldOrigin */, const RectF& /* rect */,
354 const OffsetF& /* origin */) {
355 auto sheetNode = sheetNodeWk.Upgrade();
356 CHECK_NULL_VOID(sheetNode);
357 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
358 CHECK_NULL_VOID(sheetPattern);
359 if (sheetPattern->GetSheetType() == SheetType::SHEET_POPUP) {
360 auto sheetWrapper = sheetNode->GetParent();
361 CHECK_NULL_VOID(sheetWrapper);
362 sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
363 }
364 };
365 auto eventHub = targetNode->GetEventHub<EventHub>();
366 CHECK_NULL_VOID(eventHub);
367 eventHub->AddInnerOnAreaChangedCallback(host->GetId(), std::move(onAreaChangedFunc));
368
369 auto gesture = host->GetOrCreateGestureEventHub();
370 CHECK_NULL_VOID(gesture);
371 auto touchTask = [](TouchEventInfo& info) {
372 info.SetStopPropagation(true);
373 TAG_LOGD(AceLogTag::ACE_SHEET, "The sheet hits the touch event.");
374 };
375 gesture->AddTouchEvent(MakeRefPtr<TouchEventImpl>(std::move(touchTask)));
376 RegisterHoverModeChangeCallback();
377 RegisterAvoidInfoChangeListener(host);
378 }
379
OnDetachFromFrameNode(FrameNode * sheetNode)380 void SheetPresentationPattern::OnDetachFromFrameNode(FrameNode* sheetNode)
381 {
382 CHECK_NULL_VOID(sheetNode);
383 auto pipeline = sheetNode->GetContext();
384 CHECK_NULL_VOID(pipeline);
385 pipeline->RemoveWindowSizeChangeCallback(sheetNode->GetId());
386 auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
387 CHECK_NULL_VOID(targetNode);
388 auto eventHub = targetNode->GetEventHub<EventHub>();
389 CHECK_NULL_VOID(eventHub);
390 eventHub->RemoveInnerOnAreaChangedCallback(sheetNode->GetId());
391 if (HasHoverModeChangedCallbackId()) {
392 pipeline->UnRegisterHalfFoldHoverChangedCallback(hoverModeChangedCallbackId_.value_or(-1));
393 }
394 UnRegisterAvoidInfoChangeListener(sheetNode);
395 }
396
RegisterHoverModeChangeCallback()397 void SheetPresentationPattern::RegisterHoverModeChangeCallback()
398 {
399 auto host = GetHost();
400 CHECK_NULL_VOID(host);
401 auto context = host->GetContext();
402 CHECK_NULL_VOID(context);
403 auto hoverModeChangeCallback = [weak = WeakClaim(this)](bool isHalfFoldHover) {
404 auto pattern = weak.Upgrade();
405 CHECK_NULL_VOID(pattern);
406 auto sheetType = pattern->GetSheetType();
407 if (sheetType != SheetType::SHEET_CENTER) {
408 return;
409 }
410 auto host = pattern->GetHost();
411 CHECK_NULL_VOID(host);
412 auto context = host->GetContext();
413 CHECK_NULL_VOID(context);
414 AnimationOption optionPosition;
415 auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(0.35f, 1.0f, 0.0f);
416 optionPosition.SetCurve(motion);
417 context->FlushUITasks();
418 context->Animate(
419 optionPosition, motion,
420 [host, context]() {
421 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
422 context->FlushUITasks();
423 },
424 [weak]() {
425 auto pattern = weak.Upgrade();
426 CHECK_NULL_VOID(pattern);
427 pattern->FireHoverModeChangeCallback();
428 });
429 };
430 auto hoverModeCallId = context->RegisterHalfFoldHoverChangedCallback(std::move(hoverModeChangeCallback));
431 UpdateHoverModeChangedCallbackId(hoverModeCallId);
432 }
433
SetSheetBorderWidth(bool isPartialUpdate)434 void SheetPresentationPattern::SetSheetBorderWidth(bool isPartialUpdate)
435 {
436 auto host = GetHost();
437 CHECK_NULL_VOID(host);
438 auto pipeline = host->GetContext();
439 CHECK_NULL_VOID(pipeline);
440 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
441 CHECK_NULL_VOID(sheetTheme);
442 auto sheetType = GetSheetType();
443 auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
444 CHECK_NULL_VOID(layoutProperty);
445 auto sheetStyle = layoutProperty->GetSheetStyleValue();
446 auto renderContext = host->GetRenderContext();
447 CHECK_NULL_VOID(renderContext);
448 renderContext->SetClipToBounds(true);
449 if (sheetStyle.borderWidth.has_value()) {
450 auto borderWidth = sheetStyle.borderWidth.value();
451 bool bottomDimenInvalid = !(sheetType == SheetType::SHEET_CENTER || sheetType == SheetType::SHEET_POPUP ||
452 sheetType == SheetType::SHEET_BOTTOM_OFFSET);
453 if (bottomDimenInvalid) {
454 borderWidth.bottomDimen = 0.0_vp;
455 }
456 layoutProperty->UpdateBorderWidth(borderWidth);
457 renderContext->UpdateBorderWidth(borderWidth);
458 } else if (renderContext->GetBorderWidth().has_value() && !isPartialUpdate) {
459 BorderWidthProperty borderWidth;
460 borderWidth.SetBorderWidth(0.0_vp);
461 layoutProperty->UpdateBorderWidth(borderWidth);
462 renderContext->UpdateBorderWidth(borderWidth);
463 }
464
465 SetSheetOuterBorderWidth(sheetTheme, sheetStyle);
466 }
467
468 // initial drag gesture event
InitPanEvent()469 void SheetPresentationPattern::InitPanEvent()
470 {
471 auto host = GetHost();
472 CHECK_NULL_VOID(host);
473 auto focusHub = host->GetFocusHub();
474 CHECK_NULL_VOID(focusHub);
475 InitOnkeyEvent(focusHub);
476 if (IsShowInSubWindowTwoInOne()) {
477 return;
478 }
479
480 auto hub = host->GetEventHub<EventHub>();
481 CHECK_NULL_VOID(hub);
482 auto gestureHub = hub->GetOrCreateGestureEventHub();
483 CHECK_NULL_VOID(gestureHub);
484 if (panEvent_) {
485 return;
486 }
487
488 auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& event) {
489 auto pattern = weak.Upgrade();
490 if (pattern) {
491 pattern->HandleDragStart();
492 }
493 };
494
495 auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
496 auto pattern = weak.Upgrade();
497 if (pattern) {
498 pattern->HandleDragUpdate(info);
499 }
500 };
501
502 auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
503 auto pattern = weak.Upgrade();
504 if (pattern) {
505 pattern->HandleDragEnd(info.GetMainVelocity());
506 }
507 };
508 auto actionCancelTask = [weak = WeakClaim(this)]() {
509 auto pattern = weak.Upgrade();
510 if (pattern) {
511 pattern->HandleDragEnd({});
512 }
513 };
514 PanDirection panDirection;
515 panDirection.type = PanDirection::VERTICAL;
516 panEvent_ = MakeRefPtr<PanEvent>(
517 std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
518 gestureHub->AddPanEvent(panEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
519 }
520
InitOnkeyEvent(const RefPtr<FocusHub> & focusHub)521 void SheetPresentationPattern::InitOnkeyEvent(const RefPtr<FocusHub>& focusHub)
522 {
523 CHECK_NULL_VOID(focusHub);
524 focusHub->SetOnFocusInternal([weak = WeakClaim(this)]() {
525 auto pattern = weak.Upgrade();
526 if (pattern) {
527 pattern->HandleFocusEvent();
528 }
529 });
530
531 focusHub->SetOnBlurInternal([weak = WeakClaim(this)]() {
532 auto pattern = weak.Upgrade();
533 if (pattern) {
534 pattern->HandleBlurEvent();
535 }
536 });
537 }
538
SetShadowStyle(bool isFocused)539 void SheetPresentationPattern::SetShadowStyle(bool isFocused)
540 {
541 auto host = GetHost();
542 CHECK_NULL_VOID(host);
543 auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
544 CHECK_NULL_VOID(layoutProperty);
545 auto sheetStyle = layoutProperty->GetSheetStyleValue();
546 if (sheetStyle.shadow.has_value()) {
547 return;
548 }
549 auto pipeline = host->GetContext();
550 CHECK_NULL_VOID(pipeline);
551 auto renderContext = host->GetRenderContext();
552 CHECK_NULL_VOID(renderContext);
553 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
554 CHECK_NULL_VOID(sheetTheme);
555 auto style = static_cast<ShadowStyle>(sheetTheme->GetSheetShadowConfig());
556 if (!isFocused) {
557 style = static_cast<ShadowStyle>(sheetTheme->GetSheetShadowConfigS());
558 }
559 auto shadow = GetShadowFromTheme(style);
560 renderContext->UpdateBackShadow(shadow);
561 }
562
HandleFocusEvent()563 void SheetPresentationPattern::HandleFocusEvent()
564 {
565 auto host = GetHost();
566 CHECK_NULL_VOID(host);
567 auto sheetId = host->GetId();
568 TAG_LOGI(AceLogTag::ACE_SHEET, "Sheet get focus, and id is : %{public}d", sheetId);
569 SheetManager::GetInstance().SetFocusSheetId(sheetId);
570 SetShadowStyle(true);
571 }
572
HandleBlurEvent()573 void SheetPresentationPattern::HandleBlurEvent()
574 {
575 TAG_LOGI(AceLogTag::ACE_SHEET, "Sheet lost focus");
576 SheetManager::GetInstance().SetFocusSheetId(std::nullopt);
577 SetShadowStyle(false);
578 }
579
HandleDragStart()580 void SheetPresentationPattern::HandleDragStart()
581 {
582 InitScrollProps();
583 SetIsDragging(true);
584 if (animation_ && isAnimationProcess_) {
585 AnimationUtils::StopAnimation(animation_);
586 isAnimationBreak_ = true;
587 }
588 currentOffset_ = 0.0f;
589 isDirectionUp_ = true;
590 GetCurrentBroadcastDetentsIndex();
591 }
592
HandleDragUpdate(const GestureEvent & info)593 void SheetPresentationPattern::HandleDragUpdate(const GestureEvent& info)
594 {
595 auto sheetType = GetSheetType();
596 if (sheetType == SheetType::SHEET_POPUP) {
597 return;
598 }
599 auto mainDelta = static_cast<float>(info.GetMainDelta());
600 auto host = GetHost();
601 CHECK_NULL_VOID(host);
602 auto tempOffset = currentOffset_;
603 auto detentSize = sheetDetentHeight_.size();
604 if (detentSize <= 0) {
605 return;
606 }
607 auto height = GetSheetHeightBeforeDragUpdate();
608 auto maxDetentSize = GetMaxSheetHeightBeforeDragUpdate();
609 if (GreatOrEqual((height - currentOffset_), maxDetentSize)) {
610 if (LessNotEqual(mainDelta, 0) && GreatNotEqual(sheetMaxHeight_, 0.0f)) {
611 auto friction = CalculateFriction((height - currentOffset_) / sheetMaxHeight_, GetRadio());
612 mainDelta = mainDelta * friction;
613 }
614 }
615 currentOffset_ = currentOffset_ + mainDelta;
616 if (NearEqual(currentOffset_, tempOffset)) {
617 return;
618 }
619 auto pageHeight = GetPageHeightWithoutOffset();
620 auto offset = pageHeight - height + currentOffset_;
621 if (LessOrEqual(offset, (pageHeight - sheetMaxHeight_))) {
622 offset = pageHeight - sheetMaxHeight_;
623 currentOffset_ = height - sheetMaxHeight_;
624 }
625 bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && currentOffset_ < 0;
626 if (isNeedChangeScrollHeight) {
627 ChangeScrollHeight(height - currentOffset_);
628 }
629 HandleFollowAccessibilityEvent(height - currentOffset_);
630 auto renderContext = host->GetRenderContext();
631 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
632 if (IsSheetBottomStyle()) {
633 OnHeightDidChange(height_ - currentOffset_ + sheetHeightUp_);
634 }
635 }
636
SendTextUpdateEvent()637 void SheetPresentationPattern::SendTextUpdateEvent()
638 {
639 auto sheetNode = GetHost();
640 CHECK_NULL_VOID(sheetNode);
641 // Use TEXT_CHANGE to send events.
642 TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet sent TEXT_CHANGE event, when follow up.");
643 sheetNode->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, "", "");
644 }
645
SendSelectedEvent()646 void SheetPresentationPattern::SendSelectedEvent()
647 {
648 auto sheetNode = GetHost();
649 CHECK_NULL_VOID(sheetNode);
650 // Use SELECTED to send events.
651 TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet sent SELECTED event, when get out of your hands.");
652 sheetNode->OnAccessibilityEvent(AccessibilityEventType::SELECTED, "", "");
653 }
654
RegisterElementInfoCallBack()655 void SheetPresentationPattern::RegisterElementInfoCallBack()
656 {
657 auto sheetNode = GetHost();
658 CHECK_NULL_VOID(sheetNode);
659 auto accessibilityProperty = sheetNode->GetAccessibilityProperty<NG::AccessibilityProperty>();
660 CHECK_NULL_VOID(accessibilityProperty);
661 auto callBack = [sheetDetents = std::to_string(static_cast<int32_t>(sheetDetents_))]
662 (Accessibility::ExtraElementInfo& extraElementInfo) {
663 extraElementInfo.SetExtraElementInfo("BindSheet", sheetDetents);
664 };
665 accessibilityProperty->SetRelatedElementInfoCallback(callBack);
666 }
667
UpdateAccessibilityDetents(float height)668 bool SheetPresentationPattern::UpdateAccessibilityDetents(float height)
669 {
670 auto sheetDetentsSize = sheetDetentHeight_.size();
671 bool invalid = sheetDetentsSize < 2 || !IsSheetBottomStyle();
672 if (invalid) {
673 return false;
674 }
675 for (uint32_t i = 0; i < sheetDetentsSize; i++) {
676 if (NearEqual(height, sheetDetentHeight_[i])) {
677 // size is 2, corresponds to high and low.
678 // size is 3, corresponds to high、medium and low.
679 // The lower of the two detents, corresponds to "LOW".
680 bool lowOfTwoDetents = sheetDetentsSize == 2 && i == 0;
681 sheetDetents_ = lowOfTwoDetents
682 ? static_cast<SheetAccessibilityDetents>(sheetDetentsSize - i)
683 : static_cast<SheetAccessibilityDetents>(sheetDetentsSize -1 - i);
684 TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet detents enum value: %{public}d", sheetDetents_);
685 RegisterElementInfoCallBack();
686 return true;
687 }
688 }
689 return false;
690 }
691
GetCurrentBroadcastDetentsIndex()692 uint32_t SheetPresentationPattern::GetCurrentBroadcastDetentsIndex()
693 {
694 bool invalid = sheetDetentHeight_.size() < 2 || !IsSheetBottomStyle();
695 if (invalid) {
696 return broadcastPreDetentsIndex_;
697 }
698 // get currrent detents index.
699 auto it = std::find(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), height_);
700 if (it != sheetDetentHeight_.end()) {
701 broadcastPreDetentsIndex_ = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), it));
702 }
703 return broadcastPreDetentsIndex_;
704 }
705
HandleFollowAccessibilityEvent(float currHeight)706 void SheetPresentationPattern::HandleFollowAccessibilityEvent(float currHeight)
707 {
708 auto sheetDetentsSize = sheetDetentHeight_.size();
709 bool invalid = sheetDetentsSize < 2 || !IsSheetBottomStyle();
710 if (invalid) {
711 return;
712 }
713 if (currHeight < sheetDetentHeight_[0] || currHeight > sheetDetentHeight_[sheetDetentsSize - 1]) {
714 return;
715 }
716 float upHeight = 0.0f;
717 float downHeight = 0.0f;
718 float finalHeight = 0.0f;
719
720 // record current position info.
721 uint32_t detentsLowerPos = 0;
722 uint32_t detentsUpperPos = 0;
723 uint32_t broadcastCurrDetentsIndex = 0;
724 ComputeDetentsPos(currHeight, upHeight, downHeight, detentsLowerPos, detentsUpperPos);
725
726 if (GreatNotEqual(std::abs(currHeight - upHeight), std::abs(currHeight - downHeight))) {
727 finalHeight = downHeight;
728 broadcastCurrDetentsIndex = detentsLowerPos;
729 } else if (LessNotEqual(std::abs(currHeight - upHeight), std::abs(currHeight - downHeight))) {
730 finalHeight = upHeight;
731 broadcastCurrDetentsIndex = detentsUpperPos;
732 }
733
734 // Broadcast once when enter other effect area.
735 if (broadcastCurrDetentsIndex != broadcastPreDetentsIndex_) {
736 UpdateAccessibilityDetents(finalHeight);
737 SendTextUpdateEvent();
738 broadcastPreDetentsIndex_ = broadcastCurrDetentsIndex;
739 }
740 }
741
HandleDragEndAccessibilityEvent()742 void SheetPresentationPattern::HandleDragEndAccessibilityEvent()
743 {
744 if (UpdateAccessibilityDetents(GetSheetHeightBeforeDragUpdate())) {
745 SendSelectedEvent();
746 }
747 }
HandleDragEnd(float dragVelocity)748 void SheetPresentationPattern::HandleDragEnd(float dragVelocity)
749 {
750 isNeedProcessHeight_ = true;
751 SetIsDragging(false);
752 auto sheetDetentsSize = sheetDetentHeight_.size();
753 if ((sheetDetentsSize == 0) || (GetSheetType() == SheetType::SHEET_POPUP) || IsShowInSubWindowTwoInOne()) {
754 return;
755 }
756 float upHeight = 0.0f;
757 float downHeight = 0.0f;
758 auto height = GetSheetHeightBeforeDragUpdate();
759 auto currentSheetHeight =
760 GreatNotEqual((height - currentOffset_), sheetMaxHeight_) ? sheetMaxHeight_ : (height - currentOffset_);
761 start_ = currentSheetHeight;
762 TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet HandleDragEnd, current height is: %{public}f", currentSheetHeight);
763
764 // record the drag position
765 uint32_t detentsLowerPos = 0;
766 uint32_t detentsUpperPos = 0;
767 ComputeDetentsPos(currentSheetHeight, upHeight, downHeight, detentsLowerPos, detentsUpperPos);
768
769 // when drag velocity is under the threshold and the sheet height is not in the middle of lower and upper bound.
770 if ((LessNotEqual(std::abs(dragVelocity), SHEET_VELOCITY_THRESHOLD)) &&
771 (!NearEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight)))) {
772 // check whether the lower or upper index is closer to the current height of the sheet page
773 if (GreatNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
774 if (NearZero(downHeight)) {
775 SheetInteractiveDismiss(BindSheetDismissReason::SLIDE_DOWN, std::abs(dragVelocity));
776 } else {
777 detentsIndex_ = detentsLowerPos;
778 ChangeSheetHeight(downHeight);
779 ChangeSheetPage(height);
780 SheetTransition(true, std::abs(dragVelocity));
781 }
782 } else if (LessNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
783 detentsIndex_ = detentsUpperPos;
784 ChangeSheetHeight(upHeight);
785 ChangeSheetPage(height);
786 SheetTransition(true, std::abs(dragVelocity));
787 }
788 } else {
789 // when drag velocity is over the threshold
790 if (GreatOrEqual(dragVelocity, 0.0f)) {
791 if (NearZero(downHeight)) {
792 SheetInteractiveDismiss(BindSheetDismissReason::SLIDE_DOWN, std::abs(dragVelocity));
793 } else {
794 detentsIndex_ = detentsLowerPos;
795 ChangeSheetHeight(downHeight);
796 ChangeSheetPage(height);
797 SheetTransition(true, std::abs(dragVelocity));
798 }
799 } else {
800 detentsIndex_ = detentsUpperPos;
801 ChangeSheetHeight(upHeight);
802 ChangeSheetPage(height);
803 SheetTransition(true, std::abs(dragVelocity));
804 }
805 }
806
807 // match the sorted detents index to the unsorted one
808 auto detentHeight = sheetDetentHeight_[detentsIndex_];
809 auto pos = std::find(unSortedSheetDentents_.begin(), unSortedSheetDentents_.end(), detentHeight);
810 if (pos != std::end(unSortedSheetDentents_)) {
811 auto idx = static_cast<uint32_t>(std::distance(unSortedSheetDentents_.begin(), pos));
812 detentsFinalIndex_ = idx;
813 }
814 }
815
ComputeDetentsPos(float currentSheetHeight,float & upHeight,float & downHeight,uint32_t & detentsLowerPos,uint32_t & detentsUpperPos)816 void SheetPresentationPattern::ComputeDetentsPos(
817 float currentSheetHeight, float& upHeight, float& downHeight, uint32_t& detentsLowerPos, uint32_t& detentsUpperPos)
818 {
819 // when drag the sheet page, find the lower and upper index range
820 auto lowerIter = std::lower_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
821 auto upperIter = std::upper_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
822 auto sheetDetentsSize = sheetDetentHeight_.size();
823 if (lowerIter == sheetDetentHeight_.end() || upperIter == sheetDetentHeight_.end()) {
824 // when drag over the highest sheet page
825 upHeight = sheetDetentHeight_[sheetDetentsSize - 1];
826 downHeight = sheetDetentHeight_[sheetDetentsSize - 1];
827 detentsLowerPos = sheetDetentsSize - 1;
828 detentsUpperPos = sheetDetentsSize - 1;
829 } else {
830 auto lowerPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), lowerIter));
831 auto upperPosition = static_cast<uint32_t>(std::distance(sheetDetentHeight_.begin(), upperIter));
832 if (lowerPosition == 0) {
833 upHeight = sheetDetentHeight_[lowerPosition];
834 downHeight = 0;
835 } else {
836 // the first largest height greater than the currentsheet height
837 upHeight = sheetDetentHeight_[upperPosition];
838
839 // the largest height lower than the currentsheet height
840 downHeight = sheetDetentHeight_[lowerPosition - 1];
841 detentsLowerPos = lowerPosition - 1;
842 detentsUpperPos = upperPosition;
843 }
844 }
845 }
846
ChangeSheetPage(float height)847 void SheetPresentationPattern::ChangeSheetPage(float height)
848 {
849 if (IsAvoidingKeyboard() && keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL) {
850 return;
851 }
852 ChangeScrollHeight(height);
853 }
854
OnCoordScrollStart()855 void SheetPresentationPattern::OnCoordScrollStart()
856 {
857 if (animation_ && isAnimationProcess_) {
858 AnimationUtils::StopAnimation(animation_);
859 isAnimationBreak_ = true;
860 }
861 currentOffset_ = 0.0f;
862 GetCurrentBroadcastDetentsIndex();
863 }
864
OnCoordScrollUpdate(float scrollOffset)865 bool SheetPresentationPattern::OnCoordScrollUpdate(float scrollOffset)
866 {
867 if (!GetShowState() || !IsScrollable()) {
868 return false;
869 }
870
871 auto sheetType = GetSheetType();
872 auto sheetDetentsSize = sheetDetentHeight_.size();
873 if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0)) {
874 return false;
875 }
876 auto height = GetSheetHeightBeforeDragUpdate();
877 if ((NearZero(currentOffset_)) && (LessNotEqual(scrollOffset, 0.0f)) &&
878 (GreatOrEqual(height, GetMaxSheetHeightBeforeDragUpdate()))) {
879 return false;
880 }
881 auto host = GetHost();
882 CHECK_NULL_RETURN(host, false);
883 currentOffset_ = currentOffset_ + scrollOffset;
884 auto pageHeight = GetPageHeightWithoutOffset();
885 auto offset = pageHeight - height + currentOffset_;
886 if (LessOrEqual(offset, pageHeight - sheetMaxHeight_)) {
887 offset = pageHeight - sheetMaxHeight_;
888 currentOffset_ = height - sheetMaxHeight_;
889 }
890 HandleFollowAccessibilityEvent(height - currentOffset_);
891 auto renderContext = host->GetRenderContext();
892 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
893 return true;
894 }
895
OnCoordScrollEnd(float dragVelocity)896 void SheetPresentationPattern::OnCoordScrollEnd(float dragVelocity)
897 {
898 HandleDragEnd(dragVelocity);
899 }
900
InitialLayoutProps()901 void SheetPresentationPattern::InitialLayoutProps()
902 {
903 CheckSheetHeightChange();
904 InitSheetDetents();
905 }
906
GetWindowButtonRect(NG::RectF & floatButtons)907 bool SheetPresentationPattern::GetWindowButtonRect(NG::RectF& floatButtons)
908 {
909 if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_EIGHTEEN)) {
910 return false;
911 }
912 auto host = GetHost();
913 CHECK_NULL_RETURN(host, false);
914 auto pipelineContext = host->GetContext();
915 CHECK_NULL_RETURN(pipelineContext, false);
916 auto avoidInfoMgr = pipelineContext->GetAvoidInfoManager();
917 CHECK_NULL_RETURN(avoidInfoMgr, false);
918 NG::RectF floatContainerModal;
919 if (avoidInfoMgr->NeedAvoidContainerModal() &&
920 avoidInfoMgr->GetContainerModalButtonsRect(floatContainerModal, floatButtons)) {
921 TAG_LOGD(AceLogTag::ACE_SHEET, "When hidden, floatButtons rect is %{public}s", floatButtons.ToString().c_str());
922 return true;
923 };
924 TAG_LOGD(AceLogTag::ACE_SHEET, "Window title builder shown");
925 return false;
926 }
927
InitialSingleGearHeight(NG::SheetStyle & sheetStyle)928 float SheetPresentationPattern::InitialSingleGearHeight(NG::SheetStyle& sheetStyle)
929 {
930 auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
931 float sheetHeight = largeHeight;
932 auto sheetNode = GetHost();
933 CHECK_NULL_RETURN(sheetNode, sheetHeight);
934 if (sheetStyle.sheetHeight.sheetMode.has_value()) {
935 auto pipelineContext = sheetNode->GetContext();
936 CHECK_NULL_RETURN(pipelineContext, sheetHeight);
937 auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
938 CHECK_NULL_RETURN(sheetTheme, sheetHeight);
939 if (sheetStyle.sheetHeight.sheetMode == SheetMode::MEDIUM) {
940 sheetHeight = pageHeight_ * sheetTheme->GetMediumPercent();
941 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
942 sheetHeight = pageHeight_ * MEDIUM_SIZE_PRE;
943 }
944 } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::LARGE) {
945 sheetHeight = sheetTheme->GetHeightApplyFullScreen() ? pageHeight_ : largeHeight;
946 sheetHeight *= sheetTheme->GetLargePercent();
947 } else if (sheetStyle.sheetHeight.sheetMode == SheetMode::AUTO) {
948 sheetHeight = GetFitContentHeight();
949 if (sheetHeight > largeHeight) {
950 sheetHeight = largeHeight;
951 }
952 HandleFitContontChange(sheetHeight);
953 }
954 } else {
955 float height = 0.0f;
956 if (sheetStyle.sheetHeight.height->Unit() == DimensionUnit::PERCENT) {
957 height = sheetStyle.sheetHeight.height->ConvertToPxWithSize(sheetMaxHeight_);
958 } else {
959 height = sheetStyle.sheetHeight.height->ConvertToPx();
960 }
961 if (GreatNotEqual(height, largeHeight)) {
962 sheetHeight = largeHeight;
963 } else if (LessNotEqual(height, 0)) {
964 sheetHeight = largeHeight;
965 } else {
966 sheetHeight = height;
967 }
968 }
969 return sheetHeight;
970 }
971
AvoidSafeArea(bool forceAvoid)972 void SheetPresentationPattern::AvoidSafeArea(bool forceAvoid)
973 {
974 auto sheetType = GetSheetType();
975 if (sheetType == SheetType::SHEET_POPUP || IsCurSheetNeedHalfFoldHover() ||
976 sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
977 return;
978 }
979 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
980 AvoidKeyboardBySheetMode(forceAvoid);
981 return;
982 }
983 auto host = GetHost();
984 CHECK_NULL_VOID(host);
985 auto pipelineContext = PipelineContext::GetCurrentContext();
986 CHECK_NULL_VOID(pipelineContext);
987 auto manager = pipelineContext->GetSafeAreaManager();
988 if (!forceAvoid && keyboardHeight_ == manager->GetKeyboardInset().Length()) {
989 return;
990 }
991 keyboardHeight_ = manager->GetKeyboardInset().Length();
992 CHECK_NULL_VOID(host->GetFocusHub());
993 auto heightUp = host->GetFocusHub()->IsCurrentFocus() ? GetSheetHeightChange() : 0.0f;
994 sheetHeightUp_ = heightUp;
995 if (isDismissProcess_) {
996 TAG_LOGD(AceLogTag::ACE_SHEET,
997 "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
998 return;
999 }
1000 TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet height increase %{public}f.", heightUp);
1001 auto offset = pageHeight_ - height_ - heightUp;
1002 auto renderContext = host->GetRenderContext();
1003 if (isScrolling_) {
1004 // if scrolling and keyboard will down, scroll needs to reset.
1005 if (NearZero(heightUp)) {
1006 ScrollTo(.0f);
1007 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1008 } else {
1009 sheetHeightUp_ = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
1010 // Otherwise, sheet is necessary to raise and trigger scroll scrolling
1011 // sheet is raised to the top first
1012 renderContext->UpdateTransformTranslate(
1013 { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
1014 // Then adjust the remaining height(heightUp = h - maxH) difference by scrolling
1015 ScrollTo(heightUp);
1016 }
1017 } else {
1018 // offset: translate endpoint, calculated from top
1019 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1020 }
1021 if (IsSheetBottomStyle()) {
1022 OnHeightDidChange(height_ + sheetHeightUp_);
1023 }
1024 }
1025
GetSheetHeightChange()1026 float SheetPresentationPattern::GetSheetHeightChange()
1027 {
1028 // TextFieldManagerNG::GetClickPosition: The upper left corner offset of the cursor position relative to rootNode
1029 // TextFieldManagerNG::GetHeight: the cursor Height + 24vp
1030 auto host = GetHost();
1031 CHECK_NULL_RETURN(host, .0f);
1032 auto pipelineContext = host->GetContext();
1033 CHECK_NULL_RETURN(pipelineContext, .0f);
1034 auto manager = pipelineContext->GetSafeAreaManager();
1035 auto keyboardInsert = manager->GetKeyboardInset();
1036 if (keyboardInsert.Length() == 0) {
1037 return 0.f;
1038 }
1039 auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipelineContext->GetTextFieldManager());
1040 // inputH : Distance from input component's Caret to bottom of screen
1041 // = caret's offset + caret's height + 24vp
1042 if (textFieldManager && !textFieldManager->GetOptionalClickPosition().has_value() &&
1043 !pipelineContext->UsingCaretAvoidMode()) {
1044 TAG_LOGD(AceLogTag::ACE_SHEET, "illegal caret position, don't calc height this time");
1045 return .0f;
1046 }
1047 float inputH = 0.f;
1048 if (pipelineContext->UsingCaretAvoidMode()) {
1049 // when user scroll after avoiding keyboard, we need to update scroll offset before avoid keyboard twice.
1050 GetCurrentScrollHeight();
1051 // when avoiding keyboard twice, recover input height before avoiding is needed.
1052 inputH = textFieldManager ? pipelineContext->GetRootHeight() -
1053 textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight() - sheetHeightUp_ -
1054 scrollHeight_ : 0.f;
1055 } else {
1056 inputH = textFieldManager ? (pipelineContext->GetRootHeight() -
1057 textFieldManager->GetFocusedNodeCaretRect().Top() - textFieldManager->GetHeight()) : 0.f;
1058 }
1059 // keyboardH : keyboard height + height of the bottom navigation bar
1060 auto keyboardH = keyboardInsert.Length() + manager->GetSystemSafeArea().bottom_.Length();
1061 // The minimum height of the input component from the bottom of the screen after popping up the soft keyboard
1062 auto inputMinH = keyboardH;
1063 // the LARGE sheet is 15vp from the status bar, and SHEET_CENTER's Node height not equal to screen height.
1064 auto largeHeight = pipelineContext->GetRootHeight() - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - sheetTopSafeArea_;
1065 // maxH : height that the sheet can reach the stage = the LARGE sheet - Current sheet height
1066 auto maxH = largeHeight - height_;
1067 if (inputH >= inputMinH) {
1068 // sheet needs not up
1069 TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet needs not up");
1070 return .0f;
1071 }
1072 // The expected height of the sheet to be lifted
1073 auto h = inputMinH - inputH;
1074 if (h <= maxH) {
1075 RecoverScrollOrResizeAvoidStatus();
1076 // sheet is lifted up with h
1077 TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is lifted up with h = %{public}f", h);
1078 return h;
1079 }
1080 // h > maxH, sheet goes up to the LARGE, then adjust the remaining height(h - maxH) difference by scrolling
1081 if (IsResizeWhenAvoidKeyboard()) {
1082 // remaing height need to update to (keyboardH - bottomDistance) when in resize mode after translate
1083 inputH = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
1084 h = inputMinH - inputH;
1085 }
1086 TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet is LARGE, and there is [%{public}f] height left to be processed.", h - maxH);
1087 isScrolling_ = true;
1088 return h - maxH;
1089 }
1090
CreatePropertyCallback()1091 void SheetPresentationPattern::CreatePropertyCallback()
1092 {
1093 if (property_) {
1094 return;
1095 }
1096 auto propertyCallback = [weak = AceType::WeakClaim(this)](float position) {
1097 auto ref = weak.Upgrade();
1098 CHECK_NULL_VOID(ref);
1099 ref->OnHeightDidChange(static_cast<int>(position));
1100 };
1101 property_ = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(0.0, std::move(propertyCallback));
1102 }
1103
ModifyFireSheetTransition(float dragVelocity)1104 void SheetPresentationPattern::ModifyFireSheetTransition(float dragVelocity)
1105 {
1106 TAG_LOGD(AceLogTag::ACE_SHEET, "ModifyFireSheetTransition function enter");
1107 auto host = GetHost();
1108 CHECK_NULL_VOID(host);
1109 auto renderContext = host->GetRenderContext();
1110 CHECK_NULL_VOID(renderContext);
1111 AnimationOption option;
1112 const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
1113 dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
1114 option.SetCurve(curve);
1115 option.SetFillMode(FillMode::FORWARDS);
1116 auto offset = UpdateSheetTransitionOffset();
1117 CreatePropertyCallback();
1118 CHECK_NULL_VOID(property_);
1119 renderContext->AttachNodeAnimatableProperty(property_);
1120 property_->SetPropertyUnit(PropertyUnit::PIXEL_POSITION);
1121
1122 auto finishCallback = [weak = AceType::WeakClaim(this)]() {
1123 auto ref = weak.Upgrade();
1124 CHECK_NULL_VOID(ref);
1125 if (!ref->GetAnimationBreak()) {
1126 ref->SetAnimationProcess(false);
1127 ref->ChangeSheetPage(ref->height_);
1128 } else {
1129 ref->isAnimationBreak_ = false;
1130 }
1131 ref->AvoidAiBar();
1132 ref->isNeedProcessHeight_ = false;
1133 ref->FireOnDetentsDidChange(ref->height_);
1134 ref->preDidHeight_ = ref->height_;
1135 ref->isSpringBack_ = false;
1136 };
1137
1138 isAnimationProcess_ = true;
1139 HandleDragEndAccessibilityEvent();
1140 property_->Set(start_);
1141 animation_ = AnimationUtils::StartAnimation(option,
1142 [weak = AceType::WeakClaim(this), renderContext, offset]() {
1143 auto ref = weak.Upgrade();
1144 CHECK_NULL_VOID(ref);
1145 if (renderContext) {
1146 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1147 ref->property_->Set(ref->height_ + ref->sheetHeightUp_);
1148 bool isNeedChangeScrollHeight =
1149 ref->scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && ref->isDirectionUp_;
1150 if (isNeedChangeScrollHeight) {
1151 ref->ChangeScrollHeight(ref->height_);
1152 }
1153 }
1154 },
1155 finishCallback);
1156 }
1157
1158 /**
1159 * @brief Get the max height before drag or nestedScroll.
1160 * the height is relative to the bottom of screen.
1161 */
GetMaxSheetHeightBeforeDragUpdate()1162 float SheetPresentationPattern::GetMaxSheetHeightBeforeDragUpdate()
1163 {
1164 if (IsCurSheetNeedHalfFoldHover() || sheetType_ == SheetType::SHEET_BOTTOM_OFFSET || IsShowInSubWindow()) {
1165 return GetPageHeightWithoutOffset() - sheetOffsetY_;
1166 }
1167 auto sheetDetentsSize = sheetDetentHeight_.size();
1168 if (sheetDetentsSize <= 0) {
1169 TAG_LOGW(AceLogTag::ACE_SHEET, "sheetDetentsSize is nonPositive");
1170 return 0.0f;
1171 }
1172 // The value can be returned in other scenarios as follows:
1173 // 1. bottom sheet tyle : maxHeight is maxDetent.
1174 // 2. center and other sheet tyle, except for popup tyle :
1175 // maxHeight is the height of the top left corner of sheet from the bottom of screen
1176 // 3. scene in setting offsetY : add offsetY to the following value
1177 return sheetDetentHeight_[sheetDetentsSize - 1];
1178 }
1179
1180 /**
1181 * @brief Get the height before drag or nestedScroll.
1182 * the height is relative to the bottom of screen.
1183 */
GetSheetHeightBeforeDragUpdate()1184 float SheetPresentationPattern::GetSheetHeightBeforeDragUpdate()
1185 {
1186 if (IsCurSheetNeedHalfFoldHover() || sheetType_ == SheetType::SHEET_BOTTOM_OFFSET || IsShowInSubWindow()) {
1187 return GetPageHeightWithoutOffset() - sheetOffsetY_;
1188 }
1189 // height_ : from the bottom of screen, after the sheet entry action has ended.
1190 // sheetHeightUp_ : increased height to avoid soft keyboard.
1191 // -bottomOffsetY_ : increased height by setting offsetY. bottomOffsetY_ is a negative number.
1192 return height_ + sheetHeightUp_;
1193 }
1194
UpdateSheetTransitionOffset()1195 float SheetPresentationPattern::UpdateSheetTransitionOffset()
1196 {
1197 // dentets greater than 1 and no rebound
1198 if (!WillSpringBack() && sheetDetentHeight_.size() > 1) {
1199 // When avoiding keyboards
1200 // don't consider the height difference introduced by avoidance after switching detents
1201 sheetHeightUp_ = 0.0f;
1202 }
1203 // apply to springBack scene
1204 // return the offset before drag
1205 auto offset = GetPageHeightWithoutOffset() - GetSheetHeightBeforeDragUpdate();
1206 return offset;
1207 }
1208
SetSheetAnimationOption(AnimationOption & option) const1209 void SheetPresentationPattern::SetSheetAnimationOption(AnimationOption& option) const
1210 {
1211 option.SetFillMode(FillMode::FORWARDS);
1212 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_EIGHTEEN)) {
1213 option.SetDuration(SHEET_ANIMATION_DURATION);
1214 }
1215 }
1216
SheetTransition(bool isTransitionIn,float dragVelocity)1217 void SheetPresentationPattern::SheetTransition(bool isTransitionIn, float dragVelocity)
1218 {
1219 bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && isDirectionUp_;
1220 if ((HasOnHeightDidChange() && IsSheetBottomStyle() && isTransitionIn && isNeedProcessHeight_)
1221 || isNeedChangeScrollHeight) {
1222 ModifyFireSheetTransition(dragVelocity);
1223 return;
1224 }
1225 auto host = GetHost();
1226 CHECK_NULL_VOID(host);
1227 AnimationOption option;
1228 const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
1229 dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
1230 option.SetCurve(curve);
1231 SetSheetAnimationOption(option);
1232 auto offset = UpdateSheetTransitionOffset();
1233 if (!isTransitionIn) {
1234 const auto& overlayManager = GetOverlayManager();
1235 CHECK_NULL_VOID(overlayManager);
1236 auto maskNode = overlayManager->GetSheetMask(host);
1237 if (maskNode) {
1238 overlayManager->PlaySheetMaskTransition(maskNode, host, false);
1239 }
1240 }
1241 option.SetOnFinishEvent([weak = AceType::WeakClaim(this), isTransitionIn]() {
1242 auto pattern = weak.Upgrade();
1243 CHECK_NULL_VOID(pattern);
1244 if (isTransitionIn) {
1245 if (!pattern->GetAnimationBreak()) {
1246 pattern->SetAnimationProcess(false);
1247 pattern->ChangeSheetPage(pattern->height_);
1248 } else {
1249 pattern->isAnimationBreak_ = false;
1250 }
1251 pattern->AvoidAiBar();
1252 pattern->FireOnDetentsDidChange(pattern->height_);
1253 pattern->isSpringBack_ = false;
1254 } else {
1255 pattern->SetAnimationProcess(false);
1256 const auto& overlayManager = pattern->GetOverlayManager();
1257 CHECK_NULL_VOID(overlayManager);
1258 auto host = pattern->GetHost();
1259 CHECK_NULL_VOID(host);
1260 overlayManager->FireAutoSave(host);
1261 pattern->OnDisappear();
1262 overlayManager->RemoveSheet(host);
1263 pattern->FireCallback("false");
1264 }
1265 });
1266 StartSheetTransitionAnimation(option, isTransitionIn, offset);
1267 }
1268
SheetInteractiveDismiss(BindSheetDismissReason dismissReason,float dragVelocity)1269 void SheetPresentationPattern::SheetInteractiveDismiss(BindSheetDismissReason dismissReason, float dragVelocity)
1270 {
1271 isDirectionUp_ = false;
1272 if (HasShouldDismiss() || HasOnWillDismiss()) {
1273 const auto& overlayManager = GetOverlayManager();
1274 CHECK_NULL_VOID(overlayManager);
1275 overlayManager->SetDismissTarget(DismissTarget(sheetKey_));
1276 auto host = GetHost();
1277 CHECK_NULL_VOID(host);
1278 SheetManager::GetInstance().SetDismissSheet(host->GetId());
1279 if (dismissReason == BindSheetDismissReason::SLIDE_DOWN) {
1280 isSpringBack_ = true;
1281 if (HasSheetSpringBack()) {
1282 CallSheetSpringBack();
1283 } else {
1284 isDismissProcess_ = false;
1285 SheetTransition(true);
1286 }
1287 }
1288 CallShouldDismiss();
1289 CallOnWillDismiss(static_cast<int32_t>(dismissReason));
1290 } else {
1291 DismissTransition(false, dragVelocity);
1292 }
1293 }
1294
DismissTransition(bool isTransitionIn,float dragVelocity)1295 void SheetPresentationPattern::DismissTransition(bool isTransitionIn, float dragVelocity)
1296 {
1297 isDismissProcess_ = true;
1298 const auto& overlayManager = GetOverlayManager();
1299 CHECK_NULL_VOID(overlayManager);
1300 overlayManager->ModalPageLostFocus(GetHost());
1301 if (!isTransitionIn) {
1302 OnWillDisappear();
1303 }
1304 auto sheetType = GetSheetType();
1305 if (sheetType == SheetType::SHEET_POPUP) {
1306 BubbleStyleSheetTransition(isTransitionIn);
1307 } else {
1308 SheetTransition(isTransitionIn, dragVelocity);
1309 }
1310 }
1311
ChangeScrollHeight(float height)1312 void SheetPresentationPattern::ChangeScrollHeight(float height)
1313 {
1314 auto host = GetHost();
1315 CHECK_NULL_VOID(host);
1316 auto geometryNode = host->GetGeometryNode();
1317 CHECK_NULL_VOID(geometryNode);
1318 auto operationNode = GetTitleBuilderNode();
1319 CHECK_NULL_VOID(operationNode);
1320 auto perationGeometryNode = operationNode->GetGeometryNode();
1321 CHECK_NULL_VOID(perationGeometryNode);
1322 auto operationHeight = perationGeometryNode->GetFrameSize().Height();
1323 auto scrollNode = GetSheetScrollNode();
1324 CHECK_NULL_VOID(scrollNode);
1325 auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
1326 CHECK_NULL_VOID(scrollProps);
1327 auto scrollHeight = height - operationHeight - resizeDecreasedHeight_;
1328 auto sheetType = GetSheetType();
1329 if (sheetType == SheetType::SHEET_POPUP || sheetType == SheetType::SHEET_CENTER ||
1330 sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
1331 auto sheetHeight = geometryNode->GetFrameSize().Height();
1332 scrollHeight = sheetHeight - operationHeight - resizeDecreasedHeight_;
1333 }
1334 scrollProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(scrollHeight)));
1335 scrollNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1336 }
1337
UpdateDragBarStatus()1338 void SheetPresentationPattern::UpdateDragBarStatus()
1339 {
1340 auto host = GetHost();
1341 CHECK_NULL_VOID(host);
1342 auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1343 CHECK_NULL_VOID(layoutProperty);
1344 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1345 auto showDragIndicator = sheetStyle.showDragBar.value_or(true);
1346
1347 auto titleColumn = DynamicCast<FrameNode>(host->GetFirstChild());
1348 CHECK_NULL_VOID(titleColumn);
1349 auto sheetDragBar = DynamicCast<FrameNode>(titleColumn->GetFirstChild());
1350 CHECK_NULL_VOID(sheetDragBar);
1351 auto dragBarLayoutProperty = sheetDragBar->GetLayoutProperty();
1352 CHECK_NULL_VOID(dragBarLayoutProperty);
1353 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1354 dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1355 sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1356 return;
1357 }
1358 if (IsSheetBottomStyle() && (sheetDetentHeight_.size() > 1)) {
1359 if (sheetStyle.isTitleBuilder.has_value()) {
1360 dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1361 } else {
1362 dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
1363 }
1364 } else {
1365 if (sheetStyle.isTitleBuilder.has_value()) {
1366 dragBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1367 } else {
1368 dragBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
1369 }
1370 }
1371 sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1372 }
1373
GetCloseIconPosX(const SizeF & sheetSize,const RefPtr<SheetTheme> & sheetTheme)1374 float SheetPresentationPattern::GetCloseIconPosX(const SizeF& sheetSize, const RefPtr<SheetTheme>& sheetTheme)
1375 {
1376 auto closeIconX = sheetSize.Width() - static_cast<float>(SHEET_CLOSE_ICON_WIDTH.ConvertToPx()) -
1377 static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1378 if (AceApplicationInfo::GetInstance().IsRightToLeft() &&
1379 AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1380 closeIconX = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
1381 }
1382 return closeIconX;
1383 }
1384
IsShowCloseIcon()1385 bool SheetPresentationPattern::IsShowCloseIcon()
1386 {
1387 auto host = GetHost();
1388 CHECK_NULL_RETURN(host, false);
1389 auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1390 CHECK_NULL_RETURN(layoutProperty, false);
1391 return layoutProperty->GetSheetStyleValue().showCloseIcon.value_or(true);
1392 }
1393
GetTitleNode()1394 RefPtr<FrameNode> SheetPresentationPattern::GetTitleNode()
1395 {
1396 auto operationNode = GetTitleBuilderNode();
1397 CHECK_NULL_RETURN(operationNode, nullptr);
1398 return DynamicCast<FrameNode>(operationNode->GetChildAtIndex(1));
1399 }
1400
UpdateTitleTextColor()1401 void SheetPresentationPattern::UpdateTitleTextColor()
1402 {
1403 auto host = GetHost();
1404 CHECK_NULL_VOID(host);
1405 auto pipeline = host->GetContext();
1406 CHECK_NULL_VOID(pipeline);
1407 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1408 CHECK_NULL_VOID(sheetTheme);
1409 auto firstChild = host->GetChildAtIndex(0);
1410 CHECK_NULL_VOID(firstChild);
1411 auto sheetTitleColumn = firstChild->GetChildAtIndex(1);
1412 CHECK_NULL_VOID(sheetTitleColumn);
1413 auto mainRow = sheetTitleColumn->GetChildAtIndex(0);
1414 CHECK_NULL_VOID(mainRow);
1415 auto mainTitleText = DynamicCast<FrameNode>(mainRow->GetChildAtIndex(0));
1416 CHECK_NULL_VOID(mainTitleText);
1417 auto mainTitleProp = mainTitleText->GetLayoutProperty<TextLayoutProperty>();
1418 CHECK_NULL_VOID(mainTitleProp);
1419 mainTitleProp->UpdateTextColor(sheetTheme->GetTitleTextFontColor());
1420
1421 auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1422 CHECK_NULL_VOID(layoutProperty);
1423 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1424 if (sheetStyle.sheetSubtitle.has_value()) {
1425 auto subRow = sheetTitleColumn->GetChildAtIndex(1);
1426 CHECK_NULL_VOID(subRow);
1427 auto subTitleText = DynamicCast<FrameNode>(subRow->GetChildAtIndex(0));
1428 CHECK_NULL_VOID(subTitleText);
1429 auto subTitleProp = subTitleText->GetLayoutProperty<TextLayoutProperty>();
1430 CHECK_NULL_VOID(subTitleProp);
1431 subTitleProp->UpdateTextColor(sheetTheme->GetSubtitleTextFontColor());
1432 }
1433 }
1434
UpdateTitlePadding()1435 void SheetPresentationPattern::UpdateTitlePadding()
1436 {
1437 auto host = GetHost();
1438 CHECK_NULL_VOID(host);
1439 auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1440 CHECK_NULL_VOID(layoutProperty);
1441 if (!layoutProperty->GetSheetStyleValue().isTitleBuilder.has_value()) {
1442 return;
1443 }
1444
1445 auto titleNode = GetTitleNode();
1446 CHECK_NULL_VOID(titleNode);
1447 auto titleLayoutProperty = DynamicCast<LinearLayoutProperty>(titleNode->GetLayoutProperty());
1448 CHECK_NULL_VOID(titleLayoutProperty);
1449 auto pipeline = host->GetContext();
1450 CHECK_NULL_VOID(pipeline);
1451 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1452 CHECK_NULL_VOID(sheetTheme);
1453 auto showCloseIcon = true;
1454 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN)) {
1455 showCloseIcon = IsShowCloseIcon();
1456 }
1457 PaddingProperty padding;
1458
1459 // The title bar area is reserved for the close button area size by default.
1460 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1461 auto sheetCloseIconTitleSpace = sheetTheme->IsOuterBorderEnable() ? 0.0_vp : SHEET_CLOSE_ICON_TITLE_SPACE_NEW;
1462 padding.end = CalcLength(showCloseIcon ? sheetCloseIconTitleSpace + SHEET_CLOSE_ICON_WIDTH : 0.0_vp);
1463 } else {
1464 padding.right = CalcLength(SHEET_CLOSE_ICON_TITLE_SPACE + SHEET_CLOSE_ICON_WIDTH);
1465 }
1466 titleLayoutProperty->UpdatePadding(padding);
1467 auto titleColumnPattern = titleNode->GetPattern<LinearLayoutPattern>();
1468 CHECK_NULL_VOID(titleColumnPattern);
1469 titleColumnPattern->CheckLocalized();
1470 titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1471 }
1472
UpdateCloseIconStatus()1473 void SheetPresentationPattern::UpdateCloseIconStatus()
1474 {
1475 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1476 TAG_LOGI(AceLogTag::ACE_SHEET, "PlatformVersion less or equal to version 10");
1477 return;
1478 }
1479 auto showCloseIcon = IsShowCloseIcon();
1480 auto sheetCloseIcon = GetSheetCloseIcon();
1481 CHECK_NULL_VOID(sheetCloseIcon);
1482 auto iconLayoutProperty = sheetCloseIcon->GetLayoutProperty();
1483 CHECK_NULL_VOID(iconLayoutProperty);
1484 iconLayoutProperty->UpdateVisibility(showCloseIcon ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
1485 sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1486 }
1487
UpdateSheetTitle()1488 void SheetPresentationPattern::UpdateSheetTitle()
1489 {
1490 auto host = GetHost();
1491 CHECK_NULL_VOID(host);
1492 auto pipeline = PipelineContext::GetCurrentContext();
1493 CHECK_NULL_VOID(pipeline);
1494 auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1495 CHECK_NULL_VOID(layoutProperty);
1496 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1497 if (sheetStyle.sheetTitle.has_value()) {
1498 auto titleId = GetTitleId();
1499 auto titleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(titleId));
1500 CHECK_NULL_VOID(titleNode);
1501 auto titleProp = titleNode->GetLayoutProperty<TextLayoutProperty>();
1502 CHECK_NULL_VOID(titleProp);
1503 titleProp->UpdateContent(sheetStyle.sheetTitle.value());
1504 if (pipeline->GetFontScale() != scale_) {
1505 titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1506 }
1507 titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1508 if (sheetStyle.sheetSubtitle.has_value()) {
1509 auto subtitleId = GetSubtitleId();
1510 auto subtitleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(subtitleId));
1511 CHECK_NULL_VOID(subtitleNode);
1512 auto subtitleProp = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
1513 CHECK_NULL_VOID(subtitleProp);
1514 subtitleProp->UpdateContent(sheetStyle.sheetSubtitle.value());
1515 subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1516 }
1517 }
1518 }
1519
UpdateFontScaleStatus()1520 void SheetPresentationPattern::UpdateFontScaleStatus()
1521 {
1522 auto host = GetHost();
1523 CHECK_NULL_VOID(host);
1524 auto pipeline = PipelineContext::GetCurrentContext();
1525 CHECK_NULL_VOID(pipeline);
1526 auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
1527 CHECK_NULL_VOID(layoutProperty);
1528 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1529 if (pipeline->GetFontScale() != scale_) {
1530 auto operationNode = GetTitleBuilderNode();
1531 CHECK_NULL_VOID(operationNode);
1532 auto titleColumnNode = DynamicCast<FrameNode>(operationNode->GetChildAtIndex(1));
1533 CHECK_NULL_VOID(titleColumnNode);
1534 auto layoutProps = operationNode->GetLayoutProperty<LinearLayoutProperty>();
1535 CHECK_NULL_VOID(layoutProps);
1536 auto titleLayoutProps = titleColumnNode->GetLayoutProperty<LinearLayoutProperty>();
1537 CHECK_NULL_VOID(titleLayoutProps);
1538 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1539 CHECK_NULL_VOID(sheetTheme);
1540 bool isSheetHasNoTitle = !sheetStyle.isTitleBuilder.has_value();
1541 bool isFontScaledInSystemTitle = sheetStyle.isTitleBuilder.has_value() && !sheetStyle.isTitleBuilder.value() &&
1542 GreatNotEqual(pipeline->GetFontScale(), sheetTheme->GetSheetNormalScale());
1543 if (isSheetHasNoTitle || isFontScaledInSystemTitle) {
1544 layoutProps->ClearUserDefinedIdealSize(false, true);
1545 titleLayoutProps->ClearUserDefinedIdealSize(false, true);
1546 } else if (sheetStyle.isTitleBuilder.has_value()) {
1547 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1548 CHECK_NULL_VOID(sheetTheme);
1549 auto operationAreaHeight = sheetTheme->GetOperationAreaHeight();
1550 layoutProps->UpdateUserDefinedIdealSize(
1551 CalcSize(std::nullopt, CalcLength(operationAreaHeight - sheetTheme->GetSheetTitleAreaMargin())));
1552 titleLayoutProps->UpdateUserDefinedIdealSize(
1553 CalcSize(std::nullopt, CalcLength(operationAreaHeight)));
1554 if (sheetStyle.sheetSubtitle.has_value()) {
1555 layoutProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
1556 CalcLength(SHEET_OPERATION_AREA_HEIGHT_DOUBLE - sheetTheme->GetSheetTitleAreaMargin())));
1557 titleLayoutProps->UpdateUserDefinedIdealSize(
1558 CalcSize(std::nullopt,
1559 CalcLength(SHEET_OPERATION_AREA_HEIGHT_DOUBLE - SHEET_DOUBLE_TITLE_BOTTON_MARGIN)));
1560 }
1561 }
1562 UpdateSheetTitle();
1563 scale_ = pipeline->GetFontScale();
1564 auto sheetWrapper = host->GetParent();
1565 CHECK_NULL_VOID(sheetWrapper);
1566 sheetWrapper->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1567 }
1568 }
1569
OnColorConfigurationUpdate()1570 void SheetPresentationPattern::OnColorConfigurationUpdate()
1571 {
1572 auto host = GetHost();
1573 CHECK_NULL_VOID(host);
1574 auto pipeline = host->GetContext();
1575 CHECK_NULL_VOID(pipeline);
1576 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1577 CHECK_NULL_VOID(sheetTheme);
1578
1579 UpdateTitleTextColor();
1580 auto sheetCloseIcon = DynamicCast<FrameNode>(host->GetChildAtIndex(2));
1581 CHECK_NULL_VOID(sheetCloseIcon);
1582 auto renderContext = sheetCloseIcon->GetRenderContext();
1583 CHECK_NULL_VOID(renderContext);
1584 renderContext->UpdateBackgroundColor(sheetTheme->GetCloseIconColor());
1585 sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1586 auto iconNode = DynamicCast<FrameNode>(sheetCloseIcon->GetChildAtIndex(0));
1587 CHECK_NULL_VOID(iconNode);
1588
1589 // when api >= 12, use symbol format image, else use image format.
1590 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
1591 SystemProperties::IsNeedSymbol()) {
1592 auto symbolLayoutProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
1593 CHECK_NULL_VOID(symbolLayoutProperty);
1594 symbolLayoutProperty->UpdateSymbolColorList({sheetTheme->GetCloseIconSymbolColor()});
1595 } else {
1596 auto imagePaintProperty = iconNode->GetPaintProperty<ImageRenderProperty>();
1597 CHECK_NULL_VOID(imagePaintProperty);
1598 imagePaintProperty->UpdateSvgFillColor(sheetTheme->GetCloseIconImageColor());
1599 }
1600 iconNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1601 }
1602
GetWrapperHeight()1603 float SheetPresentationPattern::GetWrapperHeight()
1604 {
1605 auto host = GetHost();
1606 CHECK_NULL_RETURN(host, 0.0f);
1607 auto sheetWrapper = host->GetParent();
1608 CHECK_NULL_RETURN(sheetWrapper, 0.0f);
1609 auto sheetWrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
1610 CHECK_NULL_RETURN(sheetWrapperNode, 0.0f);
1611 auto sheetWrapperGeometryNode = sheetWrapperNode->GetGeometryNode();
1612 CHECK_NULL_RETURN(sheetWrapperGeometryNode, 0.0f);
1613 return sheetWrapperGeometryNode->GetFrameSize().Height();
1614 }
1615
SheetHeightNeedChanged()1616 bool SheetPresentationPattern::SheetHeightNeedChanged()
1617 {
1618 auto host = GetHost();
1619 CHECK_NULL_RETURN(host, false);
1620 auto sheetGeometryNode = host->GetGeometryNode();
1621 CHECK_NULL_RETURN(sheetGeometryNode, false);
1622 if (!NearEqual(sheetGeometryNode->GetFrameSize().Height(), sheetHeight_) ||
1623 !NearEqual(GetWrapperHeight(), wrapperHeight_)) {
1624 return true;
1625 }
1626 return false;
1627 }
1628
UpdateMaskBackgroundColor()1629 void SheetPresentationPattern::UpdateMaskBackgroundColor()
1630 {
1631 auto host = GetHost();
1632 CHECK_NULL_VOID(host);
1633 auto pipeline = host->GetContext();
1634 CHECK_NULL_VOID(pipeline);
1635 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1636 CHECK_NULL_VOID(sheetTheme);
1637 auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1638 CHECK_NULL_VOID(layoutProperty);
1639 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1640 sheetMaskColor_ = sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor());
1641 if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1642 if (sheetStyle.maskColor.has_value()) {
1643 sheetMaskColor_ = sheetStyle.maskColor.value();
1644 } else {
1645 sheetMaskColor_ = Color::TRANSPARENT;
1646 }
1647 } else {
1648 if ((!sheetStyle.interactive.has_value() && GetSheetType() == SheetType::SHEET_POPUP) ||
1649 sheetStyle.interactive.value_or(false)) {
1650 sheetMaskColor_ = Color::TRANSPARENT;
1651 }
1652 }
1653 }
1654
UpdateMaskBackgroundColorRender()1655 void SheetPresentationPattern::UpdateMaskBackgroundColorRender()
1656 {
1657 auto host = GetHost();
1658 CHECK_NULL_VOID(host);
1659 UpdateMaskBackgroundColor();
1660 const auto& overlayManager = GetOverlayManager();
1661 CHECK_NULL_VOID(overlayManager);
1662 auto maskNode = overlayManager->GetSheetMask(host);
1663 CHECK_NULL_VOID(maskNode);
1664 auto maskRenderContext = maskNode->GetRenderContext();
1665 CHECK_NULL_VOID(maskRenderContext);
1666 maskRenderContext->UpdateBackgroundColor(sheetMaskColor_);
1667 }
1668
FireCommonCallback()1669 void SheetPresentationPattern::FireCommonCallback()
1670 {
1671 auto host = GetHost();
1672 CHECK_NULL_VOID(host);
1673 FireOnTypeDidChange();
1674 FireOnWidthDidChange(host);
1675 FireOnHeightDidChange();
1676 }
1677
CheckSheetHeightChange()1678 void SheetPresentationPattern::CheckSheetHeightChange()
1679 {
1680 auto host = GetHost();
1681 CHECK_NULL_VOID(host);
1682 auto sheetGeometryNode = host->GetGeometryNode();
1683 CHECK_NULL_VOID(sheetGeometryNode);
1684 if (isFirstInit_) {
1685 sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
1686 wrapperHeight_ = GetWrapperHeight();
1687 isFirstInit_ = false;
1688 } else {
1689 if (sheetType_ != GetSheetType()) {
1690 if (sheetType_ == SheetType::SHEET_POPUP) {
1691 MarkSheetPageNeedRender();
1692 }
1693 SetSheetBorderWidth();
1694 }
1695 if (SheetHeightNeedChanged() || (sheetType_ != GetSheetType()) || windowChanged_ || topSafeAreaChanged_) {
1696 sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
1697 wrapperHeight_ = GetWrapperHeight();
1698 const auto& overlayManager = GetOverlayManager();
1699 CHECK_NULL_VOID(overlayManager);
1700 auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
1701 CHECK_NULL_VOID(layoutProperty);
1702 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1703 overlayManager->ComputeSheetOffset(sheetStyle, host);
1704 if (sheetType_ == SheetType::SHEET_POPUP) {
1705 auto renderContext = GetRenderContext();
1706 CHECK_NULL_VOID(renderContext);
1707 renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_), 0.0f });
1708 renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
1709 FireCommonCallback();
1710 } else {
1711 overlayManager->PlaySheetTransition(host, true, false);
1712 }
1713 auto maskNode = overlayManager->GetSheetMask(host);
1714 if (maskNode) {
1715 UpdateMaskBackgroundColorRender();
1716 }
1717 windowChanged_ = false;
1718 topSafeAreaChanged_ = false;
1719 }
1720 }
1721 GetBuilderInitHeight();
1722 }
1723
IsCustomDetentsChanged(SheetStyle sheetStyle)1724 void SheetPresentationPattern::IsCustomDetentsChanged(SheetStyle sheetStyle)
1725 {
1726 unsigned int preDetentsSize = preDetents_.size();
1727 unsigned int userSetDetentsSize = sheetStyle.detents.size();
1728 // if preview detents size is not equal to the new one, set detents index to zero
1729 if (preDetentsSize != userSetDetentsSize) {
1730 detentsFinalIndex_ = 0;
1731 return;
1732 }
1733
1734 // check whether the new coming one's content is equal to the last time input
1735 unsigned int length = std::min(preDetentsSize, userSetDetentsSize);
1736 for (unsigned int index = 0; index < length; index++) {
1737 if (sheetStyle.detents[index] != preDetents_[index]) {
1738 // if detents has been changed, set detents index to zero
1739 detentsFinalIndex_ = 0;
1740 break;
1741 }
1742 }
1743 }
1744
InitSheetDetents()1745 void SheetPresentationPattern::InitSheetDetents()
1746 {
1747 // record input detents
1748 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1749 CHECK_NULL_VOID(layoutProperty);
1750 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1751 IsCustomDetentsChanged(sheetStyle);
1752 preDetents_.clear();
1753 sheetDetentHeight_.clear();
1754 unSortedSheetDentents_.clear();
1755 float height = 0.0f;
1756 auto sheetNode = GetHost();
1757 CHECK_NULL_VOID(sheetNode);
1758 auto geometryNode = sheetNode->GetGeometryNode();
1759 CHECK_NULL_VOID(geometryNode);
1760 auto pipelineContext = sheetNode->GetContext();
1761 CHECK_NULL_VOID(pipelineContext);
1762 auto sheetTheme = pipelineContext->GetTheme<SheetTheme>();
1763 CHECK_NULL_VOID(sheetTheme);
1764 auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1765 auto sheetType = GetSheetType();
1766 auto sheetFrameHeight = geometryNode->GetFrameSize().Height();
1767 auto mediumSize = sheetTheme->GetMediumPercent();
1768 float largeHeightOfTheme = sheetTheme->GetHeightApplyFullScreen() ? pageHeight_ : largeHeight;
1769 largeHeightOfTheme *= sheetTheme->GetLargePercent();
1770 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1771 mediumSize = MEDIUM_SIZE_PRE;
1772 }
1773 switch (sheetType) {
1774 case SheetType::SHEET_BOTTOMLANDSPACE:
1775 if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1776 height = sheetFrameHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1777 sheetDetentHeight_.emplace_back(height);
1778 break;
1779 }
1780 [[fallthrough]];
1781 case SheetType::SHEET_BOTTOM:
1782 [[fallthrough]];
1783 case SheetType::SHEET_BOTTOM_FREE_WINDOW:
1784 if (sheetStyle.detents.size() <= 0) {
1785 height = InitialSingleGearHeight(sheetStyle);
1786 sheetDetentHeight_.emplace_back(height);
1787 break;
1788 }
1789 InitDetents(sheetStyle, height, mediumSize, largeHeightOfTheme, largeHeight);
1790 std::sort(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), std::less<float>());
1791 sheetDetentHeight_.erase(
1792 std::unique(sheetDetentHeight_.begin(), sheetDetentHeight_.end()), sheetDetentHeight_.end());
1793 break;
1794 case SheetType::SHEET_CENTER:
1795 height = (centerHeight_ + pageHeight_) / SHEET_HALF_HEIGHT;
1796 sheetDetentHeight_.emplace_back(height);
1797 break;
1798 case SheetType::SHEET_BOTTOM_OFFSET:
1799 height = InitialSingleGearHeight(sheetStyle);
1800 sheetDetentHeight_.emplace_back(height);
1801 break;
1802 default:
1803 break;
1804 }
1805 }
1806
InitDetents(SheetStyle sheetStyle,float height,double mediumSize,float largeHeightOfTheme,double largeHeight)1807 void SheetPresentationPattern::InitDetents(
1808 SheetStyle sheetStyle, float height, double mediumSize, float largeHeightOfTheme, double largeHeight)
1809 {
1810 for (auto iter : sheetStyle.detents) {
1811 preDetents_.emplace_back(iter);
1812 if (iter.sheetMode.has_value()) {
1813 if (iter.sheetMode == SheetMode::MEDIUM) {
1814 height = pageHeight_ * mediumSize;
1815 } else if (iter.sheetMode == SheetMode::LARGE) {
1816 height = largeHeightOfTheme;
1817 } else if (iter.sheetMode == SheetMode::AUTO) {
1818 height = GetFitContentHeight();
1819 height = GreatNotEqual(height, largeHeight) ? largeHeight : height;
1820 HandleFitContontChange(height);
1821 }
1822 } else {
1823 if (iter.height->Unit() == DimensionUnit::PERCENT) {
1824 height = iter.height->ConvertToPxWithSize(sheetMaxHeight_);
1825 } else {
1826 height = iter.height->ConvertToPx();
1827 }
1828 if (GreatNotEqual(height, largeHeight)) {
1829 height = largeHeight;
1830 } else if (LessNotEqual(height, 0)) {
1831 height = largeHeight;
1832 }
1833 }
1834 sheetDetentHeight_.emplace_back(height);
1835 unSortedSheetDentents_.emplace_back(height);
1836 }
1837 }
1838
HandleFitContontChange(float height)1839 void SheetPresentationPattern::HandleFitContontChange(float height)
1840 {
1841 if ((NearEqual(height_, sheetFitContentHeight_)) && (!NearEqual(height, sheetFitContentHeight_))) {
1842 ChangeSheetHeight(height);
1843 ChangeSheetPage(height_);
1844 SheetTransition(true);
1845 }
1846 sheetFitContentHeight_ = height;
1847 }
1848
ComputeTransitionOffset(float sheetHeight)1849 float SheetPresentationPattern::ComputeTransitionOffset(float sheetHeight)
1850 {
1851 float offset = 0.0f;
1852 auto sheetType = GetSheetType();
1853 if (sheetType == SheetType::SHEET_POPUP ||
1854 sheetType == SheetType::SHEET_BOTTOM_OFFSET || IsCurSheetNeedHalfFoldHover()
1855 || IsShowInSubWindow()) {
1856 offset = GetSheetOffset();
1857 } else {
1858 offset = GetPageHeightWithoutOffset() - sheetHeight;
1859 }
1860 return offset;
1861 }
1862
GetSubWindowId()1863 int32_t SheetPresentationPattern::GetSubWindowId()
1864 {
1865 auto host = GetHost();
1866 CHECK_NULL_RETURN(host, INVALID_SUBWINDOW_ID);
1867 auto sheetWrapper = host->GetParent();
1868 CHECK_NULL_RETURN(sheetWrapper, INVALID_SUBWINDOW_ID);
1869 auto wrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper);
1870 auto sheetWrapperPattern = wrapperNode->GetPattern<SheetWrapperPattern>();
1871 CHECK_NULL_RETURN(sheetWrapperPattern, INVALID_SUBWINDOW_ID);
1872 return sheetWrapperPattern->GetSubWindowId();
1873 }
1874
ComputeSheetTypeInSubWindow()1875 SheetType SheetPresentationPattern::ComputeSheetTypeInSubWindow()
1876 {
1877 SheetType sheetType = SheetType::SHEET_CENTER;
1878 auto instanceId = SubwindowManager::GetInstance()->GetParentContainerId(GetSubWindowId());
1879 auto container = AceEngine::Get().GetContainer(instanceId);
1880 CHECK_NULL_RETURN(container, sheetType);
1881 auto mainWindowContext = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1882 CHECK_NULL_RETURN(mainWindowContext, sheetType);
1883 auto windowWidth = mainWindowContext->GetDisplayWindowRectInfo().Width();
1884 if (container->IsUIExtensionWindow()) {
1885 auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(GetSubWindowId(),
1886 SubwindowType::TYPE_SHEET);
1887 CHECK_NULL_RETURN(subwindow, sheetType);
1888 windowWidth = subwindow->GetUIExtensionHostWindowRect().Width();
1889 }
1890 if (GreatOrEqual(windowWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())
1891 && sheetKey_.hasValidTargetNode) {
1892 sheetType = SheetType::SHEET_POPUP;
1893 }
1894 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1895 CHECK_NULL_RETURN(layoutProperty, sheetType);
1896 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1897 if (sheetStyle.sheetType.has_value()) {
1898 sheetType = sheetStyle.sheetType.value();
1899 }
1900 if (sheetType == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
1901 sheetType = SheetType::SHEET_CENTER;
1902 }
1903 return sheetType;
1904 }
1905
InitSheetTransitionAction(float offset)1906 void SheetPresentationPattern::InitSheetTransitionAction(float offset)
1907 {
1908 auto sheetNode = GetHost();
1909 CHECK_NULL_VOID(sheetNode);
1910 auto context = sheetNode->GetRenderContext();
1911 CHECK_NULL_VOID(context);
1912 if (IsShowInSubWindowTwoInOne()) {
1913 context->UpdateOpacity(0.0);
1914 context->UpdateTransformTranslate({ 0.0f, SUBWINDOW_SHEET_TRANSLATION.ConvertToPx() + offset, 0.0f });
1915 } else {
1916 context->UpdateTransformTranslate({ 0.0f, pageHeight_, 0.0f });
1917 }
1918 }
1919
SheetTransitionAction(float offset,bool isStart,bool isTransitionIn)1920 void SheetPresentationPattern::SheetTransitionAction(float offset, bool isStart, bool isTransitionIn)
1921 {
1922 auto sheetNode = GetHost();
1923 CHECK_NULL_VOID(sheetNode);
1924 auto context = sheetNode->GetRenderContext();
1925 CHECK_NULL_VOID(context);
1926 if (!isTransitionIn) {
1927 // play sheet dismiss transition and move sheet down to out of screen
1928 InitSheetTransitionAction(offset);
1929 return;
1930 }
1931 // play sheet enter transition
1932 if (isStart) {
1933 // move sheet down to out of screen
1934 InitSheetTransitionAction(offset);
1935 } else {
1936 // move sheet up
1937 if (IsShowInSubWindowTwoInOne()) {
1938 context->UpdateOpacity(1.0);
1939 }
1940 context->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
1941 }
1942 }
1943
GetSheetType()1944 SheetType SheetPresentationPattern::GetSheetType()
1945 {
1946 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1947 return SHEET_BOTTOM;
1948 }
1949 SheetType sheetType = SheetType::SHEET_BOTTOM;
1950 auto pipelineContext = PipelineContext::GetCurrentContext();
1951 CHECK_NULL_RETURN(pipelineContext, sheetType);
1952 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1953 CHECK_NULL_RETURN(layoutProperty, sheetType);
1954 auto sheetStyle = layoutProperty->GetSheetStyleValue();
1955 if (sheetStyle.showInSubWindow.value_or(false)) {
1956 return ComputeSheetTypeInSubWindow();
1957 }
1958 auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
1959 TAG_LOGD(AceLogTag::ACE_SHEET, "GetSheetType displayWindowRect info is : %{public}s",
1960 windowGlobalRect.ToString().c_str());
1961 DeviceType deviceType = SystemProperties::GetDeviceType();
1962 // only bottom when width is less than 600vp
1963 if ((windowGlobalRect.Width() < SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) ||
1964 (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM)) {
1965 return sheetStyle.bottomOffset.has_value() && deviceType == DeviceType::TWO_IN_ONE ?
1966 SheetType::SHEET_BOTTOM_OFFSET : SheetType::SHEET_BOTTOM;
1967 }
1968 if (sheetThemeType_ == "auto") {
1969 GetSheetTypeWithAuto(sheetType);
1970 } else if (sheetThemeType_ == "popup") {
1971 GetSheetTypeWithPopup(sheetType);
1972 }
1973 return sheetType;
1974 }
1975
InitSheetMode()1976 void SheetPresentationPattern::InitSheetMode()
1977 {
1978 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
1979 CHECK_NULL_VOID(layoutProperty);
1980 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
1981 scrollSizeMode_ = sheetStyle.scrollSizeMode.value_or(ScrollSizeMode::FOLLOW_DETENT);
1982 keyboardAvoidMode_ = sheetStyle.sheetKeyboardAvoidMode.value_or(SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL);
1983 sheetEffectEdge_ = sheetStyle.sheetEffectEdge.value_or(SheetEffectEdge::ALL);
1984 }
1985
GetSheetTypeWithAuto(SheetType & sheetType)1986 void SheetPresentationPattern::GetSheetTypeWithAuto(SheetType& sheetType)
1987 {
1988 auto rootHeight = PipelineContext::GetCurrentRootHeight();
1989 auto rootWidth = PipelineContext::GetCurrentRootWidth();
1990 auto pipeline = PipelineContext::GetCurrentContext();
1991 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1992 CHECK_NULL_VOID(sheetTheme);
1993 #ifdef PREVIEW
1994 auto container = Container::Current();
1995 CHECK_NULL_VOID(container);
1996 if (container->IsFoldable() && container->GetCurrentFoldStatus() == FoldStatus::EXPAND) {
1997 #else
1998 // when big fold expand
1999 if (IsFoldExpand() && !sheetTheme->IsOnlyBottom()) {
2000 #endif
2001 sheetType = SheetType::SHEET_CENTER;
2002 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2003 CHECK_NULL_VOID(layoutProperty);
2004 auto sheetStyle = layoutProperty->GetSheetStyleValue();
2005 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN) &&
2006 sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_POPUP) {
2007 sheetType = SheetType::SHEET_POPUP;
2008 }
2009 } else {
2010 if (LessNotEqual(rootHeight, rootWidth)) {
2011 sheetType = SheetType::SHEET_BOTTOMLANDSPACE;
2012 } else {
2013 sheetType = SheetType::SHEET_BOTTOM;
2014 }
2015 }
2016 }
2017
2018 void SheetPresentationPattern::GetSheetTypeWithPopup(SheetType& sheetType)
2019 {
2020 auto pipelineContext = PipelineContext::GetCurrentContext();
2021 double rootWidth = 0.0;
2022 if (windowSize_.has_value()) {
2023 rootWidth = windowSize_.value().Width();
2024 } else {
2025 rootWidth = PipelineContext::GetCurrentRootWidth();
2026 }
2027 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2028 CHECK_NULL_VOID(layoutProperty);
2029 auto sheetStyle = layoutProperty->GetSheetStyleValue();
2030 #ifdef PREVIEW
2031 rootWidth = pipelineContext->GetDisplayWindowRectInfo().Width();
2032 #endif
2033 if (GreatOrEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
2034 if (sheetStyle.sheetType.has_value()) {
2035 sheetType = sheetStyle.sheetType.value();
2036 } else {
2037 sheetType = SheetType::SHEET_POPUP;
2038 }
2039 } else if (GreatOrEqual(rootWidth, SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) &&
2040 LessNotEqual(rootWidth, SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
2041 if (sheetStyle.sheetType.has_value()) {
2042 sheetType = sheetStyle.sheetType.value();
2043 } else {
2044 sheetType = SheetType::SHEET_CENTER;
2045 }
2046 } else {
2047 sheetType = SheetType::SHEET_BOTTOM_FREE_WINDOW;
2048 }
2049 if (sheetType == SheetType::SHEET_POPUP && !sheetKey_.hasValidTargetNode) {
2050 sheetType = SheetType::SHEET_CENTER;
2051 }
2052 }
2053
2054 void SheetPresentationPattern::SetUIFirstSwitch(bool isFirstTransition, bool isNone)
2055 {
2056 #ifdef ENABLE_ROSEN_BACKEND
2057 if (!isFirstTransition) {
2058 return;
2059 }
2060 auto host = GetHost();
2061 CHECK_NULL_VOID(host);
2062 auto rosenContext = DynamicCast<RosenRenderContext>(host->GetRenderContext());
2063 CHECK_NULL_VOID(rosenContext);
2064 rosenContext->SetUIFirstSwitch(
2065 isNone ? OHOS::Rosen::RSUIFirstSwitch::NONE : OHOS::Rosen::RSUIFirstSwitch::MODAL_WINDOW_CLOSE);
2066 #endif
2067 }
2068
2069 void SheetPresentationPattern::BubbleStyleSheetTransition(bool isTransitionIn)
2070 {
2071 auto host = this->GetHost();
2072 CHECK_NULL_VOID(host);
2073 if (!isTransitionIn) {
2074 const auto& overlayManager = GetOverlayManager();
2075 CHECK_NULL_VOID(overlayManager);
2076 auto maskNode = overlayManager->GetSheetMask(host);
2077 if (maskNode) {
2078 overlayManager->PlaySheetMaskTransition(maskNode, host, false);
2079 }
2080 StartOffsetExitingAnimation();
2081 StartAlphaExitingAnimation(
2082 [weakNode = AceType::WeakClaim(AceType::RawPtr(host)), weakPattern = AceType::WeakClaim(this)]() {
2083 auto node = weakNode.Upgrade();
2084 CHECK_NULL_VOID(node);
2085 auto pattern = weakPattern.Upgrade();
2086 CHECK_NULL_VOID(pattern);
2087 const auto& overlayManager = pattern->GetOverlayManager();
2088 CHECK_NULL_VOID(overlayManager);
2089 overlayManager->FireAutoSave(node);
2090 pattern->OnDisappear();
2091 overlayManager->RemoveSheet(node);;
2092 pattern->FireCallback("false");
2093 });
2094 overlayManager->CleanSheet(host, GetSheetKey());
2095 }
2096 }
2097
2098 void SheetPresentationPattern::StartOffsetEnteringAnimation()
2099 {
2100 AnimationOption optionPosition;
2101 optionPosition.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
2102 optionPosition.SetCurve(Curves::FRICTION);
2103 AnimationUtils::Animate(
2104 optionPosition,
2105 [weak = WeakClaim(this)]() {
2106 auto pattern = weak.Upgrade();
2107 CHECK_NULL_VOID(pattern);
2108 auto renderContext = pattern->GetRenderContext();
2109 CHECK_NULL_VOID(renderContext);
2110 renderContext->UpdateTransformTranslate({ 0.0f, Dimension(pattern->sheetOffsetY_), 0.0f });
2111 },
2112 nullptr);
2113 }
2114
2115 void SheetPresentationPattern::StartAlphaEnteringAnimation(std::function<void()> finish)
2116 {
2117 AnimationOption optionAlpha;
2118 optionAlpha.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
2119 optionAlpha.SetCurve(Curves::SHARP);
2120 AnimationUtils::Animate(
2121 optionAlpha,
2122 [weak = WeakClaim(this)]() {
2123 auto pattern = weak.Upgrade();
2124 CHECK_NULL_VOID(pattern);
2125 auto renderContext = pattern->GetRenderContext();
2126 CHECK_NULL_VOID(renderContext);
2127 renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
2128 },
2129 finish);
2130 }
2131
2132 void SheetPresentationPattern::StartOffsetExitingAnimation()
2133 {
2134 AnimationOption optionPosition;
2135 optionPosition.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
2136 optionPosition.SetCurve(Curves::FRICTION);
2137 AnimationUtils::Animate(
2138 optionPosition,
2139 [weak = WeakClaim(this)]() {
2140 auto pattern = weak.Upgrade();
2141 CHECK_NULL_VOID(pattern);
2142 auto renderContext = pattern->GetRenderContext();
2143 CHECK_NULL_VOID(renderContext);
2144 renderContext->UpdateTransformTranslate(
2145 { 0.0f, Dimension(pattern->sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
2146 },
2147 nullptr);
2148 }
2149
2150 void SheetPresentationPattern::StartAlphaExitingAnimation(std::function<void()> finish)
2151 {
2152 AnimationOption optionAlpha;
2153 optionAlpha.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
2154 optionAlpha.SetCurve(Curves::SHARP);
2155 AnimationUtils::Animate(
2156 optionAlpha,
2157 [weak = WeakClaim(this)]() {
2158 auto pattern = weak.Upgrade();
2159 CHECK_NULL_VOID(pattern);
2160 auto renderContext = pattern->GetRenderContext();
2161 CHECK_NULL_VOID(renderContext);
2162 renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
2163 },
2164 finish);
2165 }
2166
2167 RefPtr<RenderContext> SheetPresentationPattern::GetRenderContext()
2168 {
2169 auto frameNode = GetHost();
2170 CHECK_NULL_RETURN(frameNode, nullptr);
2171 return frameNode->GetRenderContext();
2172 }
2173
2174 bool SheetPresentationPattern::PostTask(const TaskExecutor::Task& task, const std::string& name)
2175 {
2176 auto pipeline = PipelineBase::GetCurrentContext();
2177 CHECK_NULL_RETURN(pipeline, false);
2178 auto taskExecutor = pipeline->GetTaskExecutor();
2179 CHECK_NULL_RETURN(taskExecutor, false);
2180 return taskExecutor->PostTask(task, TaskExecutor::TaskType::UI, name);
2181 }
2182
2183 void SheetPresentationPattern::ResetToInvisible()
2184 {
2185 auto renderContext = GetRenderContext();
2186 CHECK_NULL_VOID(renderContext);
2187 renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
2188 renderContext->UpdateTransformTranslate({ 0.0f, Dimension(sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
2189 }
2190
2191 bool SheetPresentationPattern::IsFoldExpand()
2192 {
2193 bool isExpand = false;
2194 auto container = Container::Current();
2195 CHECK_NULL_RETURN(container, false);
2196 auto foldStatus = container->GetCurrentFoldStatus();
2197 isExpand = foldStatus != FoldStatus::FOLDED && foldStatus != FoldStatus::UNKNOWN;
2198 if (isExpand) {
2199 TAG_LOGD(AceLogTag::ACE_SHEET, "Get Fold status IsFoldExpand is true");
2200 return true;
2201 } else {
2202 return false;
2203 }
2204 }
2205
2206 void SheetPresentationPattern::ChangeSheetHeight(float height)
2207 {
2208 if (!NearEqual(height_, height)) {
2209 isDirectionUp_ = GreatNotEqual(height, height_);
2210 height_ = height;
2211 SetCurrentHeightToOverlay(height_);
2212 }
2213 }
2214
2215 void SheetPresentationPattern::StartSheetTransitionAnimation(
2216 const AnimationOption& option, bool isTransitionIn, float offset)
2217 {
2218 auto host = GetHost();
2219 CHECK_NULL_VOID(host);
2220 auto context = host->GetRenderContext();
2221 CHECK_NULL_VOID(context);
2222 isAnimationProcess_ = true;
2223 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
2224 CHECK_NULL_VOID(sheetPattern);
2225 auto sheetParent = DynamicCast<FrameNode>(host->GetParent());
2226 CHECK_NULL_VOID(sheetParent);
2227 if (isTransitionIn) {
2228 HandleDragEndAccessibilityEvent();
2229 animation_ = AnimationUtils::StartAnimation(
2230 option,
2231 [context, offset]() {
2232 if (context) {
2233 context->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
2234 }
2235 },
2236 option.GetOnFinishEvent());
2237 } else {
2238 host->OnAccessibilityEvent(
2239 AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
2240 sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
2241 HitTestMode::HTMTRANSPARENT);
2242 animation_ = AnimationUtils::StartAnimation(
2243 option,
2244 [context, weak = WeakClaim(this), offset, isTransitionIn]() {
2245 if (context) {
2246 auto pattern = weak.Upgrade();
2247 pattern->SheetTransitionAction(offset, false, isTransitionIn);
2248 pattern->DismissSheetShadow(context);
2249 }
2250 },
2251 option.GetOnFinishEvent());
2252 const auto& overlayManager = GetOverlayManager();
2253 CHECK_NULL_VOID(overlayManager);
2254 overlayManager->CleanSheet(host, GetSheetKey());
2255 }
2256 }
2257
2258 void SheetPresentationPattern::DismissSheetShadow(const RefPtr<RenderContext>& context)
2259 {
2260 auto shadow = context->GetBackShadow();
2261 if (!shadow.has_value()) {
2262 shadow = Shadow::CreateShadow(ShadowStyle::None);
2263 }
2264 auto color = shadow->GetColor();
2265 auto newColor = color.ChangeAlpha(0);
2266 shadow->SetColor(newColor);
2267 context->UpdateBackShadow(shadow.value());
2268 }
2269
2270 void SheetPresentationPattern::ClipSheetNode()
2271 {
2272 auto host = GetHost();
2273 CHECK_NULL_VOID(host);
2274 auto geometryNode = host->GetGeometryNode();
2275 CHECK_NULL_VOID(geometryNode);
2276 auto sheetSize = geometryNode->GetFrameSize();
2277 auto pipeline = PipelineContext::GetCurrentContext();
2278 CHECK_NULL_VOID(pipeline);
2279 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
2280 CHECK_NULL_VOID(sheetTheme);
2281 auto renderContext = host->GetRenderContext();
2282 CHECK_NULL_VOID(renderContext);
2283 auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
2284 CHECK_NULL_VOID(layoutProperty);
2285 auto sheetStyle = layoutProperty->GetSheetStyleValue();
2286 ResetClipShape();
2287 auto sheetType = GetSheetType();
2288 BorderRadiusProperty borderRadius(sheetTheme->GetSheetRadius());
2289 CalculateSheetRadius(borderRadius);
2290 if (IsSheetBottom()) {
2291 // set 1px for avoiding doudble radius black lines.
2292 borderRadius.radiusBottomLeft = 1.0_px;
2293 borderRadius.radiusBottomRight = 1.0_px;
2294 }
2295 renderContext->UpdateBorderRadius(borderRadius);
2296 if (sheetTheme->IsOuterBorderEnable() && !sheetStyle.borderWidth.has_value()) {
2297 renderContext->UpdateOuterBorderRadius(borderRadius);
2298 }
2299 if (sheetType == SheetType::SHEET_POPUP && sheetPopupInfo_.showArrow) {
2300 std::string clipPath;
2301 clipPath = GetPopupStyleSheetClipPath(sheetSize, borderRadius);
2302 auto path = AceType::MakeRefPtr<Path>();
2303 path->SetValue(clipPath);
2304 path->SetBasicShapeType(BasicShapeType::PATH);
2305 renderContext->UpdateClipShape(path);
2306 }
2307 }
2308
2309 bool SheetPresentationPattern::IsWindowSizeChangedWithUndefinedReason(
2310 int32_t width, int32_t height, WindowSizeChangeReason type)
2311 {
2312 bool isWindowChanged = false;
2313 if (windowSize_.has_value()) {
2314 isWindowChanged = (type == WindowSizeChangeReason::UNDEFINED &&
2315 (windowSize_->Width() != width || windowSize_->Height() != height));
2316 }
2317 return isWindowChanged;
2318 }
2319
2320 void SheetPresentationPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
2321 {
2322 TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet WindowSizeChangeReason type is: %{public}d", type);
2323 auto sheetType = GetSheetType();
2324 if ((type == WindowSizeChangeReason::ROTATION) &&
2325 ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOMLANDSPACE) ||
2326 (sheetType == SheetType::SHEET_BOTTOM_OFFSET))) {
2327 windowRotate_ = true;
2328 SetColumnMinSize(true);
2329 // Before rotation, reset to the initial mode sheet ratio of the current vertical or horizontal screen
2330 // It's actually a state where the soft keyboard is not pulled up
2331 if (isScrolling_) {
2332 ScrollTo(.0f);
2333 }
2334 }
2335 if (IsWindowSizeChangedWithUndefinedReason(width, height, type)) {
2336 windowChanged_ = true;
2337 }
2338 windowSize_ = SizeT<int32_t>(width, height);
2339 if (type == WindowSizeChangeReason::ROTATION || type == WindowSizeChangeReason::DRAG ||
2340 type == WindowSizeChangeReason::RESIZE) {
2341 windowChanged_ = true;
2342 }
2343
2344 if (type == WindowSizeChangeReason::ROTATION && sheetType == SheetType::SHEET_CENTER) {
2345 auto recoverTask = [weak = WeakClaim(this), id = Container::CurrentId()] () {
2346 ContainerScope scope(id);
2347 auto pattern = weak.Upgrade();
2348 CHECK_NULL_VOID(pattern);
2349 pattern->RecoverHalfFoldOrAvoidStatus();
2350 };
2351 PostTask(recoverTask, "ArkUISheetHalfFoldStatusSwitch");
2352 }
2353
2354 auto host = GetHost();
2355 CHECK_NULL_VOID(host);
2356 auto pipelineContext = host->GetContext();
2357 CHECK_NULL_VOID(pipelineContext);
2358 UpdateSheetWhenSheetTypeChanged();
2359 auto windowManager = pipelineContext->GetWindowManager();
2360 if (windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
2361 host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2362 }
2363 }
2364
2365 void SheetPresentationPattern::TranslateTo(float height)
2366 {
2367 auto host = GetHost();
2368 CHECK_NULL_VOID(host);
2369 auto context = host->GetRenderContext();
2370 CHECK_NULL_VOID(context);
2371 context->UpdateTransformTranslate({ 0.0f, height, 0.0f });
2372 }
2373
2374 void SheetPresentationPattern::ScrollTo(float height)
2375 {
2376 // height = 0 or height > 0
2377 auto host = GetHost();
2378 CHECK_NULL_VOID(host);
2379 auto scroll = GetSheetScrollNode();
2380 CHECK_NULL_VOID(scroll);
2381 auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2382 CHECK_NULL_VOID(scrollPattern);
2383 auto layoutProp = scrollPattern->GetLayoutProperty<ScrollLayoutProperty>();
2384 CHECK_NULL_VOID(layoutProp);
2385 auto geometryNode = scroll->GetGeometryNode();
2386 CHECK_NULL_VOID(geometryNode);
2387 // height > 0, Scroll will reduce height, and become scrolling.
2388 isScrolling_ = height > 0;
2389 SetColumnMinSize(!isScrolling_);
2390 if (!AdditionalScrollTo(scroll, height)) {
2391 scrollHeight_ = height;
2392 float maxScrollDecreaseHeight = scrollHeight_;
2393 float maxAvoidSize = keyboardHeight_ - (sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.f);
2394 auto pipelineContext = host->GetContext();
2395 CHECK_NULL_VOID(pipelineContext);
2396 auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2397 /*
2398 * when the screen rotates from portrait to landscape, and the sheet needs to avoid caret twice,
2399 * there is a condition that, the caret position that does not exceed the height of sheet in portrait mode,
2400 * may be exceed the height of sheet in landscape mode. In that case,
2401 * the distance to avoid caret may exceed as well. To keep bindSheet display normally,
2402 * we need to obtain the minimum content height and then the avoidance is made.
2403 */
2404 if (useCaretAvoidMode && NonNegative(maxAvoidSize) && NonNegative(maxAvoidSize - sheetHeightUp_) &&
2405 maxScrollDecreaseHeight > maxAvoidSize - sheetHeightUp_) {
2406 maxScrollDecreaseHeight = maxAvoidSize - sheetHeightUp_;
2407 }
2408 layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt,
2409 CalcLength(GetScrollHeight() - maxScrollDecreaseHeight)));
2410 auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2411 scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2412 }
2413 scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2414 }
2415
2416 bool SheetPresentationPattern::AdditionalScrollTo(const RefPtr<FrameNode>& scroll, float height)
2417 {
2418 if (NonPositive(height)) {
2419 return false;
2420 }
2421 // If ScrollHeight is larger than childHeight
2422 // there will be a scene that is still larger than childHeight after reducing Scrollheight to moving sheet up
2423 // At this point, even if JumpToPosition is negative, the Scroll will still not to scroll
2424 auto buildContent = GetFirstFrameNodeOfBuilder();
2425 CHECK_NULL_RETURN(buildContent, false);
2426 auto scrollHeight = scroll->GetGeometryNode() ? scroll->GetGeometryNode()->GetFrameSize().Height() : .0f;
2427 auto host = GetHost();
2428 CHECK_NULL_RETURN(host, false);
2429 auto pipelineContext = host->GetContext();
2430 CHECK_NULL_RETURN(pipelineContext, false);
2431 auto useCaretAvoidMode = pipelineContext->UsingCaretAvoidMode();
2432 if (useCaretAvoidMode) {
2433 scrollHeight = GetScrollHeight();
2434 }
2435 auto childHeight = buildContent->GetGeometryNode() ? buildContent->GetGeometryNode()->GetFrameSize().Height() : .0f;
2436 if (scrollHeight <= childHeight) {
2437 return false;
2438 }
2439 auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
2440 CHECK_NULL_RETURN(layoutProp, false);
2441 auto geometryNode = scroll->GetGeometryNode();
2442 CHECK_NULL_RETURN(geometryNode, false);
2443 auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2444 CHECK_NULL_RETURN(scrollPattern, false);
2445 // Scroll first shrinks to the same size as childHeight, then reduces the height to allow it to scroll
2446 scrollHeight_ = scrollHeight - childHeight + height;
2447 layoutProp->UpdateUserDefinedIdealSize(
2448 CalcSize(std::nullopt, CalcLength(GetScrollHeight() - (scrollHeight - childHeight + height))));
2449 // And then scroll move the content with '-height' offset
2450 auto curScrollOffset = (useCaretAvoidMode && Positive(height)) ? scrollPattern->GetTotalOffset() : 0.f;
2451 scrollPattern->UpdateCurrentOffset(-height + curScrollOffset, SCROLL_FROM_JUMP);
2452 return true;
2453 }
2454
2455 float SheetPresentationPattern::GetFirstChildHeight() const
2456 {
2457 auto firstChildNode = GetTitleBuilderNode();
2458 CHECK_NULL_RETURN(firstChildNode, 0.0f);
2459 auto firstChildGeometryNode = firstChildNode->GetGeometryNode();
2460 CHECK_NULL_RETURN(firstChildGeometryNode, 0.0f);
2461 auto titleHeight = firstChildGeometryNode->GetFrameSize().Height();
2462 return titleHeight;
2463 }
2464
2465 void SheetPresentationPattern::SetColumnMinSize(bool reset)
2466 {
2467 auto buildContent = GetFirstFrameNodeOfBuilder();
2468 CHECK_NULL_VOID(buildContent);
2469 auto geometryNode = buildContent->GetGeometryNode();
2470 CHECK_NULL_VOID(geometryNode);
2471 auto props = buildContent->GetLayoutProperty<LayoutProperty>();
2472 CHECK_NULL_VOID(props);
2473 if (reset) {
2474 props->ResetCalcMinSize();
2475 return;
2476 }
2477 props->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(builderHeight_)));
2478 }
2479
2480 void SheetPresentationPattern::CalculateSheetRadius(BorderRadiusProperty& sheetRadius)
2481 {
2482 auto host = GetHost();
2483 CHECK_NULL_VOID(host);
2484 auto geometryNode = host->GetGeometryNode();
2485 CHECK_NULL_VOID(geometryNode);
2486 auto sheetSize = geometryNode->GetFrameSize();
2487 auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
2488 CHECK_NULL_VOID(layoutProperty);
2489 auto sheetStyle = layoutProperty->GetSheetStyleValue();
2490 if (sheetSize.IsPositive()) {
2491 CalculateAloneSheetRadius(sheetRadius.radiusTopLeft, sheetStyle.radius->radiusTopLeft);
2492 CalculateAloneSheetRadius(sheetRadius.radiusTopRight, sheetStyle.radius->radiusTopRight);
2493 CalculateAloneSheetRadius(sheetRadius.radiusBottomLeft, sheetStyle.radius->radiusBottomLeft);
2494 CalculateAloneSheetRadius(sheetRadius.radiusBottomRight, sheetStyle.radius->radiusBottomRight);
2495 }
2496 }
2497
2498 void SheetPresentationPattern::CalculateAloneSheetRadius(
2499 std::optional<Dimension>& sheetRadius, const std::optional<Dimension>& sheetStyleRadius)
2500 {
2501 auto host = GetHost();
2502 CHECK_NULL_VOID(host);
2503 auto geometryNode = host->GetGeometryNode();
2504 CHECK_NULL_VOID(geometryNode);
2505 auto sheetSize = geometryNode->GetFrameSize();
2506 float half = 0.5f;
2507 if (sheetStyleRadius.has_value() && GreatOrEqual(sheetStyleRadius->Value(), 0.0f)) {
2508 if (sheetStyleRadius->Unit() == DimensionUnit::PERCENT) {
2509 sheetRadius = Dimension(sheetStyleRadius->Value() * sheetSize.Width());
2510 } else {
2511 sheetRadius = sheetStyleRadius;
2512 }
2513 }
2514 // The maximum value of radius is half the width of the page.
2515 if (sheetSize.Width() * half < sheetRadius->ConvertToPx()) {
2516 sheetRadius = Dimension(sheetSize.Width() * half);
2517 }
2518 }
2519
2520 std::string SheetPresentationPattern::GetPopupStyleSheetClipPath(
2521 const SizeF& sheetSize, const BorderRadiusProperty& sheetRadius)
2522 {
2523 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
2524 return GetPopupStyleSheetClipPathNew(sheetSize, sheetRadius);
2525 }
2526 auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
2527 auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
2528 auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
2529 auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
2530 std::string path = MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopLeft);
2531 path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, SHEET_ARROW_HEIGHT.ConvertToPx());
2532 path +=
2533 LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
2534 path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
2535 SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P2_OFFSET_Y.ConvertToPx()); // P2
2536 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
2537 arrowOffset_.GetX() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
2538 SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P4_OFFSET_Y.ConvertToPx()); // P4
2539 path +=
2540 LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
2541 path += LineTo(sheetSize.Width() - radiusTopRight, SHEET_ARROW_HEIGHT.ConvertToPx());
2542 path += ArcTo(
2543 radiusTopRight, radiusTopRight, 0.0f, 0, sheetSize.Width(), SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopRight);
2544 path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
2545 path +=
2546 ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0, sheetSize.Width() - radiusBottomRight, sheetSize.Height());
2547 path += LineTo(radiusBottomLeft, sheetSize.Height());
2548 path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0, 0.0f, sheetSize.Height() - radiusBottomLeft);
2549 return path + "Z";
2550 }
2551
2552 std::string SheetPresentationPattern::GetCenterStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2553 {
2554 std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2555 path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2556 path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2557 path += ArcTo(
2558 sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2559 path += LineTo(sheetSize.Width(), sheetSize.Height() - sheetRadius.ConvertToPx());
2560 path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0,
2561 sheetSize.Width() - sheetRadius.ConvertToPx(), sheetSize.Height());
2562 path += LineTo(sheetRadius.ConvertToPx(), sheetSize.Height());
2563 path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, 0.0f,
2564 sheetSize.Height() - sheetRadius.ConvertToPx());
2565 return path + "Z";
2566 }
2567
2568 std::string SheetPresentationPattern::GetBottomStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
2569 {
2570 std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
2571 path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
2572 path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
2573 path += ArcTo(
2574 sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
2575 path += LineTo(sheetSize.Width(), sheetSize.Height());
2576 path += LineTo(0.0f, sheetSize.Height());
2577 return path + "Z";
2578 }
2579
2580 std::string SheetPresentationPattern::MoveTo(double x, double y)
2581 {
2582 return "M" + std::to_string(x) + " " + std::to_string(y) + " ";
2583 }
2584
2585 std::string SheetPresentationPattern::LineTo(double x, double y)
2586 {
2587 return "L" + std::to_string(x) + " " + std::to_string(y) + " ";
2588 }
2589
2590 std::string SheetPresentationPattern::ArcTo(double rx, double ry, double rotation, int32_t arc_flag, double x, double y)
2591 {
2592 int32_t sweep_flag = 1;
2593 return "A" + std::to_string(rx) + " " + std::to_string(ry) + " " + std::to_string(rotation) + " " +
2594 std::to_string(arc_flag) + " " + std::to_string(sweep_flag) + " " + std::to_string(x) + " " +
2595 std::to_string(y) + " ";
2596 }
2597
2598 float SheetPresentationPattern::GetFitContentHeight()
2599 {
2600 auto sheetNode = GetHost();
2601 CHECK_NULL_RETURN(sheetNode, 0.0f);
2602 auto titleColumn = DynamicCast<FrameNode>(sheetNode->GetFirstChild());
2603 CHECK_NULL_RETURN(titleColumn, 0.0f);
2604 auto titleGeometryNode = titleColumn->GetGeometryNode();
2605 auto builderNode = GetFirstFrameNodeOfBuilder();
2606 CHECK_NULL_RETURN(builderNode, 0.0f);
2607 auto builderGeometryNode = builderNode->GetGeometryNode();
2608 return builderGeometryNode->GetMarginFrameSize().Height() + titleGeometryNode->GetFrameSize().Height();
2609 }
2610
2611 RefPtr<OverlayManager> SheetPresentationPattern::GetOverlayManager()
2612 {
2613 const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2614 CHECK_NULL_RETURN(layoutProp, nullptr);
2615 auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2616
2617 if (layoutProp->GetSheetStyleValue(SheetStyle()).showInSubWindow.value_or(false)) {
2618 auto aceContainer = AceEngine::Get().GetContainer(GetSubWindowId());
2619 CHECK_NULL_RETURN(aceContainer, nullptr);
2620 auto context = DynamicCast<NG::PipelineContext>(aceContainer->GetPipelineContext());
2621 CHECK_NULL_RETURN(context, nullptr);
2622 auto overlayManager = context->GetOverlayManager();
2623 return overlayManager;
2624 }
2625 if (!showInPage) {
2626 return PipelineContext::GetCurrentContext()->GetOverlayManager();
2627 }
2628 auto host = GetHost();
2629 CHECK_NULL_RETURN(host, nullptr);
2630 auto sheetWrapper = host->GetParent();
2631 CHECK_NULL_RETURN(sheetWrapper, nullptr);
2632 auto node = AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2633 CHECK_NULL_RETURN(node, nullptr);
2634 RefPtr<OverlayManager> overlay;
2635 if (node->GetTag() == V2::PAGE_ETS_TAG) {
2636 auto pattern = node->GetPattern<PagePattern>();
2637 CHECK_NULL_RETURN(pattern, nullptr);
2638 overlay = pattern->GetOverlayManager();
2639 } else if (node->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
2640 auto pattern = node->GetPattern<NavDestinationPattern>();
2641 CHECK_NULL_RETURN(pattern, nullptr);
2642 overlay = pattern->GetOverlayManager();
2643 }
2644 if (!overlay) {
2645 auto overlayManager = overlayManager_.Upgrade();
2646 overlay = overlayManager;
2647 }
2648 return overlay;
2649 }
2650
2651 RefPtr<FrameNode> SheetPresentationPattern::GetFirstFrameNodeOfBuilder() const
2652 {
2653 auto scrollNode = GetSheetScrollNode();
2654 CHECK_NULL_RETURN(scrollNode, nullptr);
2655 auto buildNode = scrollNode->GetChildAtIndex(0);
2656 CHECK_NULL_RETURN(buildNode, nullptr);
2657 return AceType::DynamicCast<FrameNode>(buildNode->GetFrameChildByIndex(0, true));
2658 }
2659
2660 void SheetPresentationPattern::GetBuilderInitHeight()
2661 {
2662 auto buildContent = GetFirstFrameNodeOfBuilder();
2663 CHECK_NULL_VOID(buildContent);
2664 auto geometryNode = buildContent->GetGeometryNode();
2665 CHECK_NULL_VOID(geometryNode);
2666 builderHeight_ = geometryNode->GetFrameSize().Height();
2667 }
2668
2669 RefPtr<FrameNode> SheetPresentationPattern::GetOverlayRoot()
2670 {
2671 const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2672 CHECK_NULL_RETURN(layoutProp, nullptr);
2673 auto showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2674 if (!showInPage) {
2675 auto overlay = PipelineContext::GetCurrentContext()->GetOverlayManager();
2676 CHECK_NULL_RETURN(overlay, nullptr);
2677 return AceType::DynamicCast<FrameNode>(overlay->GetRootNode().Upgrade());
2678 }
2679 auto host = GetHost();
2680 CHECK_NULL_RETURN(host, nullptr);
2681 auto sheetWrapper = host->GetParent();
2682 CHECK_NULL_RETURN(sheetWrapper, nullptr);
2683 return AceType::DynamicCast<FrameNode>(sheetWrapper->GetParent());
2684 }
2685
2686 float SheetPresentationPattern::GetRootOffsetYToWindow()
2687 {
2688 const auto& layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2689 CHECK_NULL_RETURN(layoutProp, .0f);
2690 const auto& showInPage = layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false);
2691 CHECK_NULL_RETURN(showInPage, .0f);
2692 const auto& overlayNode = GetOverlayRoot();
2693 CHECK_NULL_RETURN(overlayNode, .0f);
2694 auto parertOffset = overlayNode->GetOffsetRelativeToWindow();
2695 TAG_LOGD(AceLogTag::ACE_OVERLAY, "PageLevel Node's offset to window: %{public}s", parertOffset.ToString().c_str());
2696 return parertOffset.GetY();
2697 }
2698
2699 void SheetPresentationPattern::DumpAdvanceInfo()
2700 {
2701 DumpLog::GetInstance().AddDesc("------------------------------------------");
2702 DumpLog::GetInstance().AddDesc(
2703 "TargetId: " + std::to_string(static_cast<int32_t>(targetId_)) + " , TargetTag : " + targetTag_);
2704 DumpLog::GetInstance().AddDesc("------------ SheetPage Pattern : ");
2705 DumpLog::GetInstance().AddDesc(
2706 std::string("SheetType: ").append(std::to_string(static_cast<int32_t>(GetSheetType()))));
2707 DumpLog::GetInstance().AddDesc(std::string("SheetPage Node Height: ").append(std::to_string(centerHeight_)));
2708 DumpLog::GetInstance().AddDesc(
2709 std::string("Sheet Height [start from the bottom, KeyboardHeight = 0]: ").append(std::to_string(height_)));
2710 DumpLog::GetInstance().AddDesc(
2711 std::string("SheetMaxHeight [start from the bottom, pageHeight - sheetTopSafeArea]: ")
2712 .append(std::to_string(sheetMaxHeight_)));
2713 DumpLog::GetInstance().AddDesc(std::string("Page Height: ").append(std::to_string(pageHeight_)));
2714 DumpLog::GetInstance().AddDesc(
2715 std::string("StatusBar Height [current sheetType needed]: ").append(std::to_string(sheetTopSafeArea_)));
2716 DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetX: ").append(std::to_string(sheetOffsetX_)));
2717 DumpLog::GetInstance().AddDesc(std::string("PopupSheet OffsetY: ").append(std::to_string(sheetOffsetY_)));
2718 DumpLog::GetInstance().AddDesc(std::string("SheetMaxWidth: ").append(std::to_string(sheetMaxWidth_)));
2719 DumpLog::GetInstance().AddDesc(std::string("FitContent Height: ").append(std::to_string(sheetFitContentHeight_)));
2720 DumpLog::GetInstance().AddDesc("SheetThemeType: " + sheetThemeType_);
2721 DumpLog::GetInstance().AddDesc(std::string("currentOffset: ").append(std::to_string(currentOffset_)));
2722 DumpLog::GetInstance().AddDesc("------------");
2723 DumpLog::GetInstance().AddDesc(
2724 std::string("Height ScrollTo [KeyboardHeight > 0, and is scrolling]: ").append(std::to_string(-scrollHeight_)));
2725 DumpLog::GetInstance().AddDesc(std::string("KeyboardHeight: ").append(std::to_string(keyboardHeight_)));
2726 DumpLog::GetInstance().AddDesc(std::string("is scrolling: ").append(isScrolling_ ? "true" : "false"));
2727 DumpLog::GetInstance().AddDesc(std::string("SheetHeightUp[sheet offset to move up when avoiding keyboard]: ")
2728 .append(std::to_string(sheetHeightUp_)));
2729 DumpLog::GetInstance().AddDesc("------------");
2730 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2731 CHECK_NULL_VOID(layoutProperty);
2732 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2733 DumpLog::GetInstance().AddDesc(
2734 std::string("height: ").append(sheetStyle.sheetHeight.height.has_value() ?
2735 sheetStyle.sheetHeight.height->ToString() : "None"));
2736 DumpLog::GetInstance().AddDesc(
2737 ("sheetMode: ") + (sheetStyle.sheetHeight.sheetMode.has_value()
2738 ? std::to_string(static_cast<int32_t>(sheetStyle.sheetHeight.sheetMode.value()))
2739 : "None"));
2740 DumpLog::GetInstance().AddDesc(std::string("detents' Size: ").append(std::to_string(sheetStyle.detents.size())));
2741 DumpLog::GetInstance().AddDesc(std::string("IsShouldDismiss: ").append(shouldDismiss_ ? "true" : "false"));
2742 }
2743
2744 void SheetPresentationPattern::FireOnHeightDidChange()
2745 {
2746 auto height = 0.0f;
2747 if (!IsSheetBottomStyle()) {
2748 height = centerHeight_;
2749 } else {
2750 height = height_;
2751 }
2752 if (NearEqual(preDidHeight_, height)) {
2753 return;
2754 }
2755 OnHeightDidChange(height);
2756 preDidHeight_ = height;
2757 }
2758
2759 void SheetPresentationPattern::FireOnDetentsDidChange(float height)
2760 {
2761 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2762 CHECK_NULL_VOID(layoutProperty);
2763 auto sheetStyle = layoutProperty->GetSheetStyleValue();
2764 if (!IsSheetBottomStyle() || NearEqual(preDetentsHeight_, height) ||
2765 LessOrEqual(sheetStyle.detents.size(), 0)) {
2766 return;
2767 }
2768 OnDetentsDidChange(height);
2769 preDetentsHeight_ = height;
2770 }
2771
2772 void SheetPresentationPattern::FireOnWidthDidChange(RefPtr<FrameNode> sheetNode)
2773 {
2774 auto sheetGeo = sheetNode->GetGeometryNode();
2775 CHECK_NULL_VOID(sheetGeo);
2776 auto width = sheetGeo->GetFrameSize().Width();
2777 if (NearEqual(preWidth_, width)) {
2778 return;
2779 }
2780 onWidthDidChange(width);
2781 preWidth_ = width;
2782 }
2783
2784 void SheetPresentationPattern::FireOnTypeDidChange()
2785 {
2786 auto sheetType = sheetType_;
2787 if (IsSheetBottomStyle() || sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
2788 sheetType = SheetType::SHEET_BOTTOM;
2789 }
2790 if (preType_ == sheetType) {
2791 return;
2792 }
2793 onTypeDidChange(sheetType);
2794 preType_ = sheetType;
2795 }
2796
2797 bool SheetPresentationPattern::IsScrollOutOfBoundary()
2798 {
2799 auto scrollNode = GetSheetScrollNode();
2800 CHECK_NULL_RETURN(scrollNode, false);
2801 auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
2802 CHECK_NULL_RETURN(scrollPattern, false);
2803 return scrollPattern->OutBoundaryCallback();
2804 }
2805
2806 void SheetPresentationPattern::OnScrollStartRecursive(
2807 WeakPtr<NestableScrollContainer> child, float position, float velocity)
2808 {
2809 InitScrollProps();
2810 if (animation_ && isAnimationProcess_) {
2811 AnimationUtils::StopAnimation(animation_);
2812 isAnimationBreak_ = true;
2813 }
2814 currentOffset_ = 0.0f;
2815 isSheetNeedScroll_ = false;
2816 isDirectionUp_ = true;
2817 GetCurrentBroadcastDetentsIndex();
2818 }
2819
2820 ScrollResult SheetPresentationPattern::HandleScroll(float scrollOffset, int32_t source, NestedState state,
2821 float velocity)
2822 {
2823 if (state == NestedState::CHILD_CHECK_OVER_SCROLL) {
2824 return {scrollOffset, true};
2825 }
2826 ScrollResult result = {0, true};
2827 if (GreatOrEqual(currentOffset_, 0.0) && (source == SCROLL_FROM_UPDATE) && !isSheetNeedScroll_) {
2828 isSheetNeedScroll_ = true;
2829 }
2830 if (!isSheetNeedScroll_ || IsScrollOutOfBoundary()) {
2831 return {scrollOffset, true};
2832 }
2833 ScrollState scrollState = source == SCROLL_FROM_ANIMATION ? ScrollState::FLING : ScrollState::SCROLL;
2834 if (state == NestedState::CHILD_SCROLL) {
2835 if (scrollState == ScrollState::SCROLL) {
2836 return HandleScrollWithSheet(scrollOffset);
2837 }
2838 if (isSheetPosChanged_) {
2839 HandleDragEnd(scrollOffset > 0 ? SHEET_VELOCITY_THRESHOLD : -SHEET_VELOCITY_THRESHOLD);
2840 isSheetPosChanged_ = false;
2841 }
2842 } else if (state == NestedState::CHILD_OVER_SCROLL) {
2843 isSheetNeedScroll_ = false;
2844 return {scrollOffset, true};
2845 }
2846 return result;
2847 }
2848
2849 ScrollResult SheetPresentationPattern::HandleScrollWithSheet(float scrollOffset)
2850 {
2851 ScrollResult result = {0, true};
2852 auto sheetType = GetSheetType();
2853 auto sheetDetentsSize = sheetDetentHeight_.size();
2854 if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0) || IsShowInSubWindowTwoInOne()) {
2855 isSheetNeedScroll_ = false;
2856 return {scrollOffset, true};
2857 }
2858
2859 auto currentHeightPos = GetSheetHeightBeforeDragUpdate();
2860 bool isDraggingUp = LessNotEqual(scrollOffset, 0.0f);
2861 bool isReachMaxSheetHeight = GreatOrEqual(currentHeightPos, GetMaxSheetHeightBeforeDragUpdate());
2862
2863 // When dragging up the sheet, and sheet height is larger than sheet content height,
2864 // the sheet height should be updated.
2865 // When dragging up the sheet, and sheet height is less than or equal to sheet content height,
2866 // the sheet content should scrolling.
2867 if ((NearZero(currentOffset_)) && isDraggingUp && isReachMaxSheetHeight) {
2868 isSheetNeedScroll_ = false;
2869 return {scrollOffset, true};
2870 }
2871
2872 // When dragging up the sheet, and sheet height is larger than max height,
2873 // should set the coefficient of friction.
2874 bool isExceedMaxSheetHeight =
2875 GreatNotEqual((currentHeightPos - currentOffset_), GetMaxSheetHeightBeforeDragUpdate());
2876 bool isNeedCalculateFriction = isExceedMaxSheetHeight && isDraggingUp;
2877 if (isNeedCalculateFriction && GreatNotEqual(sheetMaxHeight_, 0.0f)) {
2878 auto friction = CalculateFriction((currentHeightPos - currentOffset_) / sheetMaxHeight_, GetRadio());
2879 scrollOffset = scrollOffset * friction;
2880 }
2881
2882 auto host = GetHost();
2883 CHECK_NULL_RETURN(host, result);
2884 currentOffset_ = currentOffset_ + scrollOffset;
2885 auto pageHeight = GetPageHeightWithoutOffset();
2886 auto sheetOffsetInPage = pageHeight - currentHeightPos + currentOffset_;
2887 if (LessOrEqual(sheetOffsetInPage, pageHeight - sheetMaxHeight_)) {
2888 sheetOffsetInPage = pageHeight - sheetMaxHeight_;
2889 currentOffset_ = currentHeightPos - sheetMaxHeight_;
2890 }
2891 bool isNeedChangeScrollHeight = scrollSizeMode_ == ScrollSizeMode::CONTINUOUS && isDraggingUp;
2892 if (isNeedChangeScrollHeight) {
2893 ChangeScrollHeight(currentHeightPos - currentOffset_);
2894 }
2895 HandleFollowAccessibilityEvent(currentHeightPos - currentOffset_);
2896 auto renderContext = host->GetRenderContext();
2897 renderContext->UpdateTransformTranslate({ 0.0f, sheetOffsetInPage, 0.0f });
2898 isSheetPosChanged_ = NearZero(scrollOffset) ? false : true;
2899 if (IsSheetBottomStyle()) {
2900 OnHeightDidChange(height_ - currentOffset_ + sheetHeightUp_);
2901 }
2902 isSheetPosChanged_ = true;
2903 return result;
2904 }
2905
2906 void SheetPresentationPattern::OnScrollEndRecursive(const std::optional<float>& velocity)
2907 {
2908 if (isSheetPosChanged_) {
2909 HandleDragEnd(velocity.value_or(0.f));
2910 isSheetPosChanged_ = false;
2911 }
2912 }
2913
2914 bool SheetPresentationPattern::HandleScrollVelocity(float velocity, const RefPtr<NestableScrollContainer>& child)
2915 {
2916 if (isSheetPosChanged_) {
2917 HandleDragEnd(velocity);
2918 isSheetPosChanged_ = false;
2919 }
2920 // Use child edge effect
2921 if (!isSheetNeedScroll_) {
2922 return false;
2923 }
2924 return true;
2925 }
2926
2927 bool SheetPresentationPattern::IsTypeNeedAvoidAiBar()
2928 {
2929 auto overlay = GetOverlayManager();
2930 auto layoutProp = GetLayoutProperty<SheetPresentationProperty>();
2931 if (overlay && overlay->IsRootExpansive() &&
2932 layoutProp->GetSheetStyleValue(SheetStyle()).showInPage.value_or(false)) {
2933 return false;
2934 }
2935 return sheetType_ == SheetType::SHEET_BOTTOM || sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE ||
2936 sheetType_ == SheetType::SHEET_BOTTOM_OFFSET;
2937 }
2938
2939 void SheetPresentationPattern::IsNeedPlayTransition(const SheetStyle& inputStyle)
2940 {
2941 isPlayTransition_ = false;
2942 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2943 CHECK_NULL_VOID(layoutProperty);
2944 auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2945 if (preStyle.sheetHeight.height != inputStyle.sheetHeight.height) {
2946 isPlayTransition_ = true;
2947 return;
2948 }
2949 if (preStyle.detents != inputStyle.detents) {
2950 isPlayTransition_ = true;
2951 return;
2952 }
2953 if (preStyle.sheetHeight.sheetMode != inputStyle.sheetHeight.sheetMode) {
2954 isPlayTransition_ = true;
2955 return;
2956 }
2957 isPlayTransition_ = UpdateIndexByDetentSelection(inputStyle, false) || isPlayTransition_;
2958 }
2959
2960 bool SheetPresentationPattern::UpdateIndexByDetentSelection(const SheetStyle& inputStyle, bool isFirstTransition)
2961 {
2962 if (!inputStyle.detentSelection.has_value() || inputStyle.detents.size() == 0) {
2963 // when input detentSelection or detent selection is invalid
2964 return false;
2965 }
2966 auto selection = inputStyle.detentSelection.value();
2967 if ((selection.sheetMode.has_value() && selection.sheetMode.value() == NG::SheetMode::AUTO) ||
2968 (selection.height.has_value() && selection.height.value().IsNegative())) {
2969 return false;
2970 }
2971 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
2972 CHECK_NULL_RETURN(layoutProperty, false);
2973 auto preStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
2974 if (!isFirstTransition && preStyle.detentSelection == inputStyle.detentSelection) {
2975 // only when sheet is first pulled up or pre-detents equal to current detents, otherwise false
2976 return false;
2977 }
2978 for (uint32_t index = 0; index < inputStyle.detents.size(); index++) {
2979 if (inputStyle.detents[index] == inputStyle.detentSelection.value()) {
2980 detentsFinalIndex_ = index;
2981 TAG_LOGI(AceLogTag::ACE_SHEET, "find detent selection is %u", index);
2982 return true;
2983 }
2984 }
2985 return false;
2986 }
2987
2988 void SheetPresentationPattern::OverlayDismissSheet()
2989 {
2990 auto overlayManager = GetOverlayManager();
2991 CHECK_NULL_VOID(overlayManager);
2992 overlayManager->DismissSheet();
2993 }
2994
2995 void SheetPresentationPattern::OverlaySheetSpringBack()
2996 {
2997 auto overlayManager = GetOverlayManager();
2998 CHECK_NULL_VOID(overlayManager);
2999 overlayManager->SheetSpringBack();
3000 }
3001
3002 PipelineContext* SheetPresentationPattern::GetSheetMainPipeline() const
3003 {
3004 auto host = GetHost();
3005 CHECK_NULL_RETURN(host, nullptr);
3006 auto pipelineContext = host->GetContext();
3007 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3008 CHECK_NULL_RETURN(layoutProperty, nullptr);
3009 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3010
3011 if (sheetStyle.instanceId.has_value()) {
3012 // need to get mainWindow's pipeline, and get mainWindow's cutoutSafeArea
3013 auto container = Container::GetContainer(sheetStyle.instanceId.value());
3014 CHECK_NULL_RETURN(container, nullptr);
3015 auto parentId = container->GetParentId();
3016 TAG_LOGI(AceLogTag::ACE_SHEET, "mainWindow id : %{public}d", parentId);
3017 auto parentContainer = Container::GetContainer(parentId);
3018 CHECK_NULL_RETURN(parentContainer, nullptr);
3019 auto parentPipelineBase = parentContainer->GetPipelineContext();
3020 CHECK_NULL_RETURN(parentPipelineBase, nullptr);
3021 auto parentPipelineContext = AceType::DynamicCast<PipelineContext>(parentPipelineBase);
3022 pipelineContext = RawPtr(parentPipelineContext);
3023 }
3024 return pipelineContext;
3025 }
3026
3027 float SheetPresentationPattern::GetBottomSafeArea()
3028 {
3029 auto pipelineContext = GetSheetMainPipeline();
3030 CHECK_NULL_RETURN(pipelineContext, .0f);
3031 auto safeAreaInsets = pipelineContext->GetSafeAreaWithoutProcess();
3032 auto manager = pipelineContext->GetSafeAreaManager();
3033 CHECK_NULL_RETURN(manager, .0f);
3034 auto cutoutSafeArea = manager->GetCutoutSafeAreaWithoutProcess();
3035 if (cutoutSafeArea.top_.IsValid()) {
3036 auto topAreaInWindow = GetTopAreaInWindow();
3037 TAG_LOGD(AceLogTag::ACE_SHEET, "rosen window sheetTopSafeArea of sheet is : %{public}f", topAreaInWindow);
3038 return topAreaInWindow;
3039 } else {
3040 return safeAreaInsets.top_.Length();
3041 }
3042 }
3043
3044 // Height of status bar
3045 float SheetPresentationPattern::GetTopAreaInWindow() const
3046 {
3047 auto host = GetHost();
3048 CHECK_NULL_RETURN(host, 0.0f);
3049 auto pipelineContext = host->GetContext();
3050 CHECK_NULL_RETURN(pipelineContext, 0.0f);
3051 auto window = pipelineContext->GetWindow();
3052 CHECK_NULL_RETURN(window, 0.0f);
3053 return window->GetStatusBarHeight();
3054 }
3055
3056 void SheetPresentationPattern::MarkSheetPageNeedRender()
3057 {
3058 auto parentHost = GetHost()->GetParent();
3059 CHECK_NULL_VOID(parentHost);
3060 auto frameNode = AceType::DynamicCast<FrameNode>(parentHost);
3061 CHECK_NULL_VOID(frameNode);
3062 frameNode->MarkNeedRenderOnly();
3063 }
3064
3065 void SheetPresentationPattern::SetSheetOuterBorderWidth(
3066 const RefPtr<SheetTheme>& sheetTheme, const NG::SheetStyle& sheetStyle)
3067 {
3068 auto host = GetHost();
3069 CHECK_NULL_VOID(host);
3070 auto renderContext = host->GetRenderContext();
3071 CHECK_NULL_VOID(renderContext);
3072 auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
3073 CHECK_NULL_VOID(layoutProperty);
3074 auto sheetType = GetSheetType();
3075 if (sheetTheme->IsOuterBorderEnable() && !sheetStyle.borderWidth.has_value()) {
3076 BorderWidthProperty borderWidth;
3077 BorderWidthProperty outBorderWidth;
3078 BorderColorProperty borderColor;
3079 BorderColorProperty outBorderColor;
3080 borderWidth.SetBorderWidth(0.0_vp);
3081 outBorderWidth.SetBorderWidth(0.0_vp);
3082 if (sheetType != SheetType::SHEET_POPUP) {
3083 borderColor.SetColor(sheetTheme->GetSheetInnerBorderColor());
3084 outBorderColor.SetColor(sheetTheme->GetSheetOuterBorderColor());
3085 renderContext->UpdateOuterBorderColor(outBorderColor);
3086 renderContext->UpdateBorderColor(borderColor);
3087 if (sheetType == SheetType::SHEET_CENTER || sheetType == SheetType::SHEET_BOTTOM_OFFSET) {
3088 borderWidth.SetBorderWidth(sheetTheme->GetSheetInnerBorderWidth());
3089 outBorderWidth.SetBorderWidth(sheetTheme->GetSheetOuterBorderWidth());
3090 } else {
3091 borderWidth.leftDimen = sheetTheme->GetSheetInnerBorderWidth();
3092 borderWidth.topDimen = sheetTheme->GetSheetInnerBorderWidth();
3093 borderWidth.rightDimen = sheetTheme->GetSheetInnerBorderWidth();
3094 outBorderWidth.leftDimen = sheetTheme->GetSheetOuterBorderWidth();
3095 outBorderWidth.topDimen = sheetTheme->GetSheetOuterBorderWidth();
3096 outBorderWidth.rightDimen = sheetTheme->GetSheetOuterBorderWidth();
3097 }
3098 }
3099 layoutProperty->UpdateBorderWidth(borderWidth);
3100 renderContext->UpdateBorderWidth(borderWidth);
3101 layoutProperty->UpdateOuterBorderWidth(outBorderWidth);
3102 renderContext->UpdateOuterBorderWidth(outBorderWidth);
3103 }
3104 }
3105
3106 void SheetPresentationPattern::DumpAdvanceInfo(std::unique_ptr<JsonValue>& json)
3107 {
3108 json->Put("TargetId", static_cast<int32_t>(targetId_));
3109 json->Put("TargetTag", targetTag_.c_str());
3110 std::unique_ptr<JsonValue> children = JsonUtil::Create(true);
3111 children->Put("SheetType", static_cast<int32_t>(GetSheetType()));
3112 children->Put("SheetPage Node Height", centerHeight_);
3113 children->Put("Sheet Height [start from the bottom, KeyboardHeight = 0]", height_);
3114 children->Put("SheetMaxHeight [start from the bottom, pageHeight - sheetTopSafeArea]", sheetMaxHeight_);
3115 children->Put("Page Height", pageHeight_);
3116 children->Put("StatusBar Height [current sheetType needed]", sheetTopSafeArea_);
3117 children->Put("PopupSheet OffsetX", sheetOffsetX_);
3118 children->Put("PopupSheet OffsetX", sheetOffsetY_);
3119 children->Put("SheetMaxWidth", sheetMaxWidth_);
3120 children->Put("FitContent Height", sheetFitContentHeight_);
3121 children->Put("SheetThemeType", sheetThemeType_.c_str());
3122 children->Put("currentOffset", currentOffset_);
3123 json->Put("SheetPage Pattern", children);
3124
3125 json->Put("Height ScrollTo [KeyboardHeight > 0, and is scrolling]", -scrollHeight_);
3126 json->Put("KeyboardHeight", static_cast<int32_t>(keyboardHeight_));
3127 json->Put("is scrolling", isScrolling_);
3128 json->Put("SheetHeightUp[sheet offset to move up when avoiding keyboard]", sheetHeightUp_);
3129
3130 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3131 CHECK_NULL_VOID(layoutProperty);
3132 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3133 json->Put("height", sheetStyle.sheetHeight.height.has_value() ?
3134 sheetStyle.sheetHeight.height->ToString().c_str() : "None");
3135 json->Put("sheetMode", sheetStyle.sheetHeight.sheetMode.has_value()
3136 ? std::to_string(static_cast<int32_t>(sheetStyle.sheetHeight.sheetMode.value())).c_str()
3137 : "None");
3138 json->Put("detents Size", static_cast<int32_t>(sheetStyle.detents.size()));
3139 json->Put("IsShouldDismiss", shouldDismiss_ ? "true" : "false");
3140 }
3141
3142 void SheetPresentationPattern::AvoidKeyboardBySheetMode(bool forceAvoid)
3143 {
3144 auto host = GetHost();
3145 CHECK_NULL_VOID(host);
3146 bool isCurrentFocus = host->GetFocusHub()->IsCurrentFocus();
3147 if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::NONE || !isCurrentFocus) {
3148 TAG_LOGD(AceLogTag::ACE_SHEET,
3149 "Sheet will not avoid keyboard.keyboardAvoidMode:%{public}d, isCurrentFocus:%{public}d.",
3150 keyboardAvoidMode_, isCurrentFocus);
3151 return;
3152 }
3153 auto pipelineContext = host->GetContext();
3154 CHECK_NULL_VOID(pipelineContext);
3155 auto manager = pipelineContext->GetSafeAreaManager();
3156 if (keyboardHeight_ == manager->GetKeyboardInset().Length() && !forceAvoid) {
3157 return;
3158 }
3159 keyboardHeight_ = manager->GetKeyboardInset().Length();
3160
3161 if (isDismissProcess_) {
3162 TAG_LOGD(AceLogTag::ACE_SHEET,
3163 "The sheet will disappear, so there's no need to handle canceling keyboard avoidance here.");
3164 return;
3165 }
3166
3167 // 1.handle non upward logic: avoidKeyboardMode::RESIZE_ONLY
3168 if (AvoidKeyboardBeforeTranslate()) {
3169 return;
3170 }
3171
3172 // 2.handle upward logic
3173 CHECK_NULL_VOID(host->GetFocusHub());
3174 // When bindSheet lift height exceed the max height, hightUp = the remaining height that needs to scroll,
3175 // otherwise, hightUp = the height to be lifted up
3176 auto heightUp = isCurrentFocus ? GetSheetHeightChange() : 0.0f;
3177 sheetHeightUp_ = heightUp;
3178 TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, sheet needs to deal with %{public}f height.", heightUp);
3179 auto offset = pageHeight_ - height_ - heightUp;
3180 auto renderContext = host->GetRenderContext();
3181
3182 // when bindSheet height exceed the max height, lift it up to the maxHeight,
3183 // otherwise, lift it up to show input area
3184 if (isScrolling_) {
3185 if (NearZero(heightUp)) {
3186 // scroll needs to reset first when keyboard is down.
3187 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
3188 } else {
3189 sheetHeightUp_ = pageHeight_ - (SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_) - height_;
3190 // sheet is raised to the top first
3191 renderContext->UpdateTransformTranslate(
3192 { 0.0f, SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + sheetTopSafeArea_, 0.0f });
3193 }
3194 } else {
3195 // offset: translate endpoint, calculated from top
3196 renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
3197 }
3198
3199 // 3.deal with left height, scroll or resize
3200 if (isScrolling_) {
3201 AvoidKeyboardAfterTranslate(heightUp);
3202 }
3203
3204 if (IsSheetBottomStyle()) {
3205 OnHeightDidChange(height_ + sheetHeightUp_);
3206 }
3207 }
3208
3209 bool SheetPresentationPattern::AvoidKeyboardBeforeTranslate()
3210 {
3211 if (keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY) {
3212 // resize bindSheet need to keep safe distance from keyboard
3213 auto distanceFromBottom = sheetType_ == SheetType::SHEET_CENTER ? height_ - centerHeight_ : 0.0f;
3214 DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : keyboardHeight_ - distanceFromBottom);
3215 return true;
3216 }
3217 return false;
3218 }
3219
3220 void SheetPresentationPattern::AvoidKeyboardAfterTranslate(float height)
3221 {
3222 switch (keyboardAvoidMode_) {
3223 case SheetKeyboardAvoidMode::NONE:
3224 case SheetKeyboardAvoidMode::RESIZE_ONLY:
3225 break;
3226 case SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE:
3227 // resize bindSheet need to keep safe distance from keyboard
3228 DecreaseScrollHeightInSheet(keyboardHeight_ == 0 ? 0.0f : height);
3229 break;
3230 case SheetKeyboardAvoidMode::TRANSLATE_AND_SCROLL:
3231 ScrollTo(height);
3232 break;
3233 default:
3234 TAG_LOGW(AceLogTag::ACE_SHEET, "Invalid keyboard avoid mode %{public}d", keyboardAvoidMode_);
3235 break;
3236 }
3237 }
3238
3239 void SheetPresentationPattern::DecreaseScrollHeightInSheet(float decreaseHeight)
3240 {
3241 auto scroll = GetSheetScrollNode();
3242 CHECK_NULL_VOID(scroll);
3243 auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
3244 CHECK_NULL_VOID(layoutProp);
3245
3246 // height > 0, Scroll will reduce height, and need to set isScrolling true
3247 isScrolling_ = (decreaseHeight > 0);
3248
3249 TAG_LOGD(AceLogTag::ACE_SHEET, "To avoid Keyboard, Scroll Height reduces by height %{public}f.", decreaseHeight);
3250 layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight() - decreaseHeight)));
3251 resizeDecreasedHeight_ = decreaseHeight;
3252 scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3253 }
3254
3255 bool SheetPresentationPattern::IsResizeWhenAvoidKeyboard()
3256 {
3257 return keyboardAvoidMode_ == SheetKeyboardAvoidMode::TRANSLATE_AND_RESIZE ||
3258 keyboardAvoidMode_ == SheetKeyboardAvoidMode::RESIZE_ONLY;
3259 }
3260
3261 void SheetPresentationPattern::ResetClipShape()
3262 {
3263 // need reset clip path,when system clip path change to user defined
3264 auto host = GetHost();
3265 CHECK_NULL_VOID(host);
3266 auto renderContext = host->GetRenderContext();
3267 CHECK_NULL_VOID(renderContext);
3268 renderContext->UpdateClipShape(nullptr);
3269 renderContext->ResetClipShape();
3270 }
3271
3272 void SheetPresentationPattern::GetCurrentScrollHeight()
3273 {
3274 if (!isScrolling_) {
3275 return;
3276 }
3277 auto host = GetHost();
3278 CHECK_NULL_VOID(host);
3279 auto scrollNode = GetSheetScrollNode();
3280 CHECK_NULL_VOID(scrollNode);
3281 auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
3282 CHECK_NULL_VOID(scrollPattern);
3283 auto curOffset = scrollPattern->GetTotalOffset();
3284 if (NearEqual(scrollHeight_, curOffset)) {
3285 return;
3286 }
3287 TAG_LOGD(AceLogTag::ACE_SHEET, "scroll height changed because of user scrolling, %{public}f", curOffset);
3288 scrollHeight_ = curOffset;
3289 }
3290
3291 void SheetPresentationPattern::UpdateSheetWhenSheetTypeChanged()
3292 {
3293 auto sheetType = GetSheetType();
3294 if (sheetType_ != sheetType) {
3295 // It can only be MarkOuterBorder When the SheetType switches and the sheetType_ was SHEET_POPUP
3296 if (sheetType_ == SheetType::SHEET_POPUP) {
3297 MarkSheetPageNeedRender();
3298 }
3299 sheetType_ = sheetType;
3300 SetSheetBorderWidth();
3301 }
3302 }
3303
3304 bool SheetPresentationPattern::IsCurSheetNeedHalfFoldHover()
3305 {
3306 auto host = GetHost();
3307 CHECK_NULL_RETURN(host, false);
3308 auto pipeline = host->GetContext();
3309 CHECK_NULL_RETURN(pipeline, false);
3310 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3311 CHECK_NULL_RETURN(sheetTheme, false);
3312 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3313 CHECK_NULL_RETURN(layoutProperty, false);
3314 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3315 auto enableHoverMode = sheetStyle.enableHoverMode.value_or(sheetTheme->IsOuterBorderEnable() ? true : false);
3316 bool isHoverMode = enableHoverMode ? pipeline->IsHalfFoldHoverStatus() : false;
3317 return isHoverMode && GetSheetType() == SheetType::SHEET_CENTER;
3318 }
3319
3320 bool SheetPresentationPattern::IsShowInSubWindowTwoInOne()
3321 {
3322 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3323 CHECK_NULL_RETURN(layoutProperty, false);
3324 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3325 if (!sheetStyle.showInSubWindow.value_or(false)) {
3326 return false;
3327 }
3328 auto host = GetHost();
3329 CHECK_NULL_RETURN(host, false);
3330 auto pipeline = host->GetContext();
3331 CHECK_NULL_RETURN(pipeline, false);
3332 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3333 CHECK_NULL_RETURN(sheetTheme, false);
3334 return sheetTheme->IsOuterBorderEnable();
3335 }
3336
3337 bool SheetPresentationPattern::IsShowInSubWindow()
3338 {
3339 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3340 CHECK_NULL_RETURN(layoutProperty, false);
3341 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3342 return sheetStyle.showInSubWindow.value_or(false);
3343 }
3344
3345 void SheetPresentationPattern::InitFoldCreaseRegion()
3346 {
3347 auto host = GetHost();
3348 CHECK_NULL_VOID(host);
3349 auto pipeline = host->GetContext();
3350 CHECK_NULL_VOID(pipeline);
3351 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
3352 CHECK_NULL_VOID(sheetTheme);
3353 auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
3354 CHECK_NULL_VOID(layoutProperty);
3355 auto sheetStyle = layoutProperty->GetSheetStyleValue(SheetStyle());
3356 auto enableHoverMode = sheetStyle.enableHoverMode.value_or(sheetTheme->IsOuterBorderEnable() ? true : false);
3357 if (!enableHoverMode || !currentFoldCreaseRegion_.empty()) {
3358 return;
3359 }
3360 auto container = Container::Current();
3361 CHECK_NULL_VOID(container);
3362 auto displayInfo = container->GetDisplayInfo();
3363 CHECK_NULL_VOID(displayInfo);
3364 currentFoldCreaseRegion_ = displayInfo->GetCurrentFoldCreaseRegion();
3365 }
3366
3367 Rect SheetPresentationPattern::GetFoldScreenRect() const
3368 {
3369 if (currentFoldCreaseRegion_.empty()) {
3370 TAG_LOGW(AceLogTag::ACE_SHEET, "FoldCreaseRegion is invalid.");
3371 return Rect();
3372 }
3373 return currentFoldCreaseRegion_.front();
3374 }
3375
3376 Shadow SheetPresentationPattern::GetShadowFromTheme(ShadowStyle shadowStyle)
3377 {
3378 if (shadowStyle == ShadowStyle::None) {
3379 return Shadow();
3380 }
3381 auto host = GetHost();
3382 CHECK_NULL_RETURN(host, Shadow());
3383 auto pipelineContext = host->GetContext();
3384 CHECK_NULL_RETURN(pipelineContext, Shadow());
3385 auto colorMode = pipelineContext->GetColorMode();
3386 auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
3387 CHECK_NULL_RETURN(shadowTheme, Shadow());
3388 auto shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
3389 return shadow;
3390 }
3391
3392 void SheetPresentationPattern::FireHoverModeChangeCallback()
3393 {
3394 auto host = GetHost();
3395 CHECK_NULL_VOID(host);
3396 auto pipeline = host->GetContext();
3397 CHECK_NULL_VOID(pipeline);
3398 if (!IsCurSheetNeedHalfFoldHover()) {
3399 TAG_LOGD(AceLogTag::ACE_SHEET, "halfFoldHoverStatus: %{public}d, Sheet is not half folded.",
3400 pipeline->IsHalfFoldHoverStatus());
3401 return;
3402 }
3403 OnHeightDidChange(centerHeight_);
3404 }
3405
3406 void SheetPresentationPattern::GetArrowOffsetByPlacement(
3407 const RefPtr<SheetPresentationLayoutAlgorithm>& layoutAlgorithm)
3408 {
3409 CHECK_NULL_VOID(layoutAlgorithm);
3410 if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
3411 return;
3412 }
3413 finalPlacement_ = sheetPopupInfo_.finalPlacement;
3414 showArrow_ = sheetPopupInfo_.showArrow;
3415 arrowPosition_ = sheetPopupInfo_.arrowPosition;
3416 if (!showArrow_ || finalPlacement_ == Placement::NONE) {
3417 arrowOffset_ = OffsetF(0.f, 0.f);
3418 return;
3419 }
3420
3421 switch (finalPlacement_) {
3422 case Placement::BOTTOM_LEFT:
3423 [[fallthrough]];
3424 case Placement::BOTTOM_RIGHT:
3425 [[fallthrough]];
3426 case Placement::BOTTOM:
3427 [[fallthrough]];
3428 case Placement::TOP_LEFT:
3429 [[fallthrough]];
3430 case Placement::TOP_RIGHT:
3431 [[fallthrough]];
3432 case Placement::TOP: {
3433 arrowOffset_ = OffsetF(sheetPopupInfo_.arrowOffsetX, 0.f);
3434 break;
3435 }
3436 case Placement::RIGHT_TOP:
3437 [[fallthrough]];
3438 case Placement::RIGHT_BOTTOM:
3439 [[fallthrough]];
3440 case Placement::RIGHT:
3441 [[fallthrough]];
3442 case Placement::LEFT_TOP:
3443 [[fallthrough]];
3444 case Placement::LEFT_BOTTOM:
3445 [[fallthrough]];
3446 case Placement::LEFT: {
3447 arrowOffset_ = OffsetF(0.f, sheetPopupInfo_.arrowOffsetY);
3448 break;
3449 }
3450 default:
3451 break;
3452 }
3453 }
3454
3455 std::string SheetPresentationPattern::GetPopupStyleSheetClipPathNew(
3456 const SizeF& sheetSize, const BorderRadiusProperty& sheetRadius)
3457 {
3458 std::string drawPath;
3459 switch (finalPlacement_) {
3460 case Placement::BOTTOM_LEFT:
3461 [[fallthrough]];
3462 case Placement::BOTTOM_RIGHT:
3463 [[fallthrough]];
3464 case Placement::BOTTOM: {
3465 drawPath = DrawClipPathBottom(sheetSize, sheetRadius);
3466 break;
3467 }
3468 case Placement::TOP_LEFT:
3469 [[fallthrough]];
3470 case Placement::TOP_RIGHT:
3471 [[fallthrough]];
3472 case Placement::TOP: {
3473 drawPath = DrawClipPathTop(sheetSize, sheetRadius);
3474 break;
3475 }
3476 case Placement::RIGHT_TOP:
3477 [[fallthrough]];
3478 case Placement::RIGHT_BOTTOM:
3479 [[fallthrough]];
3480 case Placement::RIGHT: {
3481 drawPath = DrawClipPathRight(sheetSize, sheetRadius);
3482 break;
3483 }
3484 case Placement::LEFT_TOP:
3485 [[fallthrough]];
3486 case Placement::LEFT_BOTTOM:
3487 [[fallthrough]];
3488 case Placement::LEFT: {
3489 drawPath = DrawClipPathLeft(sheetSize, sheetRadius);
3490 break;
3491 }
3492 default:
3493 break;
3494 }
3495 return drawPath;
3496 }
3497
3498 std::string SheetPresentationPattern::DrawClipPathBottom(const SizeF& sheetSize,
3499 const BorderRadiusProperty& sheetRadius)
3500 {
3501 auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3502 auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3503 auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3504 auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3505 // clip path start from TopLeft, and draw Right-angled arrow first if needed
3506 std::string path;
3507 if (arrowPosition_ == SheetArrowPosition::BOTTOM_LEFT) {
3508 path += MoveTo(0.f, SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3509 path += LineTo(0.f, (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx()); // P4
3510 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3511 (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3512 (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3513 path += LineTo(SHEET_ARROW_WIDTH.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3514 } else {
3515 path += MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopLeft);
3516 path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft,
3517 SHEET_ARROW_HEIGHT.ConvertToPx());
3518 }
3519 if (arrowPosition_ == SheetArrowPosition::NONE) {
3520 path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(),
3521 SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3522 path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
3523 (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx()); // P2
3524 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3525 arrowOffset_.GetX() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
3526 (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx()); // P4
3527 path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(),
3528 SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3529 }
3530 if (arrowPosition_ == SheetArrowPosition::BOTTOM_RIGHT) {
3531 path += LineTo(sheetSize.Width() -
3532 SHEET_ARROW_WIDTH.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3533 path += LineTo(sheetSize.Width() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3534 (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3535 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3536 sheetSize.Width(), (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx()); // P4
3537 path += LineTo(sheetSize.Width(), SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3538 } else {
3539 path += LineTo(sheetSize.Width() - radiusTopRight, SHEET_ARROW_HEIGHT.ConvertToPx());
3540 path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0, sheetSize.Width(),
3541 SHEET_ARROW_HEIGHT.ConvertToPx() + radiusTopRight);
3542 }
3543 path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
3544 path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3545 sheetSize.Width() - radiusBottomRight, sheetSize.Height());
3546 path += LineTo(radiusBottomLeft, sheetSize.Height());
3547 path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0, 0.0f,
3548 sheetSize.Height() - radiusBottomLeft);
3549 return path + "Z";
3550 }
3551
3552 std::string SheetPresentationPattern::DrawClipPathTop(const SizeF& sheetSize,
3553 const BorderRadiusProperty& sheetRadius)
3554 {
3555 auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3556 auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3557 auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3558 auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3559 // clip path start from TopLeft, and draw sheet radius first
3560 std::string path;
3561 path += MoveTo(0.f, radiusTopLeft);
3562 path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, 0.f);
3563 path += LineTo(sheetSize.Width() - radiusTopRight, 0.f);
3564 path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3565 sheetSize.Width(), radiusTopRight);
3566 if (arrowPosition_ == SheetArrowPosition::TOP_RIGHT) {
3567 path += LineTo(sheetSize.Width(),
3568 sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx()); // P4
3569 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3570 sheetSize.Width() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3571 sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3572 path += LineTo(sheetSize.Width() - SHEET_ARROW_WIDTH.ConvertToPx(),
3573 sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3574 } else {
3575 path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight - SHEET_ARROW_HEIGHT.ConvertToPx());
3576 path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3577 sheetSize.Width() - radiusBottomRight, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx());
3578 }
3579 if (arrowPosition_ == SheetArrowPosition::NONE) {
3580 path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(),
3581 sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3582 path += LineTo(arrowOffset_.GetX() + ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
3583 sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx()); // P2
3584 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3585 arrowOffset_.GetX() - ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
3586 sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx()); // P4
3587 path += LineTo(arrowOffset_.GetX() - ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(),
3588 sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3589 }
3590 if (arrowPosition_ == SheetArrowPosition::TOP_LEFT) {
3591 path += LineTo(SHEET_ARROW_WIDTH.ConvertToPx(),
3592 sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
3593 path += LineTo((SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx(),
3594 sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx()); // P2
3595 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0, 0.f,
3596 sheetSize.Height() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx()); // P4
3597 path += LineTo(0.f, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
3598 } else {
3599 path += LineTo(radiusBottomLeft, sheetSize.Height() - SHEET_ARROW_HEIGHT.ConvertToPx());
3600 path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3601 0.f, sheetSize.Height() - radiusBottomLeft - SHEET_ARROW_HEIGHT.ConvertToPx());
3602 }
3603 return path + "Z";
3604 }
3605
3606 std::string SheetPresentationPattern::DrawClipPathLeft(const SizeF& sheetSize,
3607 const BorderRadiusProperty& sheetRadius)
3608 {
3609 auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3610 auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3611 auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3612 auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3613 // clip path start from TopLeft, and draw sheet radius first
3614 std::string path;
3615 path += MoveTo(0.f, radiusTopLeft);
3616 path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0, radiusTopLeft, 0.f);
3617 if (arrowPosition_ == SheetArrowPosition::LEFT_TOP) {
3618 path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), 0.f); // P4
3619 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3620 sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3621 (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3622 path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3623 SHEET_ARROW_WIDTH.ConvertToPx()); // P1
3624 } else {
3625 path += LineTo(sheetSize.Width() - radiusTopRight - SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
3626 path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3627 sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(), radiusTopRight);
3628 }
3629 if (arrowPosition_ == SheetArrowPosition::NONE) {
3630 path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3631 arrowOffset_.GetY() - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx()); // P1
3632 path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx(),
3633 arrowOffset_.GetY() - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx()); // P2
3634 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3635 sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx(),
3636 arrowOffset_.GetY() + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx()); // P4
3637 path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3638 arrowOffset_.GetY() + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx()); // P5
3639 }
3640 if (arrowPosition_ == SheetArrowPosition::LEFT_BOTTOM) {
3641 path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3642 sheetSize.Height() - SHEET_ARROW_WIDTH.ConvertToPx()); // P1
3643 path += LineTo(sheetSize.Width() - (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3644 sheetSize.Height() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3645 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0, sheetSize.Width() -
3646 (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), sheetSize.Height()); // P4
3647 path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height()); // P5
3648 } else {
3649 path += LineTo(sheetSize.Width() - SHEET_ARROW_HEIGHT.ConvertToPx(),
3650 sheetSize.Height() - radiusBottomRight);
3651 path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3652 sheetSize.Width() - radiusBottomRight - SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());
3653 }
3654 path += LineTo(radiusBottomLeft, sheetSize.Height());
3655 path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3656 0.f, sheetSize.Height() - radiusBottomLeft);
3657 return path + "Z";
3658 }
3659
3660 std::string SheetPresentationPattern::DrawClipPathRight(const SizeF& sheetSize,
3661 const BorderRadiusProperty& sheetRadius)
3662 {
3663 auto radiusTopLeft = sheetRadius.radiusTopLeft->ConvertToPx();
3664 auto radiusTopRight = sheetRadius.radiusTopRight->ConvertToPx();
3665 auto radiusBottomRight = sheetRadius.radiusBottomRight->ConvertToPx();
3666 auto radiusBottomLeft = sheetRadius.radiusBottomLeft->ConvertToPx();
3667 // clip path start from TopLeft, and if left side need draw left top Right-angled arrow, draw it first
3668 std::string path;
3669 if (arrowPosition_ == SheetArrowPosition::RIGHT_TOP) {
3670 path += MoveTo(SHEET_ARROW_HEIGHT.ConvertToPx(), SHEET_ARROW_WIDTH.ConvertToPx()); // P1
3671 path += LineTo((SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3672 (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3673 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3674 (SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), 0.f); // P4
3675 path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f); // P5
3676 } else {
3677 path += MoveTo(SHEET_ARROW_HEIGHT.ConvertToPx(), radiusTopLeft);
3678 path += ArcTo(radiusTopLeft, radiusTopLeft, 0.0f, 0,
3679 radiusTopLeft + SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
3680 }
3681 path += LineTo(sheetSize.Width() - radiusTopRight, 0.f);
3682 path += ArcTo(radiusTopRight, radiusTopRight, 0.0f, 0,
3683 sheetSize.Width(), radiusTopRight);
3684 path += LineTo(sheetSize.Width(), sheetSize.Height() - radiusBottomRight);
3685 path += ArcTo(radiusBottomRight, radiusBottomRight, 0.0f, 0,
3686 sheetSize.Width() - radiusBottomRight, sheetSize.Height());
3687 if (arrowPosition_ == SheetArrowPosition::RIGHT_BOTTOM) {
3688 path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height()); // P5
3689 path += LineTo((SHEET_ARROW_HEIGHT - ARROW_CORNER_P4_OFFSET_Y).ConvertToPx(), sheetSize.Height()); // P4
3690 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3691 (SHEET_ARROW_HEIGHT - ARROW_CORNER_P2_OFFSET_Y).ConvertToPx(),
3692 sheetSize.Height() - (SHEET_ARROW_WIDTH - ARROW_CORNER_P2_OFFSET_X).ConvertToPx()); // P2
3693 path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3694 sheetSize.Height() - SHEET_ARROW_WIDTH.ConvertToPx()); // P1
3695 } else {
3696 path += LineTo(radiusBottomLeft + SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height());
3697 path += ArcTo(radiusBottomLeft, radiusBottomLeft, 0.0f, 0,
3698 SHEET_ARROW_HEIGHT.ConvertToPx(), sheetSize.Height() - radiusBottomLeft);
3699 }
3700 if (arrowPosition_ == SheetArrowPosition::NONE) {
3701 path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3702 arrowOffset_.GetY() + ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx()); // P1
3703 path += LineTo((SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P2_OFFSET_Y).ConvertToPx(),
3704 arrowOffset_.GetY() + ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx()); // P2
3705 path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
3706 (SHEET_ARROW_HEIGHT - ARROW_VERTICAL_P4_OFFSET_Y).ConvertToPx(),
3707 arrowOffset_.GetY() - ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx()); // P4
3708 path += LineTo(SHEET_ARROW_HEIGHT.ConvertToPx(),
3709 arrowOffset_.GetY() - ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx()); // P5
3710 }
3711 return path + "Z";
3712 }
3713
3714 void SheetPresentationPattern::RecoverHalfFoldOrAvoidStatus()
3715 {
3716 TAG_LOGD(AceLogTag::ACE_SHEET, "recover half fold status because of window rotate");
3717 auto host = GetHost();
3718 CHECK_NULL_VOID(host);
3719 auto pipeline = host->GetContext();
3720 CHECK_NULL_VOID(pipeline);
3721 if (IsCurSheetNeedHalfFoldHover()) {
3722 RecoverAvoidKeyboardStatus();
3723 } else {
3724 AvoidSafeArea(true);
3725 }
3726 }
3727
3728 void SheetPresentationPattern::RecoverAvoidKeyboardStatus()
3729 {
3730 RecoverScrollOrResizeAvoidStatus();
3731 sheetHeightUp_ = 0.f;
3732 OnHeightDidChange(centerHeight_);
3733 }
3734
3735 void SheetPresentationPattern::RecoverScrollOrResizeAvoidStatus()
3736 {
3737 auto scroll = GetSheetScrollNode();
3738 CHECK_NULL_VOID(scroll);
3739 auto layoutProp = scroll->GetLayoutProperty<ScrollLayoutProperty>();
3740 CHECK_NULL_VOID(layoutProp);
3741 layoutProp->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(GetScrollHeight())));
3742 resizeDecreasedHeight_ = 0.f;
3743 scrollHeight_ = 0.f;
3744 ScrollTo(0.f);
3745 isScrolling_ = false;
3746 }
3747
3748 void SheetPresentationPattern::OnWillDisappear()
3749 {
3750 if (onWillDisappear_) {
3751 TAG_LOGI(AceLogTag::ACE_SHEET, "bindsheet lifecycle change to onWillDisappear state.");
3752 onWillDisappear_();
3753 }
3754 auto hostNode = GetHost();
3755 CHECK_NULL_VOID(hostNode);
3756 auto pipelineContext = hostNode->GetContextRefPtr();
3757 CHECK_NULL_VOID(pipelineContext);
3758 auto navigationManager = pipelineContext->GetNavigationManager();
3759 CHECK_NULL_VOID(navigationManager);
3760 navigationManager->FireOverlayLifecycle(hostNode, static_cast<int32_t>(NavDestinationLifecycle::ON_INACTIVE),
3761 static_cast<int32_t>(NavDestinationActiveReason::SHEET));
3762 }
3763
3764 void SheetPresentationPattern::OnFontScaleConfigurationUpdate()
3765 {
3766 auto hostNode = GetHost();
3767 CHECK_NULL_VOID(hostNode);
3768 auto pipeline = hostNode->GetContext();
3769 CHECK_NULL_VOID(pipeline);
3770 pipeline->AddAfterReloadAnimationTask([weak = WeakClaim(this)]() {
3771 auto pattern = weak.Upgrade();
3772 CHECK_NULL_VOID(pattern);
3773 pattern->AvoidSafeArea(true);
3774 });
3775 }
3776
3777 void SheetPresentationPattern::OnAvoidInfoChange(const ContainerModalAvoidInfo& info)
3778 {
3779 auto host = GetHost();
3780 CHECK_NULL_VOID(host);
3781 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3782 }
3783
3784 void SheetPresentationPattern::RegisterAvoidInfoChangeListener(const RefPtr<FrameNode>& hostNode)
3785 {
3786 CHECK_NULL_VOID(hostNode);
3787 auto pipeline = hostNode->GetContext();
3788 CHECK_NULL_VOID(pipeline);
3789 auto mgr = pipeline->GetAvoidInfoManager();
3790 CHECK_NULL_VOID(mgr);
3791 mgr->AddAvoidInfoListener(WeakClaim(this));
3792 }
3793
3794 void SheetPresentationPattern::UnRegisterAvoidInfoChangeListener(FrameNode* hostNode)
3795 {
3796 CHECK_NULL_VOID(hostNode);
3797 auto pipeline = hostNode->GetContext();
3798 CHECK_NULL_VOID(pipeline);
3799 auto mgr = pipeline->GetAvoidInfoManager();
3800 CHECK_NULL_VOID(mgr);
3801 mgr->RemoveAvoidInfoListener(WeakClaim(this));
3802 }
3803 } // namespace OHOS::Ace::NG
3804