• 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 
18 #include "base/geometry/axis.h"
19 #include "base/geometry/ng/offset_t.h"
20 #include "base/geometry/ng/size_t.h"
21 #include "base/log/ace_trace.h"
22 #include "base/memory/ace_type.h"
23 #include "base/utils/utils.h"
24 #include "base/window/foldable_window.h"
25 #include "core/components/common/layout/grid_system_manager.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/layout/layout_algorithm.h"
28 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
29 #include "core/components_ng/property/layout_constraint.h"
30 #include "core/components_ng/property/measure_property.h"
31 #include "core/components_ng/property/measure_utils.h"
32 #include "core/components_v2/inspector/inspector_constants.h"
33 #include "core/pipeline_ng/pipeline_context.h"
34 
35 namespace OHOS::Ace::NG {
36 namespace {
37 constexpr int32_t SHEET_HALF_SIZE = 2;
38 constexpr Dimension WINDOW_EDGE_SPACE = 6.0_vp;
39 constexpr Dimension ARROW_VERTICAL_P1_OFFSET_X = 8.0_vp;
40 constexpr Dimension ARROW_VERTICAL_P5_OFFSET_X = 8.0_vp;
41 std::map<Placement, std::vector<Placement>> DIRECTIONS_STATES = {
42     { Placement::BOTTOM,
43         {
44             Placement::BOTTOM,
45         } },
46 };
47 std::map<Placement, std::vector<Placement>> PLACEMENT_STATES = {
48     { Placement::BOTTOM,
49         {
50             Placement::BOTTOM,
51             Placement::BOTTOM_RIGHT,
52             Placement::BOTTOM_LEFT,
53         } },
54 };
55 } // namespace
56 
InitParameter()57 void SheetPresentationLayoutAlgorithm::InitParameter()
58 {
59     auto pipeline = PipelineContext::GetCurrentContext();
60     CHECK_NULL_VOID(pipeline);
61     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
62     CHECK_NULL_VOID(sheetTheme);
63     sheetRadius_ = sheetTheme->GetSheetRadius().ConvertToPx();
64 }
65 
Measure(LayoutWrapper * layoutWrapper)66 void SheetPresentationLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
67 {
68     CHECK_NULL_VOID(layoutWrapper);
69     auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
70     CHECK_NULL_VOID(layoutProperty);
71     sheetStyle_ = layoutProperty->GetSheetStyleValue();
72     auto layoutConstraint = layoutProperty->GetLayoutConstraint();
73     if (!layoutConstraint) {
74         TAG_LOGE(AceLogTag::ACE_SHEET, "fail to measure sheet due to layoutConstraint is nullptr");
75         return;
76     }
77     auto pipeline = PipelineContext::GetCurrentContext();
78     CHECK_NULL_VOID(pipeline);
79     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
80     CHECK_NULL_VOID(sheetTheme);
81     auto maxSize = layoutConstraint->maxSize;
82     if (layoutWrapper->GetGeometryNode() && layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint()) {
83         auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
84         layoutConstraint = parentConstraint.value();
85         layoutProperty->UpdateLayoutConstraint(layoutConstraint.value());
86         maxSize = layoutConstraint->maxSize;
87         sheetMaxHeight_ = maxSize.Height();
88         sheetMaxWidth_ = maxSize.Width();
89         sheetWidth_ = GetWidthByScreenSizeType(maxSize, layoutWrapper);
90         sheetHeight_ = GetHeightByScreenSizeType(maxSize);
91         if (sheetStyle_.width.has_value()) {
92             float width = 0.0f;
93             if (sheetStyle_.width->Unit() == DimensionUnit::PERCENT) {
94                 width = sheetStyle_.width->ConvertToPxWithSize(maxSize.Width());
95             } else {
96                 width = sheetStyle_.width->ConvertToPx();
97             }
98             if (width > maxSize.Width() || width < 0.0f) {
99                 width = sheetWidth_;
100             }
101             sheetWidth_ = width;
102         }
103         SizeF idealSize(sheetWidth_, sheetHeight_);
104         layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
105         layoutWrapper->GetGeometryNode()->SetContentSize(idealSize);
106         auto childConstraint = CreateSheetChildConstraint(layoutProperty);
107         layoutConstraint->percentReference = SizeF(sheetWidth_, sheetHeight_);
108         for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
109             child->Measure(childConstraint);
110         }
111         auto scrollNode = layoutWrapper->GetChildByIndex(1);
112         CHECK_NULL_VOID(scrollNode);
113         childConstraint.selfIdealSize.SetWidth(childConstraint.maxSize.Width());
114         scrollNode->Measure(childConstraint);
115         if ((sheetType_ == SheetType::SHEET_CENTER || sheetType_ == SheetType::SHEET_POPUP)
116             && (sheetStyle_.sheetMode.value_or(SheetMode::LARGE) == SheetMode::AUTO)) {
117             auto&& children = layoutWrapper->GetAllChildrenWithBuild();
118             auto secondIter = std::next(children.begin(), 1);
119             auto secondChild = *secondIter;
120             CHECK_NULL_VOID(secondChild);
121             auto&& scrollChild = secondChild->GetAllChildrenWithBuild();
122             auto builder = scrollChild.front();
123             CHECK_NULL_VOID(builder);
124             auto operatoration = children.front();
125             CHECK_NULL_VOID(operatoration);
126             auto operatorGeometryNode = operatoration->GetGeometryNode();
127             CHECK_NULL_VOID(operatorGeometryNode);
128             auto builderGeometryNode = builder->GetGeometryNode();
129             CHECK_NULL_VOID(builderGeometryNode);
130             sheetHeight_ =
131                 operatorGeometryNode->GetFrameSize().Height() + builderGeometryNode->GetFrameSize().Height();
132             float sheetMaxHeight = sheetMaxHeight_;
133             if (SheetInSplitWindow()) {
134                 auto pipelineContext = PipelineContext::GetCurrentContext();
135                 auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
136                 sheetMaxHeight = windowGlobalRect.Height() - SHEET_SPLIT_STATUS_BAR.ConvertToPx()-
137                     SHEET_SPLIT_AI_BAR.ConvertToPx();
138             }
139             auto maxHeight = std::min(sheetMaxHeight, sheetMaxWidth_) * POPUP_LARGE_SIZE;
140             maxHeight = SheetInSplitWindow()
141                 ? maxHeight : std::max(maxHeight, static_cast<float>(SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()));
142             if (LessNotEqual(sheetHeight_, 0.0f)) {
143                 sheetHeight_ = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
144             } else if (LessOrEqual(sheetHeight_, SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()) && !SheetInSplitWindow()) {
145                 sheetHeight_ = SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx();
146             } else if (GreatOrEqual(sheetHeight_, maxHeight)) {
147                 sheetHeight_ = maxHeight;
148             }
149             SizeF idealSize(sheetWidth_, sheetHeight_);
150             layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
151             childConstraint.maxSize.SetWidth(sheetWidth_);
152             childConstraint.maxSize.SetHeight(sheetHeight_);
153             secondChild->Measure(childConstraint);
154         }
155     }
156 }
157 
Layout(LayoutWrapper * layoutWrapper)158 void SheetPresentationLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
159 {
160     CHECK_NULL_VOID(layoutWrapper);
161     const auto& pipeline = PipelineContext::GetCurrentContext();
162     CHECK_NULL_VOID(pipeline);
163     sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / SHEET_HALF_SIZE;
164     if (sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE) {
165         sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / SHEET_HALF_SIZE;
166     } else if (sheetType_ == SheetType::SHEET_CENTER) {
167         sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / SHEET_HALF_SIZE;
168     } else if (sheetType_ == SheetType::SHEET_POPUP) {
169         auto frameNode = layoutWrapper->GetHostNode();
170         CHECK_NULL_VOID(frameNode);
171         auto parent = DynamicCast<FrameNode>(frameNode->GetParent());
172         CHECK_NULL_VOID(parent);
173         auto parentOffset = parent->GetPaintRectOffset();
174         OffsetF popupStyleSheetOffset = GetPopupStyleSheetOffset();
175         // need to subtract the SheetWrapper relative to the upper left corner of the window,
176         // which is the offset of the upper left corner of the bubble relative to the SheetWrapper
177         sheetOffsetX_ = popupStyleSheetOffset.GetX() - parentOffset.GetX();
178         sheetOffsetY_ = popupStyleSheetOffset.GetY() - parentOffset.GetY();
179     }
180     TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet layout info, sheetOffsetX_ is: %{public}f, sheetOffsetY_ is: %{public}f",
181         sheetOffsetX_, sheetOffsetY_);
182     OffsetF positionOffset;
183     positionOffset.SetX(sheetOffsetX_);
184     positionOffset.SetY(0.0f);
185     auto geometryNode = layoutWrapper->GetGeometryNode();
186     CHECK_NULL_VOID(geometryNode);
187     // This step is only to determine the position of x, because y is to be done by the bit movement effect
188     geometryNode->SetMarginFrameOffset(positionOffset);
189     OffsetF translate(0.0f, 0.0f);
190     if (sheetType_ == SheetType::SHEET_POPUP) {
191         translate += OffsetF(0, SHEET_ARROW_HEIGHT.ConvertToPx());
192     }
193     for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
194         child->GetGeometryNode()->SetMarginFrameOffset(translate);
195         child->Layout();
196         translate += OffsetF(0, child->GetGeometryNode()->GetFrameSize().Height());
197     }
198 }
199 
200 // Get the offset of the popupSheet relative to the upper left corner of the window
GetPopupStyleSheetOffset()201 OffsetF SheetPresentationLayoutAlgorithm::GetPopupStyleSheetOffset()
202 {
203     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetNodeId_);
204     CHECK_NULL_RETURN(targetNode, OffsetF());
205     auto geometryNode = targetNode->GetGeometryNode();
206     CHECK_NULL_RETURN(geometryNode, OffsetF());
207     auto targetSize = geometryNode->GetFrameSize();
208     auto targetOffset = targetNode->GetPaintRectOffset();
209     return GetOffsetInAvoidanceRule(targetSize, targetOffset);
210 }
211 
GetOffsetInAvoidanceRule(const SizeF & targetSize,const OffsetF & targetOffset)212 OffsetF SheetPresentationLayoutAlgorithm::GetOffsetInAvoidanceRule(const SizeF& targetSize, const OffsetF& targetOffset)
213 {
214     // The current default Placement is Placement::BOTTOM
215     auto placement = Placement::BOTTOM;
216     auto targetPlacement = AvoidanceRuleOfPlacement(placement, targetSize, targetOffset);
217     if (getOffsetFunc_.find(targetPlacement) == getOffsetFunc_.end()) {
218         TAG_LOGW(AceLogTag::ACE_SHEET, "It is an invalid Placement for current PopSheet.");
219         return {};
220     }
221     auto offsetFunc = getOffsetFunc_[targetPlacement];
222     CHECK_NULL_RETURN(offsetFunc, OffsetF());
223     return (this->*offsetFunc)(targetSize, targetOffset);
224 }
225 
AvoidanceRuleOfPlacement(const Placement & currentPlacement,const SizeF & targetSize,const OffsetF & targetOffset)226 Placement SheetPresentationLayoutAlgorithm::AvoidanceRuleOfPlacement(
227     const Placement& currentPlacement, const SizeF& targetSize, const OffsetF& targetOffset)
228 {
229     Placement targetPlacement = currentPlacement;
230     TAG_LOGD(AceLogTag::ACE_SHEET, "Init PopupSheet placement: %{public}s",
231         PlacementUtils::ConvertPlacementToString(targetPlacement).c_str());
232     // Step1: Determine the direction
233     auto& directionVec = DIRECTIONS_STATES[targetPlacement];
234     for (auto placement : directionVec) {
235         auto& placementFunc = directionCheckFunc_[placement];
236         if (placementFunc == nullptr) {
237             continue;
238         }
239         if ((this->*placementFunc)(targetSize, targetOffset)) {
240             targetPlacement = placement;
241             break;
242         }
243     }
244     TAG_LOGD(AceLogTag::ACE_SHEET, "After step1, placement: %{public}s",
245         PlacementUtils::ConvertPlacementToString(targetPlacement).c_str());
246     // Step2: Determine the Placement in that direction
247     auto& placementVec = PLACEMENT_STATES[targetPlacement];
248     for (auto placement : placementVec) {
249         auto& placementFunc = placementCheckFunc_[placement];
250         if (placementFunc == nullptr) {
251             continue;
252         }
253         if ((this->*placementFunc)(targetSize, targetOffset)) {
254             targetPlacement = placement;
255             break;
256         }
257     }
258     TAG_LOGD(AceLogTag::ACE_SHEET, "After step2, placement: %{public}s",
259         PlacementUtils::ConvertPlacementToString(targetPlacement).c_str());
260     return targetPlacement;
261 }
262 
CheckDirectionBottom(const SizeF & targetSize,const OffsetF & targetOffset)263 bool SheetPresentationLayoutAlgorithm::CheckDirectionBottom(const SizeF& targetSize, const OffsetF& targetOffset)
264 {
265     // Generalized bottom direction,
266     // determine whether the space below the component is enough to place the sheet of size
267     return true;
268 }
269 
CheckPlacementBottom(const SizeF & targetSize,const OffsetF & targetOffset)270 bool SheetPresentationLayoutAlgorithm::CheckPlacementBottom(const SizeF& targetSize, const OffsetF& targetOffset)
271 {
272     auto pipelineContext = PipelineContext::GetCurrentContext();
273     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
274     return GreatOrEqual(
275         windowGlobalRect.Width() - WINDOW_EDGE_SPACE.ConvertToPx(),
276         targetOffset.GetX() + targetSize.Width() / SHEET_HALF_SIZE + sheetWidth_ / SHEET_HALF_SIZE) &&
277         LessOrEqual(
278             WINDOW_EDGE_SPACE.ConvertToPx(),
279             targetOffset.GetX() + targetSize.Width() / SHEET_HALF_SIZE - sheetWidth_ / SHEET_HALF_SIZE);
280 }
281 
CheckPlacementBottomLeft(const SizeF & targetSize,const OffsetF & targetOffset)282 bool SheetPresentationLayoutAlgorithm::CheckPlacementBottomLeft(const SizeF& targetSize, const OffsetF& targetOffset)
283 {
284     auto pipelineContext = PipelineContext::GetCurrentContext();
285     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
286     return LessOrEqual(WINDOW_EDGE_SPACE.ConvertToPx(), targetOffset.GetX()) &&
287            GreatOrEqual(windowGlobalRect.Width() - WINDOW_EDGE_SPACE.ConvertToPx(), targetOffset.GetX() + sheetWidth_);
288 }
289 
CheckPlacementBottomRight(const SizeF & targetSize,const OffsetF & targetOffset)290 bool SheetPresentationLayoutAlgorithm::CheckPlacementBottomRight(const SizeF& targetSize, const OffsetF& targetOffset)
291 {
292     auto pipelineContext = PipelineContext::GetCurrentContext();
293     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
294     return LessOrEqual(WINDOW_EDGE_SPACE.ConvertToPx(), targetOffset.GetX() + targetSize.Width() - sheetWidth_) &&
295            GreatOrEqual(
296                windowGlobalRect.Width() - WINDOW_EDGE_SPACE.ConvertToPx(), targetOffset.GetX() + targetSize.Width());
297 }
298 
GetOffsetWithBottom(const SizeF & targetSize,const OffsetF & targetOffset)299 OffsetF SheetPresentationLayoutAlgorithm::GetOffsetWithBottom(const SizeF& targetSize, const OffsetF& targetOffset)
300 {
301     arrowOffsetX_ = sheetWidth_ / SHEET_HALF_SIZE;
302     return OffsetF(targetOffset.GetX() + (targetSize.Width() - sheetWidth_) / SHEET_HALF_SIZE,
303         targetOffset.GetY() + targetSize.Height() + SHEET_TARGET_SPACE.ConvertToPx());
304 }
305 
GetOffsetWithBottomLeft(const SizeF & targetSize,const OffsetF & targetOffset)306 OffsetF SheetPresentationLayoutAlgorithm::GetOffsetWithBottomLeft(const SizeF& targetSize, const OffsetF& targetOffset)
307 {
308     arrowOffsetX_ = targetSize.Width() / SHEET_HALF_SIZE;
309     auto sheetOffset =
310         OffsetF(targetOffset.GetX(), targetOffset.GetY() + targetSize.Height() + SHEET_TARGET_SPACE.ConvertToPx());
311 
312     // if the arrow overlaps the sheet left corner, move sheet to the 6vp from the left edge
313     if (LessNotEqual(arrowOffsetX_ - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(), sheetRadius_)) {
314         sheetOffset.SetX(WINDOW_EDGE_SPACE.ConvertToPx());
315         arrowOffsetX_ = targetOffset.GetX() + targetSize.Width() / SHEET_HALF_SIZE - sheetOffset.GetX();
316         TAG_LOGD(AceLogTag::ACE_SHEET, "Adjust sheet to the left boundary of the screen");
317     }
318 
319     // if the arrow still overlaps the sheet left corner, the arrow will become a right angle.
320     if (LessNotEqual(arrowOffsetX_ - ARROW_VERTICAL_P1_OFFSET_X.ConvertToPx(), sheetRadius_)) {
321         isRightAngleArrow_ = true;
322         TAG_LOGD(AceLogTag::ACE_SHEET, "Need to switch the arrow into the right-angle arrow");
323     }
324     return sheetOffset;
325 }
326 
GetOffsetWithBottomRight(const SizeF & targetSize,const OffsetF & targetOffset)327 OffsetF SheetPresentationLayoutAlgorithm::GetOffsetWithBottomRight(const SizeF& targetSize, const OffsetF& targetOffset)
328 {
329     auto pipelineContext = PipelineContext::GetCurrentContext();
330     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
331     arrowOffsetX_ = sheetWidth_ - targetSize.Width() / SHEET_HALF_SIZE;
332     auto sheetOffset = OffsetF(targetOffset.GetX() + targetSize.Width() - sheetWidth_,
333         targetOffset.GetY() + targetSize.Height() + SHEET_TARGET_SPACE.ConvertToPx());
334 
335     // if the arrow overlaps the sheet right corner, move sheet to the 6vp from the right edge
336     if (GreatNotEqual(arrowOffsetX_ + sheetRadius_ + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(), sheetWidth_)) {
337         sheetOffset.SetX(windowGlobalRect.Width() - WINDOW_EDGE_SPACE.ConvertToPx() - sheetWidth_);
338         arrowOffsetX_ = targetOffset.GetX() + targetSize.Width() / SHEET_HALF_SIZE - sheetOffset.GetX();
339         TAG_LOGD(AceLogTag::ACE_SHEET, "Adjust sheet to the right boundary of the screen");
340     }
341 
342     // if the arrow still overlaps the sheet right corner, the arrow will become a right angle.
343     if (GreatNotEqual(arrowOffsetX_ + sheetRadius_ + ARROW_VERTICAL_P5_OFFSET_X.ConvertToPx(), sheetWidth_)) {
344         isRightAngleArrow_ = true;
345         TAG_LOGD(AceLogTag::ACE_SHEET, "Need to switch the arrow into the right angle arrow");
346     }
347     return sheetOffset;
348 }
349 
GetHeightByScreenSizeType(const SizeF & maxSize) const350 float SheetPresentationLayoutAlgorithm::GetHeightByScreenSizeType(const SizeF& maxSize) const
351 {
352     float height = maxSize.Height();
353     switch (sheetType_) {
354         case SheetType::SHEET_BOTTOM:
355         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
356         case SheetType::SHEET_BOTTOMLANDSPACE:
357             height = maxSize.Height();
358             break;
359         case SheetType::SHEET_CENTER:
360             height = GetHeightBySheetStyle();
361             break;
362         case SheetType::SHEET_POPUP:
363             height = GetHeightBySheetStyle() + SHEET_ARROW_HEIGHT.ConvertToPx();
364             break;
365         default:
366             break;
367     }
368 
369     return height;
370 }
371 
GetWidthByScreenSizeType(const SizeF & maxSize,LayoutWrapper * layoutWrapper) const372 float SheetPresentationLayoutAlgorithm::GetWidthByScreenSizeType(const SizeF& maxSize,
373     LayoutWrapper* layoutWrapper) const
374 {
375     float width = maxSize.Width();
376     auto host = layoutWrapper->GetHostNode();
377     CHECK_NULL_RETURN(host, width);
378     auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
379     CHECK_NULL_RETURN(sheetPattern, width);
380     switch (sheetType_) {
381         case SheetType::SHEET_BOTTOM:
382             if (sheetPattern->IsPhoneInLandScape()) {
383                 width = std::min(static_cast<float>(SHEET_LANDSCAPE_WIDTH.ConvertToPx()), maxSize.Width());
384                 break;
385             }
386         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
387             width = maxSize.Width();
388             break;
389         case SheetType::SHEET_BOTTOMLANDSPACE:
390         case SheetType::SHEET_CENTER:
391             width = SHEET_LANDSCAPE_WIDTH.ConvertToPx();
392             break;
393         case SheetType::SHEET_POPUP:
394             width = SHEET_POPUP_WIDTH.ConvertToPx();
395             break;
396         default:
397             break;
398     }
399     return width;
400 }
401 
GetHeightBySheetStyle() const402 float SheetPresentationLayoutAlgorithm::GetHeightBySheetStyle() const
403 {
404     float height = 0.0f;
405     bool isMediumOrLargeMode = false;
406     if (sheetStyle_.sheetMode == SheetMode::MEDIUM || sheetStyle_.sheetMode == SheetMode::LARGE) {
407         isMediumOrLargeMode =  true;
408     }
409     if (sheetStyle_.height.has_value() || isMediumOrLargeMode) {
410         float sheetMaxHeight = sheetMaxHeight_;
411         if (SheetInSplitWindow()) {
412             sheetMaxHeight = sheetMaxHeight_ - SHEET_SPLIT_STATUS_BAR.ConvertToPx()-
413                 SHEET_SPLIT_AI_BAR.ConvertToPx();
414         }
415         auto maxHeight = std::min(sheetMaxHeight, sheetMaxWidth_) * POPUP_LARGE_SIZE;
416         if (sheetStyle_.height->Unit() == DimensionUnit::PERCENT) {
417             height = sheetStyle_.height->ConvertToPxWithSize(maxHeight);
418         } else if (isMediumOrLargeMode) {
419             height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
420         } else {
421             height = sheetStyle_.height->ConvertToPx();
422         }
423 
424         maxHeight = SheetInSplitWindow()
425             ? maxHeight : std::max(maxHeight, static_cast<float>(SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()));
426         if (LessNotEqual(height, 0.0f)) {
427             height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
428         } else if (LessOrEqual(height, SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()) && !SheetInSplitWindow()) {
429             height = SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx();
430         } else if (GreatOrEqual(height, maxHeight)) {
431             height = maxHeight;
432         }
433     } else {
434         height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
435     }
436     return height;
437 }
438 
CreateSheetChildConstraint(RefPtr<SheetPresentationProperty> layoutprop)439 LayoutConstraintF SheetPresentationLayoutAlgorithm::CreateSheetChildConstraint(
440     RefPtr<SheetPresentationProperty> layoutprop)
441 {
442     auto childConstraint = layoutprop->CreateChildConstraint();
443     auto pipeline = PipelineContext::GetCurrentContext();
444     CHECK_NULL_RETURN(pipeline, childConstraint);
445     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
446     CHECK_NULL_RETURN(sheetTheme, childConstraint);
447 
448     childConstraint.maxSize.SetWidth(sheetWidth_);
449     auto maxHeight = sheetHeight_;
450     if ((sheetStyle_.isTitleBuilder.has_value()) &&
451         ((sheetType_ == SheetType::SHEET_CENTER) || (sheetType_ == SheetType::SHEET_POPUP))) {
452         maxHeight -= SHEET_OPERATION_AREA_HEIGHT.ConvertToPx();
453     }
454     childConstraint.maxSize.SetHeight(maxHeight);
455     childConstraint.parentIdealSize = OptionalSizeF(sheetWidth_, sheetHeight_);
456     childConstraint.percentReference = SizeF(sheetWidth_, sheetHeight_);
457     return childConstraint;
458 }
459 
SheetInSplitWindow() const460 bool SheetPresentationLayoutAlgorithm::SheetInSplitWindow() const
461 {
462     //whether window in up and down split mode
463     auto pipelineContext = PipelineContext::GetCurrentContext();
464     auto windowManager = pipelineContext->GetWindowManager();
465     auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
466     int32_t deviceHeight = SystemProperties::GetDeviceHeight();
467     if (sheetType_ == SheetType::SHEET_CENTER && windowManager && windowGlobalRect.Height() < deviceHeight &&
468         (windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
469         windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY)) {
470         return true;
471     }
472     return false;
473 }
474 } // namespace OHOS::Ace::NG