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