• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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_pattern.h"
17 
18 #include <algorithm>
19 
20 #include "base/i18n/localization.h"
21 #include "core/components_ng/pattern/button/button_event_hub.h"
22 #include "core/components_ng/pattern/button/button_pattern.h"
23 #include "core/components_ng/pattern/image/image_pattern.h"
24 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
25 #include "core/components_ng/pattern/loading_progress/loading_progress_pattern.h"
26 #include "core/components_ng/pattern/stepper/stepper_item_layout_property.h"
27 #include "core/components_ng/pattern/stepper/stepper_node.h"
28 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
29 #include "core/components_ng/pattern/text/text_pattern.h"
30 
31 namespace OHOS::Ace::NG {
32 
OnModifyDone()33 void StepperPattern::OnModifyDone()
34 {
35     Pattern::OnModifyDone();
36     auto hostNode = DynamicCast<StepperNode>(GetHost());
37     CHECK_NULL_VOID(hostNode);
38     auto swiperNode =
39         DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId())));
40     CHECK_NULL_VOID(swiperNode);
41     index_ = swiperNode->GetLayoutProperty<SwiperLayoutProperty>()->GetIndex().value_or(0);
42 
43     auto swiperEventHub = swiperNode->GetOrCreateEventHub<SwiperEventHub>();
44     CHECK_NULL_VOID(swiperEventHub);
45     auto stepperLayoutProperty = hostNode->GetLayoutProperty();
46     auto layoutPolicy = stepperLayoutProperty->GetLayoutPolicyProperty();
47     if (layoutPolicy.has_value()) {
48         swiperNode->GetLayoutProperty()->UpdateLayoutPolicyProperty(
49             layoutPolicy.value().widthLayoutPolicy_.value_or(LayoutCalPolicy::NO_MATCH), true);
50         swiperNode->GetLayoutProperty()->UpdateLayoutPolicyProperty(
51             layoutPolicy.value().heightLayoutPolicy_.value_or(LayoutCalPolicy::NO_MATCH), false);
52     }
53     maxIndex_ = TotalCount();
54     if (index_ > maxIndex_) {
55         index_ = 0;
56         hostNode->GetLayoutProperty<StepperLayoutProperty>()->UpdateIndex(index_);
57         swiperNode->GetLayoutProperty<SwiperLayoutProperty>()->UpdateIndex(index_);
58         swiperNode->MarkModifyDone();
59         swiperNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
60     }
61     InitSwiperChangeEvent(swiperEventHub);
62     UpdateOrCreateLeftButtonNode(index_);
63     UpdateOrCreateRightButtonNode(index_);
64     InitButtonClickEvent();
65     SetAccessibilityAction();
66 }
67 
OnAttachToFrameNode()68 void StepperPattern::OnAttachToFrameNode()
69 {
70     auto host = GetHost();
71     CHECK_NULL_VOID(host);
72     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
73     host->GetRenderContext()->UpdateClipEdge(true);
74 }
75 
InitSwiperChangeEvent(const RefPtr<SwiperEventHub> & swiperEventHub)76 void StepperPattern::InitSwiperChangeEvent(const RefPtr<SwiperEventHub>& swiperEventHub)
77 {
78     ChangeEvent changeEvent = [weak = WeakClaim(this)](int32_t index) {
79         auto stepperPattern = weak.Upgrade();
80         CHECK_NULL_VOID(stepperPattern->TotalCount() > -1);
81         stepperPattern->UpdateIndexWithoutMeasure(index);
82         stepperPattern->UpdateOrCreateLeftButtonNode(index);
83         stepperPattern->UpdateOrCreateRightButtonNode(index);
84         stepperPattern->InitButtonClickEvent();
85     };
86     if (swiperChangeEvent_) {
87         (*swiperChangeEvent_).swap(changeEvent);
88     } else {
89         swiperChangeEvent_ = std::make_shared<ChangeEvent>(std::move(changeEvent));
90         swiperEventHub->AddOnChangeEvent(swiperChangeEvent_);
91     }
92 }
93 
UpdateIndexWithoutMeasure(int32_t index)94 void StepperPattern::UpdateIndexWithoutMeasure(int32_t index)
95 {
96     auto hostNode = DynamicCast<StepperNode>(GetHost());
97     CHECK_NULL_VOID(hostNode);
98     auto stepperLayoutProperty = hostNode->GetLayoutProperty<StepperLayoutProperty>();
99     CHECK_NULL_VOID(stepperLayoutProperty);
100     stepperLayoutProperty->UpdateIndexWithoutMeasure(index);
101 
102     auto swiperNode =
103         DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId())));
104     CHECK_NULL_VOID(swiperNode);
105     auto swiperLayoutProperty = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
106     CHECK_NULL_VOID(swiperLayoutProperty);
107     swiperLayoutProperty->UpdateIndexWithoutMeasure(index);
108 }
109 
UpdateOrCreateLeftButtonNode(int32_t index)110 void StepperPattern::UpdateOrCreateLeftButtonNode(int32_t index)
111 {
112     auto hostNode = DynamicCast<StepperNode>(GetHost());
113     CHECK_NULL_VOID(hostNode);
114     auto stepperLayoutProperty = hostNode->GetLayoutProperty<StepperLayoutProperty>();
115     CHECK_NULL_VOID(stepperLayoutProperty);
116     isRightToLeft_ = stepperLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
117     if (index <= 0) {
118         hostNode->RemoveLeftButtonNode();
119     } else if (!hostNode->HasLeftButtonNode()) {
120         CreateLeftButtonNode();
121         UpdateLeftButtonNode(index);
122     } else {
123         UpdateLeftButtonNode(index);
124     }
125     index_ = index;
126     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
127 }
128 
CreateLeftButtonNode()129 void StepperPattern::CreateLeftButtonNode()
130 {
131     auto stepperTheme = GetTheme();
132     CHECK_NULL_VOID(stepperTheme);
133     auto hostNode = DynamicCast<StepperNode>(GetHost());
134     CHECK_NULL_VOID(hostNode);
135     // Create buttonNode
136     auto buttonId = hostNode->GetLeftButtonId();
137     auto buttonPattern = AceType::MakeRefPtr<NG::ButtonPattern>();
138     CHECK_NULL_VOID(buttonPattern);
139     buttonPattern->setComponentButtonType(ComponentButtonType::STEPPER);
140     buttonPattern->SetFocusBorderColor(stepperTheme->GetFocusColor());
141     auto buttonNode = FrameNode::CreateFrameNode(V2::BUTTON_ETS_TAG, buttonId, buttonPattern);
142     auto focusHub = buttonNode->GetOrCreateFocusHub();
143     CHECK_NULL_VOID(focusHub);
144     focusHub->SetFocusDependence(FocusDependence::SELF);
145     buttonNode->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
146     auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
147     CHECK_NULL_VOID(buttonLayoutProperty);
148     buttonLayoutProperty->UpdateType(ButtonType::NORMAL);
149     buttonLayoutProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
150     buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(stepperTheme->GetRadius()));
151     buttonNode->MountToParent(hostNode);
152     buttonNode->MarkModifyDone();
153 
154     // Create rowNode
155     auto rowNode = FrameNode::GetOrCreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
156         []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
157     auto rowLayoutProperty = rowNode->GetLayoutProperty<LinearLayoutProperty>();
158     CHECK_NULL_VOID(rowLayoutProperty);
159     rowLayoutProperty->UpdateSpace(stepperTheme->GetControlPadding());
160     rowLayoutProperty->UpdateMargin(
161         { CalcLength(stepperTheme->GetControlPadding()), CalcLength(stepperTheme->GetControlPadding()) });
162     rowLayoutProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
163     rowNode->MountToParent(buttonNode);
164     rowNode->MarkModifyDone();
165 
166     // Create imageNode
167     auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
168         []() { return AceType::MakeRefPtr<ImagePattern>(); });
169     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
170     CHECK_NULL_VOID(imageLayoutProperty);
171     imageLayoutProperty->UpdateUserDefinedIdealSize(
172         CalcSize(CalcLength(stepperTheme->GetArrowWidth()), CalcLength(stepperTheme->GetArrowHeight())));
173     imageLayoutProperty->UpdateImageFit(ImageFit::FILL);
174     ImageSourceInfo imageSourceInfo;
175     auto stepperLayoutProperty = hostNode->GetLayoutProperty<StepperLayoutProperty>();
176     CHECK_NULL_VOID(stepperLayoutProperty);
177     if (isRightToLeft_) {
178         rowNode->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::RTL);
179         imageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_NEXT_ARROW);
180     } else {
181         rowNode->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::LTR);
182         imageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_BACK_ARROW);
183     }
184     leftImage_ = imageNode;
185     imageSourceInfo.SetFillColor(stepperTheme->GetArrowColor());
186     imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
187     SizeF sourceSize(static_cast<float>(stepperTheme->GetArrowWidth().ConvertToPx()),
188         static_cast<float>(stepperTheme->GetArrowHeight().ConvertToPx()));
189     imageLayoutProperty->UpdateSourceSize(sourceSize);
190     imageNode->MountToParent(rowNode);
191     imageNode->MarkModifyDone();
192 
193     // Create textNode
194     auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
195         []() { return AceType::MakeRefPtr<TextPattern>(); });
196     textNode->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
197     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
198     CHECK_NULL_VOID(textLayoutProperty);
199     textLayoutProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
200     textLayoutProperty->UpdateTextColor(stepperTheme->GetTextStyle().GetTextColor());
201     textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
202     textLayoutProperty->UpdateFontSize(stepperTheme->GetTextStyle().GetFontSize());
203     textLayoutProperty->UpdateAdaptMinFontSize(stepperTheme->GetMinFontSize());
204     textLayoutProperty->UpdateAdaptMaxFontSize(stepperTheme->GetTextStyle().GetFontSize());
205     textLayoutProperty->UpdateFontWeight(stepperTheme->GetTextStyle().GetFontWeight());
206     textLayoutProperty->UpdateMaxLines(stepperTheme->GetTextMaxLines());
207     textNode->GetLayoutProperty()->UpdateAlignment(Alignment::CENTER);
208     textNode->GetFocusHub()->SetFocusable(true);
209     textNode->MountToParent(rowNode);
210     textNode->MarkModifyDone();
211 }
212 
UpdateLeftButtonNode(int32_t index)213 void StepperPattern::UpdateLeftButtonNode(int32_t index)
214 {
215     auto hostNode = DynamicCast<StepperNode>(GetHost());
216     CHECK_NULL_VOID(hostNode);
217     auto buttonNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetLeftButtonId()));
218     auto rowNode = buttonNode->GetChildAtIndex(0);
219     auto textNode = DynamicCast<FrameNode>(rowNode->GetChildAtIndex(1));
220 
221     auto swiperNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId()));
222     auto stepperItemNode = DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(static_cast<int32_t>(index)));
223     CHECK_NULL_VOID(stepperItemNode);
224     auto stepperItemLayoutProperty = stepperItemNode->GetLayoutProperty<StepperItemLayoutProperty>();
225     auto theme = GetTheme();
226     auto buttonBackText = theme ? theme->GetStepperBack() : "";
227     auto leftLabel = stepperItemLayoutProperty->GetLeftLabel().value_or(buttonBackText);
228     textNode->GetLayoutProperty<TextLayoutProperty>()->UpdateContent(leftLabel);
229 
230     textNode->MarkModifyDone();
231     textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
232 }
233 
UpdateOrCreateRightButtonNode(int32_t index)234 void StepperPattern::UpdateOrCreateRightButtonNode(int32_t index)
235 {
236     auto hostNode = DynamicCast<StepperNode>(GetHost());
237     CHECK_NULL_VOID(hostNode);
238     CreateRightButtonNode(index);
239     index_ = index;
240     hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
241 }
CreateRightButtonNode(int32_t index)242 void StepperPattern::CreateRightButtonNode(int32_t index)
243 {
244     auto hostNode = DynamicCast<StepperNode>(GetHost());
245     CHECK_NULL_VOID(hostNode);
246     auto swiperNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId()));
247     auto stepperItemNode = DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(static_cast<int32_t>(index)));
248     CHECK_NULL_VOID(stepperItemNode);
249     auto theme = GetTheme();
250     CHECK_NULL_VOID(theme);
251     auto labelStatus =
252         stepperItemNode->GetLayoutProperty<StepperItemLayoutProperty>()->GetLabelStatus().value_or("normal");
253     if (labelStatus == "normal") {
254         if (index == maxIndex_) {
255             CreateArrowlessRightButtonNode(index, false, theme->GetStepperStart());
256         } else {
257             CreateArrowRightButtonNode(index, false);
258         }
259     } else if (labelStatus == "disabled") {
260         if (index == maxIndex_) {
261             CreateArrowlessRightButtonNode(index, true, theme->GetStepperStart());
262         } else {
263             CreateArrowRightButtonNode(index, true);
264         }
265     } else if (labelStatus == "waiting") {
266         CreateWaitingRightButtonNode();
267     } else if (labelStatus == "skip") {
268         CreateArrowlessRightButtonNode(index, false, theme->GetStepperSkip());
269     }
270 }
271 
CreateArrowRightButtonNode(int32_t index,bool isDisabled)272 void StepperPattern::CreateArrowRightButtonNode(int32_t index, bool isDisabled)
273 {
274     auto stepperTheme = GetTheme();
275     CHECK_NULL_VOID(stepperTheme);
276     auto hostNode = DynamicCast<StepperNode>(GetHost());
277     CHECK_NULL_VOID(hostNode);
278     // get rightLabel
279     auto swiperNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId()));
280     auto stepperItemNode = DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(static_cast<int32_t>(index)));
281     CHECK_NULL_VOID(stepperItemNode);
282     auto buttonNextText = stepperTheme->GetStepperNext();
283     auto rightLabel =
284         stepperItemNode->GetLayoutProperty<StepperItemLayoutProperty>()->GetRightLabel().value_or(buttonNextText);
285     // Create or get buttonNode
286     if (isLoadingButton_) {
287         hostNode->RemoveRightButtonNode();
288         isLoadingButton_ = false;
289     }
290     auto hasRightButton = hostNode->HasRightButtonNode();
291     auto buttonNode = FrameNode::GetOrCreateFrameNode(
292         V2::BUTTON_ETS_TAG, hostNode->GetRightButtonId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
293     if (hasRightButton) {
294         buttonNode->Clean(true);
295         buttonNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
296     } else {
297         auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
298         CHECK_NULL_VOID(buttonPattern);
299         buttonPattern->setComponentButtonType(ComponentButtonType::STEPPER);
300         buttonPattern->SetFocusBorderColor(stepperTheme->GetFocusColor());
301         buttonNode->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
302         auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
303         CHECK_NULL_VOID(buttonLayoutProperty);
304         buttonLayoutProperty->UpdateType(ButtonType::NORMAL);
305         buttonLayoutProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
306         buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(stepperTheme->GetRadius()));
307         buttonNode->MountToParent(hostNode);
308     }
309     isDisabled ? buttonNode->GetOrCreateEventHub<ButtonEventHub>()->SetEnabled(false)
310                : buttonNode->GetOrCreateEventHub<ButtonEventHub>()->SetEnabled(true);
311     if (!isDisabled) {
312         auto focusHub = buttonNode->GetOrCreateFocusHub();
313         CHECK_NULL_VOID(focusHub);
314         focusHub->SetFocusDependence(FocusDependence::SELF);
315     }
316     buttonNode->MarkModifyDone();
317 
318     // Create rowNode
319     auto rowNode = FrameNode::GetOrCreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
320         []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
321     auto rowLayoutProperty = rowNode->GetLayoutProperty<LinearLayoutProperty>();
322     CHECK_NULL_VOID(rowLayoutProperty);
323     rowLayoutProperty->UpdateSpace(stepperTheme->GetControlPadding());
324     rowLayoutProperty->UpdateMargin(
325         { CalcLength(stepperTheme->GetControlPadding()), CalcLength(stepperTheme->GetControlPadding()) });
326     rowNode->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
327     rowNode->MountToParent(buttonNode);
328     rowNode->MarkModifyDone();
329 
330     // Create textNode
331     auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
332         []() { return AceType::MakeRefPtr<TextPattern>(); });
333     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
334     CHECK_NULL_VOID(textLayoutProperty);
335     textLayoutProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
336     textLayoutProperty->UpdateContent(rightLabel);
337     auto textColor = stepperTheme->GetTextStyle().GetTextColor();
338     if (isDisabled) {
339         textColor = textColor.BlendOpacity(stepperTheme->GetDisabledAlpha());
340     }
341     textLayoutProperty->UpdateTextColor(textColor);
342     textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
343     textLayoutProperty->UpdateFontSize(stepperTheme->GetTextStyle().GetFontSize());
344     textLayoutProperty->UpdateAdaptMinFontSize(stepperTheme->GetMinFontSize());
345     textLayoutProperty->UpdateAdaptMaxFontSize(stepperTheme->GetTextStyle().GetFontSize());
346     textLayoutProperty->UpdateFontWeight(stepperTheme->GetTextStyle().GetFontWeight());
347     textLayoutProperty->UpdateMaxLines(stepperTheme->GetTextMaxLines());
348     textLayoutProperty->UpdateAlignment(Alignment::CENTER);
349     textNode->GetFocusHub()->SetFocusable(true);
350     textNode->MountToParent(rowNode);
351     textNode->MarkModifyDone();
352 
353     // Create imageNode
354     auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
355         []() { return AceType::MakeRefPtr<ImagePattern>(); });
356     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
357     CHECK_NULL_VOID(imageLayoutProperty);
358     imageLayoutProperty->UpdateUserDefinedIdealSize(
359         CalcSize(CalcLength(stepperTheme->GetArrowWidth()), CalcLength(stepperTheme->GetArrowHeight())));
360     imageLayoutProperty->UpdateImageFit(ImageFit::FILL);
361     ImageSourceInfo imageSourceInfo;
362     if (isRightToLeft_) {
363         rowNode->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::RTL);
364         imageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_BACK_ARROW);
365     } else {
366         rowNode->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::LTR);
367         imageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_NEXT_ARROW);
368     }
369     rightImage_ = imageNode;
370     auto imageColor = stepperTheme->GetArrowColor();
371     if (isDisabled) {
372         imageColor = imageColor.BlendOpacity(stepperTheme->GetDisabledAlpha());
373     }
374     imageSourceInfo.SetFillColor(imageColor);
375     imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
376     SizeF sourceSize(static_cast<float>(stepperTheme->GetArrowWidth().ConvertToPx()),
377         static_cast<float>(stepperTheme->GetArrowHeight().ConvertToPx()));
378     imageLayoutProperty->UpdateSourceSize(sourceSize);
379     imageNode->MountToParent(rowNode);
380     imageNode->MarkModifyDone();
381 }
382 
CreateArrowlessRightButtonNode(int32_t index,bool isDisabled,const std::string & defaultContent)383 void StepperPattern::CreateArrowlessRightButtonNode(int32_t index, bool isDisabled, const std::string& defaultContent)
384 {
385     auto stepperTheme = GetTheme();
386     CHECK_NULL_VOID(stepperTheme);
387     auto hostNode = DynamicCast<StepperNode>(GetHost());
388     CHECK_NULL_VOID(hostNode);
389     // get rightLabel
390     auto swiperNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId()));
391     auto stepperItemNode = DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(static_cast<int32_t>(index)));
392     auto rightLabel =
393         stepperItemNode->GetLayoutProperty<StepperItemLayoutProperty>()->GetRightLabel().value_or(defaultContent);
394     // Create or get buttonNode
395     if (isLoadingButton_) {
396         hostNode->RemoveRightButtonNode();
397         isLoadingButton_ = false;
398     }
399     auto hasRightButton = hostNode->HasRightButtonNode();
400     auto buttonNode = FrameNode::GetOrCreateFrameNode(
401         V2::BUTTON_ETS_TAG, hostNode->GetRightButtonId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
402     if (hasRightButton) {
403         buttonNode->Clean(true);
404         buttonNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
405     } else {
406         auto buttonPattern = buttonNode->GetPattern<ButtonPattern>();
407         CHECK_NULL_VOID(buttonPattern);
408         buttonPattern->setComponentButtonType(ComponentButtonType::STEPPER);
409         buttonPattern->SetFocusBorderColor(stepperTheme->GetFocusColor());
410         buttonNode->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
411         auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
412         CHECK_NULL_VOID(buttonLayoutProperty);
413         buttonLayoutProperty->UpdateType(ButtonType::NORMAL);
414         buttonLayoutProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
415         buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(stepperTheme->GetRadius()));
416         buttonNode->MountToParent(hostNode);
417     }
418     isDisabled ? buttonNode->GetOrCreateEventHub<ButtonEventHub>()->SetEnabled(false)
419                : buttonNode->GetOrCreateEventHub<ButtonEventHub>()->SetEnabled(true);
420     if (!isDisabled) {
421         auto focusHub = buttonNode->GetOrCreateFocusHub();
422         CHECK_NULL_VOID(focusHub);
423         focusHub->SetFocusDependence(FocusDependence::SELF);
424     }
425     buttonNode->MarkModifyDone();
426 
427     // Create textNode
428     auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
429         []() { return AceType::MakeRefPtr<TextPattern>(); });
430     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
431     CHECK_NULL_VOID(textLayoutProperty);
432     textLayoutProperty->UpdateContent(rightLabel);
433     textLayoutProperty->UpdateFontSize(stepperTheme->GetTextStyle().GetFontSize());
434     textLayoutProperty->UpdateAdaptMinFontSize(stepperTheme->GetMinFontSize());
435     textLayoutProperty->UpdateAdaptMaxFontSize(stepperTheme->GetTextStyle().GetFontSize());
436     textLayoutProperty->UpdateMaxLines(stepperTheme->GetTextMaxLines());
437     textLayoutProperty->UpdateFontWeight(stepperTheme->GetTextStyle().GetFontWeight());
438     auto textColor = stepperTheme->GetTextStyle().GetTextColor();
439     if (isDisabled) {
440         textColor = textColor.BlendOpacity(stepperTheme->GetDisabledAlpha());
441     }
442     textLayoutProperty->UpdateTextColor(textColor);
443     textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
444     textLayoutProperty->UpdateAlignment(Alignment::CENTER);
445     textLayoutProperty->UpdateMargin(
446         { CalcLength(stepperTheme->GetControlPadding()), CalcLength(stepperTheme->GetControlPadding()) });
447     textNode->GetFocusHub()->SetFocusable(true);
448     textNode->MountToParent(buttonNode);
449     textNode->MarkModifyDone();
450 }
451 
CreateWaitingRightButtonNode()452 void StepperPattern::CreateWaitingRightButtonNode()
453 {
454     auto stepperTheme = GetTheme();
455     CHECK_NULL_VOID(stepperTheme);
456     auto hostNode = DynamicCast<StepperNode>(GetHost());
457     CHECK_NULL_VOID(hostNode);
458     // Create loadingProgressNode
459     hostNode->RemoveRightButtonNode();
460     auto loadingProgressNode = FrameNode::GetOrCreateFrameNode(V2::LOADING_PROGRESS_ETS_TAG,
461         hostNode->GetRightButtonId(), []() { return AceType::MakeRefPtr<LoadingProgressPattern>(); });
462     loadingProgressNode->GetLayoutProperty()->UpdateUserDefinedIdealSize(
463         CalcSize(CalcLength(stepperTheme->GetProgressDiameter()), CalcLength(stepperTheme->GetProgressDiameter())));
464     loadingProgressNode->GetPaintProperty<LoadingProgressPaintProperty>()->UpdateColor(
465         stepperTheme->GetProgressColor());
466     loadingProgressNode->GetRenderContext()->UpdateForegroundColor(stepperTheme->GetProgressColor());
467     loadingProgressNode->MountToParent(hostNode);
468     loadingProgressNode->MarkModifyDone();
469     isLoadingButton_ = true;
470 }
471 
InitButtonClickEvent()472 void StepperPattern::InitButtonClickEvent()
473 {
474     auto hostNode = DynamicCast<StepperNode>(GetHost());
475     CHECK_NULL_VOID(hostNode);
476 
477     if (hostNode->HasLeftButtonNode()) {
478         auto leftButtonNode =
479             DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetLeftButtonId())));
480         CHECK_NULL_VOID(leftButtonNode);
481         auto leftGestureHub = leftButtonNode->GetOrCreateGestureEventHub();
482         CHECK_NULL_VOID(leftGestureHub);
483         if (leftGestureHub->IsClickEventsEmpty()) {
484             auto leftClickEvent = [weak = WeakClaim(this)](const GestureEvent& info) {
485                 auto stepperPattern = weak.Upgrade();
486                 CHECK_NULL_VOID(stepperPattern);
487                 stepperPattern->HandlingLeftButtonClickEvent();
488             };
489             leftGestureHub->AddClickEvent(MakeRefPtr<ClickEvent>(std::move(leftClickEvent)));
490         }
491     }
492 
493     if (hostNode->HasRightButtonNode()) {
494         auto rightButtonNode = DynamicCast<FrameNode>(
495             hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetRightButtonId())));
496         CHECK_NULL_VOID(rightButtonNode);
497         auto rightGestureHub = rightButtonNode->GetOrCreateGestureEventHub();
498         CHECK_NULL_VOID(rightGestureHub);
499         if (rightGestureHub->IsClickEventsEmpty()) {
500             auto rightClickEvent = [weak = WeakClaim(this)](const GestureEvent& info) {
501                 auto stepperPattern = weak.Upgrade();
502                 CHECK_NULL_VOID(stepperPattern);
503                 stepperPattern->HandlingRightButtonClickEvent();
504             };
505             rightGestureHub->AddClickEvent(MakeRefPtr<ClickEvent>(std::move(rightClickEvent)));
506         }
507     }
508 }
509 
HandlingLeftButtonClickEvent()510 void StepperPattern::HandlingLeftButtonClickEvent()
511 {
512     auto hostNode = DynamicCast<StepperNode>(GetHost());
513     CHECK_NULL_VOID(hostNode);
514     auto stepperHub = hostNode->GetOrCreateEventHub<StepperEventHub>();
515     CHECK_NULL_VOID(stepperHub);
516     auto swiperNode =
517         DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId())));
518     auto swiperAnimationController = swiperNode->GetPattern<SwiperPattern>()->GetController();
519     if (swiperAnimationController && !swiperAnimationController->IsStopped()) {
520         return;
521     }
522     auto swiperController = swiperNode->GetPattern<SwiperPattern>()->GetSwiperController();
523     stepperHub->FireChangeEvent(index_, std::clamp<int32_t>(index_ - 1, 0, maxIndex_));
524     stepperHub->FirePreviousEvent(index_, std::clamp<int32_t>(index_ - 1, 0, maxIndex_));
525     swiperController->SwipeTo(std::clamp<int32_t>(index_ - 1, 0, maxIndex_));
526 }
527 
HandlingRightButtonClickEvent()528 void StepperPattern::HandlingRightButtonClickEvent()
529 {
530     auto hostNode = DynamicCast<StepperNode>(GetHost());
531     CHECK_NULL_VOID(hostNode);
532     auto stepperHub = hostNode->GetOrCreateEventHub<StepperEventHub>();
533     CHECK_NULL_VOID(stepperHub);
534     auto swiperNode =
535         DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId())));
536     auto swiperAnimationController = swiperNode->GetPattern<SwiperPattern>()->GetController();
537     if (swiperAnimationController && !swiperAnimationController->IsStopped()) {
538         return;
539     }
540     auto stepperItemNode = DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(static_cast<int32_t>(index_)));
541     CHECK_NULL_VOID(stepperItemNode);
542     auto labelStatus =
543         stepperItemNode->GetLayoutProperty<StepperItemLayoutProperty>()->GetLabelStatus().value_or("normal");
544     if (labelStatus == "skip") {
545         stepperHub->FireSkipEvent(index_);
546     } else if (labelStatus == "normal") {
547         if (index_ == maxIndex_) {
548             stepperHub->FireFinishEvent(index_);
549         } else {
550             stepperHub->FireChangeEvent(index_, std::clamp<int32_t>(index_ + 1, 0, maxIndex_));
551             stepperHub->FireNextEvent(index_, std::clamp<int32_t>(index_ + 1, 0, maxIndex_));
552             auto swiperController = swiperNode->GetPattern<SwiperPattern>()->GetSwiperController();
553             swiperController->SwipeTo(std::clamp<int32_t>(index_ + 1, 0, maxIndex_));
554         }
555     }
556 }
557 
TotalCount() const558 int32_t StepperPattern::TotalCount() const
559 {
560     auto hostNode = DynamicCast<StepperNode>(GetHost());
561     CHECK_NULL_RETURN(hostNode, 0);
562     auto swiperNode =
563         DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId())));
564     CHECK_NULL_RETURN(swiperNode, 0);
565     return swiperNode->TotalChildCount() - 1;
566 }
567 
SetAccessibilityAction()568 void StepperPattern::SetAccessibilityAction()
569 {
570     auto host = GetHost();
571     CHECK_NULL_VOID(host);
572     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
573     CHECK_NULL_VOID(accessibilityProperty);
574     accessibilityProperty->SetActionScrollForward([weakPtr = WeakClaim(this)]() {
575         const auto& pattern = weakPtr.Upgrade();
576         CHECK_NULL_VOID(pattern);
577         pattern->HandlingRightButtonClickEvent();
578     });
579 
580     accessibilityProperty->SetActionScrollBackward([weakPtr = WeakClaim(this)]() {
581         const auto& pattern = weakPtr.Upgrade();
582         CHECK_NULL_VOID(pattern);
583         pattern->HandlingLeftButtonClickEvent();
584     });
585 }
586 
GetFocusNode(FocusStep step,const WeakPtr<FocusHub> & currentFocusNode)587 WeakPtr<FocusHub> StepperPattern::GetFocusNode(FocusStep step, const WeakPtr<FocusHub>& currentFocusNode)
588 {
589     auto curFocusNode = currentFocusNode.Upgrade();
590     CHECK_NULL_RETURN(curFocusNode, nullptr);
591     auto hostNode = DynamicCast<StepperNode>(GetHost());
592     CHECK_NULL_RETURN(hostNode, nullptr);
593 
594     auto swiperNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetSwiperId()));
595     CHECK_NULL_RETURN(swiperNode, nullptr);
596     auto stepperItemNode = DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(static_cast<int32_t>(index_)));
597     CHECK_NULL_RETURN(stepperItemNode, nullptr);
598     auto buttonFocusHub = stepperItemNode->GetOrCreateFocusHub();
599     CHECK_NULL_RETURN(buttonFocusHub, nullptr);
600 
601     auto stepperItemLayoutProperty = stepperItemNode->GetLayoutProperty<StepperItemLayoutProperty>();
602     CHECK_NULL_RETURN(stepperItemLayoutProperty, nullptr);
603     auto labelStatus = stepperItemLayoutProperty->GetLabelStatus().value_or("normal");
604 
605     if (hostNode->HasLeftButtonNode()) {
606         auto leftButtonNode =
607             DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetLeftButtonId())));
608         CHECK_NULL_RETURN(leftButtonNode, nullptr);
609         leftFocusHub_ = leftButtonNode->GetOrCreateFocusHub();
610     }
611 
612     auto rightButtonNode =
613         DynamicCast<FrameNode>(hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetRightButtonId())));
614     CHECK_NULL_RETURN(rightButtonNode, nullptr);
615     auto rightFocusHub = rightButtonNode->GetOrCreateFocusHub();
616     CHECK_NULL_RETURN(rightFocusHub, nullptr);
617 
618     if (labelStatus == "normal" || labelStatus == "skip") {
619         if (step == FocusStep::UP || step == FocusStep::LEFT || step == FocusStep::SHIFT_TAB) {
620             return curFocusNode == leftFocusHub_ ? buttonFocusHub : leftFocusHub_;
621         }
622 
623         if (curFocusNode != leftFocusHub_ && curFocusNode != rightFocusHub) {
624             return hostNode->HasLeftButtonNode() ? leftFocusHub_ : rightFocusHub;
625         }
626 
627         if (curFocusNode == rightFocusHub && !hostNode->HasLeftButtonNode()) {
628             return buttonFocusHub;
629         }
630 
631         if (step == FocusStep::DOWN || step == FocusStep::RIGHT || step == FocusStep::TAB) {
632             return curFocusNode == buttonFocusHub ? leftFocusHub_ : rightFocusHub;
633         }
634     } else if (labelStatus == "disabled" || labelStatus == "waiting") {
635         return curFocusNode == leftFocusHub_ ? buttonFocusHub : leftFocusHub_;
636     }
637     return nullptr;
638 }
639 
OnColorConfigurationUpdate()640 void StepperPattern::OnColorConfigurationUpdate()
641 {
642     auto host = GetHost();
643     CHECK_NULL_VOID(host);
644     auto hostNode = DynamicCast<StepperNode>(GetHost());
645     CHECK_NULL_VOID(hostNode);
646     auto stepperTheme = GetTheme();
647     CHECK_NULL_VOID(stepperTheme);
648     auto textColor = stepperTheme->GetTextStyle().GetTextColor();
649     auto leftButtonNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetLeftButtonId()));
650     if (leftButtonNode) {
651         auto leftButtonFrameNode = DynamicCast<FrameNode>(leftButtonNode);
652         CHECK_NULL_VOID(leftButtonFrameNode);
653         ButtonSkipColorConfigurationUpdate(leftButtonFrameNode);
654         auto renderContext = leftButtonFrameNode->GetRenderContext();
655         CHECK_NULL_VOID(renderContext);
656         renderContext->UpdateBackgroundColor(stepperTheme->GetMouseHoverColor().ChangeOpacity(0));
657         auto rowNode = leftButtonFrameNode->GetChildAtIndex(0);
658         CHECK_NULL_VOID(rowNode);
659         auto textFrameNode = DynamicCast<FrameNode>(rowNode->GetChildAtIndex(1));
660         CHECK_NULL_VOID(textFrameNode);
661         auto layoutProperty = textFrameNode->GetLayoutProperty<TextLayoutProperty>();
662         CHECK_NULL_VOID(layoutProperty);
663         layoutProperty->UpdateTextColor(textColor);
664     }
665     auto rightButtonNode = hostNode->GetChildAtIndex(hostNode->GetChildIndexById(hostNode->GetRightButtonId()));
666     if (rightButtonNode) {
667         auto rightButtonFrameNode = DynamicCast<FrameNode>(rightButtonNode);
668         CHECK_NULL_VOID(rightButtonFrameNode);
669         ButtonSkipColorConfigurationUpdate(rightButtonFrameNode);
670         auto renderContext = rightButtonFrameNode->GetRenderContext();
671         CHECK_NULL_VOID(renderContext);
672         renderContext->UpdateBackgroundColor(stepperTheme->GetMouseHoverColor().ChangeOpacity(0));
673         auto firstChild = rightButtonFrameNode->GetFirstChild();
674         CHECK_NULL_VOID(firstChild);
675         if (firstChild->GetTag() == V2::ROW_ETS_TAG) {
676             auto textFrameNode = DynamicCast<FrameNode>(firstChild->GetChildAtIndex(0));
677             CHECK_NULL_VOID(textFrameNode);
678             auto layoutProperty = textFrameNode->GetLayoutProperty<TextLayoutProperty>();
679             CHECK_NULL_VOID(layoutProperty);
680             layoutProperty->UpdateTextColor(textColor);
681         }
682         if (firstChild->GetTag() == V2::TEXT_ETS_TAG) {
683             auto textFrameNode = DynamicCast<FrameNode>(firstChild);
684             CHECK_NULL_VOID(textFrameNode);
685             auto layoutProperty = textFrameNode->GetLayoutProperty<TextLayoutProperty>();
686             CHECK_NULL_VOID(layoutProperty);
687             layoutProperty->UpdateTextColor(textColor);
688         }
689     }
690 }
691 
ButtonSkipColorConfigurationUpdate(const RefPtr<FrameNode> & buttonNode)692 void StepperPattern::ButtonSkipColorConfigurationUpdate(const RefPtr<FrameNode>& buttonNode)
693 {
694     auto pattern = buttonNode->GetPattern<ButtonPattern>();
695     CHECK_NULL_VOID(pattern);
696     pattern->SetSkipColorConfigurationUpdate();
697 }
698 
OnLanguageConfigurationUpdate()699 void StepperPattern::OnLanguageConfigurationUpdate()
700 {
701     auto hostNode = DynamicCast<StepperNode>(GetHost());
702     CHECK_NULL_VOID(hostNode);
703     auto stepperLayoutProperty = hostNode->GetLayoutProperty<StepperLayoutProperty>();
704     CHECK_NULL_VOID(stepperLayoutProperty);
705     auto isRightToLeft = stepperLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
706     if (isRightToLeft != isRightToLeft_) {
707         auto hostNode = AceType::DynamicCast<StepperNode>(GetHost());
708         CHECK_NULL_VOID(hostNode);
709         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
710         isRightToLeft_ = isRightToLeft;
711 
712         auto stepperTheme = GetTheme();
713         CHECK_NULL_VOID(stepperTheme);
714         if (leftImage_) {
715             auto leftimageLayoutProperty = leftImage_->GetLayoutProperty<ImageLayoutProperty>();
716             CHECK_NULL_VOID(leftimageLayoutProperty);
717             auto leftRow = DynamicCast<FrameNode>(leftImage_->GetParent());
718             CHECK_NULL_VOID(leftRow);
719 
720             ImageSourceInfo leftimageSourceInfo;
721             if (isRightToLeft_) {
722                 leftRow->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::RTL);
723                 leftimageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_NEXT_ARROW);
724             } else {
725                 leftRow->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::LTR);
726                 leftimageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_BACK_ARROW);
727             }
728             leftimageSourceInfo.SetFillColor(stepperTheme->GetArrowColor());
729             leftimageLayoutProperty->UpdateImageSourceInfo(leftimageSourceInfo);
730             leftImage_->MarkModifyDone();
731         }
732         if (rightImage_) {
733             auto rightimageLayoutProperty = rightImage_->GetLayoutProperty<ImageLayoutProperty>();
734             CHECK_NULL_VOID(rightimageLayoutProperty);
735             auto rightRow = DynamicCast<FrameNode>(rightImage_->GetParent());
736             CHECK_NULL_VOID(rightRow);
737             ImageSourceInfo rightimageSourceInfo;
738             if (isRightToLeft_) {
739                 rightRow->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::RTL);
740                 rightimageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_BACK_ARROW);
741             } else {
742                 rightRow->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::LTR);
743                 rightimageSourceInfo.SetResourceId(InternalResource::ResourceId::STEPPER_NEXT_ARROW);
744             }
745             rightimageSourceInfo.SetFillColor(stepperTheme->GetArrowColor());
746             rightimageLayoutProperty->UpdateImageSourceInfo(rightimageSourceInfo);
747             rightImage_->MarkModifyDone();
748         }
749     }
750 }
751 } // namespace OHOS::Ace::NG
752