• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
17 
18 #include "sheet_presentation_property.h"
19 
20 #include "base/geometry/dimension.h"
21 #include "base/utils/utils.h"
22 #include "base/window/foldable_window.h"
23 #include "core/animation/animation_pub.h"
24 #include "core/animation/curve.h"
25 #include "core/common/container.h"
26 #include "core/components/drag_bar/drag_bar_theme.h"
27 #include "core/components_ng/event/event_hub.h"
28 #include "core/components_ng/event/gesture_event_hub.h"
29 #include "core/components_ng/pattern/image/image_pattern.h"
30 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
31 #include "core/components_ng/pattern/overlay/sheet_style.h"
32 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
33 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
34 #include "core/components_ng/pattern/text/text_layout_property.h"
35 #include "core/components_ng/pattern/text_field/text_field_manager.h"
36 #include "core/components_ng/property/property.h"
37 #include "core/event/touch_event.h"
38 #include "core/pipeline_ng/pipeline_context.h"
39 
40 namespace OHOS::Ace::NG {
41 namespace {
42 constexpr float SHEET_VISIABLE_ALPHA = 1.0f;
43 constexpr float SHEET_INVISIABLE_ALPHA = 0.0f;
44 constexpr int32_t SHEET_ENTRY_ANIMATION_DURATION = 250;
45 constexpr int32_t SHEET_EXIT_ANIMATION_DURATION = 100;
46 constexpr float SHEET_INVISIABLE_OFFSET = 8.0;
47 constexpr int32_t SHEET_HALF_HEIGHT = 2;
48 constexpr Dimension ARROW_VERTICAL_P1_OFFSET_X = 8.0_vp;
49 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_X = 1.5_vp;
50 constexpr Dimension ARROW_VERTICAL_P2_OFFSET_Y = 7.32_vp;
51 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_X = 1.5_vp;
52 constexpr Dimension ARROW_VERTICAL_P4_OFFSET_Y = 7.32_vp;
53 constexpr Dimension ARROW_VERTICAL_P5_OFFSET_X = 8.0_vp;
54 constexpr Dimension ARROW_RADIUS = 2.0_vp;
55 } // namespace
OnModifyDone()56 void SheetPresentationPattern::OnModifyDone()
57 {
58     auto host = GetHost();
59     CHECK_NULL_VOID(host);
60     auto renderContext = host->GetRenderContext();
61     if (renderContext) {
62         auto pipeline = PipelineContext::GetCurrentContext();
63         CHECK_NULL_VOID(pipeline);
64         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
65         CHECK_NULL_VOID(sheetTheme);
66         renderContext->UpdateBackgroundColor(sheetTheme->GetSheetBackgoundColor());
67     }
68     InitPanEvent();
69     InitPageHeight();
70 }
71 
InitPageHeight()72 void SheetPresentationPattern::InitPageHeight()
73 {
74     auto context = PipelineContext::GetCurrentContext();
75     CHECK_NULL_VOID(context);
76     auto overlayManager = context->GetOverlayManager();
77     CHECK_NULL_VOID(overlayManager);
78     auto manager = context->GetSafeAreaManager();
79     CHECK_NULL_VOID(manager);
80     statusBarHeight_ = manager->GetSystemSafeArea().top_.Length();
81     auto sheetTheme = context->GetTheme<SheetTheme>();
82     CHECK_NULL_VOID(sheetTheme);
83     sheetThemeType_ = sheetTheme->GetSheetType();
84 }
85 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)86 bool SheetPresentationPattern::OnDirtyLayoutWrapperSwap(
87     const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
88 {
89     if (config.skipMeasure && config.skipLayout) {
90         return false;
91     }
92     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
93     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
94     auto sheetLayoutAlgorithm =
95         DynamicCast<SheetPresentationLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
96     CHECK_NULL_RETURN(sheetLayoutAlgorithm, false);
97     InitPageHeight();
98     if (sheetLayoutAlgorithm->GetSheetMaxHeight() > 0) {
99         pageHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight();
100         sheetMaxHeight_ = sheetLayoutAlgorithm->GetSheetMaxHeight() - statusBarHeight_;
101         sheetMaxWidth_ = sheetLayoutAlgorithm->GetSheetMaxWidth();
102         centerHeight_ = sheetLayoutAlgorithm->GetCenterHeight();
103         if (!NearEqual(sheetOffsetX_, sheetLayoutAlgorithm->GetSheetOffsetX()) ||
104             !NearEqual(sheetOffsetY_, sheetLayoutAlgorithm->GetSheetOffsetY())) {
105             sheetOffsetX_ = sheetLayoutAlgorithm->GetSheetOffsetX();
106             sheetOffsetY_ = sheetLayoutAlgorithm->GetSheetOffsetY();
107             windowChanged_ = true;
108         }
109     }
110     auto sheetType = GetSheetType();
111     if ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOMLANDSPACE)) {
112         if (windowRotate_) {
113             // When rotating the screen,
114             // first switch the sheet to the position corresponding to the proportion before rotation
115             TranslateTo(pageHeight_ - height_);
116             windowRotate_ = false;
117         } else {
118             // After rotation, if need to avoid the keyboard, trigger the avoidance behavior
119             AvoidSafeArea();
120         }
121     }
122     InitialLayoutProps();
123     UpdateDragBarStatus();
124     UpdateCloseIconStatus();
125     UpdateSheetTitle();
126     AvoidAiBar();
127     UpdateInteractive();
128     ClipSheetNode();
129     return true;
130 }
131 
AvoidAiBar()132 void SheetPresentationPattern::AvoidAiBar()
133 {
134     CHECK_NULL_VOID(Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN));
135     auto host = GetHost();
136     CHECK_NULL_VOID(host);
137     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
138     CHECK_NULL_VOID(scrollNode);
139     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
140     CHECK_NULL_VOID(scrollPattern);
141     if (NonPositive(scrollPattern->GetScrollableDistance())) {
142         return;
143     }
144     auto pipeline = PipelineContext::GetCurrentContext();
145     CHECK_NULL_VOID(pipeline);
146     auto inset = pipeline->GetSafeArea();
147     auto layoutProperty = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
148     layoutProperty->UpdateScrollContentEndOffset(inset.bottom_.Length());
149 }
150 
IsScrollable() const151 bool SheetPresentationPattern::IsScrollable() const
152 {
153     auto host = GetHost();
154     CHECK_NULL_RETURN(host, false);
155     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
156     CHECK_NULL_RETURN(scrollNode, false);
157     auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
158     CHECK_NULL_RETURN(scrollPattern, false);
159     return Positive(scrollPattern->GetScrollableDistance());
160 }
161 
OnAttachToFrameNode()162 void SheetPresentationPattern::OnAttachToFrameNode()
163 {
164     auto host = GetHost();
165     CHECK_NULL_VOID(host);
166     auto pipelineContext = PipelineContext::GetCurrentContext();
167     CHECK_NULL_VOID(pipelineContext);
168     pipelineContext->AddWindowSizeChangeCallback(host->GetId());
169     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
170     host->GetLayoutProperty()->UpdateAlignment(Alignment::TOP_LEFT);
171     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
172     CHECK_NULL_VOID(targetNode);
173     pipelineContext->AddOnAreaChangeNode(targetNode->GetId());
174     OnAreaChangedFunc onAreaChangedFunc = [sheetNodeWk = WeakPtr<FrameNode>(host)](const RectF& /* oldRect */,
175                                               const OffsetF& /* oldOrigin */, const RectF& /* rect */,
176                                               const OffsetF& /* origin */) {
177         auto sheetNode = sheetNodeWk.Upgrade();
178         CHECK_NULL_VOID(sheetNode);
179         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
180         CHECK_NULL_VOID(sheetPattern);
181         if (sheetPattern->GetSheetType() == SheetType::SHEET_POPUP) {
182             sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
183         }
184     };
185     targetNode->SetOnAreaChangeCallback(std::move(onAreaChangedFunc));
186 }
187 
OnDetachFromFrameNode(FrameNode * frameNode)188 void SheetPresentationPattern::OnDetachFromFrameNode(FrameNode* frameNode)
189 {
190     auto pipeline = PipelineContext::GetCurrentContext();
191     CHECK_NULL_VOID(pipeline);
192     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
193     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetId_);
194     CHECK_NULL_VOID(targetNode);
195     pipeline->RemoveOnAreaChangeNode(targetNode->GetId());
196 }
197 
198 // initial drag gesture event
InitPanEvent()199 void SheetPresentationPattern::InitPanEvent()
200 {
201     auto host = GetHost();
202     CHECK_NULL_VOID(host);
203 
204     auto hub = host->GetEventHub<EventHub>();
205     CHECK_NULL_VOID(hub);
206     auto gestureHub = hub->GetOrCreateGestureEventHub();
207     CHECK_NULL_VOID(gestureHub);
208     if (panEvent_) {
209         return;
210     }
211 
212     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& event) {
213         auto pattern = weak.Upgrade();
214         if (pattern) {
215             pattern->HandleDragStart();
216         }
217     };
218 
219     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
220         auto pattern = weak.Upgrade();
221         if (pattern) {
222             pattern->HandleDragUpdate(info);
223         }
224     };
225 
226     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
227         auto pattern = weak.Upgrade();
228         if (pattern) {
229             pattern->HandleDragEnd(info.GetMainVelocity());
230         }
231     };
232     auto actionCancelTask = [weak = WeakClaim(this)]() {
233         auto pattern = weak.Upgrade();
234         if (pattern) {
235             pattern->HandleDragEnd({});
236         }
237     };
238     PanDirection panDirection;
239     panDirection.type = PanDirection::VERTICAL;
240     panEvent_ = MakeRefPtr<PanEvent>(
241         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
242     gestureHub->AddPanEvent(panEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
243 }
244 
HandleDragStart()245 void SheetPresentationPattern::HandleDragStart()
246 {
247     if (animation_ && isAnimationProcess_) {
248         AnimationUtils::StopAnimation(animation_);
249         isAnimationBreak_ = true;
250     }
251     currentOffset_ = 0.0f;
252 }
253 
HandleDragUpdate(const GestureEvent & info)254 void SheetPresentationPattern::HandleDragUpdate(const GestureEvent& info)
255 {
256     auto sheetType = GetSheetType();
257     if (sheetType == SheetType::SHEET_POPUP) {
258         return;
259     }
260     auto mainDelta = static_cast<float>(info.GetMainDelta());
261     auto host = GetHost();
262     CHECK_NULL_VOID(host);
263     auto tempOffset = currentOffset_;
264     auto detentSize = sheetDetentHeight_.size();
265     if (detentSize <= 0) {
266         return;
267     }
268     auto maxDetentSize = sheetDetentHeight_[detentSize - 1];
269     if (GreatNotEqual((height_ - currentOffset_), maxDetentSize)) {
270         if (LessNotEqual(mainDelta, 0)) {
271             auto friction = CalculateFriction((height_ - currentOffset_) / sheetMaxHeight_);
272             mainDelta = mainDelta * friction;
273         }
274     }
275     currentOffset_ = currentOffset_ + mainDelta;
276     if (NearEqual(currentOffset_, tempOffset)) {
277         return;
278     }
279     auto offset = pageHeight_ - height_ + currentOffset_;
280     if (LessOrEqual(offset, (pageHeight_ - sheetMaxHeight_))) {
281         offset = pageHeight_ - sheetMaxHeight_;
282         currentOffset_ = height_ - sheetMaxHeight_;
283     }
284     ProcessColumnRect(height_ - currentOffset_);
285     auto renderContext = host->GetRenderContext();
286     renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
287 }
288 
HandleDragEnd(float dragVelocity)289 void SheetPresentationPattern::HandleDragEnd(float dragVelocity)
290 {
291     auto sheetDetentsSize = sheetDetentHeight_.size();
292     if ((sheetDetentsSize == 0) || (GetSheetType() == SheetType::SHEET_POPUP)) {
293         return;
294     }
295     float upHeight = 0.0f;
296     float downHeight = 0.0f;
297     auto currentSheetHeight =
298         GreatNotEqual((height_ - currentOffset_), sheetMaxHeight_) ? sheetMaxHeight_ : (height_ - currentOffset_);
299     auto lowerIter = std::lower_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
300     auto upperIter = std::upper_bound(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), currentSheetHeight);
301     if (lowerIter == sheetDetentHeight_.end()) {
302         upHeight = sheetDetentHeight_[sheetDetentsSize - 1];
303         downHeight = sheetDetentHeight_[sheetDetentsSize - 1];
304     } else {
305         auto lowerPosition = std::distance(sheetDetentHeight_.begin(), lowerIter);
306         auto upperPosition = std::distance(sheetDetentHeight_.begin(), upperIter);
307         if (lowerPosition == 0) {
308             upHeight = sheetDetentHeight_[lowerPosition];
309             downHeight = 0;
310         } else {
311             upHeight = sheetDetentHeight_[upperPosition];
312             downHeight = sheetDetentHeight_[lowerPosition - 1];
313         }
314     }
315     // current sheet animation
316     if ((LessNotEqual(std::abs(dragVelocity), SHEET_VELOCITY_THRESHOLD)) &&
317         (!NearEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight)))) {
318         if (GreatNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
319             if (NearZero(downHeight)) {
320                 SheetInteractiveDismiss(true, std::abs(dragVelocity));
321             } else {
322                 ChangeSheetHeight(downHeight);
323                 ChangeScrollHeight(height_);
324                 SheetTransition(true, std::abs(dragVelocity));
325             }
326         } else if (LessNotEqual(std::abs(currentSheetHeight - upHeight), std::abs(currentSheetHeight - downHeight))) {
327             ChangeSheetHeight(upHeight);
328             ChangeScrollHeight(height_);
329             ProcessColumnRect(height_);
330             SheetTransition(true, std::abs(dragVelocity));
331         }
332     } else {
333         if (GreatOrEqual(dragVelocity, 0.0f)) {
334             if (NearZero(downHeight)) {
335                 SheetInteractiveDismiss(true, std::abs(dragVelocity));
336             } else {
337                 ChangeSheetHeight(downHeight);
338                 ChangeScrollHeight(height_);
339                 SheetTransition(true, std::abs(dragVelocity));
340             }
341         } else {
342             ChangeSheetHeight(upHeight);
343             if (!NearEqual(upHeight, downHeight)) {
344                 ChangeScrollHeight(height_);
345                 ProcessColumnRect(height_);
346             }
347             SheetTransition(true, std::abs(dragVelocity));
348         }
349     }
350 }
351 
OnCoordScrollStart()352 void SheetPresentationPattern::OnCoordScrollStart()
353 {
354     if (animation_ && isAnimationProcess_) {
355         AnimationUtils::StopAnimation(animation_);
356         isAnimationBreak_ = true;
357     }
358     currentOffset_ = 0.0f;
359 }
360 
OnCoordScrollUpdate(float scrollOffset)361 bool SheetPresentationPattern::OnCoordScrollUpdate(float scrollOffset)
362 {
363     if (!GetShowState() || !IsScrollable()) {
364         return false;
365     }
366 
367     auto sheetType = GetSheetType();
368     auto sheetDetentsSize = sheetDetentHeight_.size();
369     if ((sheetType == SheetType::SHEET_POPUP) || (sheetDetentsSize == 0)) {
370         return false;
371     }
372 
373     if ((NearZero(currentOffset_)) && (LessNotEqual(scrollOffset, 0.0f)) &&
374         (GreatOrEqual(height_, sheetDetentHeight_[sheetDetentsSize - 1]))) {
375         return false;
376     }
377     auto host = GetHost();
378     CHECK_NULL_RETURN(host, false);
379     currentOffset_ = currentOffset_ + scrollOffset;
380     auto offset = pageHeight_ - height_ + currentOffset_;
381     if (offset <= (pageHeight_ - sheetMaxHeight_)) {
382         offset = pageHeight_ - sheetMaxHeight_;
383         currentOffset_ = height_ - sheetMaxHeight_;
384     }
385     ProcessColumnRect(height_ - currentOffset_);
386     auto renderContext = host->GetRenderContext();
387     renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
388     return true;
389 }
390 
OnCoordScrollEnd(float dragVelocity)391 void SheetPresentationPattern::OnCoordScrollEnd(float dragVelocity)
392 {
393     HandleDragEnd(dragVelocity);
394 }
InitialLayoutProps()395 void SheetPresentationPattern::InitialLayoutProps()
396 {
397     CheckSheetHeightChange();
398     InitSheetDetents();
399 }
400 
InitialSingleGearHeight(NG::SheetStyle & sheetStyle)401 float SheetPresentationPattern::InitialSingleGearHeight(NG::SheetStyle& sheetStyle)
402 {
403     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
404     float sheetHeight = largeHeight;
405     auto sheetNode = GetHost();
406     CHECK_NULL_RETURN(sheetNode, sheetHeight);
407     if (sheetStyle.sheetMode.has_value()) {
408         if (sheetStyle.sheetMode == SheetMode::MEDIUM) {
409             sheetHeight = pageHeight_ * MEDIUM_SIZE;
410             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
411                 sheetHeight = pageHeight_ * MEDIUM_SIZE_PRE;
412             }
413         } else if (sheetStyle.sheetMode == SheetMode::LARGE) {
414             sheetHeight = largeHeight;
415         } else if (sheetStyle.sheetMode == SheetMode::AUTO) {
416             sheetHeight = GetFitContentHeight();
417             if (sheetHeight > largeHeight) {
418                 sheetHeight = largeHeight;
419             }
420             HandleFitContontChange(sheetHeight);
421         }
422     } else {
423         float height = 0.0f;
424         if (sheetStyle.height->Unit() == DimensionUnit::PERCENT) {
425             height = sheetStyle.height->ConvertToPxWithSize(sheetMaxHeight_);
426         } else {
427             height = sheetStyle.height->ConvertToPx();
428         }
429         if (GreatNotEqual(height, largeHeight)) {
430             sheetHeight = largeHeight;
431         } else if (LessNotEqual(height, 0)) {
432             sheetHeight = largeHeight;
433         } else {
434             sheetHeight = height;
435         }
436     }
437     return sheetHeight;
438 }
439 
AvoidSafeArea()440 void SheetPresentationPattern::AvoidSafeArea()
441 {
442     auto host = GetHost();
443     CHECK_NULL_VOID(host);
444     auto pipelineContext = PipelineContext::GetCurrentContext();
445     CHECK_NULL_VOID(pipelineContext);
446     auto manager = pipelineContext->GetSafeAreaManager();
447     if (keyboardHeight_ == manager->GetKeyboardInset().Length()) {
448         return;
449     }
450     keyboardHeight_ = manager->GetKeyboardInset().Length();
451     CHECK_NULL_VOID(host->GetFocusHub()->IsCurrentFocus());
452     auto heightUp = GetSheetHeightChange();
453     auto offset = pageHeight_ - height_ - heightUp;
454     auto renderContext = host->GetRenderContext();
455     if (isScrolling_) {
456         // if scrolling and keyboard will down, scroll needs to reset.
457         if (NearZero(heightUp)) {
458             ScrollTo(-scrollHeight_);
459             renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
460         } else {
461             // Otherwise, sheet is necessary to raise and trigger scroll scrolling
462             // sheet is raised to the top first
463             renderContext->UpdateTransformTranslate(
464                 { 0.0f, pageHeight_ - sheetHeight_ + SHEET_BLANK_MINI_HEIGHT.ConvertToPx() + statusBarHeight_, 0.0f });
465             // Then adjust the remaining height(heightUp = h - maxH) difference by scrolling
466             ScrollTo(heightUp);
467         }
468     } else {
469         // offset: translate endpoint, calculated from top
470         renderContext->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
471     }
472 }
473 
GetSheetHeightChange()474 float SheetPresentationPattern::GetSheetHeightChange()
475 {
476     auto pipelineContext = PipelineContext::GetCurrentContext();
477     CHECK_NULL_RETURN(pipelineContext, .0f);
478     auto manager = pipelineContext->GetSafeAreaManager();
479     auto keyboardInsert = manager->GetKeyboardInset();
480     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipelineContext->GetTextFieldManager());
481     // inputH : Distance from input component's Caret to bottom of screen
482     // = caret's offset + caret's height + 24vp
483     auto inputH = textFieldManager ? (pipelineContext->GetRootHeight() - textFieldManager->GetClickPosition().GetY() -
484                                          textFieldManager->GetHeight())
485                                    : .0;
486     // keyboardH : keyboard height + height of the bottom navigation bar
487     auto keyboardH = keyboardInsert.Length() + manager->GetSystemSafeArea().bottom_.Length();
488     // The minimum height of the input component from the bottom of the screen after popping up the soft keyboard
489     auto inputMinH = keyboardH;
490     // maxH : height that the sheet can reach the stage = the LARGE sheet - Current sheet height
491     auto sheetHeight = GetHost()->GetGeometryNode()->GetFrameSize().Height();
492     auto largeHeight = sheetHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - statusBarHeight_;
493     auto maxH = largeHeight - height_;
494     if (inputH >= inputMinH) {
495         // sheet needs not up
496         return .0f;
497     }
498     // The expected height of the sheet to be lifted
499     auto h = inputMinH - inputH;
500     if (h <= maxH) {
501         // sheet is lifted up with h
502         return h;
503     }
504     // h > maxH, sheet goes up to the LARGE, then adjust the remaining height(h - maxH) difference by scrolling
505     isScrolling_ = true;
506     return h - maxH;
507 }
508 
SheetTransition(bool isTransitionIn,float dragVelocity)509 void SheetPresentationPattern::SheetTransition(bool isTransitionIn, float dragVelocity)
510 {
511     auto host = GetHost();
512     CHECK_NULL_VOID(host);
513     auto context = host->GetRenderContext();
514     CHECK_NULL_VOID(context);
515     AnimationOption option;
516     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(
517         dragVelocity / SHEET_VELOCITY_THRESHOLD, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
518     option.SetCurve(curve);
519     option.SetFillMode(FillMode::FORWARDS);
520     auto offset = pageHeight_ - height_;
521     if (!isTransitionIn) {
522         auto pipelineContext = PipelineContext::GetCurrentContext();
523         CHECK_NULL_VOID(pipelineContext);
524         auto overlayManager = pipelineContext->GetOverlayManager();
525         CHECK_NULL_VOID(overlayManager);
526         auto maskNode = overlayManager->GetSheetMask(host);
527         if (maskNode) {
528             overlayManager->PlaySheetMaskTransition(maskNode, false);
529         }
530     }
531     option.SetOnFinishEvent([weak = AceType::WeakClaim(this), isTransitionIn]() {
532         auto pattern = weak.Upgrade();
533         CHECK_NULL_VOID(pattern);
534         if (isTransitionIn) {
535             if (!pattern->GetAnimationBreak()) {
536                 pattern->SetCurrentOffset(0.0f);
537                 pattern->ProcessColumnRect(pattern->height_);
538                 pattern->ChangeScrollHeight(pattern->height_);
539                 pattern->SetAnimationProcess(false);
540             } else {
541                 pattern->isAnimationBreak_ = false;
542             }
543         } else {
544             pattern->SetAnimationProcess(false);
545             auto context = PipelineContext::GetCurrentContext();
546             CHECK_NULL_VOID(context);
547             auto overlayManager = context->GetOverlayManager();
548             CHECK_NULL_VOID(overlayManager);
549             auto host = pattern->GetHost();
550             CHECK_NULL_VOID(host);
551             overlayManager->DestroySheet(host, pattern->GetTargetId());
552             pattern->FireCallback("false");
553         }
554     });
555     StartSheetTransitionAnimation(option, isTransitionIn, offset);
556 }
557 
SheetInteractiveDismiss(bool isDragClose,float dragVelocity)558 void SheetPresentationPattern::SheetInteractiveDismiss(bool isDragClose, float dragVelocity)
559 {
560     if (hasShouldDismiss()) {
561         auto pipeline = PipelineContext::GetCurrentContext();
562         CHECK_NULL_VOID(pipeline);
563         auto overlayManager = pipeline->GetOverlayManager();
564         CHECK_NULL_VOID(overlayManager);
565         overlayManager->SetDismissTargetId(targetId_);
566         if (isDragClose) {
567             ProcessColumnRect(height_);
568             SheetTransition(true);
569         }
570         CallShouldDismiss();
571     } else {
572         DismissTransition(false, dragVelocity);
573     }
574 }
575 
DismissTransition(bool isTransitionIn,float dragVelocity)576 void SheetPresentationPattern::DismissTransition(bool isTransitionIn, float dragVelocity)
577 {
578     auto pipeline = PipelineContext::GetCurrentContext();
579     CHECK_NULL_VOID(pipeline);
580     auto overlayManager = pipeline->GetOverlayManager();
581     CHECK_NULL_VOID(overlayManager);
582     overlayManager->ModalPageLostFocus(GetHost());
583 
584     auto sheetType = GetSheetType();
585     if (sheetType == SheetType::SHEET_POPUP) {
586         BubbleStyleSheetTransition(isTransitionIn);
587     } else {
588         SheetTransition(isTransitionIn, dragVelocity);
589     }
590 }
591 
ChangeScrollHeight(float height)592 void SheetPresentationPattern::ChangeScrollHeight(float height)
593 {
594     auto host = GetHost();
595     CHECK_NULL_VOID(host);
596     auto geometryNode = host->GetGeometryNode();
597     CHECK_NULL_VOID(geometryNode);
598     auto operationNode = DynamicCast<FrameNode>(host->GetChildAtIndex(0));
599     CHECK_NULL_VOID(operationNode);
600     auto perationGeometryNode = operationNode->GetGeometryNode();
601     CHECK_NULL_VOID(perationGeometryNode);
602     auto operationHeight = perationGeometryNode->GetFrameSize().Height();
603     auto scrollNode = DynamicCast<FrameNode>(host->GetChildAtIndex(1));
604     CHECK_NULL_VOID(scrollNode);
605     auto scrollProps = scrollNode->GetLayoutProperty<ScrollLayoutProperty>();
606     CHECK_NULL_VOID(scrollProps);
607     auto scrollHeight = height - operationHeight;
608     auto sheetType = GetSheetType();
609     if ((sheetType == SheetType::SHEET_POPUP) || (sheetType == SheetType::SHEET_CENTER)) {
610         auto sheetHeight = geometryNode->GetFrameSize().Height();
611         scrollHeight = sheetHeight - operationHeight;
612     }
613     scrollProps->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(scrollHeight)));
614     scrollNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
615 }
616 
UpdateDragBarStatus()617 void SheetPresentationPattern::UpdateDragBarStatus()
618 {
619     auto host = GetHost();
620     CHECK_NULL_VOID(host);
621     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
622     CHECK_NULL_VOID(layoutProperty);
623     auto sheetStyle = layoutProperty->GetSheetStyleValue();
624     auto showDragIndicator = sheetStyle.showDragBar.value_or(true);
625 
626     auto titleColumn = DynamicCast<FrameNode>(host->GetFirstChild());
627     CHECK_NULL_VOID(titleColumn);
628     auto sheetDragBar = DynamicCast<FrameNode>(titleColumn->GetFirstChild());
629     CHECK_NULL_VOID(sheetDragBar);
630     auto dragBarLayoutProperty = sheetDragBar->GetLayoutProperty();
631     CHECK_NULL_VOID(dragBarLayoutProperty);
632     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
633         dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
634         sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
635         return;
636     }
637     auto sheetType = GetSheetType();
638     if (((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOM_FREE_WINDOW)) &&
639         (sheetDetentHeight_.size() > 1)) {
640         if (sheetStyle.isTitleBuilder.has_value()) {
641             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
642         } else {
643             dragBarLayoutProperty->UpdateVisibility(showDragIndicator ? VisibleType::VISIBLE : VisibleType::GONE);
644         }
645     } else {
646         if (sheetStyle.isTitleBuilder.has_value()) {
647             dragBarLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
648         } else {
649             dragBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
650         }
651     }
652     sheetDragBar->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
653 }
654 
UpdateCloseIconStatus()655 void SheetPresentationPattern::UpdateCloseIconStatus()
656 {
657     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
658         return;
659     }
660     auto host = GetHost();
661     CHECK_NULL_VOID(host);
662     auto pipeline = PipelineContext::GetCurrentContext();
663     CHECK_NULL_VOID(pipeline);
664     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
665     CHECK_NULL_VOID(sheetTheme);
666     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
667     CHECK_NULL_VOID(layoutProperty);
668     auto sheetStyle = layoutProperty->GetSheetStyleValue();
669     auto showCloseIcon = layoutProperty->GetSheetStyleValue().showCloseIcon.value_or(true);
670     auto sheetCloseIcon = DynamicCast<FrameNode>(host->GetChildAtIndex(2));
671     CHECK_NULL_VOID(sheetCloseIcon);
672     auto geometryNode = host->GetGeometryNode();
673     CHECK_NULL_VOID(geometryNode);
674     auto size = geometryNode->GetFrameSize();
675     auto closeIconX = size.Width() - static_cast<float>(SHEET_CLOSE_ICON_WIDTH.ConvertToPx()) -
676                       static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
677     auto closeIconY = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
678     OffsetT<Dimension> positionOffset;
679     positionOffset.SetX(Dimension(closeIconX));
680     auto sheetType = GetSheetType();
681     if (sheetType == SheetType::SHEET_POPUP) {
682         positionOffset.SetY(Dimension(closeIconY) + SHEET_ARROW_HEIGHT);
683     } else {
684         positionOffset.SetY(Dimension(closeIconY));
685     }
686     auto renderContext = sheetCloseIcon->GetRenderContext();
687     CHECK_NULL_VOID(renderContext);
688     renderContext->UpdatePosition(positionOffset);
689     auto iconLayoutProperty = sheetCloseIcon->GetLayoutProperty();
690     CHECK_NULL_VOID(iconLayoutProperty);
691     iconLayoutProperty->UpdateVisibility(showCloseIcon ? VisibleType::VISIBLE : VisibleType::INVISIBLE);
692     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
693 }
694 
UpdateSheetTitle()695 void SheetPresentationPattern::UpdateSheetTitle()
696 {
697     auto host = GetHost();
698     CHECK_NULL_VOID(host);
699     auto layoutProperty = DynamicCast<SheetPresentationProperty>(host->GetLayoutProperty());
700     CHECK_NULL_VOID(layoutProperty);
701     auto sheetStyle = layoutProperty->GetSheetStyleValue();
702     if (sheetStyle.sheetTitle.has_value()) {
703         auto titleId = GetTitleId();
704         auto titleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(titleId));
705         CHECK_NULL_VOID(titleNode);
706         auto titleProp = titleNode->GetLayoutProperty<TextLayoutProperty>();
707         CHECK_NULL_VOID(titleProp);
708         titleProp->UpdateContent(sheetStyle.sheetTitle.value());
709         titleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
710         if (sheetStyle.sheetSubtitle.has_value()) {
711             auto subtitleId = GetSubtitleId();
712             auto subtitleNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetNodeById(subtitleId));
713             CHECK_NULL_VOID(subtitleNode);
714             auto subtitleProp = subtitleNode->GetLayoutProperty<TextLayoutProperty>();
715             CHECK_NULL_VOID(subtitleProp);
716             subtitleProp->UpdateContent(sheetStyle.sheetSubtitle.value());
717             subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
718         }
719     }
720 }
721 
UpdateInteractive()722 void SheetPresentationPattern::UpdateInteractive()
723 {
724     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
725         return;
726     }
727     auto host = GetHost();
728     CHECK_NULL_VOID(host);
729     auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
730     CHECK_NULL_VOID(layoutProperty);
731     auto sheetStyle = layoutProperty->GetSheetStyleValue();
732     auto pipelineContext = PipelineContext::GetCurrentContext();
733     CHECK_NULL_VOID(pipelineContext);
734     auto overlayManager = pipelineContext->GetOverlayManager();
735     CHECK_NULL_VOID(overlayManager);
736     auto maskNode = overlayManager->GetSheetMask(host);
737     CHECK_NULL_VOID(maskNode);
738     if (!sheetStyle.interactive.has_value()) {
739         if (GetSheetType() == SheetType::SHEET_POPUP) {
740             maskNode->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
741         } else {
742             maskNode->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
743         }
744     } else {
745         if (sheetStyle.interactive == true) {
746             maskNode->GetLayoutProperty()->UpdateVisibility(VisibleType::INVISIBLE);
747         } else {
748             maskNode->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
749         }
750     }
751     maskNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
752 }
753 
OnColorConfigurationUpdate()754 void SheetPresentationPattern::OnColorConfigurationUpdate()
755 {
756     auto host = GetHost();
757     CHECK_NULL_VOID(host);
758     auto pipeline = PipelineContext::GetCurrentContext();
759     CHECK_NULL_VOID(pipeline);
760     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
761     CHECK_NULL_VOID(sheetTheme);
762     auto sheetCloseIcon = DynamicCast<FrameNode>(host->GetChildAtIndex(2));
763     CHECK_NULL_VOID(sheetCloseIcon);
764     auto renderContext = sheetCloseIcon->GetRenderContext();
765     CHECK_NULL_VOID(renderContext);
766     renderContext->UpdateBackgroundColor(sheetTheme->GetCloseIconColor());
767     sheetCloseIcon->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
768     auto imageNode = DynamicCast<FrameNode>(sheetCloseIcon->GetChildAtIndex(0));
769     CHECK_NULL_VOID(imageNode);
770     auto imagePaintProperty = imageNode->GetPaintProperty<ImageRenderProperty>();
771     CHECK_NULL_VOID(imagePaintProperty);
772     imagePaintProperty->UpdateSvgFillColor(sheetTheme->GetCloseIconImageColor());
773     imageNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
774 }
775 
CheckSheetHeightChange()776 void SheetPresentationPattern::CheckSheetHeightChange()
777 {
778     auto host = GetHost();
779     CHECK_NULL_VOID(host);
780     auto sheetGeometryNode = host->GetGeometryNode();
781     CHECK_NULL_VOID(sheetGeometryNode);
782     if (isFirstInit_) {
783         sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
784         sheetType_ = GetSheetType();
785         isFirstInit_ = false;
786     } else {
787         if ((!NearEqual(sheetGeometryNode->GetFrameSize().Height(), sheetHeight_)) || (sheetType_ != GetSheetType()) ||
788             windowChanged_) {
789             sheetType_ = GetSheetType();
790             sheetHeight_ = sheetGeometryNode->GetFrameSize().Height();
791             auto pipelineContext = PipelineContext::GetCurrentContext();
792             CHECK_NULL_VOID(pipelineContext);
793             auto overlayManager = pipelineContext->GetOverlayManager();
794             CHECK_NULL_VOID(overlayManager);
795             auto layoutProperty = host->GetLayoutProperty<SheetPresentationProperty>();
796             CHECK_NULL_VOID(layoutProperty);
797             auto sheetStyle = layoutProperty->GetSheetStyleValue();
798             overlayManager->ComputeSheetOffset(sheetStyle, host);
799             if (sheetType_ == SheetType::SHEET_POPUP) {
800                 auto renderContext = GetRenderContext();
801                 CHECK_NULL_VOID(renderContext);
802                 renderContext->OnTransformTranslateUpdate({ 0.0f, Dimension(sheetOffsetY_), 0.0f });
803                 renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
804             }
805             overlayManager->PlaySheetTransition(host, true, false, true);
806             windowChanged_ = false;
807         }
808     }
809 }
810 
InitSheetDetents()811 void SheetPresentationPattern::InitSheetDetents()
812 {
813     sheetDetentHeight_.clear();
814     float height = 0.0f;
815     auto sheetNode = GetHost();
816     CHECK_NULL_VOID(sheetNode);
817     auto geometryNode = sheetNode->GetGeometryNode();
818     CHECK_NULL_VOID(geometryNode);
819     auto largeHeight = sheetMaxHeight_ - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
820     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
821     CHECK_NULL_VOID(layoutProperty);
822     auto sheetStyle = layoutProperty->GetSheetStyleValue();
823     auto sheetType = GetSheetType();
824     auto sheetFrameHeight = geometryNode->GetFrameSize().Height();
825     auto mediumSize = MEDIUM_SIZE;
826     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
827         mediumSize = MEDIUM_SIZE_PRE;
828     }
829     switch (sheetType) {
830         case SheetType::SHEET_BOTTOM:
831         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
832             if (sheetStyle.detents.size() <= 0) {
833                 height = InitialSingleGearHeight(sheetStyle);
834                 sheetDetentHeight_.emplace_back(height);
835                 break;
836             }
837             for (auto iter : sheetStyle.detents) {
838                 if (iter.sheetMode.has_value()) {
839                     if (iter.sheetMode == SheetMode::MEDIUM) {
840                         height = pageHeight_ * mediumSize;
841                     } else if (iter.sheetMode == SheetMode::LARGE) {
842                         height = largeHeight;
843                     } else if (iter.sheetMode == SheetMode::AUTO) {
844                         height = GetFitContentHeight();
845                         height = GreatNotEqual(height, largeHeight) ? largeHeight : height;
846                         HandleFitContontChange(height);
847                     }
848                 } else {
849                     if (iter.height->Unit() == DimensionUnit::PERCENT) {
850                         height = iter.height->ConvertToPxWithSize(sheetMaxHeight_);
851                     } else {
852                         height = iter.height->ConvertToPx();
853                     }
854                     if (GreatNotEqual(height, largeHeight)) {
855                         height = largeHeight;
856                     } else if (LessNotEqual(height, 0)) {
857                         height = largeHeight;
858                     }
859                 }
860                 sheetDetentHeight_.emplace_back(height);
861             }
862             std::sort(sheetDetentHeight_.begin(), sheetDetentHeight_.end(), std::less<float>());
863             sheetDetentHeight_.erase(std::unique(sheetDetentHeight_.begin(), sheetDetentHeight_.end()),
864                 sheetDetentHeight_.end());
865             break;
866         case SheetType::SHEET_BOTTOMLANDSPACE:
867             height = sheetFrameHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
868             sheetDetentHeight_.emplace_back(height);
869             break;
870         case SheetType::SHEET_CENTER:
871             height = (centerHeight_ + pageHeight_) / SHEET_HALF_HEIGHT;
872             sheetDetentHeight_.emplace_back(height);
873             break;
874         default:
875             break;
876     }
877 }
878 
HandleFitContontChange(float height)879 void SheetPresentationPattern::HandleFitContontChange(float height)
880 {
881     if ((NearEqual(height_, sheetFitContentHeight_)) && (!NearEqual(height, sheetFitContentHeight_))) {
882         ChangeSheetHeight(height);
883         ProcessColumnRect(height_);
884         ChangeScrollHeight(height_);
885         SheetTransition(true);
886     }
887     sheetFitContentHeight_ = height;
888 }
889 
GetSheetType()890 SheetType SheetPresentationPattern::GetSheetType()
891 {
892     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
893         return SHEET_BOTTOM;
894     }
895     SheetType sheetType = SheetType::SHEET_BOTTOM;
896     auto rootHeight = PipelineContext::GetCurrentRootHeight();
897     auto rootWidth = PipelineContext::GetCurrentRootWidth();
898     auto pipelineContext = PipelineContext::GetCurrentContext();
899     CHECK_NULL_RETURN(pipelineContext, sheetType);
900     auto windowRect = pipelineContext->GetCurrentWindowRect();
901     auto layoutProperty = GetLayoutProperty<SheetPresentationProperty>();
902     CHECK_NULL_RETURN(layoutProperty, sheetType);
903     auto sheetStyle = layoutProperty->GetSheetStyleValue();
904     if (sheetThemeType_ == "auto") {
905         if (IsFold()) {
906             sheetType = SheetType::SHEET_CENTER;
907         } else {
908             if (rootHeight < rootWidth) {
909                 sheetType = SheetType::SHEET_BOTTOMLANDSPACE;
910             } else {
911                 sheetType = SheetType::SHEET_BOTTOM;
912             }
913         }
914     } else if (sheetThemeType_ == "popup") {
915         if (windowRect.Width() >= SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) {
916             if (sheetStyle.sheetType.has_value()) {
917                 sheetType = sheetStyle.sheetType.value();
918             } else {
919                 sheetType = SheetType::SHEET_POPUP;
920             }
921         } else if ((windowRect.Width() >= SHEET_DEVICE_WIDTH_BREAKPOINT.ConvertToPx()) &&
922                    (windowRect.Width() < SHEET_PC_DEVICE_WIDTH_BREAKPOINT.ConvertToPx())) {
923             if (sheetStyle.sheetType.has_value()) {
924                 sheetType = sheetStyle.sheetType.value();
925             } else {
926                 sheetType = SheetType::SHEET_CENTER;
927             }
928         } else {
929             sheetType = SheetType::SHEET_BOTTOM_FREE_WINDOW;
930         }
931     }
932     return sheetType;
933 }
934 
BubbleStyleSheetTransition(bool isTransitionIn)935 void SheetPresentationPattern::BubbleStyleSheetTransition(bool isTransitionIn)
936 {
937     auto host = this->GetHost();
938     CHECK_NULL_VOID(host);
939     if (!isTransitionIn) {
940         auto pipelineContext = PipelineContext::GetCurrentContext();
941         CHECK_NULL_VOID(pipelineContext);
942         auto overlayManager = pipelineContext->GetOverlayManager();
943         CHECK_NULL_VOID(overlayManager);
944         auto maskNode = overlayManager->GetSheetMask(host);
945         if (maskNode) {
946             overlayManager->PlaySheetMaskTransition(maskNode, false);
947         }
948         StartOffsetExitingAnimation();
949         StartAlphaExitingAnimation(
950             [weakNode = AceType::WeakClaim(AceType::RawPtr(host)), weakPattern = AceType::WeakClaim(this)]() {
951                 auto node = weakNode.Upgrade();
952                 CHECK_NULL_VOID(node);
953                 auto pattern = weakPattern.Upgrade();
954                 CHECK_NULL_VOID(pattern);
955                 auto context = PipelineContext::GetCurrentContext();
956                 CHECK_NULL_VOID(context);
957                 auto overlayManager = context->GetOverlayManager();
958                 CHECK_NULL_VOID(overlayManager);
959                 overlayManager->DestroySheet(node, pattern->GetTargetId());
960                 pattern->FireCallback("false");
961             });
962     }
963 }
964 
StartOffsetEnteringAnimation()965 void SheetPresentationPattern::StartOffsetEnteringAnimation()
966 {
967     AnimationOption optionPosition;
968     optionPosition.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
969     optionPosition.SetCurve(Curves::FRICTION);
970     AnimationUtils::Animate(
971         optionPosition,
972         [weak = WeakClaim(this)]() {
973             auto pattern = weak.Upgrade();
974             CHECK_NULL_VOID(pattern);
975             auto renderContext = pattern->GetRenderContext();
976             CHECK_NULL_VOID(renderContext);
977             renderContext->OnTransformTranslateUpdate({ 0.0f, Dimension(pattern->sheetOffsetY_), 0.0f });
978         },
979         nullptr);
980 }
981 
StartAlphaEnteringAnimation(std::function<void ()> finish)982 void SheetPresentationPattern::StartAlphaEnteringAnimation(std::function<void()> finish)
983 {
984     AnimationOption optionAlpha;
985     optionAlpha.SetDuration(SHEET_ENTRY_ANIMATION_DURATION);
986     optionAlpha.SetCurve(Curves::SHARP);
987     AnimationUtils::Animate(
988         optionAlpha,
989         [weak = WeakClaim(this)]() {
990             auto pattern = weak.Upgrade();
991             CHECK_NULL_VOID(pattern);
992             auto renderContext = pattern->GetRenderContext();
993             CHECK_NULL_VOID(renderContext);
994             renderContext->UpdateOpacity(SHEET_VISIABLE_ALPHA);
995         },
996         finish);
997 }
998 
StartOffsetExitingAnimation()999 void SheetPresentationPattern::StartOffsetExitingAnimation()
1000 {
1001     AnimationOption optionPosition;
1002     optionPosition.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
1003     optionPosition.SetCurve(Curves::FRICTION);
1004     AnimationUtils::Animate(
1005         optionPosition,
1006         [weak = WeakClaim(this)]() {
1007             auto pattern = weak.Upgrade();
1008             CHECK_NULL_VOID(pattern);
1009             auto renderContext = pattern->GetRenderContext();
1010             CHECK_NULL_VOID(renderContext);
1011             renderContext->OnTransformTranslateUpdate(
1012                 { 0.0f, Dimension(pattern->sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
1013         },
1014         nullptr);
1015 }
1016 
StartAlphaExitingAnimation(std::function<void ()> finish)1017 void SheetPresentationPattern::StartAlphaExitingAnimation(std::function<void()> finish)
1018 {
1019     AnimationOption optionAlpha;
1020     optionAlpha.SetDuration(SHEET_EXIT_ANIMATION_DURATION);
1021     optionAlpha.SetCurve(Curves::SHARP);
1022     AnimationUtils::Animate(
1023         optionAlpha,
1024         [weak = WeakClaim(this)]() {
1025             auto pattern = weak.Upgrade();
1026             CHECK_NULL_VOID(pattern);
1027             auto renderContext = pattern->GetRenderContext();
1028             CHECK_NULL_VOID(renderContext);
1029             renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
1030         },
1031         finish);
1032 }
1033 
GetRenderContext()1034 RefPtr<RenderContext> SheetPresentationPattern::GetRenderContext()
1035 {
1036     auto frameNode = GetHost();
1037     CHECK_NULL_RETURN(frameNode, nullptr);
1038     return frameNode->GetRenderContext();
1039 }
1040 
PostTask(const TaskExecutor::Task & task)1041 bool SheetPresentationPattern::PostTask(const TaskExecutor::Task& task)
1042 {
1043     auto pipeline = PipelineBase::GetCurrentContext();
1044     CHECK_NULL_RETURN(pipeline, false);
1045     auto taskExecutor = pipeline->GetTaskExecutor();
1046     CHECK_NULL_RETURN(taskExecutor, false);
1047     return taskExecutor->PostTask(task, TaskExecutor::TaskType::UI);
1048 }
1049 
ResetToInvisible()1050 void SheetPresentationPattern::ResetToInvisible()
1051 {
1052     auto renderContext = GetRenderContext();
1053     CHECK_NULL_VOID(renderContext);
1054     renderContext->UpdateOpacity(SHEET_INVISIABLE_ALPHA);
1055     renderContext->OnTransformTranslateUpdate({ 0.0f, Dimension(sheetOffsetY_ - SHEET_INVISIABLE_OFFSET), 0.0f });
1056 }
1057 
IsFold()1058 bool SheetPresentationPattern::IsFold()
1059 {
1060     auto containerId = Container::CurrentId();
1061     auto foldWindow = FoldableWindow::CreateFoldableWindow(containerId);
1062     CHECK_NULL_RETURN(foldWindow, false);
1063     if (foldWindow->IsFoldExpand()) {
1064         return true;
1065     } else {
1066         return false;
1067     }
1068 }
1069 
ChangeSheetHeight(float height)1070 void SheetPresentationPattern::ChangeSheetHeight(float height)
1071 {
1072     if (!NearEqual(height_, height)) {
1073         height_ = height;
1074         SetCurrentHeightToOverlay(height_);
1075     }
1076 }
1077 
StartSheetTransitionAnimation(const AnimationOption & option,bool isTransitionIn,float offset)1078 void SheetPresentationPattern::StartSheetTransitionAnimation(
1079     const AnimationOption& option, bool isTransitionIn, float offset)
1080 {
1081     auto host = GetHost();
1082     CHECK_NULL_VOID(host);
1083     auto context = host->GetRenderContext();
1084     CHECK_NULL_VOID(context);
1085     isAnimationProcess_ = true;
1086     if (isTransitionIn) {
1087         animation_ = AnimationUtils::StartAnimation(
1088             option,
1089             [context, offset]() {
1090                 if (context) {
1091                     context->OnTransformTranslateUpdate({ 0.0f, offset, 0.0f });
1092                 }
1093             },
1094             option.GetOnFinishEvent());
1095     } else {
1096         animation_ = AnimationUtils::StartAnimation(
1097             option,
1098             [context, this]() {
1099                 if (context) {
1100                     context->OnTransformTranslateUpdate({ 0.0f, pageHeight_, 0.0f });
1101                 }
1102             },
1103             option.GetOnFinishEvent());
1104     }
1105 }
1106 
ClipSheetNode()1107 void SheetPresentationPattern::ClipSheetNode()
1108 {
1109     auto host = GetHost();
1110     CHECK_NULL_VOID(host);
1111     auto geometryNode = host->GetGeometryNode();
1112     CHECK_NULL_VOID(geometryNode);
1113     auto sheetSize = geometryNode->GetFrameSize();
1114     auto pipeline = PipelineContext::GetCurrentContext();
1115     CHECK_NULL_VOID(pipeline);
1116     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
1117     CHECK_NULL_VOID(sheetTheme);
1118     auto sheetRadius = sheetTheme->GetSheetRadius();
1119     auto renderContext = host->GetRenderContext();
1120     CHECK_NULL_VOID(renderContext);
1121     auto sheetType = GetSheetType();
1122     std::string clipPath;
1123     if (sheetType == SheetType::SHEET_POPUP) {
1124         clipPath = GetPopupStyleSheetClipPath(sheetSize, sheetRadius);
1125     } else if (sheetType == SheetType::SHEET_CENTER) {
1126         clipPath = GetCenterStyleSheetClipPath(sheetSize, sheetRadius);
1127     } else {
1128         clipPath = GetBottomStyleSheetClipPath(sheetSize, sheetRadius);
1129     }
1130     auto path = AceType::MakeRefPtr<Path>();
1131     path->SetValue(clipPath);
1132     path->SetBasicShapeType(BasicShapeType::PATH);
1133     renderContext->UpdateClipShape(path);
1134 }
1135 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)1136 void SheetPresentationPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
1137 {
1138     auto sheetType = GetSheetType();
1139     if ((type == WindowSizeChangeReason::ROTATION) &&
1140         ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOMLANDSPACE))) {
1141         windowRotate_ = true;
1142         firstMeasure_ = true;
1143         SetColumnMinSize(true);
1144         // Before rotation, reset to the initial mode sheet ratio of the current vertical or horizontal screen
1145         // It's actually a state where the soft keyboard is not pulled up
1146         if (isScrolling_) {
1147             ScrollTo(-scrollHeight_);
1148         }
1149         TranslateTo(height_);
1150     }
1151     if (type == WindowSizeChangeReason::ROTATION || type == WindowSizeChangeReason::UNDEFINED ||
1152         type == WindowSizeChangeReason::DRAG) {
1153         windowChanged_ = true;
1154     }
1155 }
1156 
TranslateTo(float height)1157 void SheetPresentationPattern::TranslateTo(float height)
1158 {
1159     auto host = GetHost();
1160     CHECK_NULL_VOID(host);
1161     auto context = host->GetRenderContext();
1162     CHECK_NULL_VOID(context);
1163     context->OnTransformTranslateUpdate(
1164         {0.0f, height, 0.0f });
1165 }
1166 
ScrollTo(float height)1167 void SheetPresentationPattern::ScrollTo(float height)
1168 {
1169     auto host = GetHost();
1170     CHECK_NULL_VOID(host);
1171     auto scroll = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1));
1172     CHECK_NULL_VOID(scroll);
1173     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
1174     CHECK_NULL_VOID(scrollPattern);
1175     auto layoutProp = scrollPattern->GetLayoutProperty<ScrollLayoutProperty>();
1176     CHECK_NULL_VOID(layoutProp);
1177     auto geometryNode = scroll->GetGeometryNode();
1178     CHECK_NULL_VOID(geometryNode);
1179     scrollHeight_ = height;
1180     isScrolling_ = height > 0;
1181     layoutProp->UpdateScrollEnabled(isScrolling_);
1182     layoutProp->UpdateUserDefinedIdealSize(CalcSize(
1183         CalcLength(geometryNode->GetFrameSize().Width()), CalcLength(geometryNode->GetFrameSize().Height() - height)));
1184     scrollPattern->JumpToPosition(-height);
1185     scroll->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1186 }
1187 
SetColumnMinSize(bool reset)1188 void SheetPresentationPattern::SetColumnMinSize(bool reset)
1189 {
1190     if (!firstMeasure_) {
1191         return;
1192     }
1193     auto host = GetHost();
1194     CHECK_NULL_VOID(host);
1195     auto scroll = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1));
1196     CHECK_NULL_VOID(scroll);
1197     auto buildContent = AceType::DynamicCast<FrameNode>(scroll->GetChildAtIndex(0));
1198     CHECK_NULL_VOID(buildContent);
1199     auto geometryNode = buildContent->GetGeometryNode();
1200     CHECK_NULL_VOID(geometryNode);
1201     auto props = buildContent->GetLayoutProperty<LayoutProperty>();
1202     CHECK_NULL_VOID(props);
1203     if (reset) {
1204         props->ResetCalcMinSize();
1205         return;
1206     }
1207     props->UpdateCalcMinSize(
1208         CalcSize(CalcLength(geometryNode->GetFrameSize().Width()), CalcLength(geometryNode->GetFrameSize().Height())));
1209     firstMeasure_ = false;
1210 }
1211 
GetPopupStyleSheetClipPath(SizeF sheetSize,Dimension sheetRadius)1212 std::string SheetPresentationPattern::GetPopupStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
1213 {
1214     float half = 0.5f;
1215     std::string path = MoveTo(0.0f, SHEET_ARROW_HEIGHT.ConvertToPx() + sheetRadius.ConvertToPx());
1216     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(),
1217         SHEET_ARROW_HEIGHT.ConvertToPx());
1218     path += LineTo(sheetSize.Width() * half - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(),
1219         SHEET_ARROW_HEIGHT.ConvertToPx()); // P1
1220     path += LineTo(sheetSize.Width() * half - ARROW_VERTICAL_P2_OFFSET_X.ConvertToPx(),
1221         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P2_OFFSET_Y.ConvertToPx()); // P2
1222     path += ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, 0,
1223         sheetSize.Width() * half + ARROW_VERTICAL_P4_OFFSET_X.ConvertToPx(),
1224         SHEET_ARROW_HEIGHT.ConvertToPx() - ARROW_VERTICAL_P4_OFFSET_Y.ConvertToPx()); // P4
1225     path += LineTo(sheetSize.Width() * half + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(),
1226         SHEET_ARROW_HEIGHT.ConvertToPx()); // P5
1227     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), SHEET_ARROW_HEIGHT.ConvertToPx());
1228     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(),
1229         SHEET_ARROW_HEIGHT.ConvertToPx() + sheetRadius.ConvertToPx());
1230     path += LineTo(sheetSize.Width(), sheetSize.Height() - sheetRadius.ConvertToPx());
1231     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0,
1232         sheetSize.Width() - sheetRadius.ConvertToPx(), sheetSize.Height());
1233     path += LineTo(sheetRadius.ConvertToPx(), sheetSize.Height());
1234     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, 0.0f,
1235         sheetSize.Height() - sheetRadius.ConvertToPx());
1236     return path + "Z";
1237 }
1238 
GetCenterStyleSheetClipPath(SizeF sheetSize,Dimension sheetRadius)1239 std::string SheetPresentationPattern::GetCenterStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
1240 {
1241     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
1242     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
1243     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
1244     path += ArcTo(
1245         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
1246     path += LineTo(sheetSize.Width(), sheetSize.Height() - sheetRadius.ConvertToPx());
1247     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0,
1248         sheetSize.Width() - sheetRadius.ConvertToPx(), sheetSize.Height());
1249     path += LineTo(sheetRadius.ConvertToPx(), sheetSize.Height());
1250     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, 0.0f,
1251         sheetSize.Height() - sheetRadius.ConvertToPx());
1252     return path + "Z";
1253 }
1254 
GetBottomStyleSheetClipPath(SizeF sheetSize,Dimension sheetRadius)1255 std::string SheetPresentationPattern::GetBottomStyleSheetClipPath(SizeF sheetSize, Dimension sheetRadius)
1256 {
1257     std::string path = MoveTo(0.0f, sheetRadius.ConvertToPx());
1258     path += ArcTo(sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetRadius.ConvertToPx(), 0.0f);
1259     path += LineTo(sheetSize.Width() - sheetRadius.ConvertToPx(), 0.0f);
1260     path += ArcTo(
1261         sheetRadius.ConvertToPx(), sheetRadius.ConvertToPx(), 0.0f, 0, sheetSize.Width(), sheetRadius.ConvertToPx());
1262     path += LineTo(sheetSize.Width(), sheetSize.Height());
1263     path += LineTo(0.0f, sheetSize.Height());
1264     return path + "Z";
1265 }
1266 
MoveTo(double x,double y)1267 std::string SheetPresentationPattern::MoveTo(double x, double y)
1268 {
1269     return "M" + std::to_string(x) + " " + std::to_string(y) + " ";
1270 }
1271 
LineTo(double x,double y)1272 std::string SheetPresentationPattern::LineTo(double x, double y)
1273 {
1274     return "L" + std::to_string(x) + " " + std::to_string(y) + " ";
1275 }
1276 
ArcTo(double rx,double ry,double rotation,int32_t arc_flag,double x,double y)1277 std::string SheetPresentationPattern::ArcTo(double rx, double ry, double rotation, int32_t arc_flag, double x, double y)
1278 {
1279     int32_t sweep_flag = 1;
1280     return "A" + std::to_string(rx) + " " + std::to_string(ry) + " " + std::to_string(rotation) + " " +
1281            std::to_string(arc_flag) + " " + std::to_string(sweep_flag) + " " + std::to_string(x) + " " +
1282            std::to_string(y) + " ";
1283 }
1284 
GetFitContentHeight()1285 float SheetPresentationPattern::GetFitContentHeight()
1286 {
1287     auto sheetNode = GetHost();
1288     CHECK_NULL_RETURN(sheetNode, 0.0f);
1289     auto titleColumn = DynamicCast<FrameNode>(sheetNode->GetFirstChild());
1290     CHECK_NULL_RETURN(titleColumn, 0.0f);
1291     auto titleGeometryNode = titleColumn->GetGeometryNode();
1292     auto scrollNode = DynamicCast<FrameNode>(sheetNode->GetChildAtIndex(1));
1293     CHECK_NULL_RETURN(scrollNode, 0.0f);
1294     auto builderNode = DynamicCast<FrameNode>(scrollNode->GetChildAtIndex(0));
1295     CHECK_NULL_RETURN(builderNode, 0.0f);
1296     auto builderGeometryNode = builderNode->GetGeometryNode();
1297     return builderGeometryNode->GetFrameSize().Height() + titleGeometryNode->GetFrameSize().Height();
1298 }
1299 
ProcessColumnRect(float height)1300 void SheetPresentationPattern::ProcessColumnRect(float height)
1301 {
1302     auto sheetNode = GetHost();
1303     CHECK_NULL_VOID(sheetNode);
1304     auto column = DynamicCast<FrameNode>(sheetNode->GetParent());
1305     CHECK_NULL_VOID(column);
1306     auto sheetType = GetSheetType();
1307     auto geometryNode = sheetNode->GetGeometryNode();
1308     CHECK_NULL_VOID(geometryNode);
1309     auto sheetSize = geometryNode->GetFrameSize();
1310     float sheetOffsetX = 0.0f;
1311     float sheetOffsetY = 0.0f;
1312     float sheetWidth = 0.0f;
1313     float sheetHeight = 0.0f;
1314     if (sheetType == SheetType::SHEET_POPUP) {
1315         sheetOffsetX = sheetOffsetX_;
1316         sheetWidth = sheetSize.Width();
1317         sheetOffsetY = sheetOffsetY_;
1318         sheetHeight = sheetSize.Height();
1319     } else if (sheetType == SheetType::SHEET_CENTER) {
1320         sheetOffsetX = sheetOffsetX_;
1321         sheetOffsetY = pageHeight_ - height;
1322         sheetWidth = sheetSize.Width();
1323         sheetHeight = sheetSize.Height();
1324     } else if ((sheetType == SheetType::SHEET_BOTTOM) || (sheetType == SheetType::SHEET_BOTTOM_FREE_WINDOW)) {
1325         sheetOffsetY = pageHeight_ - height;
1326         sheetWidth = sheetMaxWidth_;
1327         sheetHeight = height;
1328     } else if (sheetType == SheetType::SHEET_BOTTOMLANDSPACE) {
1329         sheetOffsetX = sheetOffsetX_;
1330         sheetOffsetY = pageHeight_ - height;
1331         sheetWidth = sheetSize.Width();
1332         sheetHeight = height;
1333     }
1334     auto hub = column->GetEventHub<EventHub>();
1335     auto gestureHub = hub->GetOrCreateGestureEventHub();
1336     std::vector<DimensionRect> mouseResponseRegion;
1337     mouseResponseRegion.emplace_back(Dimension(sheetWidth), Dimension(sheetHeight),
1338         DimensionOffset(Dimension(sheetOffsetX), Dimension(sheetOffsetY)));
1339     gestureHub->SetMouseResponseRegion(mouseResponseRegion);
1340     gestureHub->SetResponseRegion(mouseResponseRegion);
1341 }
1342 } // namespace OHOS::Ace::NG
1343