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