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