• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/stepper/stepper_layout_algorithm.h"
17 
18 #include <optional>
19 
20 #include "base/utils/utils.h"
21 #include "core/components/stepper/stepper_theme.h"
22 #include "core/components_ng/layout/layout_wrapper.h"
23 #include "core/components_ng/pattern/stepper/stepper_node.h"
24 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "core/pipeline/pipeline_base.h"
27 
28 namespace OHOS::Ace::NG {
29 
Measure(LayoutWrapper * layoutWrapper)30 void StepperLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
31 {
32     CHECK_NULL_VOID(layoutWrapper);
33     auto layoutProperty = layoutWrapper->GetLayoutProperty();
34     CHECK_NULL_VOID(layoutProperty);
35     auto geometryNode = layoutWrapper->GetGeometryNode();
36     CHECK_NULL_VOID(geometryNode);
37     auto constraint = layoutProperty->GetLayoutConstraint();
38     auto idealSize =
39         CreateIdealSize(constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(), true);
40     if (GreaterOrEqualToInfinity(idealSize.Width()) || GreaterOrEqualToInfinity(idealSize.Height())) {
41         LOGW("Size is infinity.");
42         geometryNode->SetFrameSize(SizeF());
43         return;
44     }
45     geometryNode->SetFrameSize(idealSize);
46 
47     const auto& padding = layoutProperty->CreatePaddingAndBorder();
48     MinusPaddingToSize(padding, idealSize);
49 
50     auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
51     childLayoutConstraint.parentIdealSize = OptionalSizeF(idealSize);
52 
53     MeasureSwiper(layoutWrapper, childLayoutConstraint);
54     MeasureLeftButton(layoutWrapper, childLayoutConstraint);
55     MeasureRightButton(layoutWrapper, childLayoutConstraint);
56 }
57 
MeasureSwiper(LayoutWrapper * layoutWrapper,LayoutConstraintF swiperLayoutConstraint)58 void StepperLayoutAlgorithm::MeasureSwiper(LayoutWrapper* layoutWrapper, LayoutConstraintF swiperLayoutConstraint)
59 {
60     auto pipeline = PipelineBase::GetCurrentContext();
61     CHECK_NULL_VOID(pipeline);
62     auto stepperTheme = pipeline->GetTheme<StepperTheme>();
63     CHECK_NULL_VOID(stepperTheme);
64     auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
65     CHECK_NULL_VOID(hostNode);
66     auto index = hostNode->GetChildIndexById(hostNode->GetSwiperId());
67     auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
68     CHECK_NULL_VOID(swiperWrapper);
69     auto swiperWidth = swiperLayoutConstraint.parentIdealSize.Width().value_or(0.0);
70     auto swiperHeight = swiperLayoutConstraint.parentIdealSize.Height().value_or(0.0) -
71                         static_cast<float>(stepperTheme->GetControlHeight().ConvertToPx());
72     auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(swiperWrapper->GetLayoutProperty());
73     CHECK_NULL_VOID(swiperLayoutProperty);
74     swiperLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(swiperWidth), CalcLength(swiperHeight)));
75     swiperLayoutConstraint.maxSize.SetHeight(swiperHeight);
76     swiperLayoutConstraint.selfIdealSize.SetHeight(swiperHeight);
77     swiperLayoutConstraint.selfIdealSize.SetWidth(swiperWidth);
78     swiperWrapper->Measure(swiperLayoutConstraint);
79 }
MeasureLeftButton(LayoutWrapper * layoutWrapper,LayoutConstraintF buttonLayoutConstraint)80 void StepperLayoutAlgorithm::MeasureLeftButton(LayoutWrapper* layoutWrapper, LayoutConstraintF buttonLayoutConstraint)
81 {
82     auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
83     CHECK_NULL_VOID(hostNode);
84     CHECK_NULL_VOID_NOLOG(hostNode->HasLeftButtonNode());
85 
86     auto pipeline = PipelineBase::GetCurrentContext();
87     CHECK_NULL_VOID(pipeline);
88     auto stepperTheme = pipeline->GetTheme<StepperTheme>();
89     CHECK_NULL_VOID(stepperTheme);
90     auto padding =
91         static_cast<float>((stepperTheme->GetDefaultPaddingStart() + stepperTheme->GetControlPadding()).ConvertToPx());
92     auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
93     auto buttonWidth = (buttonLayoutConstraint.parentIdealSize.Width().value() / 2) - padding - margin;
94     auto buttonHeight = static_cast<float>(
95         stepperTheme->GetArrowHeight().ConvertToPx() + 2 * stepperTheme->GetControlMargin().ConvertToPx());
96     buttonLayoutConstraint.minSize = { 0, buttonHeight };
97     buttonLayoutConstraint.maxSize = { buttonWidth, buttonHeight };
98     buttonLayoutConstraint.selfIdealSize = OptionalSizeF(std::nullopt, buttonHeight);
99 
100     auto index = hostNode->GetChildIndexById(hostNode->GetLeftButtonId());
101     auto leftButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
102     leftButtonWrapper->Measure(buttonLayoutConstraint);
103     MeasureText(leftButtonWrapper, buttonLayoutConstraint, true);
104 }
MeasureRightButton(LayoutWrapper * layoutWrapper,LayoutConstraintF buttonLayoutConstraint)105 void StepperLayoutAlgorithm::MeasureRightButton(LayoutWrapper* layoutWrapper, LayoutConstraintF buttonLayoutConstraint)
106 {
107     auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
108     CHECK_NULL_VOID(hostNode);
109     CHECK_NULL_VOID_NOLOG(hostNode->HasRightButtonNode());
110 
111     auto pipeline = PipelineBase::GetCurrentContext();
112     CHECK_NULL_VOID(pipeline);
113     auto stepperTheme = pipeline->GetTheme<StepperTheme>();
114     CHECK_NULL_VOID(stepperTheme);
115     auto padding =
116         static_cast<float>((stepperTheme->GetDefaultPaddingEnd() + stepperTheme->GetControlPadding()).ConvertToPx());
117     auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
118     auto buttonWidth = (buttonLayoutConstraint.parentIdealSize.Width().value() / 2) - padding - margin;
119     auto buttonHeight = static_cast<float>(
120         stepperTheme->GetArrowHeight().ConvertToPx() + 2 * stepperTheme->GetControlMargin().ConvertToPx());
121     buttonLayoutConstraint.minSize = { 0, buttonHeight };
122     buttonLayoutConstraint.maxSize = { buttonWidth, buttonHeight };
123     buttonLayoutConstraint.selfIdealSize = OptionalSizeF(std::nullopt, buttonHeight);
124 
125     auto index = hostNode->GetChildIndexById(hostNode->GetRightButtonId());
126     auto rightButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
127     rightButtonWrapper->Measure(buttonLayoutConstraint);
128     MeasureText(rightButtonWrapper, buttonLayoutConstraint, false);
129 }
130 
MeasureText(const RefPtr<LayoutWrapper> & layoutWrapper,const LayoutConstraintF & buttonLayoutConstraint,bool isLeft)131 void StepperLayoutAlgorithm::MeasureText(
132     const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& buttonLayoutConstraint, bool isLeft)
133 {
134     CHECK_NULL_VOID_NOLOG(layoutWrapper->GetHostTag() == std::string(V2::BUTTON_ETS_TAG));
135     auto rowWrapper = layoutWrapper->GetOrCreateChildByIndex(0);
136     CHECK_NULL_VOID_NOLOG(rowWrapper->GetHostTag() == std::string(V2::ROW_ETS_TAG));
137     auto textWrapper = rowWrapper->GetOrCreateChildByIndex(isLeft ? 1 : 0);
138     CHECK_NULL_VOID(textWrapper->GetHostTag() == std::string(V2::TEXT_ETS_TAG));
139 
140     auto pipeline = PipelineBase::GetCurrentContext();
141     CHECK_NULL_VOID(pipeline);
142     auto stepperTheme = pipeline->GetTheme<StepperTheme>();
143     CHECK_NULL_VOID(stepperTheme);
144 
145     LayoutConstraintF textLayoutConstraint = buttonLayoutConstraint;
146     auto controlPadding = static_cast<float>(stepperTheme->GetControlPadding().ConvertToPx());
147     auto arrowWidth = static_cast<float>(stepperTheme->GetArrowWidth().ConvertToPx());
148     auto textMaxWidth =
149         buttonLayoutConstraint.maxSize.Width() - controlPadding - controlPadding - arrowWidth - controlPadding;
150     textLayoutConstraint.minSize = { 0, 0 };
151     textLayoutConstraint.maxSize.SetWidth(textMaxWidth);
152     textLayoutConstraint.selfIdealSize = OptionalSizeF(std::nullopt, std::nullopt);
153     textWrapper->Measure(textLayoutConstraint);
154 }
155 
Layout(LayoutWrapper * layoutWrapper)156 void StepperLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
157 {
158     auto pipeline = PipelineBase::GetCurrentContext();
159     CHECK_NULL_VOID(pipeline);
160     auto stepperTheme = pipeline->GetTheme<StepperTheme>();
161     CHECK_NULL_VOID(stepperTheme);
162     CHECK_NULL_VOID(layoutWrapper);
163     auto geometryNode = layoutWrapper->GetGeometryNode();
164     CHECK_NULL_VOID(geometryNode);
165     auto frameSize = geometryNode->GetFrameSize();
166     if (!frameSize.IsPositive()) {
167         LOGW("Frame size is not positive.");
168         return;
169     }
170     LayoutSwiper(layoutWrapper);
171     LayoutLeftButton(layoutWrapper);
172     LayoutRightButton(layoutWrapper);
173 }
174 
LayoutSwiper(LayoutWrapper * layoutWrapper)175 void StepperLayoutAlgorithm::LayoutSwiper(LayoutWrapper* layoutWrapper)
176 {
177     auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
178     CHECK_NULL_VOID(hostNode);
179     auto index = hostNode->GetChildIndexById(hostNode->GetSwiperId());
180     auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
181     CHECK_NULL_VOID(swiperWrapper);
182     OffsetF swiperOffset = { 0.0f, 0.0f };
183     auto layoutProperty = layoutWrapper->GetLayoutProperty();
184     CHECK_NULL_VOID(layoutProperty);
185     const auto& padding = layoutProperty->CreatePaddingAndBorder();
186     swiperOffset += OffsetF(padding.left.value_or(0.0), padding.top.value_or(0.0));
187     swiperWrapper->GetGeometryNode()->SetMarginFrameOffset(swiperOffset);
188     swiperWrapper->Layout();
189 }
190 
LayoutLeftButton(LayoutWrapper * layoutWrapper)191 void StepperLayoutAlgorithm::LayoutLeftButton(LayoutWrapper* layoutWrapper)
192 {
193     auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
194     CHECK_NULL_VOID(hostNode);
195     CHECK_NULL_VOID_NOLOG(hostNode->HasLeftButtonNode());
196     auto index = hostNode->GetChildIndexById(hostNode->GetLeftButtonId());
197     auto leftButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
198     auto pipeline = PipelineBase::GetCurrentContext();
199     CHECK_NULL_VOID(pipeline);
200     auto stepperTheme = pipeline->GetTheme<StepperTheme>();
201     CHECK_NULL_VOID(stepperTheme);
202     auto controlHeight = static_cast<float>(stepperTheme->GetControlHeight().ConvertToPx());
203     auto buttonHeight = leftButtonWrapper->GetGeometryNode()->GetFrameSize().Height();
204     auto buttonHeightOffset = layoutWrapper->GetGeometryNode()->GetFrameSize().Height() - controlHeight;
205     buttonHeightOffset += (controlHeight - buttonHeight) / 2;
206     auto padding = static_cast<float>(stepperTheme->GetDefaultPaddingStart().ConvertToPx());
207     auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
208     auto buttonWidthOffset = padding + margin;
209     OffsetF buttonOffset = { buttonWidthOffset, buttonHeightOffset };
210     auto layoutProperty = layoutWrapper->GetLayoutProperty();
211     CHECK_NULL_VOID(layoutProperty);
212     const auto& stepperPadding = layoutProperty->CreatePaddingAndBorder();
213     buttonOffset += OffsetF(stepperPadding.left.value_or(0.0), -stepperPadding.bottom.value_or(0.0));
214     auto geometryNode = leftButtonWrapper->GetGeometryNode();
215     geometryNode->SetMarginFrameOffset(buttonOffset);
216     leftButtonWrapper->Layout();
217 }
218 
LayoutRightButton(LayoutWrapper * layoutWrapper)219 void StepperLayoutAlgorithm::LayoutRightButton(LayoutWrapper* layoutWrapper)
220 {
221     auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
222     CHECK_NULL_VOID(hostNode);
223     CHECK_NULL_VOID_NOLOG(hostNode->HasRightButtonNode());
224     auto index = hostNode->GetChildIndexById(hostNode->GetRightButtonId());
225     auto rightButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
226     auto pipeline = PipelineBase::GetCurrentContext();
227     CHECK_NULL_VOID(pipeline);
228     auto stepperTheme = pipeline->GetTheme<StepperTheme>();
229     CHECK_NULL_VOID(stepperTheme);
230     auto frameSizeWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
231     auto rightButtonWidth = rightButtonWrapper->GetGeometryNode()->GetMarginFrameSize().Width();
232     auto padding = static_cast<float>(stepperTheme->GetDefaultPaddingEnd().ConvertToPx());
233     auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
234     auto buttonWidthOffset = frameSizeWidth - rightButtonWidth - padding - margin;
235     auto controlHeight = static_cast<float>(stepperTheme->GetControlHeight().ConvertToPx());
236     auto buttonHeight = rightButtonWrapper->GetGeometryNode()->GetFrameSize().Height();
237     auto buttonHeightOffset = layoutWrapper->GetGeometryNode()->GetFrameSize().Height() - controlHeight;
238     buttonHeightOffset += (controlHeight - buttonHeight) / 2;
239     OffsetF buttonOffset = { buttonWidthOffset, buttonHeightOffset };
240     auto layoutProperty = layoutWrapper->GetLayoutProperty();
241     CHECK_NULL_VOID(layoutProperty);
242     const auto& stepperPadding = layoutProperty->CreatePaddingAndBorder();
243     buttonOffset -= OffsetF(stepperPadding.right.value_or(0.0), stepperPadding.bottom.value_or(0.0));
244     rightButtonWrapper->GetGeometryNode()->SetMarginFrameOffset(buttonOffset);
245     rightButtonWrapper->Layout();
246 }
247 
248 } // namespace OHOS::Ace::NG
249