• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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/swiper_indicator/dot_indicator/dot_indicator_layout_algorithm.h"
17 
18 #include "base/geometry/axis.h"
19 #include "base/geometry/ng/offset_t.h"
20 #include "base/geometry/ng/size_t.h"
21 #include "base/utils/utils.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
24 #include "core/components_ng/pattern/swiper_indicator/dot_indicator/dot_indicator_paint_property.h"
25 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_pattern.h"
26 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_utils.h"
27 
28 namespace OHOS::Ace::NG {
29 namespace {
30 constexpr float SMALLEST_POINT_RATIO = 1.0f / 3.0f;
31 constexpr float SECOND_SMALLEST_POINT_RATIO = 2.0f / 3.0f;
32 constexpr int32_t OVERLONG_SMALL_COUNT = 2;
33 } // namespace
CalcIndicatorFrameSize(LayoutWrapper * layoutWrapper,float indicatorWidth,float indicatorHeight)34 SizeF DotIndicatorLayoutAlgorithm::CalcIndicatorFrameSize(
35     LayoutWrapper* layoutWrapper, float indicatorWidth, float indicatorHeight)
36 {
37     SizeF frameSize = { -1.0f, -1.0f };
38     CHECK_NULL_RETURN(layoutWrapper, frameSize);
39     auto layoutProperty = layoutWrapper->GetLayoutProperty();
40     CHECK_NULL_RETURN(layoutProperty, frameSize);
41     const auto& layoutConstraint = layoutProperty->GetLayoutConstraint();
42     CHECK_NULL_RETURN(layoutConstraint, frameSize);
43 
44     const auto& calcLayoutConstraint = layoutProperty->GetCalcLayoutConstraint();
45     if (isSingle_ && calcLayoutConstraint && calcLayoutConstraint->selfIdealSize) {
46         auto idealSize =
47             CreateIdealSize(layoutConstraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(), true);
48         auto width = calcLayoutConstraint->selfIdealSize->Width();
49         auto height = calcLayoutConstraint->selfIdealSize->Height();
50         if (width) {
51             indicatorWidth_ = std::max(indicatorWidth_, idealSize.Width());
52         }
53 
54         if (height) {
55             indicatorHeight_ = std::max(indicatorHeight_, idealSize.Height());
56         }
57     }
58 
59     do {
60         frameSize.SetSizeT(SizeF { indicatorWidth_, indicatorHeight_ });
61         if (frameSize.IsNonNegative()) {
62             break;
63         }
64         frameSize.Constrain(layoutConstraint->minSize, layoutConstraint->maxSize);
65     } while (false);
66 
67     return frameSize;
68 }
69 
Measure(LayoutWrapper * layoutWrapper)70 void DotIndicatorLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
71 {
72     CHECK_NULL_VOID(layoutWrapper);
73     auto layoutProperty = layoutWrapper->GetLayoutProperty();
74     CHECK_NULL_VOID(layoutProperty);
75     const auto& layoutConstraint = layoutProperty->GetLayoutConstraint();
76     CHECK_NULL_VOID(layoutConstraint);
77     auto frameNode = layoutWrapper->GetHostNode();
78     CHECK_NULL_VOID(frameNode);
79     auto indicatorPattern = frameNode->GetPattern<SwiperIndicatorPattern>();
80     CHECK_NULL_VOID(indicatorPattern);
81     auto direction = indicatorPattern->GetDirection();
82     auto paintProperty = frameNode->GetPaintProperty<DotIndicatorPaintProperty>();
83     CHECK_NULL_VOID(paintProperty);
84 
85     auto pipeline = PipelineBase::GetCurrentContext();
86     CHECK_NULL_VOID(pipeline);
87     auto theme = pipeline->GetTheme<SwiperIndicatorTheme>();
88     CHECK_NULL_VOID(theme);
89 
90     // Diameter of a single indicator circle, item or selected-item width and height
91     auto userItemWidth = paintProperty->GetItemWidthValue(theme->GetSize()).ConvertToPx();
92     auto userItemHeight = paintProperty->GetItemHeightValue(theme->GetSize()).ConvertToPx();
93     auto userSelectedItemWidth = paintProperty->GetSelectedItemWidthValue(theme->GetSize()).ConvertToPx();
94     auto userSelectedItemHeight = paintProperty->GetSelectedItemHeightValue(theme->GetSize()).ConvertToPx();
95     if (LessNotEqual(userItemWidth, 0.0) || LessNotEqual(userItemHeight, 0.0) ||
96         LessNotEqual(userSelectedItemWidth, 0.0) || LessNotEqual(userSelectedItemHeight, 0.0)) {
97         userItemWidth = theme->GetSize().ConvertToPx();
98         userItemHeight = theme->GetSize().ConvertToPx();
99         userSelectedItemWidth = theme->GetSize().ConvertToPx();
100         userSelectedItemHeight = theme->GetSize().ConvertToPx();
101     }
102 
103     // To the size of the hover after the layout, in order to prevent the components after the hover draw boundaries
104     float indicatorScale = theme->GetIndicatorScale();
105     if (maxDisplayCount_ > 0 || (!indicatorInteractive_ && isBindIndicator_)) {
106         indicatorScale = 1.0f;
107     }
108     userItemWidth *= indicatorScale;
109     userItemHeight *= indicatorScale;
110     userSelectedItemWidth *= indicatorScale;
111     userSelectedItemHeight *= indicatorScale;
112 
113     // The width and height of the entire indicator.
114     Dimension indicatorHeightPadding = theme->GetIndicatorBgHeight();
115     auto indicatorHeight =
116         static_cast<float>(((userItemHeight > userSelectedItemHeight) ?
117             userItemHeight : userSelectedItemHeight) + indicatorHeightPadding.ConvertToPx() * 2);
118     auto noPaddingIndicatorHeight = indicatorHeight - indicatorHeightPadding.ConvertToPx();
119     auto allPointDiameterSum = userItemWidth * (indicatorDisplayCount_ + 1);
120     if (paintProperty->GetIsCustomSizeValue(false)) {
121         allPointDiameterSum = userItemWidth * (indicatorDisplayCount_ - 1) + userSelectedItemWidth;
122     }
123 
124     auto indicatorDotItemSpace = paintProperty->GetSpaceValue(theme->GetIndicatorDotItemSpace());
125     auto allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (indicatorDisplayCount_ - 1);
126     if (maxDisplayCount_ > 0) {
127         allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (maxDisplayCount_ - 1);
128         allPointDiameterSum = userItemWidth * (maxDisplayCount_ - OVERLONG_SMALL_COUNT - 1) + userSelectedItemWidth +
129                               userItemWidth * SECOND_SMALLEST_POINT_RATIO + userItemWidth * SMALLEST_POINT_RATIO;
130     }
131     auto paddingSide = theme->GetIndicatorPaddingDot().ConvertToPx();
132 
133     auto indicatorWidth = paddingSide + allPointDiameterSum + allPointSpaceSum + paddingSide;
134     auto noPaddingIndicatorWidth = indicatorWidth - paddingSide * 1.5;
135     auto ignoreSize = paintProperty->GetIgnoreSizeValue(false);
136     if (direction == Axis::HORIZONTAL) {
137         indicatorWidth_ = indicatorWidth;
138         indicatorHeight_ = indicatorHeight;
139         ignorSizeIndicatorWidth_ = indicatorWidth;
140         ignorSizeIndicatorHeight_ = ignoreSize ? noPaddingIndicatorHeight : indicatorHeight;
141     } else {
142         indicatorWidth_ = indicatorHeight;
143         indicatorHeight_ = indicatorWidth;
144         ignorSizeIndicatorWidth_ = indicatorHeight;
145         ignorSizeIndicatorHeight_ = ignoreSize ? noPaddingIndicatorWidth : indicatorWidth;
146     }
147 
148     auto frameSize = CalcIndicatorFrameSize(layoutWrapper, indicatorWidth, indicatorHeight);
149     auto geometryNode = layoutWrapper->GetGeometryNode();
150     CHECK_NULL_VOID(geometryNode);
151     geometryNode->SetFrameSize(frameSize);
152 }
153 
Layout(LayoutWrapper * layoutWrapper)154 void DotIndicatorLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
155 {
156     CHECK_NULL_VOID(layoutWrapper);
157     auto frameNode = layoutWrapper->GetHostNode();
158     CHECK_NULL_VOID(frameNode);
159     auto indicatorPattern = frameNode->GetPattern<SwiperIndicatorPattern>();
160     CHECK_NULL_VOID(indicatorPattern);
161     OffsetF currentOffset = OffsetF(0.0f, 0.0f);
162     auto needSet = indicatorPattern->GetDotCurrentOffset(currentOffset, ignorSizeIndicatorWidth_,
163         ignorSizeIndicatorHeight_);
164     if (needSet) {
165         auto geometryNode = layoutWrapper->GetGeometryNode();
166         CHECK_NULL_VOID(geometryNode);
167         geometryNode->SetMarginFrameOffset(currentOffset);
168     }
169 }
170 
GetValidEdgeLength(float swiperLength,float indicatorLength,const Dimension & edge)171 double DotIndicatorLayoutAlgorithm::GetValidEdgeLength(float swiperLength, float indicatorLength, const Dimension& edge)
172 {
173     return SwiperIndicatorUtils::GetValidEdgeLength(swiperLength, indicatorLength, edge);
174 }
175 } // namespace OHOS::Ace::NG
176