From e4ad3d364611064785d2a5ce440e1d5f980c7b70 Mon Sep 17 00:00:00 2001 From: zhanghang Date: Wed, 9 Jul 2025 10:03:31 +0800 Subject: [PATCH] popup_targetSpace Signed-off-by: zhanghang --- .../bubble/bubble_layout_algorithm.cpp | 107 ++++++++++++++---- .../pattern/bubble/bubble_layout_algorithm.h | 4 + .../pattern/bubble/bubble_test_two_ng.cpp | 100 ++++++++++++++++ 3 files changed, 190 insertions(+), 21 deletions(-) diff --git a/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.cpp index 11e8d48ddef..14337befc16 100644 --- a/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.cpp @@ -1677,6 +1677,67 @@ Rect BubbleLayoutAlgorithm::GetLeftRect() return rect; } +Rect BubbleLayoutAlgorithm::GetAvoidParentToBottomRect() +{ + Rect rect; + float targetOffsetY = targetOffset_.GetY(); + targetOffsetY += (targetSpace_.ConvertToPx()); + auto y = std::max(targetOffsetY + targetSize_.Height(), marginTop_); + auto height = std::min(wrapperSize_.Height() - marginBottom_ - targetOffsetY - targetSize_.Height(), + wrapperSize_.Height() - marginBottom_ - marginTop_); + rect.SetRect(marginStart_, y, wrapperSize_.Width() - marginEnd_ - marginStart_, height); + if (isHalfFoldHover_) { + y = std::max(targetOffsetY + targetSize_.Height(), static_cast(wrapperRect_.Top())); + height = std::min(static_cast(wrapperRect_.Bottom()) - targetOffsetY - targetSize_.Height(), + wrapperSize_.Height() - marginBottom_ - marginTop_); + rect.SetRect(marginStart_, y, wrapperSize_.Width() - marginEnd_ - marginStart_, height); + } + return rect; +} + +Rect BubbleLayoutAlgorithm::GetAvoidParentToTopRect() +{ + Rect rect; + float targetOffsetY = targetOffset_.GetY(); + targetOffsetY += (-targetSpace_.ConvertToPx()); + auto height = std::min(targetOffsetY - marginTop_, wrapperSize_.Height() - marginTop_ - marginBottom_); + rect.SetRect(marginStart_, marginTop_, wrapperSize_.Width() - marginEnd_ - marginStart_, height); + if (isHalfFoldHover_) { + height = std::min( + targetOffsetY - static_cast(wrapperRect_.Top()), wrapperSize_.Height() - marginTop_ - marginBottom_); + rect.SetRect(marginStart_, wrapperRect_.Top(), wrapperSize_.Width() - marginEnd_ - marginStart_, height); + } + return rect; +} + +Rect BubbleLayoutAlgorithm::GetAvoidParentToRightRect() +{ + Rect rect; + float targetOffsetX = targetOffset_.GetX(); + targetOffsetX += (targetSpace_.ConvertToPx()); + auto x = std::max(targetOffsetX + targetSize_.Width(), marginStart_); + auto width = std::min(wrapperSize_.Width() - targetOffsetX - targetSize_.Width() - marginEnd_, + wrapperSize_.Width() - marginStart_ - marginEnd_); + rect.SetRect(x, marginTop_, width, wrapperSize_.Height() - marginBottom_ - marginTop_); + if (isHalfFoldHover_) { + rect.SetRect(x, wrapperRect_.Top(), width, wrapperRect_.Height()); + } + return rect; +} + +Rect BubbleLayoutAlgorithm::GetAvoidParentToLeftRect() +{ + Rect rect; + float targetOffsetX = targetOffset_.GetX(); + targetOffsetX += (-targetSpace_.ConvertToPx()); + auto width = std::min(targetOffsetX - marginStart_, wrapperSize_.Width() - marginEnd_ - marginStart_); + rect.SetRect(marginStart_, marginTop_, width, wrapperSize_.Height() - marginBottom_ - marginTop_); + if (isHalfFoldHover_) { + rect.SetRect(marginStart_, wrapperRect_.Top(), width, wrapperRect_.Height()); + } + return rect; +} + OffsetF BubbleLayoutAlgorithm::AvoidToTopOrBottomByWidth( const SizeF& childSize, OffsetF& arrowPosition, SizeF& resultSize) { @@ -1686,21 +1747,21 @@ OffsetF BubbleLayoutAlgorithm::AvoidToTopOrBottomByWidth( BottomAndTopPosition(bottomPosition, topPosition, childSize); OffsetF resultPosition; auto topHeight = std::min( - targetOffset_.GetY() - userSetTargetSpace_.ConvertToPx() - marginTop_ - BUBBLE_ARROW_HEIGHT.ConvertToPx(), + targetOffset_.GetY() - targetSpace_.ConvertToPx() - marginTop_ - BUBBLE_ARROW_HEIGHT.ConvertToPx(), wrapperSize_.Height() - marginTop_ - marginBottom_); auto bottomHeight = std::min(wrapperSize_.Height() - marginBottom_ - targetOffset_.GetY() - - userSetTargetSpace_.ConvertToPx() - targetSize_.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), + targetSpace_.ConvertToPx() - targetSize_.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), wrapperSize_.Height() - marginBottom_ - marginTop_); if (GreatNotEqual(bottomHeight, topHeight)) { placement_ = Placement::BOTTOM; resultPosition = GetPositionWithPlacementBottom(childSize, topPosition, bottomPosition, arrowPosition); - Rect rect = GetBottomRect(); + Rect rect = GetAvoidParentToBottomRect(); auto maxHeight = std::min(rect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); auto maxWidth = std::min(rect.Width(), childSize.Width()); resultSize = SizeF(maxWidth, maxHeight); } else { placement_ = Placement::TOP; - Rect rect = GetTopRect(); + Rect rect = GetAvoidParentToTopRect(); auto maxHeight = std::min(rect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); auto maxWidth = std::min(rect.Width(), childSize.Width()); resultSize = SizeF(maxWidth, maxHeight); @@ -1768,7 +1829,7 @@ bool BubbleLayoutAlgorithm::AvoidToTargetBottom( resultPosition = beforePosition; float maxHeight = 0.0f; float maxWidth = 0.0f; - Rect rect = GetBottomRect(); + Rect rect = GetAvoidParentToBottomRect(); maxHeight = std::min(rect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); if (placement_ == Placement::BOTTOM_LEFT) { resultPosition = beforePosition; @@ -1807,7 +1868,7 @@ bool BubbleLayoutAlgorithm::AvoidToTargetTop( float bubbleSpacing = scaledBubbleSpacing_; float arrowHalfWidth = BUBBLE_ARROW_WIDTH.ConvertToPx() / BUBBLE_ARROW_HALF; float radius = borderRadius_.ConvertToPx(); - Rect rect = GetTopRect(); + Rect rect = GetAvoidParentToTopRect(); float maxHeight = std::min(rect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); if (placement_ == Placement::TOP_LEFT) { OffsetF newTopPosition = OffsetF( @@ -1852,7 +1913,7 @@ bool BubbleLayoutAlgorithm::AvoidToTargetTopMid( float bubbleSpacing = scaledBubbleSpacing_; float arrowHalfWidth = BUBBLE_ARROW_WIDTH.ConvertToPx() / BUBBLE_ARROW_HALF; float radius = borderRadius_.ConvertToPx(); - Rect rect = GetTopRect(); + Rect rect = GetAvoidParentToTopRect(); float maxHeight = std::min(rect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); OffsetF newTopPosition = OffsetF(targetOffset_.GetX() + (targetSize_.Width() - childSize.Width()) / HALF, targetOffset_.GetY() - maxHeight - targetSpace_.ConvertToPx() - bubbleSpacing); @@ -1884,7 +1945,7 @@ bool BubbleLayoutAlgorithm::AvoidToTargetRight( resultPosition = beforePosition; float maxHeight = 0.0f; float maxWidth = 0.0f; - Rect rect = GetRightRect(); + Rect rect = GetAvoidParentToRightRect(); if (canCompress == false && GreatNotEqual(childSize.Width(), rect.Width() - BUBBLE_ARROW_HEIGHT.ConvertToPx())) { return false; } @@ -1919,7 +1980,7 @@ bool BubbleLayoutAlgorithm::AvoidToTargetLeft( float bubbleSpacing = scaledBubbleSpacing_; float arrowHalfWidth = BUBBLE_ARROW_WIDTH.ConvertToPx() / BUBBLE_ARROW_HALF; float radius = borderRadius_.ConvertToPx(); - Rect rect = GetLeftRect(); + Rect rect = GetAvoidParentToLeftRect(); if (canCompress == false && GreatNotEqual(childSize.Width(), rect.Width() - BUBBLE_ARROW_HEIGHT.ConvertToPx())) { return false; } @@ -2364,13 +2425,14 @@ bool BubbleLayoutAlgorithm::CheckPositionBottom( const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition) { Rect rect = GetBottomRect(); - auto maxHeight = std::min(rect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); - auto maxWidth = std::min(rect.Width(), childSize.Width()); + Rect avoidParentRect = GetAvoidParentToBottomRect(); + auto maxHeight = std::min(avoidParentRect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); + auto maxWidth = std::min(avoidParentRect.Width(), childSize.Width()); maxHeight = std::max(0.0f, maxHeight); maxWidth = std::max(0.0f, maxWidth); auto maxAreaSpace = maxHeight * maxWidth; auto minHeight = BUBBLE_ARROW_HEIGHT.ConvertToPx() + POPUP_MIN_HEIGHT.ConvertToPx(); - if (GreatNotEqual(rect.Height(), minHeight)) { + if (GreatNotEqual(avoidParentRect.Height(), minHeight)) { canPlacement_.bottom = true; RecordMaxSpace(maxAreaSpace, position, maxWidth, maxHeight, arrowPosition); } @@ -2387,13 +2449,14 @@ bool BubbleLayoutAlgorithm::CheckPositionTop( const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition) { Rect rect = GetTopRect(); - auto maxHeight = std::min(rect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); - auto maxWidth = std::min(rect.Width(), childSize.Width()); + Rect avoidParentRect = GetAvoidParentToTopRect(); + auto maxHeight = std::min(avoidParentRect.Height() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Height()); + auto maxWidth = std::min(avoidParentRect.Width(), childSize.Width()); maxHeight = std::max(0.0f, maxHeight); maxWidth = std::max(0.0f, maxWidth); auto maxAreaSpace = maxHeight * maxWidth; auto minHeight = BUBBLE_ARROW_HEIGHT.ConvertToPx() + POPUP_MIN_HEIGHT.ConvertToPx(); - if (GreatNotEqual(rect.Height(), minHeight)) { + if (GreatNotEqual(avoidParentRect.Height(), minHeight)) { canPlacement_.top = true; RecordMaxSpace(maxAreaSpace, position, maxWidth, maxHeight, arrowPosition); } @@ -2410,13 +2473,14 @@ bool BubbleLayoutAlgorithm::CheckPositionRight( const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition) { Rect rect = GetRightRect(); - auto maxHeight = std::min(rect.Height(), childSize.Height()); - auto maxWidth = std::min(rect.Width() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Width()); + Rect avoidParentRect = GetAvoidParentToRightRect(); + auto maxHeight = std::min(avoidParentRect.Height(), childSize.Height()); + auto maxWidth = std::min(avoidParentRect.Width() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Width()); maxHeight = std::max(0.0f, maxHeight); maxWidth = std::max(0.0f, maxWidth); auto maxAreaSpace = maxHeight * maxWidth; auto minWidth = BUBBLE_ARROW_HEIGHT.ConvertToPx() + POPUP_MIN_WIDTH.ConvertToPx(); - if (GreatNotEqual(rect.Width(), minWidth)) { + if (GreatNotEqual(avoidParentRect.Width(), minWidth)) { canPlacement_.right = true; RecordMaxSpace(maxAreaSpace, position, maxWidth, maxHeight, arrowPosition); } @@ -2433,13 +2497,14 @@ bool BubbleLayoutAlgorithm::CheckPositionLeft( const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition) { Rect rect = GetLeftRect(); - auto maxHeight = std::min(rect.Height(), childSize.Height()); - auto maxWidth = std::min(rect.Width() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Width()); + Rect avoidParentRect = GetAvoidParentToLeftRect(); + auto maxHeight = std::min(avoidParentRect.Height(), childSize.Height()); + auto maxWidth = std::min(avoidParentRect.Width() - BUBBLE_ARROW_HEIGHT.ConvertToPx(), childSize.Width()); maxHeight = std::max(0.0f, maxHeight); maxWidth = std::max(0.0f, maxWidth); auto maxAreaSpace = maxHeight * maxWidth; auto minWidth = BUBBLE_ARROW_HEIGHT.ConvertToPx() + POPUP_MIN_WIDTH.ConvertToPx(); - if (GreatNotEqual(rect.Width(), minWidth)) { + if (GreatNotEqual(avoidParentRect.Width(), minWidth)) { canPlacement_.left = true; RecordMaxSpace(maxAreaSpace, position, maxWidth, maxHeight, arrowPosition); } diff --git a/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.h b/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.h index c2762a9d06c..b1e4c7fa0d6 100644 --- a/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/bubble/bubble_layout_algorithm.h @@ -302,6 +302,10 @@ private: Rect GetTopRect(); Rect GetRightRect(); Rect GetLeftRect(); + Rect GetAvoidParentToBottomRect(); + Rect GetAvoidParentToTopRect(); + Rect GetAvoidParentToRightRect(); + Rect GetAvoidParentToLeftRect(); OffsetF AvoidToTopOrBottomByWidth(const SizeF& childSize, OffsetF& arrowPosition, SizeF& resultSize); OffsetF AdjustAvoidPosition(const OffsetF& position, float width, float height, OffsetF& arrowPosition); diff --git a/test/unittest/core/pattern/bubble/bubble_test_two_ng.cpp b/test/unittest/core/pattern/bubble/bubble_test_two_ng.cpp index 1ed74a39856..ef002601957 100644 --- a/test/unittest/core/pattern/bubble/bubble_test_two_ng.cpp +++ b/test/unittest/core/pattern/bubble/bubble_test_two_ng.cpp @@ -1243,6 +1243,106 @@ HWTEST_F(BubbleTestTwoNg, CheckPositionLeft001, TestSize.Level1) EXPECT_FALSE(algorithm.canPlacement_.left); } +/** + * @tc.name: GetAvoidParentToBottomRect001 + * @tc.desc: Test GetAvoidParentToBottomRect + * @tc.type: FUNC + */ +HWTEST_F(BubbleTestTwoNg, GetAvoidParentToBottomRect001, TestSize.Level1) +{ + BubbleLayoutAlgorithm algorithm; + BubbleTestTwoNg::InitGetRectSetting(algorithm); + + algorithm.isHalfFoldHover_ = false; + Rect rect = algorithm.GetAvoidParentToBottomRect(); + EXPECT_FLOAT_EQ(rect.Width(), CHILDSIZE_ONE_HUNDRED_EIGHTY); + EXPECT_FLOAT_EQ(rect.Height(), RESULT_FORTY); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_TEN); + EXPECT_FLOAT_EQ(rect.Top(), RESULT_ONE_HUNDRED_FIFTY); + + algorithm.isHalfFoldHover_ = true; + rect = algorithm.GetAvoidParentToBottomRect(); + EXPECT_FLOAT_EQ(rect.Width(), CHILDSIZE_ONE_HUNDRED_EIGHTY); + EXPECT_FLOAT_EQ(rect.Height(), RESULT_FIFTY); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_TEN); + EXPECT_FLOAT_EQ(rect.Top(), RESULT_ONE_HUNDRED_FIFTY); +} + +/** + * @tc.name: GetAvoidParentToTopRect001 + * @tc.desc: Test GetAvoidParentToTopRect + * @tc.type: FUNC + */ +HWTEST_F(BubbleTestTwoNg, GetAvoidParentToTopRect001, TestSize.Level1) +{ + BubbleLayoutAlgorithm algorithm; + BubbleTestTwoNg::InitGetRectSetting(algorithm); + + algorithm.isHalfFoldHover_ = false; + Rect rect = algorithm.GetAvoidParentToTopRect(); + EXPECT_FLOAT_EQ(rect.Width(), CHILDSIZE_ONE_HUNDRED_EIGHTY); + EXPECT_FLOAT_EQ(rect.Height(), RESULT_FORTY); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_TEN); + EXPECT_FLOAT_EQ(rect.Top(), RESULT_TEN); + + algorithm.isHalfFoldHover_ = true; + rect = algorithm.GetAvoidParentToTopRect(); + EXPECT_FLOAT_EQ(rect.Width(), CHILDSIZE_ONE_HUNDRED_EIGHTY); + EXPECT_FLOAT_EQ(rect.Height(), RESULT_FIFTY); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_TEN); + EXPECT_FLOAT_EQ(rect.Top(), 0.0f); +} + +/** + * @tc.name: GetAvoidParentToRightRect001 + * @tc.desc: Test GetAvoidParentToRightRect + * @tc.type: FUNC + */ +HWTEST_F(BubbleTestTwoNg, GetAvoidParentToRightRect001, TestSize.Level1) +{ + BubbleLayoutAlgorithm algorithm; + BubbleTestTwoNg::InitGetRectSetting(algorithm); + + algorithm.isHalfFoldHover_ = false; + Rect rect = algorithm.GetAvoidParentToRightRect(); + EXPECT_FLOAT_EQ(rect.Width(), RESULT_FORTY); + EXPECT_FLOAT_EQ(rect.Height(), CHILDSIZE_ONE_HUNDRED_EIGHTY); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_ONE_HUNDRED_FIFTY); + EXPECT_FLOAT_EQ(rect.Top(), RESULT_TEN); + + algorithm.isHalfFoldHover_ = true; + rect = algorithm.GetAvoidParentToRightRect(); + EXPECT_FLOAT_EQ(rect.Width(), RESULT_FORTY); + EXPECT_FLOAT_EQ(rect.Height(), SIZE_TWO_HUNDRED); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_ONE_HUNDRED_FIFTY); + EXPECT_FLOAT_EQ(rect.Top(), 0.0f); +} + +/** + * @tc.name: GetAvoidParentToLeftRect001 + * @tc.desc: Test GetAvoidParentToLeftRect + * @tc.type: FUNC + */ +HWTEST_F(BubbleTestTwoNg, GetAvoidParentToLeftRect001, TestSize.Level1) +{ + BubbleLayoutAlgorithm algorithm; + BubbleTestTwoNg::InitGetRectSetting(algorithm); + + algorithm.isHalfFoldHover_ = false; + Rect rect = algorithm.GetAvoidParentToLeftRect(); + EXPECT_FLOAT_EQ(rect.Width(), RESULT_FORTY); + EXPECT_FLOAT_EQ(rect.Height(), CHILDSIZE_ONE_HUNDRED_EIGHTY); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_TEN); + EXPECT_FLOAT_EQ(rect.Top(), RESULT_TEN); + + algorithm.isHalfFoldHover_ = true; + rect = algorithm.GetAvoidParentToLeftRect(); + EXPECT_FLOAT_EQ(rect.Width(), RESULT_FORTY); + EXPECT_FLOAT_EQ(rect.Height(), SIZE_TWO_HUNDRED); + EXPECT_FLOAT_EQ(rect.Left(), RESULT_TEN); + EXPECT_FLOAT_EQ(rect.Top(), 0.0f); +} + /** * @tc.name: GetBottomRect001 * @tc.desc: Test GetBottomRect -- Gitee