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