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