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