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