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 "core/components_ng/pattern/stepper/stepper_node.h"
19 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
20 #include "core/components_ng/pattern/text/text_layout_property.h"
21
22 namespace OHOS::Ace::NG {
23
24 namespace {
25 constexpr float LEVEL_ONE = 1.75f;
26 constexpr float LEVEL_TWO = 2.0f;
27 constexpr float LEVEL_THREE = 3.2f;
28 constexpr Dimension PADDING = 4.0_vp;
29 constexpr float HEIGHT_HALF_RATIO = 0.5f;
30 constexpr float HEIGHT_DOUBLE_RATIO = 2.0f;
31 } // namespace
32
Measure(LayoutWrapper * layoutWrapper)33 void StepperLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
34 {
35 CHECK_NULL_VOID(layoutWrapper);
36 auto layoutProperty = layoutWrapper->GetLayoutProperty();
37 CHECK_NULL_VOID(layoutProperty);
38 auto geometryNode = layoutWrapper->GetGeometryNode();
39 CHECK_NULL_VOID(geometryNode);
40 auto constraint = layoutProperty->GetLayoutConstraint();
41 auto idealSize = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(), true);
42 if (GreaterOrEqualToInfinity(idealSize.Width()) || GreaterOrEqualToInfinity(idealSize.Height())) {
43 geometryNode->SetFrameSize(SizeF());
44 return;
45 }
46 geometryNode->SetFrameSize(idealSize);
47
48 const auto& padding = layoutProperty->CreatePaddingAndBorder();
49 MinusPaddingToSize(padding, idealSize);
50
51 auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
52 childLayoutConstraint.parentIdealSize = OptionalSizeF(idealSize);
53 auto pipeline = PipelineBase::GetCurrentContext();
54 CHECK_NULL_VOID(pipeline);
55 auto hostNode = layoutWrapper->GetHostNode();
56 CHECK_NULL_VOID(hostNode);
57 auto stepperPattern = hostNode->GetPattern<StepperPattern>();
58 CHECK_NULL_VOID(stepperPattern);
59 isLoadingButton_ = stepperPattern->GetIsLoadingButton();
60 if ((pipeline->GetFontScale() == LEVEL_ONE || pipeline->GetFontScale() == LEVEL_TWO ||
61 pipeline->GetFontScale() == LEVEL_THREE)) {
62 MeasureLeftButton(layoutWrapper, childLayoutConstraint);
63 MeasureRightButton(layoutWrapper, childLayoutConstraint);
64 auto rightButtonHeight = CaluateButtonHeight(layoutWrapper, true);
65 auto leftButtonHeight = CaluateButtonHeight(layoutWrapper, false);
66 MeasureSwiper(layoutWrapper, childLayoutConstraint, rightButtonHeight, leftButtonHeight);
67 } else {
68 MeasureSwiper(layoutWrapper, childLayoutConstraint, 0, 0);
69 MeasureLeftButton(layoutWrapper, childLayoutConstraint);
70 MeasureRightButton(layoutWrapper, childLayoutConstraint);
71 }
72 }
73
MeasureSwiper(LayoutWrapper * layoutWrapper,LayoutConstraintF swiperLayoutConstraint,float rightButtonHeight,float leftButtonHeight)74 void StepperLayoutAlgorithm::MeasureSwiper(LayoutWrapper* layoutWrapper, LayoutConstraintF swiperLayoutConstraint,
75 float rightButtonHeight, float leftButtonHeight)
76 {
77 auto pipeline = PipelineBase::GetCurrentContext();
78 CHECK_NULL_VOID(pipeline);
79 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
80 CHECK_NULL_VOID(stepperTheme);
81 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
82 CHECK_NULL_VOID(hostNode);
83 auto index = hostNode->GetChildIndexById(hostNode->GetSwiperId());
84 auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
85 CHECK_NULL_VOID(swiperWrapper);
86 auto swiperWidth = swiperLayoutConstraint.parentIdealSize.Width().value_or(0.0);
87 auto swiperHeight = swiperLayoutConstraint.parentIdealSize.Height().value_or(0.0) -
88 static_cast<float>(stepperTheme->GetControlHeight().ConvertToPx());
89 auto stepperHeight = layoutWrapper->GetGeometryNode()->GetFrameSize().Height();
90 auto swiperCaluateHeight = stepperHeight -
91 (rightButtonHeight > leftButtonHeight ? rightButtonHeight : leftButtonHeight) -
92 (PADDING.ConvertToPx() * HEIGHT_DOUBLE_RATIO);
93 if (swiperCaluateHeight < swiperHeight) {
94 swiperHeight = swiperCaluateHeight;
95 }
96 auto swiperLayoutProperty = AceType::DynamicCast<SwiperLayoutProperty>(swiperWrapper->GetLayoutProperty());
97 CHECK_NULL_VOID(swiperLayoutProperty);
98 swiperLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(swiperWidth), CalcLength(swiperHeight)));
99 swiperLayoutConstraint.maxSize.SetHeight(swiperHeight);
100 swiperLayoutConstraint.selfIdealSize.SetHeight(swiperHeight);
101 swiperLayoutConstraint.selfIdealSize.SetWidth(swiperWidth);
102 swiperWrapper->Measure(swiperLayoutConstraint);
103 }
MeasureLeftButton(LayoutWrapper * layoutWrapper,LayoutConstraintF buttonLayoutConstraint)104 void StepperLayoutAlgorithm::MeasureLeftButton(LayoutWrapper* layoutWrapper, LayoutConstraintF buttonLayoutConstraint)
105 {
106 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
107 CHECK_NULL_VOID(hostNode);
108 CHECK_NULL_VOID(hostNode->HasLeftButtonNode());
109 auto pipeline = PipelineBase::GetCurrentContext();
110 CHECK_NULL_VOID(pipeline);
111 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
112 CHECK_NULL_VOID(stepperTheme);
113 auto padding =
114 static_cast<float>((stepperTheme->GetDefaultPaddingStart() + stepperTheme->GetControlPadding()).ConvertToPx());
115 auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
116 auto buttonWidth = (buttonLayoutConstraint.parentIdealSize.Width().value() / 2) - padding - margin;
117 auto buttonHeight = static_cast<float>(
118 stepperTheme->GetArrowHeight().ConvertToPx() + 2 * stepperTheme->GetControlMargin().ConvertToPx());
119 auto index = hostNode->GetChildIndexById(hostNode->GetLeftButtonId());
120 auto leftButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
121 buttonLayoutConstraint.minSize = { 0, buttonHeight };
122 if (pipeline->GetFontScale() == LEVEL_ONE || pipeline->GetFontScale() == LEVEL_TWO ||
123 pipeline->GetFontScale() == LEVEL_THREE) {
124 auto stepperHeight = layoutWrapper->GetGeometryNode()->GetFrameSize().Height();
125 buttonLayoutConstraint.maxSize = { buttonWidth, stepperHeight };
126 auto ButtonRow = leftButtonWrapper->GetChildByIndex(0);
127 CHECK_NULL_VOID(ButtonRow);
128 auto ButtonText = ButtonRow->GetChildByIndex(1);
129 CHECK_NULL_VOID(ButtonText);
130 auto textLayoutProperty = AceType::DynamicCast<TextLayoutProperty>(ButtonText->GetLayoutProperty());
131 CHECK_NULL_VOID(textLayoutProperty);
132 textLayoutProperty->UpdateMaxFontScale(LEVEL_TWO);
133 MeasureText(leftButtonWrapper, buttonLayoutConstraint, true);
134 float TextHeight = ButtonText->GetGeometryNode()->GetFrameSize().Height();
135 buttonLayoutConstraint.selfIdealSize =
136 OptionalSizeF(std::nullopt, TextHeight + PADDING.ConvertToPx() * HEIGHT_DOUBLE_RATIO);
137 } else {
138 buttonLayoutConstraint.maxSize = { buttonWidth, buttonHeight };
139 buttonLayoutConstraint.selfIdealSize = OptionalSizeF(std::nullopt, buttonHeight);
140 }
141 leftButtonWrapper->Measure(buttonLayoutConstraint);
142 MeasureText(leftButtonWrapper, buttonLayoutConstraint, true);
143 }
MeasureRightButton(LayoutWrapper * layoutWrapper,LayoutConstraintF buttonLayoutConstraint)144 void StepperLayoutAlgorithm::MeasureRightButton(LayoutWrapper* layoutWrapper, LayoutConstraintF buttonLayoutConstraint)
145 {
146 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
147 CHECK_NULL_VOID(hostNode);
148 CHECK_NULL_VOID(hostNode->HasRightButtonNode());
149
150 auto pipeline = PipelineBase::GetCurrentContext();
151 CHECK_NULL_VOID(pipeline);
152 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
153 CHECK_NULL_VOID(stepperTheme);
154 auto padding =
155 static_cast<float>((stepperTheme->GetDefaultPaddingEnd() + stepperTheme->GetControlPadding()).ConvertToPx());
156 auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
157 auto buttonWidth = (buttonLayoutConstraint.parentIdealSize.Width().value() / 2) - padding - margin;
158 auto buttonHeight = static_cast<float>(
159 stepperTheme->GetArrowHeight().ConvertToPx() + 2 * stepperTheme->GetControlMargin().ConvertToPx());
160 auto index = hostNode->GetChildIndexById(hostNode->GetRightButtonId());
161 auto rightButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
162 buttonLayoutConstraint.minSize = { 0, buttonHeight };
163 if ((pipeline->GetFontScale() == LEVEL_ONE || pipeline->GetFontScale() == LEVEL_TWO ||
164 pipeline->GetFontScale() == LEVEL_THREE) && !isLoadingButton_) {
165 auto stepperHeight = hostNode->GetGeometryNode()->GetFrameSize().Height();
166 buttonLayoutConstraint.maxSize = { buttonWidth, stepperHeight };
167 auto ButtonRow = rightButtonWrapper->GetChildByIndex(0);
168 CHECK_NULL_VOID(ButtonRow);
169 auto ButtonText = ButtonRow->GetChildByIndex(0);
170 if (!ButtonText) {
171 auto textLayoutProperty = AceType::DynamicCast<TextLayoutProperty>(ButtonRow->GetLayoutProperty());
172 CHECK_NULL_VOID(textLayoutProperty);
173 textLayoutProperty->UpdateMaxFontScale(LEVEL_TWO);
174 PaddingProperty textPadding;
175 textPadding.top = CalcLength(PADDING.ConvertToPx(), DimensionUnit::PX);
176 textPadding.bottom = CalcLength(PADDING.ConvertToPx(), DimensionUnit::PX);
177 rightButtonWrapper->GetLayoutProperty()->UpdatePadding(textPadding);
178 buttonLayoutConstraint.selfIdealSize = OptionalSizeF(std::nullopt, std::nullopt);
179 } else {
180 auto textLayoutProperty = AceType::DynamicCast<TextLayoutProperty>(ButtonText->GetLayoutProperty());
181 CHECK_NULL_VOID(textLayoutProperty);
182 textLayoutProperty->UpdateMaxFontScale(LEVEL_TWO);
183 MeasureText(rightButtonWrapper, buttonLayoutConstraint, false);
184 float TextHeight = ButtonText->GetGeometryNode()->GetFrameSize().Height();
185 buttonLayoutConstraint.selfIdealSize =
186 OptionalSizeF(std::nullopt, TextHeight + PADDING.ConvertToPx() * HEIGHT_DOUBLE_RATIO);
187 }
188 } else {
189 buttonLayoutConstraint.maxSize = { buttonWidth, buttonHeight };
190 buttonLayoutConstraint.selfIdealSize = OptionalSizeF(std::nullopt, buttonHeight);
191 }
192 rightButtonWrapper->Measure(buttonLayoutConstraint);
193 MeasureText(rightButtonWrapper, buttonLayoutConstraint, false);
194 }
195
MeasureText(const RefPtr<LayoutWrapper> & layoutWrapper,const LayoutConstraintF & buttonLayoutConstraint,bool isLeft)196 void StepperLayoutAlgorithm::MeasureText(
197 const RefPtr<LayoutWrapper>& layoutWrapper, const LayoutConstraintF& buttonLayoutConstraint, bool isLeft)
198 {
199 CHECK_NULL_VOID(layoutWrapper->GetHostTag() == std::string(V2::BUTTON_ETS_TAG));
200 auto rowWrapper = layoutWrapper->GetOrCreateChildByIndex(0);
201 CHECK_NULL_VOID(rowWrapper->GetHostTag() == std::string(V2::ROW_ETS_TAG));
202 auto textWrapper = rowWrapper->GetOrCreateChildByIndex(isLeft ? 1 : 0);
203 CHECK_NULL_VOID(textWrapper->GetHostTag() == std::string(V2::TEXT_ETS_TAG));
204
205 auto pipeline = PipelineBase::GetCurrentContext();
206 CHECK_NULL_VOID(pipeline);
207 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
208 CHECK_NULL_VOID(stepperTheme);
209
210 LayoutConstraintF textLayoutConstraint = buttonLayoutConstraint;
211 auto controlPadding = static_cast<float>(stepperTheme->GetControlPadding().ConvertToPx());
212 auto arrowWidth = static_cast<float>(stepperTheme->GetArrowWidth().ConvertToPx());
213 auto textMaxWidth =
214 buttonLayoutConstraint.maxSize.Width() - controlPadding - controlPadding - arrowWidth - controlPadding;
215 textLayoutConstraint.minSize = { 0, 0 };
216 textLayoutConstraint.maxSize.SetWidth(textMaxWidth);
217 textLayoutConstraint.selfIdealSize = OptionalSizeF(std::nullopt, std::nullopt);
218 textWrapper->Measure(textLayoutConstraint);
219 }
220
Layout(LayoutWrapper * layoutWrapper)221 void StepperLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
222 {
223 auto pipeline = PipelineBase::GetCurrentContext();
224 CHECK_NULL_VOID(pipeline);
225 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
226 CHECK_NULL_VOID(stepperTheme);
227 CHECK_NULL_VOID(layoutWrapper);
228 auto geometryNode = layoutWrapper->GetGeometryNode();
229 CHECK_NULL_VOID(geometryNode);
230 auto frameSize = geometryNode->GetFrameSize();
231 if (!frameSize.IsPositive()) {
232 return;
233 }
234 LayoutSwiper(layoutWrapper);
235 if (pipeline->GetFontScale() == LEVEL_ONE || pipeline->GetFontScale() == LEVEL_TWO ||
236 pipeline->GetFontScale() == LEVEL_THREE) {
237 auto layoutProperty = layoutWrapper->GetLayoutProperty();
238 CHECK_NULL_VOID(layoutProperty);
239 auto constraint = layoutProperty->GetLayoutConstraint();
240 auto idealSize = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, layoutProperty->GetMeasureType(), true);
241 if (GreaterOrEqualToInfinity(idealSize.Width()) || GreaterOrEqualToInfinity(idealSize.Height())) {
242 LOGW("Size is infinity.");
243 geometryNode->SetFrameSize(SizeF());
244 return;
245 }
246 geometryNode->SetFrameSize(idealSize);
247
248 const auto& padding = layoutProperty->CreatePaddingAndBorder();
249 MinusPaddingToSize(padding, idealSize);
250
251 auto childLayoutConstraint = layoutProperty->CreateChildConstraint();
252 childLayoutConstraint.parentIdealSize = OptionalSizeF(idealSize);
253 auto rightButtonHeight = CaluateButtonHeight(layoutWrapper, true);
254 auto leftButtonHeight = CaluateButtonHeight(layoutWrapper, false);
255 SuitAgeLayoutButton(layoutWrapper, rightButtonHeight, leftButtonHeight, true);
256 SuitAgeLayoutButton(layoutWrapper, rightButtonHeight, leftButtonHeight, false);
257 } else {
258 LayoutLeftButton(layoutWrapper);
259 LayoutRightButton(layoutWrapper);
260 }
261 }
262
SuitAgeLayoutButton(LayoutWrapper * layoutWrapper,float rightButtonHeight,float leftButtonHeight,bool isRight)263 void StepperLayoutAlgorithm::SuitAgeLayoutButton(
264 LayoutWrapper* layoutWrapper, float rightButtonHeight, float leftButtonHeight, bool isRight)
265 {
266 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
267 CHECK_NULL_VOID(hostNode);
268 if (!isRight) {
269 CHECK_NULL_VOID(hostNode->HasLeftButtonNode());
270 }
271 auto buttonIndex = isRight ? hostNode->GetChildIndexById(hostNode->GetRightButtonId())
272 : hostNode->GetChildIndexById(hostNode->GetLeftButtonId());
273 auto ButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(buttonIndex);
274 CHECK_NULL_VOID(ButtonWrapper);
275 auto pipeline = PipelineBase::GetCurrentContext();
276 CHECK_NULL_VOID(pipeline);
277 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
278 CHECK_NULL_VOID(stepperTheme);
279 auto frameSizeWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
280 auto ButtonWidth = ButtonWrapper->GetGeometryNode()->GetMarginFrameSize().Width();
281 auto padding = static_cast<float>(stepperTheme->GetDefaultPaddingEnd().ConvertToPx());
282 auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
283 auto buttonWidthOffset = isRight ? (frameSizeWidth - ButtonWidth - padding - margin) : (padding + margin);
284 auto buttonHeightOffset = layoutWrapper->GetGeometryNode()->GetFrameSize().Height();
285 auto maxButtonHeight = rightButtonHeight > leftButtonHeight ? rightButtonHeight : leftButtonHeight;
286 auto ButtonHeight = isRight ? rightButtonHeight : leftButtonHeight;
287 buttonHeightOffset -=
288 maxButtonHeight * HEIGHT_HALF_RATIO + PADDING.ConvertToPx() + ButtonHeight * HEIGHT_HALF_RATIO;
289 OffsetF buttonOffset = { buttonWidthOffset, buttonHeightOffset };
290 auto layoutProperty = layoutWrapper->GetLayoutProperty();
291 CHECK_NULL_VOID(layoutProperty);
292 const auto& stepperPadding = layoutProperty->CreatePaddingAndBorder();
293 if (isRight) {
294 buttonOffset -= OffsetF(stepperPadding.right.value_or(0.0), stepperPadding.bottom.value_or(0.0));
295 } else {
296 buttonOffset += OffsetF(stepperPadding.left.value_or(0.0), -stepperPadding.bottom.value_or(0.0));
297 }
298 auto stepperLayoutProperty = hostNode->GetLayoutProperty<StepperLayoutProperty>();
299 CHECK_NULL_VOID(stepperLayoutProperty);
300 auto isRightToLeft = stepperLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
301 if (isRightToLeft) {
302 auto frameWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
303 auto offsetX = frameWidth - ButtonWrapper->GetGeometryNode()->GetFrameSize().Width() - buttonOffset.GetX();
304 buttonOffset.SetX(offsetX);
305 }
306 ButtonWrapper->GetGeometryNode()->SetMarginFrameOffset(buttonOffset);
307 ButtonWrapper->Layout();
308 }
309
CaluateButtonHeight(LayoutWrapper * layoutWrapper,bool isRight)310 float StepperLayoutAlgorithm::CaluateButtonHeight(LayoutWrapper* layoutWrapper, bool isRight)
311 {
312 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
313 CHECK_NULL_RETURN(hostNode, 0.0f);
314 auto hasButtonNode = isRight ? hostNode->HasRightButtonNode() : hostNode->HasLeftButtonNode();
315 if (!hasButtonNode) {
316 return 0.0f;
317 }
318 auto buttonId = isRight ? hostNode->GetRightButtonId() : hostNode->GetLeftButtonId();
319 auto ButtonIndex = hostNode->GetChildIndexById(buttonId);
320 CHECK_NULL_RETURN(ButtonIndex, 0.0f);
321 auto ButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(ButtonIndex);
322 CHECK_NULL_RETURN(ButtonWrapper, 0.0f);
323 auto ButtonHeight = ButtonWrapper->GetGeometryNode()->GetFrameSize().Height();
324 return ButtonHeight;
325 }
326
LayoutSwiper(LayoutWrapper * layoutWrapper)327 void StepperLayoutAlgorithm::LayoutSwiper(LayoutWrapper* layoutWrapper)
328 {
329 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
330 CHECK_NULL_VOID(hostNode);
331 auto index = hostNode->GetChildIndexById(hostNode->GetSwiperId());
332 auto swiperWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
333 CHECK_NULL_VOID(swiperWrapper);
334 OffsetF swiperOffset = { 0.0f, 0.0f };
335 auto layoutProperty = layoutWrapper->GetLayoutProperty();
336 CHECK_NULL_VOID(layoutProperty);
337 const auto& padding = layoutProperty->CreatePaddingAndBorder();
338 swiperOffset += OffsetF(padding.left.value_or(0.0), padding.top.value_or(0.0));
339 swiperWrapper->GetGeometryNode()->SetMarginFrameOffset(swiperOffset);
340 swiperWrapper->Layout();
341 }
342
LayoutLeftButton(LayoutWrapper * layoutWrapper)343 void StepperLayoutAlgorithm::LayoutLeftButton(LayoutWrapper* layoutWrapper)
344 {
345 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
346 CHECK_NULL_VOID(hostNode);
347 CHECK_NULL_VOID(hostNode->HasLeftButtonNode());
348 auto index = hostNode->GetChildIndexById(hostNode->GetLeftButtonId());
349 auto leftButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
350 auto pipeline = PipelineBase::GetCurrentContext();
351 CHECK_NULL_VOID(pipeline);
352 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
353 CHECK_NULL_VOID(stepperTheme);
354 auto controlHeight = static_cast<float>(stepperTheme->GetControlHeight().ConvertToPx());
355 auto buttonHeight = leftButtonWrapper->GetGeometryNode()->GetFrameSize().Height();
356 auto buttonHeightOffset = layoutWrapper->GetGeometryNode()->GetFrameSize().Height() - controlHeight;
357 buttonHeightOffset += (controlHeight - buttonHeight) / 2;
358 auto padding = static_cast<float>(stepperTheme->GetDefaultPaddingStart().ConvertToPx());
359 auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
360 auto buttonWidthOffset = padding + margin;
361 OffsetF buttonOffset = { buttonWidthOffset, buttonHeightOffset };
362 auto layoutProperty = layoutWrapper->GetLayoutProperty();
363 CHECK_NULL_VOID(layoutProperty);
364 const auto& stepperPadding = layoutProperty->CreatePaddingAndBorder();
365 buttonOffset += OffsetF(stepperPadding.left.value_or(0.0), -stepperPadding.bottom.value_or(0.0));
366 auto geometryNode = leftButtonWrapper->GetGeometryNode();
367 auto stepperLayoutProperty = hostNode->GetLayoutProperty<StepperLayoutProperty>();
368 CHECK_NULL_VOID(stepperLayoutProperty);
369 auto isRightToLeft = stepperLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
370 if (isRightToLeft) {
371 auto frameWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
372 auto offsetX = frameWidth - geometryNode->GetFrameSize().Width() - buttonOffset.GetX();
373 buttonOffset.SetX(offsetX);
374 }
375 geometryNode->SetMarginFrameOffset(buttonOffset);
376 leftButtonWrapper->Layout();
377 }
378
LayoutRightButton(LayoutWrapper * layoutWrapper)379 void StepperLayoutAlgorithm::LayoutRightButton(LayoutWrapper* layoutWrapper)
380 {
381 auto hostNode = AceType::DynamicCast<StepperNode>(layoutWrapper->GetHostNode());
382 CHECK_NULL_VOID(hostNode);
383 CHECK_NULL_VOID(hostNode->HasRightButtonNode());
384 auto index = hostNode->GetChildIndexById(hostNode->GetRightButtonId());
385 auto rightButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
386 auto pipeline = PipelineBase::GetCurrentContext();
387 CHECK_NULL_VOID(pipeline);
388 auto stepperTheme = pipeline->GetTheme<StepperTheme>();
389 CHECK_NULL_VOID(stepperTheme);
390 auto frameSizeWidth = layoutWrapper->GetGeometryNode()->GetFrameSize().Width();
391 auto rightButtonWidth = rightButtonWrapper->GetGeometryNode()->GetMarginFrameSize().Width();
392 auto padding = static_cast<float>(stepperTheme->GetDefaultPaddingEnd().ConvertToPx());
393 auto margin = static_cast<float>(stepperTheme->GetControlMargin().ConvertToPx());
394 auto buttonWidthOffset = frameSizeWidth - rightButtonWidth - padding - margin;
395 auto controlHeight = static_cast<float>(stepperTheme->GetControlHeight().ConvertToPx());
396 auto buttonHeight = rightButtonWrapper->GetGeometryNode()->GetFrameSize().Height();
397 auto buttonHeightOffset = layoutWrapper->GetGeometryNode()->GetFrameSize().Height() - controlHeight;
398 buttonHeightOffset += (controlHeight - buttonHeight) / 2;
399 OffsetF buttonOffset = { buttonWidthOffset, buttonHeightOffset };
400 auto layoutProperty = layoutWrapper->GetLayoutProperty();
401 CHECK_NULL_VOID(layoutProperty);
402 const auto& stepperPadding = layoutProperty->CreatePaddingAndBorder();
403 buttonOffset -= OffsetF(stepperPadding.right.value_or(0.0), stepperPadding.bottom.value_or(0.0));
404
405 auto stepperLayoutProperty = hostNode->GetLayoutProperty<StepperLayoutProperty>();
406 CHECK_NULL_VOID(stepperLayoutProperty);
407 auto isRightToLeft = stepperLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
408 if (isRightToLeft) {
409 auto offsetX = frameSizeWidth - rightButtonWidth - buttonOffset.GetX();
410 buttonOffset.SetX(offsetX);
411 }
412 rightButtonWrapper->GetGeometryNode()->SetMarginFrameOffset(buttonOffset);
413 rightButtonWrapper->Layout();
414 }
415
416 } // namespace OHOS::Ace::NG
417