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