• 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 "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