• 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_layout_algorithm.h"
17 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
18 #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h"
19 
20 namespace OHOS::Ace::NG {
21 namespace {
22 constexpr int32_t DOUBLE_SIZE = 2;
23 } // namespace
24 
InitParameter()25 void SheetPresentationLayoutAlgorithm::InitParameter()
26 {
27     auto pipeline = PipelineContext::GetCurrentContext();
28     CHECK_NULL_VOID(pipeline);
29     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
30     CHECK_NULL_VOID(sheetTheme);
31     // if 2in1, enableHoverMode is true by default.
32     auto enableHoverMode = sheetStyle_.enableHoverMode.value_or(sheetTheme->IsOuterBorderEnable() ? true : false);
33     hoverModeArea_ = sheetStyle_.hoverModeArea.value_or(
34         sheetTheme->IsOuterBorderEnable() ? HoverModeAreaType::TOP_SCREEN : HoverModeAreaType::BOTTOM_SCREEN);
35     auto safeAreaManager = pipeline->GetSafeAreaManager();
36     auto keyboardInsert = safeAreaManager->GetKeyboardInset();
37     isKeyBoardShow_ = keyboardInsert.IsValid();
38     isHoverMode_ = enableHoverMode ? pipeline->IsHalfFoldHoverStatus() : false;
39 }
40 
CalculateSheetHeightInOtherScenes(LayoutWrapper * layoutWrapper)41 void SheetPresentationLayoutAlgorithm::CalculateSheetHeightInOtherScenes(LayoutWrapper* layoutWrapper)
42 {
43     CHECK_NULL_VOID(layoutWrapper);
44     auto host = layoutWrapper->GetHostNode();
45     CHECK_NULL_VOID(host);
46     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
47     CHECK_NULL_VOID(sheetPattern);
48     auto foldCreaseRect = sheetPattern->GetFoldScreenRect();
49     if (sheetType_ == SheetType::SHEET_CENTER && isHoverMode_) {
50         float upScreenHeight = foldCreaseRect.Top() - SHEET_HOVERMODE_UP_HEIGHT.ConvertToPx();
51         float downScreenHeight = sheetMaxHeight_ - SHEET_HOVERMODE_DOWN_HEIGHT.ConvertToPx() - foldCreaseRect.Bottom();
52         TAG_LOGD(AceLogTag::ACE_SHEET, "upScreenHeight: %{public}f, downScreenHeight: %{public}f.", upScreenHeight,
53             downScreenHeight);
54         sheetHeight_ = std::min(sheetHeight_,
55             (hoverModeArea_ == HoverModeAreaType::TOP_SCREEN || isKeyBoardShow_) ? upScreenHeight : downScreenHeight);
56     }
57 }
58 
CalculateSheetOffsetInOtherScenes(LayoutWrapper * layoutWrapper)59 void SheetPresentationLayoutAlgorithm::CalculateSheetOffsetInOtherScenes(LayoutWrapper* layoutWrapper)
60 {
61     CHECK_NULL_VOID(layoutWrapper);
62     auto host = layoutWrapper->GetHostNode();
63     CHECK_NULL_VOID(host);
64     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
65     CHECK_NULL_VOID(sheetPattern);
66     auto geometryNode = layoutWrapper->GetGeometryNode();
67     CHECK_NULL_VOID(geometryNode);
68     auto foldCreaseRect = sheetPattern->GetFoldScreenRect();
69     auto frameSizeHeight = geometryNode->GetFrameSize().Height();
70     if (sheetType_ == SheetType::SHEET_CENTER && isHoverMode_) {
71         float upScreenHeight = foldCreaseRect.Top() - SHEET_HOVERMODE_UP_HEIGHT.ConvertToPx();
72         float downScreenHeight = sheetMaxHeight_ - SHEET_HOVERMODE_DOWN_HEIGHT.ConvertToPx() - foldCreaseRect.Bottom();
73         sheetOffsetY_ = (hoverModeArea_ == HoverModeAreaType::TOP_SCREEN || isKeyBoardShow_)
74                             ? (SHEET_HOVERMODE_UP_HEIGHT.ConvertToPx() +
75                                   (upScreenHeight - frameSizeHeight) / DOUBLE_SIZE)
76                             : (foldCreaseRect.Bottom() + (downScreenHeight - frameSizeHeight) / DOUBLE_SIZE);
77     }
78 }
79 
ComputeWidthAndHeight(LayoutWrapper * layoutWrapper)80 void SheetPresentationLayoutAlgorithm::ComputeWidthAndHeight(LayoutWrapper* layoutWrapper)
81 {
82     auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
83     CHECK_NULL_VOID(layoutProperty);
84     auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
85     LayoutConstraintF layoutConstraint = parentConstraint.value();
86     layoutProperty->UpdateLayoutConstraint(layoutConstraint);
87     auto maxSize = layoutConstraint.maxSize;
88     sheetMaxHeight_ = maxSize.Height();
89     sheetMaxWidth_ = maxSize.Width();
90     auto showInSubWindow = sheetStyle_.showInSubWindow.value_or(false);
91     auto parentHeightConstraint = sheetMaxHeight_;
92     auto parentWidthConstraint = sheetMaxWidth_;
93     if (showInSubWindow) {
94         auto host = layoutWrapper->GetHostNode();
95         CHECK_NULL_VOID(host);
96         auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
97         CHECK_NULL_VOID(sheetWrapper);
98         auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
99         CHECK_NULL_VOID(sheetWrapperPattern);
100         auto mainWindowRect = sheetWrapperPattern->GetMainWindowRect();
101         parentHeightConstraint = mainWindowRect.Height();
102         parentWidthConstraint = mainWindowRect.Width();
103     }
104     sheetWidth_ = GetWidthByScreenSizeType(parentWidthConstraint, layoutWrapper);
105     sheetHeight_ = GetHeightByScreenSizeType(parentHeightConstraint, parentWidthConstraint, layoutWrapper);
106 }
107 
Measure(LayoutWrapper * layoutWrapper)108 void SheetPresentationLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
109 {
110     CHECK_NULL_VOID(layoutWrapper);
111     auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
112     CHECK_NULL_VOID(layoutProperty);
113     sheetStyle_ = layoutProperty->GetSheetStyleValue();
114     auto layoutConstraint = layoutProperty->GetLayoutConstraint();
115     if (!layoutConstraint) {
116         TAG_LOGE(AceLogTag::ACE_SHEET, "fail to measure sheet due to layoutConstraint is nullptr");
117         return;
118     }
119     InitParameter();
120     if (layoutWrapper->GetGeometryNode() && layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint()) {
121         ComputeWidthAndHeight(layoutWrapper);
122         CalculateSheetHeightInOtherScenes(layoutWrapper);
123         AddArrowHeightToSheetSize();
124         SizeF idealSize(sheetWidth_, sheetHeight_);
125         layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
126         layoutWrapper->GetGeometryNode()->SetContentSize(idealSize);
127         auto childConstraint = CreateSheetChildConstraint(layoutProperty, layoutWrapper);
128         layoutConstraint->percentReference = SizeF(sheetWidth_, sheetHeight_);
129         for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
130             child->Measure(childConstraint);
131         }
132         auto host = layoutWrapper->GetHostNode();
133         CHECK_NULL_VOID(host);
134         auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
135         CHECK_NULL_VOID(sheetPattern);
136         auto scrollNode = sheetPattern->GetSheetScrollNode();
137         CHECK_NULL_VOID(scrollNode);
138         childConstraint.selfIdealSize.SetWidth(childConstraint.maxSize.Width());
139         scrollNode->Measure(childConstraint);
140         if ((sheetType_ == SheetType::SHEET_CENTER || sheetType_ == SheetType::SHEET_POPUP ||
141             (sheetType_ == SheetType::SHEET_BOTTOM_OFFSET))
142             && (sheetStyle_.sheetHeight.sheetMode.value_or(SheetMode::LARGE) == SheetMode::AUTO)) {
143             auto&& children = layoutWrapper->GetAllChildrenWithBuild();
144             auto secondChild = AceType::DynamicCast<LayoutWrapper>(scrollNode);
145             CHECK_NULL_VOID(secondChild);
146             auto&& scrollChild = secondChild->GetAllChildrenWithBuild();
147             auto builder = scrollChild.front();
148             CHECK_NULL_VOID(builder);
149             auto operatoration = children.front();
150             CHECK_NULL_VOID(operatoration);
151             auto operatorGeometryNode = operatoration->GetGeometryNode();
152             CHECK_NULL_VOID(operatorGeometryNode);
153             auto builderGeometryNode = builder->GetGeometryNode();
154             CHECK_NULL_VOID(builderGeometryNode);
155             sheetHeight_ =
156                 operatorGeometryNode->GetFrameSize().Height() + builderGeometryNode->GetFrameSize().Height();
157             float sheetMaxHeight = sheetMaxHeight_;
158             if (SheetInSplitWindow()) {
159                 auto pipelineContext = PipelineContext::GetCurrentContext();
160                 auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
161                 sheetMaxHeight = windowGlobalRect.Height() - SHEET_SPLIT_STATUS_BAR.ConvertToPx()-
162                     SHEET_SPLIT_AI_BAR.ConvertToPx();
163             }
164             auto maxHeight = std::min(sheetMaxHeight, sheetMaxWidth_) * POPUP_LARGE_SIZE;
165             maxHeight = SheetInSplitWindow()
166                 ? maxHeight : std::max(maxHeight, static_cast<float>(SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()));
167             if (LessNotEqual(sheetHeight_, 0.0f)) {
168                 sheetHeight_ = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
169             } else if (LessOrEqual(sheetHeight_, SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()) && !SheetInSplitWindow()) {
170                 sheetHeight_ = SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx();
171             } else if (GreatOrEqual(sheetHeight_, maxHeight)) {
172                 sheetHeight_ = maxHeight;
173             }
174             SizeF idealSize(sheetWidth_, sheetHeight_);
175             layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
176             childConstraint = CreateSheetChildConstraint(layoutProperty, layoutWrapper);
177             secondChild->Measure(childConstraint);
178         }
179     }
180 }
181 
ComputeCenterStyleOffset(LayoutWrapper * layoutWrapper)182 void SheetPresentationLayoutAlgorithm::ComputeCenterStyleOffset(LayoutWrapper* layoutWrapper)
183 {
184     auto showInSubWindow = sheetStyle_.showInSubWindow.value_or(false);
185     if (!showInSubWindow) {
186         sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / DOUBLE_SIZE;
187         return;
188     }
189     auto host = layoutWrapper->GetHostNode();
190     CHECK_NULL_VOID(host);
191     auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
192     CHECK_NULL_VOID(sheetWrapper);
193     auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
194     CHECK_NULL_VOID(sheetWrapperPattern);
195     auto mainWindowRect = sheetWrapperPattern->GetMainWindowRect();
196     auto geometryNode = host->GetGeometryNode();
197     CHECK_NULL_VOID(geometryNode);
198     auto sheetFrameSize = geometryNode->GetFrameSize();
199 
200     // compute sheet offset when show in subwindow
201     RectF containerModal;
202     RectF buttonsRect;
203     auto hostWindowId = SubwindowManager::GetInstance()->GetParentContainerId(sheetWrapperPattern->GetSubWindowId());
204     ContainerScope scope(hostWindowId);
205     auto container = AceEngine::Get().GetContainer(hostWindowId);
206     CHECK_NULL_VOID(container);
207     auto mainWindowContext = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
208     sheetOffsetY_ = mainWindowRect.GetY() + mainWindowRect.Height() / DOUBLE_SIZE
209         - sheetFrameSize.Height() / DOUBLE_SIZE;
210     if (mainWindowContext && mainWindowContext->GetContainerModalButtonsRect(containerModal, buttonsRect)) {
211         sheetOffsetY_ += buttonsRect.Height() / DOUBLE_SIZE;
212         if (LessOrEqual(sheetOffsetY_, mainWindowRect.GetY() + buttonsRect.Height())) {
213             sheetOffsetY_ = mainWindowRect.GetY() + buttonsRect.Height();
214         }
215     }
216     sheetOffsetX_ = mainWindowRect.GetX() + (mainWindowRect.Width()  - sheetFrameSize.Width()) / DOUBLE_SIZE;
217     std::vector<Rect> rects;
218     auto rect = Rect(sheetOffsetX_, sheetOffsetY_,
219         sheetFrameSize.Width(), sheetFrameSize.Height());
220     rects.emplace_back(rect);
221     SubwindowManager::GetInstance()->SetHotAreas(rects, SubwindowType::TYPE_SHEET,
222         host->GetId(), sheetWrapperPattern->GetSubWindowId());
223 }
224 
ComputePopupStyleOffset(LayoutWrapper * layoutWrapper)225 void SheetPresentationLayoutAlgorithm::ComputePopupStyleOffset(LayoutWrapper* layoutWrapper)
226 {
227     sheetOffsetX_ = sheetPopupInfo_.sheetOffsetX;
228     sheetOffsetY_ = sheetPopupInfo_.sheetOffsetY;
229     auto showInSubWindow = sheetStyle_.showInSubWindow.value_or(false);
230     if (showInSubWindow) {
231         auto host = layoutWrapper->GetHostNode();
232         CHECK_NULL_VOID(host);
233         auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
234         CHECK_NULL_VOID(sheetWrapper);
235         auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
236         CHECK_NULL_VOID(sheetWrapperPattern);
237         if (sheetWrapperPattern->ShowInUEC()) {
238             auto UECId = SubwindowManager::GetInstance()->GetParentContainerId(sheetWrapperPattern->GetSubWindowId());
239             auto container = AceEngine::Get().GetContainer(UECId);
240             CHECK_NULL_VOID(container);
241             auto mainWindowContext = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
242             auto UECWindowGlobalRect = mainWindowContext->GetDisplayWindowRectInfo();
243             sheetOffsetX_ += UECWindowGlobalRect.Left();
244             sheetOffsetY_ += UECWindowGlobalRect.Top();
245         } else {
246             auto mainWindowRect = sheetWrapperPattern->GetMainWindowRect();
247             sheetOffsetX_ += mainWindowRect.GetX();
248             sheetOffsetY_ += mainWindowRect.GetY();
249         }
250         std::vector<Rect> rects;
251         auto rect = Rect(sheetOffsetX_, sheetOffsetY_,
252             host->GetGeometryNode()->GetFrameSize().Width(), host->GetGeometryNode()->GetFrameSize().Height());
253         rects.emplace_back(rect);
254         auto subWindowMgr = SubwindowManager::GetInstance();
255         subWindowMgr->SetHotAreas(rects, SubwindowType::TYPE_SHEET, host->GetId(),
256             sheetWrapperPattern->GetSubWindowId());
257     }
258 }
259 
LayoutTitleBuilder(const NG::OffsetF & translate,LayoutWrapper * layoutWrapper)260 void SheetPresentationLayoutAlgorithm::LayoutTitleBuilder(const NG::OffsetF& translate,
261     LayoutWrapper* layoutWrapper)
262 {
263     auto host = layoutWrapper->GetHostNode();
264     CHECK_NULL_VOID(host);
265     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
266     CHECK_NULL_VOID(sheetPattern);
267     auto titleBuilderNode = sheetPattern->GetTitleBuilderNode();
268     CHECK_NULL_VOID(titleBuilderNode);
269     auto index = host->GetChildIndexById(titleBuilderNode->GetId());
270     auto titleBuilderWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
271     CHECK_NULL_VOID(titleBuilderWrapper);
272     auto geometryNode = titleBuilderWrapper->GetGeometryNode();
273     CHECK_NULL_VOID(geometryNode);
274     geometryNode->SetMarginFrameOffset(translate);
275     titleBuilderWrapper->Layout();
276 }
277 
LayoutCloseIcon(const NG::OffsetF & translate,LayoutWrapper * layoutWrapper)278 void SheetPresentationLayoutAlgorithm::LayoutCloseIcon(const NG::OffsetF& translate,
279     LayoutWrapper* layoutWrapper)
280 {
281     auto host = layoutWrapper->GetHostNode();
282     CHECK_NULL_VOID(host);
283     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
284     CHECK_NULL_VOID(sheetPattern);
285     auto sheetCloseNode = sheetPattern->GetSheetCloseIcon();
286     CHECK_NULL_VOID(sheetCloseNode);
287     auto index = host->GetChildIndexById(sheetCloseNode->GetId());
288     auto closeIconWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
289     CHECK_NULL_VOID(closeIconWrapper);
290     auto geometryNode = closeIconWrapper->GetGeometryNode();
291     CHECK_NULL_VOID(geometryNode);
292 
293     auto pipeline = host->GetContext();
294     CHECK_NULL_VOID(pipeline);
295     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
296     CHECK_NULL_VOID(sheetTheme);
297     auto sheetGeometryNode = layoutWrapper->GetGeometryNode();
298     CHECK_NULL_VOID(sheetGeometryNode);
299     auto closeIconX = sheetGeometryNode->GetFrameSize().Width() -
300                       static_cast<float>(SHEET_CLOSE_ICON_WIDTH.ConvertToPx()) -
301                       static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
302     if (AceApplicationInfo::GetInstance().IsRightToLeft() &&
303         AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
304         closeIconX = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
305     }
306     auto closeIconY = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
307     OffsetF positionOffset;
308     positionOffset.SetX(closeIconX + translate.GetX());
309     positionOffset.SetY(closeIconY + translate.GetY());
310     geometryNode->SetMarginFrameOffset(positionOffset);
311     closeIconWrapper->Layout();
312 }
313 
LayoutScrollNode(const NG::OffsetF & translate,LayoutWrapper * layoutWrapper)314 void SheetPresentationLayoutAlgorithm::LayoutScrollNode(const NG::OffsetF& translate,
315     LayoutWrapper* layoutWrapper)
316 {
317     auto host = layoutWrapper->GetHostNode();
318     CHECK_NULL_VOID(host);
319     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
320     CHECK_NULL_VOID(sheetPattern);
321     auto scrollNode = sheetPattern->GetSheetScrollNode();
322     CHECK_NULL_VOID(scrollNode);
323     auto index = host->GetChildIndexById(scrollNode->GetId());
324     auto scrollWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
325     CHECK_NULL_VOID(scrollWrapper);
326 
327     auto offset = translate;
328     auto titleBuilder = sheetPattern->GetTitleBuilderNode();
329     if (titleBuilder) {
330         auto titleBuilderNode = titleBuilder->GetGeometryNode();
331         CHECK_NULL_VOID(titleBuilderNode);
332         offset += OffsetF(0, titleBuilderNode->GetFrameSize().Height());
333     }
334     auto geometryNode = scrollWrapper->GetGeometryNode();
335     geometryNode->SetMarginFrameOffset(offset);
336     scrollWrapper->Layout();
337 }
338 
Layout(LayoutWrapper * layoutWrapper)339 void SheetPresentationLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
340 {
341     CHECK_NULL_VOID(layoutWrapper);
342     const auto& pipeline = PipelineContext::GetCurrentContext();
343     CHECK_NULL_VOID(pipeline);
344     sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / DOUBLE_SIZE;
345     if (sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE) {
346         sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / DOUBLE_SIZE;
347     } else if (sheetType_ == SheetType::SHEET_CENTER) {
348         ComputeCenterStyleOffset(layoutWrapper);
349     } else if (sheetType_ == SheetType::SHEET_POPUP) {
350         ComputePopupStyleOffset(layoutWrapper);
351     } else if (sheetType_ == SheetType::SHEET_BOTTOM_OFFSET) {
352         sheetOffsetY_ = (sheetMaxHeight_ - sheetHeight_ + sheetStyle_.bottomOffset->GetY());
353         sheetOffsetX_ = sheetOffsetX_ + sheetStyle_.bottomOffset->GetX();
354     }
355     CalculateSheetOffsetInOtherScenes(layoutWrapper);
356     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet layout info, sheetOffsetX_ is: %{public}f, sheetOffsetY_ is: %{public}f",
357         sheetOffsetX_, sheetOffsetY_);
358     OffsetF positionOffset;
359     positionOffset.SetX(sheetOffsetX_);
360     positionOffset.SetY(0.0f);
361     auto geometryNode = layoutWrapper->GetGeometryNode();
362     CHECK_NULL_VOID(geometryNode);
363     // This step is only to determine the position of x, because y is to be done by the bit movement effect
364     geometryNode->SetMarginFrameOffset(positionOffset);
365     OffsetF translate(0.0f, 0.0f);
366     if (sheetType_ == SheetType::SHEET_POPUP) {
367         UpdateTranslateOffsetWithPlacement(translate);
368     }
369     LayoutCloseIcon(translate, layoutWrapper);
370     LayoutTitleBuilder(translate, layoutWrapper);
371     LayoutScrollNode(translate, layoutWrapper);
372 }
373 
UpdateTranslateOffsetWithPlacement(OffsetF & translate)374 void SheetPresentationLayoutAlgorithm::UpdateTranslateOffsetWithPlacement(OffsetF& translate)
375 {
376     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
377         translate += OffsetF(0, SHEET_ARROW_HEIGHT.ConvertToPx());
378         return;
379     }
380     if ((sheetPopupInfo_.placementRechecked && sheetPopupInfo_.placementOnTarget) ||
381         !sheetPopupInfo_.showArrow) {
382         return;
383     }
384     // child content should not show in arrow, so that child layout need translate to avoid sheet arrow.
385     switch (sheetPopupInfo_.finalPlacement) {
386         case Placement::BOTTOM_LEFT:
387             [[fallthrough]];
388         case Placement::BOTTOM_RIGHT:
389             [[fallthrough]];
390         case Placement::BOTTOM: {
391             translate += OffsetF(0.f, SHEET_ARROW_HEIGHT.ConvertToPx());
392             break;
393         }
394         case Placement::RIGHT_TOP:
395             [[fallthrough]];
396         case Placement::RIGHT_BOTTOM:
397             [[fallthrough]];
398         case Placement::RIGHT: {
399             translate += OffsetF(SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
400             break;
401         }
402         default:
403             break;
404     }
405 }
406 
GetHeightByScreenSizeType(const float parentConstraintHeight,const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const407 float SheetPresentationLayoutAlgorithm::GetHeightByScreenSizeType(const float parentConstraintHeight,
408     const float parentConstraintWidth, LayoutWrapper* layoutWrapper) const
409 {
410     float height = parentConstraintHeight;
411     switch (sheetType_) {
412         case SheetType::SHEET_BOTTOM:
413         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
414         case SheetType::SHEET_BOTTOMLANDSPACE:
415             height = parentConstraintHeight;
416             break;
417         case SheetType::SHEET_BOTTOM_OFFSET:
418         case SheetType::SHEET_CENTER:
419             height = GetHeightBySheetStyle(parentConstraintHeight, parentConstraintWidth, layoutWrapper);
420             break;
421         case SheetType::SHEET_POPUP:
422             height = GetHeightBySheetStyle(parentConstraintHeight, parentConstraintWidth, layoutWrapper) +
423                 SHEET_ARROW_HEIGHT.ConvertToPx();
424             // The sheet height can only be confirmed after the placement is confirmed.
425             if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
426                 height -= SHEET_ARROW_HEIGHT.ConvertToPx();
427             }
428             break;
429         default:
430             break;
431     }
432 
433     return height;
434 }
435 
GetWidthByScreenSizeType(const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const436 float SheetPresentationLayoutAlgorithm::GetWidthByScreenSizeType(const float parentConstraintWidth,
437     LayoutWrapper* layoutWrapper) const
438 {
439     float sheetWidth = parentConstraintWidth;
440     auto host = layoutWrapper->GetHostNode();
441     CHECK_NULL_RETURN(host, sheetWidth);
442     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
443     CHECK_NULL_RETURN(sheetPattern, sheetWidth);
444     switch (sheetType_) {
445         case SheetType::SHEET_BOTTOM:
446             if (sheetPattern->IsPhoneInLandScape()) {
447                 sheetWidth = std::min(static_cast<float>(SHEET_LANDSCAPE_WIDTH.ConvertToPx()), parentConstraintWidth);
448                 break;
449             }
450             [[fallthrough]];
451         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
452             sheetWidth = parentConstraintWidth;
453             break;
454         case SheetType::SHEET_BOTTOMLANDSPACE:
455             [[fallthrough]];
456         case SheetType::SHEET_CENTER:
457             sheetWidth = SHEET_LANDSCAPE_WIDTH.ConvertToPx();
458             break;
459         case SheetType::SHEET_POPUP:
460             sheetWidth = SHEET_POPUP_WIDTH.ConvertToPx();
461             break;
462         default:
463             break;
464     }
465 
466     if (!sheetStyle_.width.has_value()) {
467         return sheetWidth;
468     }
469     auto width = 0.0f;
470     if (sheetStyle_.width->Unit() == DimensionUnit::PERCENT) {
471         width = sheetStyle_.width->ConvertToPxWithSize(parentConstraintWidth);
472     } else {
473         width = sheetStyle_.width->ConvertToPx();
474     }
475     if (LessNotEqual(width, 0.0f) || width > parentConstraintWidth) {
476         width = sheetWidth;
477     }
478     return width;
479 }
480 
ComputeMaxHeight(const float parentConstraintHeight,const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const481 float SheetPresentationLayoutAlgorithm::ComputeMaxHeight(const float parentConstraintHeight,
482     const float parentConstraintWidth, LayoutWrapper* layoutWrapper) const
483 {
484     float sheetMaxHeight = parentConstraintHeight;
485     if (SheetInSplitWindow()) {
486         sheetMaxHeight = parentConstraintHeight - SHEET_SPLIT_STATUS_BAR.ConvertToPx() -
487             SHEET_SPLIT_AI_BAR.ConvertToPx();
488     }
489     NG::RectF floatButtons;
490     auto host = layoutWrapper->GetHostNode();
491     CHECK_NULL_RETURN(host, 0.0f);
492     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
493     CHECK_NULL_RETURN(sheetPattern, 0.0f);
494     auto maxHeight = (std::min(sheetMaxHeight, parentConstraintWidth)) * POPUP_LARGE_SIZE;
495     if (sheetPattern->GetWindowButtonRect(floatButtons)) {
496         maxHeight = sheetMaxHeight - DOUBLE_SIZE *
497             (floatButtons.Height() + SHEET_BLANK_MINI_HEIGHT.ConvertToPx());
498     } else if (sheetStyle_.showInSubWindow.value_or(false)) {
499         auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
500         CHECK_NULL_RETURN(sheetWrapper, 0.0f);
501         auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
502         CHECK_NULL_RETURN(sheetWrapperPattern, 0.0f);
503         RectF containerModal;
504         RectF buttonsRect;
505         auto subwindowId = sheetWrapperPattern->GetSubWindowId();
506         auto currentId = SubwindowManager::GetInstance()->GetParentContainerId(subwindowId);
507         ContainerScope scope(currentId);
508         auto mainWindowContext = PipelineContext::GetContextByContainerId(currentId);
509         if (mainWindowContext && mainWindowContext->GetContainerModalButtonsRect(containerModal, buttonsRect)) {
510             maxHeight = (std::min(parentConstraintHeight - buttonsRect.Height(),
511                 parentConstraintWidth)) * POPUP_LARGE_SIZE;
512         }
513     }
514     return maxHeight;
515 }
516 
GetHeightBySheetStyle(const float parentConstraintHeight,const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const517 float SheetPresentationLayoutAlgorithm::GetHeightBySheetStyle(const float parentConstraintHeight,
518     const float parentConstraintWidth, LayoutWrapper* layoutWrapper) const
519 {
520     float height = 0.0f;
521     bool isMediumOrLargeMode = false;
522     if (sheetStyle_.sheetHeight.sheetMode == SheetMode::MEDIUM ||
523         sheetStyle_.sheetHeight.sheetMode == SheetMode::LARGE) {
524         isMediumOrLargeMode =  true;
525     }
526     if (sheetStyle_.sheetHeight.height.has_value() || isMediumOrLargeMode) {
527         auto maxHeight = ComputeMaxHeight(parentConstraintHeight, parentConstraintWidth, layoutWrapper);
528         if (sheetStyle_.sheetHeight.height->Unit() == DimensionUnit::PERCENT) {
529             height = sheetStyle_.sheetHeight.height->ConvertToPxWithSize(maxHeight);
530         } else if (isMediumOrLargeMode) {
531             height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
532         } else {
533             height = sheetStyle_.sheetHeight.height->ConvertToPx();
534         }
535         maxHeight = SheetInSplitWindow()
536             ? maxHeight : std::max(maxHeight, static_cast<float>(SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()));
537         if (LessNotEqual(height, 0.0f)) {
538             height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
539         } else if (LessOrEqual(height, SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()) && !SheetInSplitWindow()) {
540             height = SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx();
541         } else if (GreatOrEqual(height, maxHeight)) {
542             height = maxHeight;
543         }
544     } else {
545         height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
546     }
547     return height;
548 }
549 
CreateSheetChildConstraint(RefPtr<SheetPresentationProperty> layoutprop,LayoutWrapper * layoutWrapper)550 LayoutConstraintF SheetPresentationLayoutAlgorithm::CreateSheetChildConstraint(
551     RefPtr<SheetPresentationProperty> layoutprop, LayoutWrapper* layoutWrapper)
552 {
553     auto childConstraint = layoutprop->CreateChildConstraint();
554     auto pipeline = PipelineContext::GetCurrentContext();
555     CHECK_NULL_RETURN(pipeline, childConstraint);
556     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
557     CHECK_NULL_RETURN(sheetTheme, childConstraint);
558 
559     childConstraint.maxSize.SetWidth(sheetWidth_);
560     auto maxHeight = sheetHeight_;
561     if ((sheetStyle_.isTitleBuilder.has_value()) &&
562         ((sheetType_ == SheetType::SHEET_CENTER) || (sheetType_ == SheetType::SHEET_POPUP))) {
563         auto host = layoutWrapper->GetHostNode();
564         CHECK_NULL_RETURN(host, childConstraint);
565         auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
566         CHECK_NULL_RETURN(sheetPattern, childConstraint);
567         auto operationNode = sheetPattern->GetTitleBuilderNode();
568         CHECK_NULL_RETURN(operationNode, childConstraint);
569         auto titleGeometryNode = operationNode->GetGeometryNode();
570         CHECK_NULL_RETURN(titleGeometryNode, childConstraint);
571         auto titleHeiht = titleGeometryNode->GetFrameSize().Height();
572         maxHeight -= titleHeiht;
573     }
574     auto maxWidth = sheetWidth_;
575     if (sheetType_ == SheetType::SHEET_POPUP) {
576         UpdateMaxSizeWithPlacement(maxWidth, maxHeight);
577     }
578     if (sheetPopupInfo_.finalPlacement != Placement::NONE) {
579         childConstraint.maxSize.SetWidth(maxWidth);
580     }
581     childConstraint.maxSize.SetHeight(maxHeight);
582     childConstraint.parentIdealSize = OptionalSizeF(sheetWidth_, sheetHeight_);
583     childConstraint.percentReference = SizeF(sheetWidth_, sheetHeight_);
584     return childConstraint;
585 }
586 
UpdateMaxSizeWithPlacement(float & maxWidth,float & maxHeight)587 void SheetPresentationLayoutAlgorithm::UpdateMaxSizeWithPlacement(float& maxWidth, float& maxHeight)
588 {
589     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
590         maxHeight -= SHEET_ARROW_HEIGHT.ConvertToPx();
591         return;
592     }
593 
594     if ((sheetPopupInfo_.placementRechecked && sheetPopupInfo_.placementOnTarget) ||
595         !sheetPopupInfo_.showArrow) {
596         return;
597     }
598 
599     switch (sheetPopupInfo_.finalPlacement) {
600         case Placement::BOTTOM_LEFT:
601             [[fallthrough]];
602         case Placement::BOTTOM_RIGHT:
603             [[fallthrough]];
604         case Placement::BOTTOM:
605             [[fallthrough]];
606         case Placement::TOP_LEFT:
607             [[fallthrough]];
608         case Placement::TOP_RIGHT:
609             [[fallthrough]];
610         case Placement::TOP: {
611             maxHeight -= SHEET_ARROW_HEIGHT.ConvertToPx();
612             break;
613         }
614         case Placement::RIGHT_TOP:
615             [[fallthrough]];
616         case Placement::RIGHT_BOTTOM:
617             [[fallthrough]];
618         case Placement::RIGHT:
619             [[fallthrough]];
620         case Placement::LEFT_TOP:
621             [[fallthrough]];
622         case Placement::LEFT_BOTTOM:
623             [[fallthrough]];
624         case Placement::LEFT: {
625             maxWidth -= SHEET_ARROW_HEIGHT.ConvertToPx();
626             break;
627         }
628         default:
629             break;
630     }
631 }
632 
SheetInSplitWindow() const633 bool SheetPresentationLayoutAlgorithm::SheetInSplitWindow() const
634 {
635     //whether window in up and down split mode
636     auto pipelineContext = PipelineContext::GetCurrentContext();
637     auto windowManager = pipelineContext->GetWindowManager();
638     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
639     int32_t deviceHeight = SystemProperties::GetDeviceHeight();
640     if (sheetType_ == SheetType::SHEET_CENTER && windowManager && windowGlobalRect.Height() < deviceHeight &&
641         (windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
642         windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY)) {
643         return true;
644     }
645     return false;
646 }
647 
UpdatePopupInfoAndRemeasure(LayoutWrapper * layoutWrapper,const SheetPopupInfo & sheetPopupInfo,const float & sheetWidth,const float & sheetHeight)648 void SheetPresentationLayoutAlgorithm::UpdatePopupInfoAndRemeasure(LayoutWrapper* layoutWrapper,
649     const SheetPopupInfo& sheetPopupInfo, const float& sheetWidth, const float& sheetHeight)
650 {
651     if (sheetType_ != SheetType::SHEET_POPUP) {
652         return;
653     }
654     sheetPopupInfo_ = sheetPopupInfo;
655     sheetOffsetX_ = sheetPopupInfo.sheetOffsetX;
656     sheetOffsetY_ = sheetPopupInfo.sheetOffsetY;
657     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
658         return;
659     }
660     sheetWidth_ = sheetWidth;
661     sheetHeight_ = sheetHeight;
662     auto sheetPageWrapper = layoutWrapper->GetChildByIndex(0);
663     CHECK_NULL_VOID(sheetPageWrapper);
664     RemeasureForPopup(sheetPageWrapper);
665 }
666 
AddArrowHeightToSheetSize()667 void SheetPresentationLayoutAlgorithm::AddArrowHeightToSheetSize()
668 {
669     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) ||
670         sheetType_ != SheetType::SHEET_POPUP) {
671         return;
672     }
673 
674     if ((sheetPopupInfo_.placementRechecked && sheetPopupInfo_.placementOnTarget) ||
675         !sheetPopupInfo_.showArrow) {
676         return;
677     }
678 
679     switch (sheetPopupInfo_.finalPlacement) {
680         case Placement::BOTTOM_LEFT:
681             [[fallthrough]];
682         case Placement::BOTTOM_RIGHT:
683             [[fallthrough]];
684         case Placement::BOTTOM:
685             [[fallthrough]];
686         case Placement::TOP_LEFT:
687             [[fallthrough]];
688         case Placement::TOP_RIGHT:
689             [[fallthrough]];
690         case Placement::TOP: {
691             sheetHeight_ += SHEET_ARROW_HEIGHT.ConvertToPx();
692             break;
693         }
694         case Placement::RIGHT_TOP:
695             [[fallthrough]];
696         case Placement::RIGHT_BOTTOM:
697             [[fallthrough]];
698         case Placement::RIGHT:
699             [[fallthrough]];
700         case Placement::LEFT_TOP:
701             [[fallthrough]];
702         case Placement::LEFT_BOTTOM:
703             [[fallthrough]];
704         case Placement::LEFT: {
705             sheetWidth_ += SHEET_ARROW_HEIGHT.ConvertToPx();
706             break;
707         }
708         default:
709             break;
710     }
711 }
712 
RemeasureForPopup(const RefPtr<LayoutWrapper> & layoutWrapper)713 void SheetPresentationLayoutAlgorithm::RemeasureForPopup(const RefPtr<LayoutWrapper>& layoutWrapper)
714 {
715     CHECK_NULL_VOID(layoutWrapper);
716     if (layoutWrapper->GetGeometryNode() && layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint()) {
717         auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
718         if (!parentConstraint.has_value()) {
719             return;
720         }
721         auto layoutConstraint = parentConstraint.value();
722         auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
723         CHECK_NULL_VOID(layoutProperty);
724         layoutProperty->UpdateLayoutConstraint(layoutConstraint);
725         AddArrowHeightToSheetSize();
726         TAG_LOGI(AceLogTag::ACE_SHEET, "remeasure size:(%{public}f, %{public}f)", sheetWidth_, sheetHeight_);
727         SizeF idealSize(sheetWidth_, sheetHeight_);
728         layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
729         layoutWrapper->GetGeometryNode()->SetContentSize(idealSize);
730         auto childConstraint = CreateSheetChildConstraint(layoutProperty, Referenced::RawPtr(layoutWrapper));
731         layoutConstraint.percentReference = SizeF(sheetWidth_, sheetHeight_);
732         for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
733             child->Measure(childConstraint);
734         }
735         auto host = layoutWrapper->GetHostNode();
736         CHECK_NULL_VOID(host);
737         auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
738         CHECK_NULL_VOID(sheetPattern);
739         auto scrollNode = sheetPattern->GetSheetScrollNode();
740         CHECK_NULL_VOID(scrollNode);
741         childConstraint.selfIdealSize.SetWidth(childConstraint.maxSize.Width());
742         scrollNode->Measure(childConstraint);
743     }
744 }
745 } // namespace OHOS::Ace::NG