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 "ui/base/referenced.h"
18 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
19 #include "core/components_ng/pattern/overlay/sheet_view.h"
20 #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h"
21
22 namespace OHOS::Ace::NG {
23 namespace {
24 constexpr int32_t DOUBLE_SIZE = 2;
25 } // namespace
26
InitParameter(LayoutWrapper * layoutWrapper)27 void SheetPresentationLayoutAlgorithm::InitParameter(LayoutWrapper* layoutWrapper)
28 {
29 CHECK_NULL_VOID(layoutWrapper);
30 auto host = layoutWrapper->GetHostNode();
31 CHECK_NULL_VOID(host);
32 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
33 CHECK_NULL_VOID(sheetPattern);
34 auto pipeline = host->GetContext();
35 CHECK_NULL_VOID(pipeline);
36 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
37 CHECK_NULL_VOID(sheetTheme);
38
39 // if 2in1, enableHoverMode is true by default.
40 DeviceType deviceType = SystemProperties::GetDeviceType();
41 auto enableHoverMode = sheetStyle_.enableHoverMode.value_or((deviceType == DeviceType::TWO_IN_ONE) ? true : false);
42 hoverModeArea_ = sheetStyle_.hoverModeArea.value_or(
43 (deviceType == DeviceType::TWO_IN_ONE) ? HoverModeAreaType::TOP_SCREEN : HoverModeAreaType::BOTTOM_SCREEN);
44 auto safeAreaManager = pipeline->GetSafeAreaManager();
45 auto keyboardInsert = safeAreaManager->GetKeyboardInset();
46 isKeyBoardShow_ = keyboardInsert.IsValid();
47 isHoverMode_ = enableHoverMode ? pipeline->IsHalfFoldHoverStatus() : false;
48 if (deviceType == DeviceType::TWO_IN_ONE) {
49 // if 2in1 WaterfallWindowMode, enableHoverMode is true by default.
50 isWaterfallWindowMode_ = sheetPattern->IsWaterfallWindowMode();
51 isHoverMode_ = enableHoverMode ? isWaterfallWindowMode_ : false;
52 }
53 }
54
CalculateSheetHeightInOtherScenes(LayoutWrapper * layoutWrapper,const float heightBefore) const55 float SheetPresentationLayoutAlgorithm::CalculateSheetHeightInOtherScenes(
56 LayoutWrapper* layoutWrapper, const float heightBefore) const
57 {
58 auto height = heightBefore;
59 CHECK_NULL_RETURN(layoutWrapper, height);
60 auto host = layoutWrapper->GetHostNode();
61 CHECK_NULL_RETURN(host, height);
62 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
63 CHECK_NULL_RETURN(sheetPattern, height);
64 auto foldCreaseRect = sheetPattern->GetFoldScreenRect(); // relative window
65 if (sheetType_ != SheetType::SHEET_CENTER || !isHoverMode_) {
66 return height;
67 }
68 float maxUpSheetHeight = foldCreaseRect.Top() - SHEET_HOVERMODE_UP_HEIGHT.ConvertToPx();
69 float maxDownSheetHeight = sheetMaxHeight_ - SHEET_HOVERMODE_DOWN_HEIGHT.ConvertToPx() - foldCreaseRect.Bottom();
70 NG::RectF floatButtons;
71 if (isWaterfallWindowMode_) {
72 auto sheetWrapper = host->GetParent();
73 CHECK_NULL_RETURN(sheetWrapper, height);
74 auto sheetWrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper);
75 CHECK_NULL_RETURN(sheetWrapperNode, height);
76 maxUpSheetHeight = foldCreaseRect.Top() - sheetWrapperNode->GetPositionToScreen().GetY() -
77 DOUBLE_SIZE * (SHEET_BLANK_MINI_HEIGHT.ConvertToPx());
78 if (sheetPattern->GetWindowButtonRectForAllAPI(floatButtons)) {
79 maxUpSheetHeight =
80 foldCreaseRect.Top() - DOUBLE_SIZE * (floatButtons.Height() + SHEET_BLANK_MINI_HEIGHT.ConvertToPx());
81 }
82 }
83 TAG_LOGD(AceLogTag::ACE_SHEET, "maxUpSheetHeight: %{public}f, maxDownSheetHeight: %{public}f.", maxUpSheetHeight,
84 maxDownSheetHeight);
85 return std::min(height,
86 (hoverModeArea_ == HoverModeAreaType::TOP_SCREEN || isKeyBoardShow_) ? maxUpSheetHeight : maxDownSheetHeight);
87 }
88
CalculateSheetOffsetInOtherScenes(LayoutWrapper * layoutWrapper)89 void SheetPresentationLayoutAlgorithm::CalculateSheetOffsetInOtherScenes(LayoutWrapper* layoutWrapper)
90 {
91 CHECK_NULL_VOID(layoutWrapper);
92 auto host = layoutWrapper->GetHostNode();
93 CHECK_NULL_VOID(host);
94 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
95 CHECK_NULL_VOID(sheetPattern);
96 auto geometryNode = layoutWrapper->GetGeometryNode();
97 CHECK_NULL_VOID(geometryNode);
98 auto foldCreaseRect = sheetPattern->GetFoldScreenRect(); // relative window
99 auto frameSizeHeight = geometryNode->GetFrameSize().Height();
100 if (sheetType_ != SheetType::SHEET_CENTER || !isHoverMode_) {
101 return;
102 }
103 float upScreenHeight = foldCreaseRect.Top() - SHEET_HOVERMODE_UP_HEIGHT.ConvertToPx();
104 float downScreenHeight = sheetMaxHeight_ - SHEET_HOVERMODE_DOWN_HEIGHT.ConvertToPx() - foldCreaseRect.Bottom();
105 float topStartOffsetY = SHEET_HOVERMODE_UP_HEIGHT.ConvertToPx();
106 NG::RectF floatButtons;
107 if (isWaterfallWindowMode_) {
108 auto sheetWrapper = host->GetParent();
109 CHECK_NULL_VOID(sheetWrapper);
110 auto sheetWrapperNode = AceType::DynamicCast<FrameNode>(sheetWrapper);
111 CHECK_NULL_VOID(sheetWrapperNode);
112 upScreenHeight = foldCreaseRect.Top() - sheetWrapperNode->GetPositionToScreen().GetY();
113 topStartOffsetY = 0.0f;
114 if (sheetPattern->GetWindowButtonRectForAllAPI(floatButtons)) {
115 upScreenHeight =
116 foldCreaseRect.Top() - DOUBLE_SIZE * (floatButtons.Height() + SHEET_BLANK_MINI_HEIGHT.ConvertToPx());
117 topStartOffsetY = floatButtons.Height() + SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
118 }
119 }
120 if (hoverModeArea_ == HoverModeAreaType::TOP_SCREEN || isKeyBoardShow_) {
121 sheetOffsetY_ = topStartOffsetY + (upScreenHeight - frameSizeHeight) / DOUBLE_SIZE;
122 } else {
123 sheetOffsetY_ = foldCreaseRect.Bottom() + (downScreenHeight - frameSizeHeight) / DOUBLE_SIZE;
124 }
125 }
126
ComputeWidthAndHeight(LayoutWrapper * layoutWrapper)127 void SheetPresentationLayoutAlgorithm::ComputeWidthAndHeight(LayoutWrapper* layoutWrapper)
128 {
129 auto host = layoutWrapper->GetHostNode();
130 CHECK_NULL_VOID(host);
131 auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
132 CHECK_NULL_VOID(sheetWrapper);
133 auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
134 CHECK_NULL_VOID(sheetWrapperPattern);
135 auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
136 CHECK_NULL_VOID(layoutProperty);
137 auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
138 LayoutConstraintF layoutConstraint = parentConstraint.value();
139 layoutProperty->UpdateLayoutConstraint(layoutConstraint);
140 auto maxSize = layoutConstraint.maxSize;
141 sheetMaxHeight_ = maxSize.Height();
142 sheetMaxWidth_ = maxSize.Width();
143 auto showInSubWindow = sheetStyle_.showInSubWindow.value_or(false);
144 auto parentHeightConstraint = sheetMaxHeight_;
145 auto parentWidthConstraint = sheetMaxWidth_;
146 if (showInSubWindow && !sheetWrapperPattern->ShowInUEC()) {
147 auto host = layoutWrapper->GetHostNode();
148 CHECK_NULL_VOID(host);
149 auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
150 CHECK_NULL_VOID(sheetWrapper);
151 auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
152 CHECK_NULL_VOID(sheetWrapperPattern);
153 auto mainWindowRect = sheetWrapperPattern->GetMainWindowRect();
154 parentHeightConstraint = mainWindowRect.Height();
155 parentWidthConstraint = mainWindowRect.Width();
156 }
157 sheetWidth_ = GetWidthByScreenSizeType(parentWidthConstraint, layoutWrapper);
158 sheetHeight_ = GetHeightByScreenSizeType(parentHeightConstraint, parentWidthConstraint, layoutWrapper);
159 }
160
MeasureDragBar(LayoutWrapper * layoutWrapper,LayoutConstraintF constraint)161 void SheetPresentationLayoutAlgorithm::MeasureDragBar(LayoutWrapper* layoutWrapper, LayoutConstraintF constraint)
162 {
163 auto host = layoutWrapper->GetHostNode();
164 CHECK_NULL_VOID(host);
165 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
166 CHECK_NULL_VOID(sheetPattern);
167 auto dragBarNode = sheetPattern->GetDragBarNode();
168 CHECK_NULL_VOID(dragBarNode);
169 dragBarNode->Measure(constraint);
170 }
171
MeasureOperation(LayoutWrapper * layoutWrapper,LayoutConstraintF constraint)172 void SheetPresentationLayoutAlgorithm::MeasureOperation(LayoutWrapper* layoutWrapper, LayoutConstraintF constraint)
173 {
174 auto host = layoutWrapper->GetHostNode();
175 CHECK_NULL_VOID(host);
176 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
177 CHECK_NULL_VOID(sheetPattern);
178 auto operationNode = sheetPattern->GetTitleBuilderNode();
179 CHECK_NULL_VOID(operationNode);
180 operationNode->Measure(constraint);
181 }
182
MeasureCloseIcon(LayoutWrapper * layoutWrapper,LayoutConstraintF constraint)183 void SheetPresentationLayoutAlgorithm::MeasureCloseIcon(LayoutWrapper* layoutWrapper, LayoutConstraintF constraint)
184 {
185 auto host = layoutWrapper->GetHostNode();
186 CHECK_NULL_VOID(host);
187 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
188 CHECK_NULL_VOID(sheetPattern);
189 auto sheetCloseIcon = sheetPattern->GetSheetCloseIcon();
190 CHECK_NULL_VOID(sheetCloseIcon);
191 sheetCloseIcon->Measure(constraint);
192 }
193
Measure(LayoutWrapper * layoutWrapper)194 void SheetPresentationLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
195 {
196 CHECK_NULL_VOID(layoutWrapper);
197 auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
198 CHECK_NULL_VOID(layoutProperty);
199 sheetStyle_ = layoutProperty->GetSheetStyleValue(SheetStyle());
200 auto layoutConstraint = layoutProperty->GetLayoutConstraint();
201 if (!layoutConstraint) {
202 TAG_LOGE(AceLogTag::ACE_SHEET, "fail to measure sheet due to layoutConstraint is nullptr");
203 return;
204 }
205 InitParameter(layoutWrapper);
206 if (layoutWrapper->GetGeometryNode() && layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint()) {
207 ComputeWidthAndHeight(layoutWrapper);
208 AddArrowHeightToSheetSize();
209 SizeF idealSize(sheetWidth_, sheetHeight_);
210 layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
211 layoutWrapper->GetGeometryNode()->SetContentSize(idealSize);
212 auto childConstraint = CreateSheetChildConstraint(layoutProperty, layoutWrapper);
213 layoutConstraint->percentReference = SizeF(sheetWidth_, sheetHeight_);
214 MeasureDragBar(layoutWrapper, childConstraint);
215 MeasureOperation(layoutWrapper, childConstraint);
216 MeasureCloseIcon(layoutWrapper, childConstraint);
217 auto host = layoutWrapper->GetHostNode();
218 CHECK_NULL_VOID(host);
219 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
220 CHECK_NULL_VOID(sheetPattern);
221 auto scrollNode = sheetPattern->GetSheetScrollNode();
222 CHECK_NULL_VOID(scrollNode);
223 childConstraint.selfIdealSize.SetWidth(childConstraint.maxSize.Width());
224 scrollNode->Measure(childConstraint);
225 if ((sheetType_ == SheetType::SHEET_CENTER || sheetType_ == SheetType::SHEET_POPUP ||
226 (sheetType_ == SheetType::SHEET_BOTTOM_OFFSET))
227 && (sheetStyle_.sheetHeight.sheetMode.value_or(SheetMode::LARGE) == SheetMode::AUTO)) {
228 auto secondChild = AceType::DynamicCast<LayoutWrapper>(scrollNode);
229 CHECK_NULL_VOID(secondChild);
230 auto&& scrollChild = secondChild->GetAllChildrenWithBuild();
231 auto builder = scrollChild.front();
232 CHECK_NULL_VOID(builder);
233 auto builderGeometryNode = builder->GetGeometryNode();
234 CHECK_NULL_VOID(builderGeometryNode);
235 sheetHeight_ = sheetPattern->GetTitleBuilderHeight() + builderGeometryNode->GetFrameSize().Height();
236 float sheetMaxHeight = sheetMaxHeight_;
237 if (SheetInSplitWindow()) {
238 auto pipelineContext = PipelineContext::GetCurrentContext();
239 auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
240 sheetMaxHeight = windowGlobalRect.Height() - SHEET_SPLIT_STATUS_BAR.ConvertToPx()-
241 SHEET_SPLIT_AI_BAR.ConvertToPx();
242 }
243 auto pipeline = host->GetContext();
244 CHECK_NULL_VOID(pipeline);
245 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
246 CHECK_NULL_VOID(sheetTheme);
247 auto bigWindowMinHeight = sheetTheme->GetBigWindowMinHeight();
248 auto maxHeight = std::min(sheetMaxHeight, sheetMaxWidth_) * POPUP_LARGE_SIZE;
249 maxHeight = SheetInSplitWindow()
250 ? maxHeight : std::max(maxHeight, static_cast<float>(bigWindowMinHeight.ConvertToPx()));
251 if (LessNotEqual(sheetHeight_, 0.0f)) {
252 sheetHeight_ = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
253 } else if (LessOrEqual(sheetHeight_, bigWindowMinHeight.ConvertToPx()) && !SheetInSplitWindow()) {
254 sheetHeight_ = bigWindowMinHeight.ConvertToPx();
255 } else if (GreatOrEqual(sheetHeight_, maxHeight)) {
256 sheetHeight_ = maxHeight;
257 }
258 SizeF idealSize(sheetWidth_, sheetHeight_);
259 layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
260 childConstraint = CreateSheetChildConstraint(layoutProperty, layoutWrapper);
261 secondChild->Measure(childConstraint);
262 }
263 }
264 }
265
ComputeCenterStyleOffset(LayoutWrapper * layoutWrapper)266 void SheetPresentationLayoutAlgorithm::ComputeCenterStyleOffset(LayoutWrapper* layoutWrapper)
267 {
268 auto showInSubWindow = sheetStyle_.showInSubWindow.value_or(false);
269 if (!showInSubWindow) {
270 sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / DOUBLE_SIZE;
271 return;
272 }
273 auto host = layoutWrapper->GetHostNode();
274 CHECK_NULL_VOID(host);
275 auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
276 CHECK_NULL_VOID(sheetWrapper);
277 auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
278 CHECK_NULL_VOID(sheetWrapperPattern);
279 auto geometryNode = host->GetGeometryNode();
280 CHECK_NULL_VOID(geometryNode);
281 auto sheetFrameSize = geometryNode->GetFrameSize();
282
283 if (sheetWrapperPattern->ShowInUEC()) {
284 ComputeCenterOffsetForUECSubwindow(layoutWrapper);
285 } else {
286 ComputeCenterOffsetForNotUECSubwindow(layoutWrapper);
287 }
288
289 std::vector<Rect> rects;
290 auto rect = Rect(sheetOffsetX_, sheetOffsetY_,
291 sheetFrameSize.Width(), sheetFrameSize.Height());
292 rects.emplace_back(rect);
293 SubwindowManager::GetInstance()->SetHotAreas(rects, SubwindowType::TYPE_SHEET,
294 host->GetId(), sheetWrapperPattern->GetSubWindowId());
295 }
296
ComputeCenterOffsetForUECSubwindow(LayoutWrapper * layoutWrapper)297 void SheetPresentationLayoutAlgorithm::ComputeCenterOffsetForUECSubwindow(
298 LayoutWrapper* layoutWrapper)
299 {
300 CHECK_NULL_VOID(layoutWrapper);
301 auto host = layoutWrapper->GetHostNode();
302 CHECK_NULL_VOID(host);
303 sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / DOUBLE_SIZE;
304 sheetOffsetY_ = (sheetMaxHeight_ - sheetHeight_) / DOUBLE_SIZE;
305 }
306
ComputeCenterOffsetForNotUECSubwindow(LayoutWrapper * layoutWrapper)307 void SheetPresentationLayoutAlgorithm::ComputeCenterOffsetForNotUECSubwindow(LayoutWrapper* layoutWrapper)
308 {
309 CHECK_NULL_VOID(layoutWrapper);
310 auto host = layoutWrapper->GetHostNode();
311 CHECK_NULL_VOID(host);
312 auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
313 CHECK_NULL_VOID(sheetWrapper);
314 auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
315 CHECK_NULL_VOID(sheetWrapperPattern);
316 auto mainWindowRect = sheetWrapperPattern->GetMainWindowRect();
317 auto geometryNode = host->GetGeometryNode();
318 CHECK_NULL_VOID(geometryNode);
319 auto sheetFrameSize = geometryNode->GetFrameSize();
320 auto hostWindowId = SubwindowManager::GetInstance()->GetParentContainerId(sheetWrapperPattern->GetSubWindowId());
321 ContainerScope scope(hostWindowId);
322 auto container = AceEngine::Get().GetContainer(hostWindowId);
323 CHECK_NULL_VOID(container);
324 auto mainWindowContext = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
325
326 auto subContainer = AceEngine::Get().GetContainer(sheetWrapperPattern->GetSubWindowId());
327 CHECK_NULL_VOID(subContainer);
328 auto subWindowContext = AceType::DynamicCast<NG::PipelineContext>(subContainer->GetPipelineContext());
329 CHECK_NULL_VOID(subWindowContext);
330 auto subwindowRootRect = subWindowContext->GetRootRect();
331 sheetOffsetY_ = (subwindowRootRect.Height() - sheetFrameSize.Height()) / DOUBLE_SIZE;
332 sheetOffsetX_ = (subwindowRootRect.Width() - sheetFrameSize.Width()) / DOUBLE_SIZE;
333
334 OffsetF windowAnchoroffset;
335 auto sheetTheme = mainWindowContext->GetTheme<SheetTheme>();
336 CHECK_NULL_VOID(sheetTheme);
337 auto bigWindowMinHeight = sheetTheme->GetBigWindowMinHeight();
338 RectF containerModal;
339 RectF buttonsRect;
340 // By default, subWindow and mainWindow are aligned based on center anchor.
341 // When mainwindow is reduced to a certain extent, centerSheet will stick to the title bar of the mainWindow layout.
342 // At this time, the anchor point of subWindow and mainWindow need to be moved down at a distance.
343 // The distance is equal to a half of the reduced height.
344 if (mainWindowContext && mainWindowContext->GetContainerModalButtonsRect(containerModal, buttonsRect)) {
345 auto maxMainWindowHeight = bigWindowMinHeight.ConvertToPx() +
346 DOUBLE_SIZE * (buttonsRect.Height() + SHEET_BLANK_MINI_HEIGHT.ConvertToPx());
347 windowAnchoroffset.SetY(mainWindowRect.Height() > maxMainWindowHeight ? 0.0f :
348 (maxMainWindowHeight - mainWindowRect.Height()) / DOUBLE_SIZE);
349 }
350 SubwindowManager::GetInstance()->SetWindowAnchorInfo(
351 windowAnchoroffset, SubwindowType::TYPE_SHEET, host->GetId(), sheetWrapperPattern->GetSubWindowId());
352 }
353
ComputePopupStyleOffset(LayoutWrapper * layoutWrapper)354 void SheetPresentationLayoutAlgorithm::ComputePopupStyleOffset(LayoutWrapper* layoutWrapper)
355 {
356 sheetOffsetX_ = sheetPopupInfo_.sheetOffsetX;
357 sheetOffsetY_ = sheetPopupInfo_.sheetOffsetY;
358 auto showInSubWindow = sheetStyle_.showInSubWindow.value_or(false);
359 if (showInSubWindow) {
360 auto host = layoutWrapper->GetHostNode();
361 CHECK_NULL_VOID(host);
362 auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
363 CHECK_NULL_VOID(sheetWrapper);
364 auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
365 CHECK_NULL_VOID(sheetWrapperPattern);
366 MinusSubwindowDistance(sheetWrapper);
367 std::vector<Rect> rects;
368 auto rect = Rect(sheetOffsetX_, sheetOffsetY_,
369 host->GetGeometryNode()->GetFrameSize().Width(), host->GetGeometryNode()->GetFrameSize().Height());
370 rects.emplace_back(rect);
371 auto subWindowMgr = SubwindowManager::GetInstance();
372 subWindowMgr->SetHotAreas(rects, SubwindowType::TYPE_SHEET, host->GetId(),
373 sheetWrapperPattern->GetSubWindowId());
374 }
375 }
376
MinusSubwindowDistance(const RefPtr<FrameNode> & sheetWrapper)377 void SheetPresentationLayoutAlgorithm::MinusSubwindowDistance(const RefPtr<FrameNode>& sheetWrapper)
378 {
379 // when subwindow is not full screen for split or small floating window
380 CHECK_NULL_VOID(sheetWrapper);
381 auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
382 CHECK_NULL_VOID(sheetWrapperPattern);
383 auto subContainer = AceEngine::Get().GetContainer(sheetWrapperPattern->GetSubWindowId());
384 CHECK_NULL_VOID(subContainer);
385 auto subWindowContext = AceType::DynamicCast<NG::PipelineContext>(subContainer->GetPipelineContext());
386 CHECK_NULL_VOID(subWindowContext);
387 auto subWindowGlobalRect = subWindowContext->GetDisplayWindowRectInfo();
388 sheetOffsetX_ -= subWindowGlobalRect.Left();
389 sheetOffsetY_ -= subWindowGlobalRect.Top();
390 }
391
LayoutTitleBuilder(const NG::OffsetF & translate,LayoutWrapper * layoutWrapper)392 void SheetPresentationLayoutAlgorithm::LayoutTitleBuilder(const NG::OffsetF& translate, LayoutWrapper* layoutWrapper)
393 {
394 auto host = layoutWrapper->GetHostNode();
395 CHECK_NULL_VOID(host);
396 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
397 CHECK_NULL_VOID(sheetPattern);
398 auto titleBuilderNode = sheetPattern->GetTitleBuilderNode();
399 CHECK_NULL_VOID(titleBuilderNode);
400 auto index = host->GetChildIndexById(titleBuilderNode->GetId());
401 auto titleBuilderWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
402 CHECK_NULL_VOID(titleBuilderWrapper);
403 auto geometryNode = titleBuilderWrapper->GetGeometryNode();
404 CHECK_NULL_VOID(geometryNode);
405 auto offset = translate;
406 auto dragBarNode = sheetPattern->GetDragBarNode();
407 CHECK_NULL_VOID(dragBarNode);
408 if (!sheetStyle_.enableFloatingDragBar.value_or(false) || !sheetPattern->IsSheetBottomStyle()) {
409 auto dragBar = dragBarNode->GetGeometryNode();
410 CHECK_NULL_VOID(dragBar);
411 offset += OffsetF(0, dragBar->GetFrameSize().Height());
412 }
413 geometryNode->SetMarginFrameOffset(offset);
414 titleBuilderWrapper->Layout();
415 }
416
LayoutCloseIcon(const NG::OffsetF & translate,LayoutWrapper * layoutWrapper)417 void SheetPresentationLayoutAlgorithm::LayoutCloseIcon(const NG::OffsetF& translate,
418 LayoutWrapper* layoutWrapper)
419 {
420 auto host = layoutWrapper->GetHostNode();
421 CHECK_NULL_VOID(host);
422 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
423 CHECK_NULL_VOID(sheetPattern);
424 auto sheetCloseNode = sheetPattern->GetSheetCloseIcon();
425 CHECK_NULL_VOID(sheetCloseNode);
426 auto index = host->GetChildIndexById(sheetCloseNode->GetId());
427 auto closeIconWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
428 CHECK_NULL_VOID(closeIconWrapper);
429 auto geometryNode = closeIconWrapper->GetGeometryNode();
430 CHECK_NULL_VOID(geometryNode);
431
432 auto pipeline = host->GetContext();
433 CHECK_NULL_VOID(pipeline);
434 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
435 CHECK_NULL_VOID(sheetTheme);
436 auto sheetGeometryNode = layoutWrapper->GetGeometryNode();
437 CHECK_NULL_VOID(sheetGeometryNode);
438 auto closeIconX = sheetGeometryNode->GetFrameSize().Width() -
439 static_cast<float>(sheetTheme->GetCloseIconButtonWidth().ConvertToPx()) -
440 static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
441 if (AceApplicationInfo::GetInstance().IsRightToLeft() &&
442 AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
443 closeIconX = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
444 }
445 auto closeIconY = static_cast<float>(sheetTheme->GetTitleTextMargin().ConvertToPx());
446 OffsetF positionOffset;
447 positionOffset.SetX(closeIconX + translate.GetX());
448 positionOffset.SetY(closeIconY + translate.GetY());
449 geometryNode->SetMarginFrameOffset(positionOffset);
450 closeIconWrapper->Layout();
451 }
452
LayoutScrollNode(const NG::OffsetF & translate,LayoutWrapper * layoutWrapper)453 void SheetPresentationLayoutAlgorithm::LayoutScrollNode(const NG::OffsetF& translate, LayoutWrapper* layoutWrapper)
454 {
455 auto host = layoutWrapper->GetHostNode();
456 CHECK_NULL_VOID(host);
457 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
458 CHECK_NULL_VOID(sheetPattern);
459 auto scrollNode = sheetPattern->GetSheetScrollNode();
460 CHECK_NULL_VOID(scrollNode);
461 auto index = host->GetChildIndexById(scrollNode->GetId());
462 auto scrollWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
463 CHECK_NULL_VOID(scrollWrapper);
464
465 auto offset = translate;
466 auto titleBuilder = sheetPattern->GetTitleBuilderNode();
467 auto dragBarNode = sheetPattern->GetDragBarNode();
468 if (titleBuilder) {
469 auto titleBuilderNode = titleBuilder->GetGeometryNode();
470 CHECK_NULL_VOID(titleBuilderNode);
471 float titleHeight =
472 Positive(titleBuilderNode->GetFrameSize().Height()) ? titleBuilderNode->GetFrameSize().Height() : 0.0f;
473 auto dragBar = dragBarNode->GetGeometryNode();
474 CHECK_NULL_VOID(dragBar);
475 if (!sheetStyle_.enableFloatingDragBar.value_or(false) || !sheetPattern->IsSheetBottomStyle()) {
476 offset += OffsetF(0, titleHeight + dragBar->GetFrameSize().Height());
477 } else {
478 offset += OffsetF(0, titleHeight);
479 }
480 }
481 auto geometryNode = scrollWrapper->GetGeometryNode();
482 geometryNode->SetMarginFrameOffset(offset);
483 scrollWrapper->Layout();
484 }
485
LayoutDragBar(const NG::OffsetF & translate,LayoutWrapper * layoutWrapper)486 void SheetPresentationLayoutAlgorithm::LayoutDragBar(const NG::OffsetF& translate, LayoutWrapper* layoutWrapper)
487 {
488 auto host = layoutWrapper->GetHostNode();
489 CHECK_NULL_VOID(host);
490 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
491 CHECK_NULL_VOID(sheetPattern);
492 auto dragBarNode = sheetPattern->GetDragBarNode();
493 CHECK_NULL_VOID(dragBarNode);
494 auto index = host->GetChildIndexById(dragBarNode->GetId());
495 auto dragBarWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
496 CHECK_NULL_VOID(dragBarWrapper);
497 auto geometryNode = dragBarWrapper->GetGeometryNode();
498 CHECK_NULL_VOID(geometryNode);
499 auto pipeline = host->GetContext();
500 CHECK_NULL_VOID(pipeline);
501 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
502 CHECK_NULL_VOID(sheetTheme);
503 auto sheetGeometryNode = layoutWrapper->GetGeometryNode();
504 CHECK_NULL_VOID(sheetGeometryNode);
505 auto dragBarX = (sheetGeometryNode->GetFrameSize().Width() - geometryNode->GetFrameSize().Width()) / 2;
506 OffsetF positionOffset;
507 positionOffset.SetX(dragBarX + translate.GetX());
508 CHECK_NULL_VOID(geometryNode);
509 geometryNode->SetMarginFrameOffset(positionOffset);
510 dragBarWrapper->Layout();
511 }
512
Layout(LayoutWrapper * layoutWrapper)513 void SheetPresentationLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
514 {
515 CHECK_NULL_VOID(layoutWrapper);
516 sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / DOUBLE_SIZE;
517 if (sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE) {
518 sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / DOUBLE_SIZE;
519 } else if (sheetType_ == SheetType::SHEET_CENTER) {
520 ComputeCenterStyleOffset(layoutWrapper);
521 } else if (sheetType_ == SheetType::SHEET_POPUP) {
522 ComputePopupStyleOffset(layoutWrapper);
523 } else if (sheetType_ == SheetType::SHEET_BOTTOM_OFFSET) {
524 sheetOffsetY_ = (sheetMaxHeight_ - sheetHeight_ + sheetStyle_.bottomOffset->GetY());
525 sheetOffsetX_ = sheetOffsetX_ + sheetStyle_.bottomOffset->GetX();
526 }
527 CalculateSheetOffsetInOtherScenes(layoutWrapper);
528 TAG_LOGD(AceLogTag::ACE_SHEET, "Sheet layout info, sheetOffsetX_ is: %{public}f, sheetOffsetY_ is: %{public}f",
529 sheetOffsetX_, sheetOffsetY_);
530 OffsetF positionOffset;
531 positionOffset.SetX(sheetOffsetX_);
532 positionOffset.SetY(0.0f);
533 auto geometryNode = layoutWrapper->GetGeometryNode();
534 CHECK_NULL_VOID(geometryNode);
535 // This step is only to determine the position of x, because y is to be done by the bit movement effect
536 geometryNode->SetMarginFrameOffset(positionOffset);
537 OffsetF translate(0.0f, 0.0f);
538 if (sheetType_ == SheetType::SHEET_POPUP) {
539 UpdateTranslateOffsetWithPlacement(translate, layoutWrapper);
540 }
541 LayoutCloseIcon(translate, layoutWrapper);
542 LayoutDragBar(translate, layoutWrapper);
543 LayoutTitleBuilder(translate, layoutWrapper);
544 LayoutScrollNode(translate, layoutWrapper);
545 }
546
UpdateTranslateOffsetWithPlacement(OffsetF & translate,LayoutWrapper * layoutWrapper)547 void SheetPresentationLayoutAlgorithm::UpdateTranslateOffsetWithPlacement(OffsetF& translate,
548 LayoutWrapper* layoutWrapper)
549 {
550 auto host = layoutWrapper->GetHostNode();
551 CHECK_NULL_VOID(host);
552 if (host->LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
553 translate += OffsetF(0, SHEET_ARROW_HEIGHT.ConvertToPx());
554 return;
555 }
556 if ((sheetPopupInfo_.placementRechecked && sheetPopupInfo_.placementOnTarget) ||
557 !sheetPopupInfo_.showArrow) {
558 return;
559 }
560 // child content should not show in arrow, so that child layout need translate to avoid sheet arrow.
561 switch (sheetPopupInfo_.finalPlacement) {
562 case Placement::BOTTOM_LEFT:
563 [[fallthrough]];
564 case Placement::BOTTOM_RIGHT:
565 [[fallthrough]];
566 case Placement::BOTTOM: {
567 translate += OffsetF(0.f, SHEET_ARROW_HEIGHT.ConvertToPx());
568 break;
569 }
570 case Placement::RIGHT_TOP:
571 [[fallthrough]];
572 case Placement::RIGHT_BOTTOM:
573 [[fallthrough]];
574 case Placement::RIGHT: {
575 translate += OffsetF(SHEET_ARROW_HEIGHT.ConvertToPx(), 0.f);
576 break;
577 }
578 default:
579 break;
580 }
581 }
582
GetHeightByScreenSizeType(const float parentConstraintHeight,const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const583 float SheetPresentationLayoutAlgorithm::GetHeightByScreenSizeType(const float parentConstraintHeight,
584 const float parentConstraintWidth, LayoutWrapper* layoutWrapper) const
585 {
586 float height = parentConstraintHeight;
587 switch (sheetType_) {
588 case SheetType::SHEET_BOTTOM:
589 case SheetType::SHEET_BOTTOM_FREE_WINDOW:
590 case SheetType::SHEET_BOTTOMLANDSPACE:
591 height = parentConstraintHeight;
592 break;
593 case SheetType::SHEET_BOTTOM_OFFSET:
594 case SheetType::SHEET_CENTER:
595 height = GetHeightBySheetStyle(parentConstraintHeight, parentConstraintWidth, layoutWrapper);
596 break;
597 case SheetType::SHEET_POPUP:
598 height = GetHeightBySheetStyle(parentConstraintHeight, parentConstraintWidth, layoutWrapper) +
599 SHEET_ARROW_HEIGHT.ConvertToPx();
600 // The sheet height can only be confirmed after the placement is confirmed.
601 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
602 height -= SHEET_ARROW_HEIGHT.ConvertToPx();
603 }
604 break;
605 default:
606 break;
607 }
608 height = CalculateSheetHeightInOtherScenes(layoutWrapper, height);
609 return height;
610 }
611
GetWidthByScreenSizeType(const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const612 float SheetPresentationLayoutAlgorithm::GetWidthByScreenSizeType(const float parentConstraintWidth,
613 LayoutWrapper* layoutWrapper) const
614 {
615 float sheetWidth = parentConstraintWidth;
616 auto host = layoutWrapper->GetHostNode();
617 CHECK_NULL_RETURN(host, sheetWidth);
618 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
619 CHECK_NULL_RETURN(sheetPattern, sheetWidth);
620 switch (sheetType_) {
621 case SheetType::SHEET_BOTTOM:
622 if (sheetPattern->IsPhoneInLandScape()) {
623 sheetWidth = std::min(static_cast<float>(SHEET_LANDSCAPE_WIDTH.ConvertToPx()), parentConstraintWidth);
624 break;
625 }
626 [[fallthrough]];
627 case SheetType::SHEET_BOTTOM_FREE_WINDOW:
628 sheetWidth = parentConstraintWidth;
629 break;
630 case SheetType::SHEET_BOTTOMLANDSPACE:
631 [[fallthrough]];
632 case SheetType::SHEET_CENTER:
633 sheetWidth = GetCenterDefaultWidth(host);
634 break;
635 case SheetType::SHEET_POPUP:
636 sheetWidth = SHEET_POPUP_WIDTH.ConvertToPx();
637 break;
638 default:
639 break;
640 }
641
642 if (!sheetStyle_.width.has_value()) {
643 return sheetWidth;
644 }
645 auto width = 0.0f;
646 if (sheetStyle_.width->Unit() == DimensionUnit::PERCENT) {
647 width = sheetStyle_.width->ConvertToPxWithSize(parentConstraintWidth);
648 } else {
649 width = sheetStyle_.width->ConvertToPx();
650 }
651 if (LessNotEqual(width, 0.0f) || width > parentConstraintWidth) {
652 width = sheetWidth;
653 }
654 return width;
655 }
656
GetCenterDefaultWidth(const RefPtr<FrameNode> & host) const657 float SheetPresentationLayoutAlgorithm::GetCenterDefaultWidth(const RefPtr<FrameNode>& host) const
658 {
659 auto sheetWidth = SHEET_LANDSCAPE_WIDTH.ConvertToPx();
660 CHECK_NULL_RETURN(host, sheetWidth);
661 auto pipeline = host->GetContext();
662 CHECK_NULL_RETURN(pipeline, sheetWidth);
663 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
664 CHECK_NULL_RETURN(sheetTheme, sheetWidth);
665 sheetWidth = sheetTheme->GetCenterDefaultWidth().ConvertToPx();
666 return sheetWidth;
667 }
668
ComputeMaxHeight(const float parentConstraintHeight,const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const669 float SheetPresentationLayoutAlgorithm::ComputeMaxHeight(const float parentConstraintHeight,
670 const float parentConstraintWidth, LayoutWrapper* layoutWrapper) const
671 {
672 float sheetMaxHeight = parentConstraintHeight;
673 if (SheetInSplitWindow()) {
674 sheetMaxHeight = parentConstraintHeight - SHEET_SPLIT_STATUS_BAR.ConvertToPx() -
675 SHEET_SPLIT_AI_BAR.ConvertToPx();
676 }
677 NG::RectF floatButtons;
678 auto host = layoutWrapper->GetHostNode();
679 CHECK_NULL_RETURN(host, 0.0f);
680 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
681 CHECK_NULL_RETURN(sheetPattern, 0.0f);
682 auto maxHeight = (std::min(sheetMaxHeight, parentConstraintWidth)) * POPUP_LARGE_SIZE;
683 if (sheetPattern->GetWindowButtonRect(floatButtons)) {
684 maxHeight = sheetMaxHeight - DOUBLE_SIZE *
685 (floatButtons.Height() + SHEET_BLANK_MINI_HEIGHT.ConvertToPx());
686 } else if (sheetStyle_.showInSubWindow.value_or(false)) {
687 auto sheetWrapper = AceType::DynamicCast<FrameNode>(host->GetParent());
688 CHECK_NULL_RETURN(sheetWrapper, 0.0f);
689 auto sheetWrapperPattern = sheetWrapper->GetPattern<SheetWrapperPattern>();
690 CHECK_NULL_RETURN(sheetWrapperPattern, 0.0f);
691 RectF containerModal;
692 RectF buttonsRect;
693 auto subwindowId = sheetWrapperPattern->GetSubWindowId();
694 auto currentId = SubwindowManager::GetInstance()->GetParentContainerId(subwindowId);
695 ContainerScope scope(currentId);
696 auto mainWindowContext = PipelineContext::GetContextByContainerId(currentId);
697 if (mainWindowContext && mainWindowContext->GetContainerModalButtonsRect(containerModal, buttonsRect)) {
698 maxHeight = (std::min(parentConstraintHeight - buttonsRect.Height(),
699 parentConstraintWidth)) * POPUP_LARGE_SIZE;
700 }
701 }
702 return maxHeight;
703 }
704
GetHeightBySheetStyle(const float parentConstraintHeight,const float parentConstraintWidth,LayoutWrapper * layoutWrapper) const705 float SheetPresentationLayoutAlgorithm::GetHeightBySheetStyle(const float parentConstraintHeight,
706 const float parentConstraintWidth, LayoutWrapper* layoutWrapper) const
707 {
708 float height = 0.0f;
709 bool isMediumOrLargeMode = false;
710 if (sheetStyle_.sheetHeight.sheetMode == SheetMode::MEDIUM ||
711 sheetStyle_.sheetHeight.sheetMode == SheetMode::LARGE) {
712 isMediumOrLargeMode = true;
713 }
714 if (sheetStyle_.sheetHeight.height.has_value() || isMediumOrLargeMode) {
715 auto maxHeight = ComputeMaxHeight(parentConstraintHeight, parentConstraintWidth, layoutWrapper);
716 if (sheetStyle_.sheetHeight.height->Unit() == DimensionUnit::PERCENT) {
717 height = sheetStyle_.sheetHeight.height->ConvertToPxWithSize(maxHeight);
718 } else if (isMediumOrLargeMode) {
719 height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
720 } else {
721 height = sheetStyle_.sheetHeight.height->ConvertToPx();
722 }
723 auto host = layoutWrapper->GetHostNode();
724 CHECK_NULL_RETURN(host, height);
725 auto pipeline = host->GetContext();
726 CHECK_NULL_RETURN(pipeline, height);
727 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
728 CHECK_NULL_RETURN(sheetTheme, height);
729 auto bigWindowMinHeight = sheetTheme->GetBigWindowMinHeight();
730 maxHeight = SheetInSplitWindow()
731 ? maxHeight : std::max(maxHeight, static_cast<float>(bigWindowMinHeight.ConvertToPx()));
732 // The minimum value of maxHeight is 320
733 if (LessNotEqual(height, 0.0f)) {
734 height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
735 } else if (LessOrEqual(height, bigWindowMinHeight.ConvertToPx()) && !SheetInSplitWindow()) {
736 height = bigWindowMinHeight.ConvertToPx();
737 } else if (GreatOrEqual(height, maxHeight)) {
738 height = maxHeight;
739 }
740 } else {
741 height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
742 }
743 return height;
744 }
745
CreateSheetChildConstraint(RefPtr<SheetPresentationProperty> layoutprop,LayoutWrapper * layoutWrapper)746 LayoutConstraintF SheetPresentationLayoutAlgorithm::CreateSheetChildConstraint(
747 RefPtr<SheetPresentationProperty> layoutprop, LayoutWrapper* layoutWrapper)
748 {
749 auto childConstraint = layoutprop->CreateChildConstraint();
750 auto host = layoutWrapper->GetHostNode();
751 CHECK_NULL_RETURN(host, childConstraint);
752 auto pipeline = host->GetContext();
753 CHECK_NULL_RETURN(pipeline, childConstraint);
754 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
755 CHECK_NULL_RETURN(sheetTheme, childConstraint);
756
757 childConstraint.maxSize.SetWidth(sheetWidth_);
758 auto maxHeight = sheetHeight_;
759 if ((sheetStyle_.isTitleBuilder.has_value()) &&
760 ((sheetType_ == SheetType::SHEET_CENTER) || (sheetType_ == SheetType::SHEET_POPUP))) {
761 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
762 CHECK_NULL_RETURN(sheetPattern, childConstraint);
763 maxHeight -= sheetPattern->GetTitleBuilderHeight();
764 }
765 auto maxWidth = sheetWidth_;
766 if (sheetType_ == SheetType::SHEET_POPUP) {
767 UpdateMaxSizeWithPlacement(maxWidth, maxHeight, layoutWrapper);
768 }
769 if (sheetPopupInfo_.finalPlacement != Placement::NONE) {
770 childConstraint.maxSize.SetWidth(maxWidth);
771 }
772 childConstraint.maxSize.SetHeight(maxHeight);
773 childConstraint.parentIdealSize = OptionalSizeF(sheetWidth_, sheetHeight_);
774 childConstraint.percentReference = SizeF(sheetWidth_, sheetHeight_);
775 return childConstraint;
776 }
777
UpdateMaxSizeWithPlacement(float & maxWidth,float & maxHeight,LayoutWrapper * layoutWrapper)778 void SheetPresentationLayoutAlgorithm::UpdateMaxSizeWithPlacement(float& maxWidth, float& maxHeight,
779 LayoutWrapper* layoutWrapper)
780 {
781 auto host = layoutWrapper->GetHostNode();
782 CHECK_NULL_VOID(host);
783 if (host->LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
784 maxHeight -= SHEET_ARROW_HEIGHT.ConvertToPx();
785 return;
786 }
787
788 if ((sheetPopupInfo_.placementRechecked && sheetPopupInfo_.placementOnTarget) ||
789 !sheetPopupInfo_.showArrow) {
790 return;
791 }
792
793 switch (sheetPopupInfo_.finalPlacement) {
794 case Placement::BOTTOM_LEFT:
795 [[fallthrough]];
796 case Placement::BOTTOM_RIGHT:
797 [[fallthrough]];
798 case Placement::BOTTOM:
799 [[fallthrough]];
800 case Placement::TOP_LEFT:
801 [[fallthrough]];
802 case Placement::TOP_RIGHT:
803 [[fallthrough]];
804 case Placement::TOP: {
805 maxHeight -= SHEET_ARROW_HEIGHT.ConvertToPx();
806 break;
807 }
808 case Placement::RIGHT_TOP:
809 [[fallthrough]];
810 case Placement::RIGHT_BOTTOM:
811 [[fallthrough]];
812 case Placement::RIGHT:
813 [[fallthrough]];
814 case Placement::LEFT_TOP:
815 [[fallthrough]];
816 case Placement::LEFT_BOTTOM:
817 [[fallthrough]];
818 case Placement::LEFT: {
819 maxWidth -= SHEET_ARROW_HEIGHT.ConvertToPx();
820 break;
821 }
822 default:
823 break;
824 }
825 }
826
SheetInSplitWindow() const827 bool SheetPresentationLayoutAlgorithm::SheetInSplitWindow() const
828 {
829 //whether window in up and down split mode
830 auto pipelineContext = PipelineContext::GetCurrentContext();
831 CHECK_NULL_RETURN(pipelineContext, false);
832 auto windowManager = pipelineContext->GetWindowManager();
833 CHECK_NULL_RETURN(windowManager, false);
834 auto windowGlobalRect = pipelineContext->GetDisplayWindowRectInfo();
835 int32_t deviceHeight = SystemProperties::GetDeviceHeight();
836 if (sheetType_ == SheetType::SHEET_CENTER && windowManager && windowGlobalRect.Height() < deviceHeight &&
837 (windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
838 windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY)) {
839 return true;
840 }
841 return false;
842 }
843
UpdatePopupInfoAndRemeasure(LayoutWrapper * layoutWrapper,const SheetPopupInfo & sheetPopupInfo,const float & sheetWidth,const float & sheetHeight)844 void SheetPresentationLayoutAlgorithm::UpdatePopupInfoAndRemeasure(LayoutWrapper* layoutWrapper,
845 const SheetPopupInfo& sheetPopupInfo, const float& sheetWidth, const float& sheetHeight)
846 {
847 if (sheetType_ != SheetType::SHEET_POPUP) {
848 return;
849 }
850 sheetPopupInfo_ = sheetPopupInfo;
851 sheetOffsetX_ = sheetPopupInfo.sheetOffsetX;
852 sheetOffsetY_ = sheetPopupInfo.sheetOffsetY;
853 auto host = layoutWrapper->GetHostNode();
854 CHECK_NULL_VOID(host);
855 if (host->LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
856 return;
857 }
858 sheetWidth_ = sheetWidth;
859 sheetHeight_ = sheetHeight;
860 auto sheetPageWrapper = layoutWrapper->GetChildByIndex(0);
861 CHECK_NULL_VOID(sheetPageWrapper);
862 RemeasureForPopup(sheetPageWrapper);
863 }
864
AddArrowHeightToSheetSize()865 void SheetPresentationLayoutAlgorithm::AddArrowHeightToSheetSize()
866 {
867 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN) ||
868 sheetType_ != SheetType::SHEET_POPUP) {
869 return;
870 }
871
872 if ((sheetPopupInfo_.placementRechecked && sheetPopupInfo_.placementOnTarget) ||
873 !sheetPopupInfo_.showArrow) {
874 return;
875 }
876
877 switch (sheetPopupInfo_.finalPlacement) {
878 case Placement::BOTTOM_LEFT:
879 [[fallthrough]];
880 case Placement::BOTTOM_RIGHT:
881 [[fallthrough]];
882 case Placement::BOTTOM:
883 [[fallthrough]];
884 case Placement::TOP_LEFT:
885 [[fallthrough]];
886 case Placement::TOP_RIGHT:
887 [[fallthrough]];
888 case Placement::TOP: {
889 sheetHeight_ += SHEET_ARROW_HEIGHT.ConvertToPx();
890 break;
891 }
892 case Placement::RIGHT_TOP:
893 [[fallthrough]];
894 case Placement::RIGHT_BOTTOM:
895 [[fallthrough]];
896 case Placement::RIGHT:
897 [[fallthrough]];
898 case Placement::LEFT_TOP:
899 [[fallthrough]];
900 case Placement::LEFT_BOTTOM:
901 [[fallthrough]];
902 case Placement::LEFT: {
903 sheetWidth_ += SHEET_ARROW_HEIGHT.ConvertToPx();
904 break;
905 }
906 default:
907 break;
908 }
909 }
910
RemeasureForPopup(const RefPtr<LayoutWrapper> & layoutWrapper)911 void SheetPresentationLayoutAlgorithm::RemeasureForPopup(const RefPtr<LayoutWrapper>& layoutWrapper)
912 {
913 CHECK_NULL_VOID(layoutWrapper);
914 if (layoutWrapper->GetGeometryNode() && layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint()) {
915 auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
916 if (!parentConstraint.has_value()) {
917 return;
918 }
919 auto layoutConstraint = parentConstraint.value();
920 auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
921 CHECK_NULL_VOID(layoutProperty);
922 layoutProperty->UpdateLayoutConstraint(layoutConstraint);
923 AddArrowHeightToSheetSize();
924 TAG_LOGI(AceLogTag::ACE_SHEET, "remeasure size:(%{public}f, %{public}f)", sheetWidth_, sheetHeight_);
925 SizeF idealSize(sheetWidth_, sheetHeight_);
926 layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
927 layoutWrapper->GetGeometryNode()->SetContentSize(idealSize);
928 auto childConstraint = CreateSheetChildConstraint(layoutProperty, Referenced::RawPtr(layoutWrapper));
929 layoutConstraint.percentReference = SizeF(sheetWidth_, sheetHeight_);
930 for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
931 child->Measure(childConstraint);
932 }
933 auto host = layoutWrapper->GetHostNode();
934 CHECK_NULL_VOID(host);
935 auto sheetPattern = host->GetPattern<SheetPresentationPattern>();
936 CHECK_NULL_VOID(sheetPattern);
937 auto scrollNode = sheetPattern->GetSheetScrollNode();
938 CHECK_NULL_VOID(scrollNode);
939 childConstraint.selfIdealSize.SetWidth(childConstraint.maxSize.Width());
940 scrollNode->Measure(childConstraint);
941 }
942 }
943 } // namespace OHOS::Ace::NG