• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components/calendar/calendar_component.h"
17 
18 #include "base/i18n/localization.h"
19 #include "core/components/box/box_component.h"
20 #include "core/components/button/button_component.h"
21 #include "core/components/button/render_button.h"
22 #include "core/components/calendar/calendar_element.h"
23 #include "core/components/calendar/render_calendar.h"
24 #include "core/components/display/display_component.h"
25 #include "core/components/flex/flex_item_component.h"
26 #include "core/components/image/image_component.h"
27 #include "core/components/padding/padding_component.h"
28 #include "core/components/text/text_component.h"
29 #include "core/event/ace_event_helper.h"
30 #include "core/event/back_end_event_manager.h"
31 
32 namespace OHOS::Ace {
33 namespace {
34 
35 constexpr double MAX_OPACITY = 255.0;
36 constexpr int32_t MAX_MONTH_CACHE_NUM = 3;
37 constexpr int32_t DISTANCE_FORM_LAST = MAX_MONTH_CACHE_NUM - 1;
38 constexpr int32_t TODAY_MONTH_INDEX_OF_CONTAINER = 1;
39 constexpr int32_t NEXT_TO_TODAY_MONTH_INDEX_OF_CONTAINER = 2;
40 constexpr int32_t LAST_TO_TODAY_MONTH_INDEX_OF_CONTAINER = 0;
41 constexpr Dimension CALENDAR_BOX_TOP_AND_BOTTOM_MARGIN = 4.0_vp;
42 constexpr Dimension CALENDAR_BOX_LEFT_AND_RIGHT_MARGIN = 24.0_vp;
43 constexpr Dimension CALENDAR_BUTTON_RADIUS = 4.0_vp;
44 
45 } // namespace
46 
CalendarController(const CalendarDataAdapterAction & dataAdapterAction,const WeakPtr<PipelineContext> & pipelineContext)47 CalendarController::CalendarController(
48     const CalendarDataAdapterAction& dataAdapterAction, const WeakPtr<PipelineContext>& pipelineContext)
49     : dataAdapter_(AceType::MakeRefPtr<CalendarDataAdapter>(dataAdapterAction, pipelineContext)) {}
50 
Initialize()51 void CalendarController::Initialize()
52 {
53     currentCalendarMonth_ = dataAdapter_->GetToday().month;
54     dataAdapter_->SetCurrentMonth(currentCalendarMonth_);
55     dataAdapter_->SetSelectedChanged(dataAdapter_->GetToday().day, TODAY_MONTH_INDEX_OF_CONTAINER);
56     CalendarDataRequest requestMonth(currentCalendarMonth_, TODAY_MONTH_INDEX_OF_CONTAINER);
57     requestMonth.state = MonthState::CUR_MONTH;
58     dataAdapter_->RequestData(requestMonth);
59     requestMonth.month = CalendarMonth::GetNextMonth(currentCalendarMonth_);
60     requestMonth.indexOfContainer = NEXT_TO_TODAY_MONTH_INDEX_OF_CONTAINER;
61     requestMonth.state = MonthState::NEXT_MONTH;
62     dataAdapter_->AddPendingRequest(requestMonth);
63     requestMonth.month = CalendarMonth::GetLastMonth(currentCalendarMonth_);
64     requestMonth.indexOfContainer = LAST_TO_TODAY_MONTH_INDEX_OF_CONTAINER;
65     requestMonth.state = MonthState::PRE_MONTH;
66     dataAdapter_->AddPendingRequest(requestMonth);
67 }
68 
GoToPrevMonth(int32_t selected)69 void CalendarController::GoToPrevMonth(int32_t selected)
70 {
71     GoToMonth(SwipeDirection::PREV, selected);
72 }
73 
GoToNextMonth(int32_t selected)74 void CalendarController::GoToNextMonth(int32_t selected)
75 {
76     GoToMonth(SwipeDirection::NEXT, selected);
77 }
78 
GoToMonth(SwipeDirection direction,int32_t selected)79 void CalendarController::GoToMonth(SwipeDirection direction, int32_t selected)
80 {
81     int32_t index;
82     CalendarMonth calendarMonth;
83     CalendarMonth cacheMonth;
84     bool reverse = false;
85     if (direction == SwipeDirection::PREV) {
86         index = (currentMonthIndex_ + 1) % MAX_MONTH_CACHE_NUM;
87         if (--currentMonthIndex_ < 0) {
88             reverse = true;
89             currentMonthIndex_ = MAX_MONTH_CACHE_NUM - 1;
90         }
91         calendarMonth = CalendarMonth::GetLastMonth(currentCalendarMonth_);
92         cacheMonth = CalendarMonth::GetLastMonth(calendarMonth);
93     } else if (direction == SwipeDirection::NEXT) {
94         index = (currentMonthIndex_ + DISTANCE_FORM_LAST) % MAX_MONTH_CACHE_NUM;
95         if (++currentMonthIndex_ >= MAX_MONTH_CACHE_NUM) {
96             reverse = true;
97             currentMonthIndex_ = 0;
98         }
99         calendarMonth = CalendarMonth::GetNextMonth(currentCalendarMonth_);
100         cacheMonth = CalendarMonth::GetNextMonth(calendarMonth);
101     } else {
102         return;
103     }
104 
105     swiperReverseCache_.push({ currentMonthIndex_, reverse });
106     dataAdapter_->SetSelectedChanged(selected, currentMonthIndex_);
107     dataAdapter_->NotifySelectedChanged();
108     currentCalendarMonth_ = calendarMonth;
109     dataAdapter_->SetCurrentMonth(currentCalendarMonth_);
110     dataAdapter_->RequestData({ cacheMonth, index });
111 }
112 
JumpToMonth(const CalendarMonth & calendarMonth,int32_t selected,SwipeDirection direction)113 void CalendarController::JumpToMonth(const CalendarMonth& calendarMonth, int32_t selected, SwipeDirection direction)
114 {
115     if (direction == SwipeDirection::PREV) {
116         // target -- last(replaced by target) -- current -- next
117         int32_t destIndex = (currentMonthIndex_ + DISTANCE_FORM_LAST) % MAX_MONTH_CACHE_NUM;
118         dataAdapter_->RequestData({ calendarMonth, destIndex });
119         CalculateNextIndex(currentMonthIndex_ - 1);
120         dataAdapter_->SetSelectedChanged(selected, currentMonthIndex_);
121 
122         int32_t lastIndex = (destIndex + DISTANCE_FORM_LAST) % MAX_MONTH_CACHE_NUM;
123         dataAdapter_->AddPendingRequest(CalendarMonth::GetLastMonth(calendarMonth), lastIndex);
124 
125         // cache the next month date after the animation ends, otherwise the content of the animation page will be
126         // changed
127         int32_t nextIndex = (destIndex + 1) % MAX_MONTH_CACHE_NUM;
128         dataAdapter_->AddPendingRequest(CalendarMonth::GetNextMonth(calendarMonth), nextIndex);
129     } else if (direction == SwipeDirection::NEXT) {
130         // last -- current -- next(replaced by target) -- target
131         int32_t destIndex = (currentMonthIndex_ + 1) % MAX_MONTH_CACHE_NUM;
132         dataAdapter_->RequestData({ calendarMonth, destIndex });
133         CalculateNextIndex(currentMonthIndex_ + 1);
134         dataAdapter_->SetSelectedChanged(selected, currentMonthIndex_);
135 
136         int32_t nextIndex = (destIndex + 1) % MAX_MONTH_CACHE_NUM;
137         dataAdapter_->AddPendingRequest(CalendarMonth::GetNextMonth(calendarMonth), nextIndex);
138 
139         // cache the previous month date after the animation ends, otherwise the content of the animation page will be
140         // changed
141         int32_t lastIndex = (destIndex + DISTANCE_FORM_LAST) % MAX_MONTH_CACHE_NUM;
142         dataAdapter_->AddPendingRequest(CalendarMonth::GetLastMonth(calendarMonth), lastIndex);
143     }
144 }
145 
GoTo(int32_t year,int32_t month,int32_t day)146 void CalendarController::GoTo(int32_t year, int32_t month, int32_t day)
147 {
148     if (!dataAdapter_) {
149         LOGE("calendar data adapter is nullptr");
150         return;
151     }
152     if (!swiperController_) {
153         LOGE("swiper controller is nullptr");
154         return;
155     }
156 
157     LOGD("go to: year=%{private}d, month=%{private}d, day=%{private}d", year, month, day);
158     CalendarMonth calendarMonth { year, month };
159     auto nextMonth = CalendarMonth::GetNextMonth(currentCalendarMonth_);
160     auto lastMonth = CalendarMonth::GetLastMonth(currentCalendarMonth_);
161     if (calendarMonth == lastMonth) {
162         GoToPrevMonth(day);
163     } else if (calendarMonth == nextMonth) {
164         GoToNextMonth(day);
165     } else if (calendarMonth < lastMonth) {
166         currentCalendarMonth_ = calendarMonth;
167         dataAdapter_->SetCurrentMonth(currentCalendarMonth_);
168         JumpToMonth(calendarMonth, day, SwipeDirection::PREV);
169     } else if (calendarMonth > nextMonth) {
170         currentCalendarMonth_ = calendarMonth;
171         dataAdapter_->SetCurrentMonth(currentCalendarMonth_);
172         JumpToMonth(calendarMonth, day, SwipeDirection::NEXT);
173     } else {
174         dataAdapter_->SetSelectedChanged(day, currentMonthIndex_);
175         dataAdapter_->NotifySelectedChanged();
176     }
177 }
178 
RequestMonthData(int32_t index)179 void CalendarController::RequestMonthData(int32_t index)
180 {
181     auto tmpPreIndex = (currentMonthIndex_ + 1) % MAX_MONTH_CACHE_NUM;
182     auto tmpNextIndex = (currentMonthIndex_ + DISTANCE_FORM_LAST) % MAX_MONTH_CACHE_NUM;
183     auto nextIndex = currentMonthIndex_;
184     auto preIndex = currentMonthIndex_;
185     CalendarMonth calendarMonth;
186     CalendarMonth cacheMonth;
187     static const int32_t selectedDay = 1;
188     if (++nextIndex >= MAX_MONTH_CACHE_NUM) {
189         nextIndex = 0;
190     }
191     if (--preIndex < 0) {
192         preIndex = MAX_MONTH_CACHE_NUM - 1;
193     }
194     if (nextIndex == index) {
195         currentMonthIndex_ = nextIndex;
196         calendarMonth = CalendarMonth::GetNextMonth(currentCalendarMonth_);
197         cacheMonth = CalendarMonth::GetNextMonth(calendarMonth);
198 
199         dataAdapter_->SetSelectedChanged(selectedDay, currentMonthIndex_);
200         CalendarDataRequest requestMonth(cacheMonth, tmpNextIndex);
201         requestMonth.state = MonthState::NEXT_MONTH;
202         currentCalendarMonth_ = calendarMonth;
203         dataAdapter_->SetCurrentMonth(currentCalendarMonth_);
204         dataAdapter_->RequestData(requestMonth);
205     } else if (preIndex == index) {
206         currentMonthIndex_ = preIndex;
207         calendarMonth = CalendarMonth::GetLastMonth(currentCalendarMonth_);
208         cacheMonth = CalendarMonth::GetLastMonth(calendarMonth);
209 
210         dataAdapter_->SetSelectedChanged(selectedDay, currentMonthIndex_);
211         CalendarDataRequest requestMonth(cacheMonth, tmpPreIndex);
212         requestMonth.state = MonthState::PRE_MONTH;
213         currentCalendarMonth_ = calendarMonth;
214         dataAdapter_->SetCurrentMonth(currentCalendarMonth_);
215         dataAdapter_->RequestData(requestMonth);
216     } else {
217         return;
218     }
219 }
220 
CalculateNextIndex(int32_t index)221 void CalendarController::CalculateNextIndex(int32_t index)
222 {
223     bool reverse = false;
224     if (index >= MAX_MONTH_CACHE_NUM) {
225         reverse = true;
226         index = 0;
227     } else if (index < 0) {
228         reverse = true;
229         index = MAX_MONTH_CACHE_NUM - 1;
230     }
231     currentMonthIndex_ = index;
232     swiperReverseCache_.push({ currentMonthIndex_, reverse });
233 }
234 
UpdateTheme()235 void CalendarController::UpdateTheme()
236 {
237     if (!renderText_) {
238         return;
239     }
240     auto theme = renderText_->GetTheme<CalendarTheme>();
241     if (!leftImage_ || !leftImageComponent_ || !rightImageComponent_ || !rightImage_ || !theme) {
242         return;
243     }
244     TextStyle style;
245     auto cardTheme = theme->GetCardCalendarTheme();
246     style.SetFontSize(cardTheme.titleFontSize);
247     style.SetTextColor(cardTheme.titleTextColor);
248     style.SetFontWeight(FontWeight::W500);
249     style.SetAllowScale(false);
250     renderText_->SetTextStyle(style);
251     renderText_->MarkNeedMeasure();
252     renderText_->MarkNeedLayout();
253     leftImageComponent_->SetImageFill(cardTheme.titleTextColor);
254     leftImage_->Update(leftImageComponent_);
255     leftImage_->MarkNeedLayout();
256     rightImageComponent_->SetImageFill(cardTheme.titleTextColor);
257     rightImage_->Update(rightImageComponent_);
258     rightImage_->MarkNeedLayout();
259     SetButtonClickColor(renderText_, cardTheme.clickEffectColor);
260     SetButtonClickColor(leftImage_, cardTheme.clickEffectColor);
261     SetButtonClickColor(rightImage_, cardTheme.clickEffectColor);
262 }
263 
SetButtonClickColor(const RefPtr<RenderNode> & node,const Color & clickColor) const264 void CalendarController::SetButtonClickColor(const RefPtr<RenderNode>& node, const Color& clickColor) const
265 {
266     auto button = AceType::DynamicCast<RenderButton>(node->GetParent().Upgrade());
267     if (!button) {
268         LOGE("this node is not button");
269         return;
270     }
271     button->SetClickedColor(clickColor);
272     button->MarkNeedLayout();
273 }
274 
UpdateTitle(const CalendarDay & today)275 void CalendarController::UpdateTitle(const CalendarDay& today)
276 {
277     if (!renderText_) {
278         return;
279     }
280     DateTime dateTime;
281     dateTime.year = today.month.year;
282     dateTime.month = today.month.month;
283     auto date = Localization::GetInstance()->FormatDateTime(dateTime, "yyyyMMM");
284     renderText_->SetTextData(date);
285     renderText_->MarkNeedMeasure();
286     renderText_->MarkNeedLayout();
287 }
288 
CalendarComponent(const ComposeId & id,const std::string & name)289 CalendarComponent::CalendarComponent(const ComposeId& id, const std::string& name) : ComposedComponent(id, name) {}
290 
Build(const WeakPtr<PipelineContext> & pipelineContext,const RefPtr<CalendarController> & calendarController)291 RefPtr<Component> CalendarComponent::Build(
292     const WeakPtr<PipelineContext>& pipelineContext, const RefPtr<CalendarController>& calendarController)
293 {
294     auto context = pipelineContext.Upgrade();
295     if (!context || !calendarController) {
296         return nullptr;
297     }
298     calendarController_ = calendarController;
299 
300     auto direction = GetTextDirection();
301 
302     if (!theme_) {
303         auto themeManager = context->GetThemeManager();
304         if (!themeManager) {
305             return nullptr;
306         }
307         theme_ = themeManager->GetTheme<CalendarTheme>();
308     }
309 
310     std::list<RefPtr<Component>> monthChildren;
311     for (int32_t index = 0; index < MAX_MONTH_CACHE_NUM; index++) {
312         auto calendarMonth = AceType::MakeRefPtr<CalendarMonthComponent>(index, calendarController_);
313         auto display = AceType::MakeRefPtr<DisplayComponent>(calendarMonth);
314         calendarMonth->SetSelectedChangeEvent(selectedChangeEvent_);
315         calendarMonth->SetCalendarTheme(theme_);
316         calendarMonth->SetCardCalendar(cardCalendar_);
317         calendarMonth->SetTextDirection(direction);
318         calendarMonth->SetCalendarType(type_);
319         display->SetOpacity(MAX_OPACITY);
320         monthChildren.emplace_back(display);
321     }
322     if (!swiperContainer_) {
323         swiperContainer_ = AceType::MakeRefPtr<SwiperComponent>(monthChildren, false);
324     }
325     swiperContainer_->SetAxis(axis_);
326     swiperContainer_->SetIndex(TODAY_MONTH_INDEX_OF_CONTAINER);
327     swiperContainer_->SetTextDirection(direction);
328     swiperContainer_->SetSlideContinue(true);
329     calendarController_->SetSwiperController(swiperContainer_->GetSwiperController());
330     swiperContainer_->SetMoveCallback([controller = WeakPtr<CalendarController>(calendarController_)](int32_t index) {
331         auto calendarController = controller.Upgrade();
332         if (calendarController) {
333             calendarController->SetHasMoved(true);
334             calendarController->RequestMonthData(index);
335         }
336     });
337     if (type_ == CalendarType::SIMPLE) {
338         swiperContainer_->SetDisabledStatus(true);
339     }
340     if (!needSlide_) {
341         swiperContainer_->SetLoop(false);
342         swiperContainer_->DisableSwipe(true);
343         swiperContainer_->SetDisableRotation(true);
344     }
345     if (!cardCalendar_) {
346         return swiperContainer_;
347     } else {
348         RefPtr<ColumnComponent> colComponent;
349         BuildCardCalendarTitle(colComponent);
350         return colComponent;
351     }
352 }
353 
CreateElement()354 RefPtr<Element> CalendarComponent::CreateElement()
355 {
356     return AceType::MakeRefPtr<CalendarElement>(GetId());
357 }
358 
GoTo(int32_t year,int32_t month,int32_t day)359 void CalendarComponent::GoTo(int32_t year, int32_t month, int32_t day)
360 {
361     if (day < 0) {
362         calendarController_->GoTo(year, month, 1);
363     } else {
364         calendarController_->SetNeedFocus(true);
365         calendarController_->GoTo(year, month, day);
366     }
367 }
368 
BuildCardCalendarTitle(RefPtr<ColumnComponent> & col)369 void CalendarComponent::BuildCardCalendarTitle(RefPtr<ColumnComponent>& col)
370 {
371     auto preButton = InitCardButton(true);
372     auto nextButton = InitCardButton(false);
373     DateTime dateTime;
374     dateTime.year = calendarController_->GetCurrentMonth().year;
375     dateTime.month = calendarController_->GetCurrentMonth().month;
376     auto date = Localization::GetInstance()->FormatDateTime(dateTime, "yyyyMMM");
377     auto text = AceType::MakeRefPtr<TextComponent>(date);
378     TextStyle style;
379     auto calendarTheme = theme_->GetCardCalendarTheme();
380     style.SetFontSize(calendarTheme.titleFontSize);
381     style.SetTextColor(calendarTheme.titleTextColor);
382     style.SetFontWeight(FontWeight::W500);
383     style.SetAllowScale(false);
384     text->SetTextStyle(style);
385 
386     auto box = AceType::MakeRefPtr<BoxComponent>();
387     Edge edge(CALENDAR_BOX_LEFT_AND_RIGHT_MARGIN, CALENDAR_BOX_TOP_AND_BOTTOM_MARGIN,
388         CALENDAR_BOX_LEFT_AND_RIGHT_MARGIN, CALENDAR_BOX_TOP_AND_BOTTOM_MARGIN);
389 
390     std::list<RefPtr<Component>> children;
391     auto padding = AceType::MakeRefPtr<PaddingComponent>();
392     padding->SetChild(text);
393     padding->SetPadding(edge);
394     children.emplace_back(padding);
395     auto button = AceType::MakeRefPtr<ButtonComponent>(children);
396     button->SetHeight(calendarTheme.buttonHeight);
397     button->SetType(ButtonType::TEXT);
398     button->SetBackgroundColor(Color::TRANSPARENT);
399     button->SetClickedColor(calendarTheme.clickEffectColor);
400     button->SetRectRadius(CALENDAR_BUTTON_RADIUS);
401     dateClickId_ = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
402     button->SetClickedEventId(dateClickId_);
403     box->SetChild(button);
404     auto flexItem = AceType::MakeRefPtr<FlexItemComponent>(0.0, 0.0, 0.0, box);
405 
406     std::list<RefPtr<Component>> rowChildren;
407     rowChildren.emplace_back(preButton);
408     rowChildren.emplace_back(flexItem);
409     rowChildren.emplace_back(nextButton);
410     auto rowComponent = AceType::MakeRefPtr<RowComponent>(FlexAlign::CENTER, FlexAlign::CENTER, rowChildren);
411     rowComponent->SetTextDirection(TextDirection::LTR);
412     std::list<RefPtr<Component>> colChildren;
413     colChildren.emplace_back(rowComponent);
414     colChildren.emplace_back(swiperContainer_);
415     col = AceType::MakeRefPtr<ColumnComponent>(FlexAlign::FLEX_START, FlexAlign::CENTER, colChildren);
416 }
417 
GetSelectedChangeEvent() const418 const EventMarker& CalendarComponent::GetSelectedChangeEvent() const
419 {
420     return selectedChangeEvent_;
421 }
422 
GetRequestDataEvent() const423 const EventMarker& CalendarComponent::GetRequestDataEvent() const
424 {
425     return requestDataEvent_;
426 }
427 
CalendarMonthComponent(int32_t indexOfContainer,const RefPtr<CalendarController> & calendarController)428 CalendarMonthComponent::CalendarMonthComponent(
429     int32_t indexOfContainer, const RefPtr<CalendarController>& calendarController)
430     : indexOfContainer_(indexOfContainer), calendarController_(calendarController) {}
431 
CreateRenderNode()432 RefPtr<RenderNode> CalendarMonthComponent::CreateRenderNode()
433 {
434     return RenderCalendar::Create();
435 }
436 
CreateElement()437 RefPtr<Element> CalendarMonthComponent::CreateElement()
438 {
439     return AceType::MakeRefPtr<CalendarMonthElement>();
440 }
441 
SetCalendarData(const std::string & value)442 void CalendarComponent::SetCalendarData(const std::string& value)
443 {
444     if (calendarController_) {
445         calendarData_ = value;
446         auto dataAdapter = calendarController_->GetDataAdapter();
447         if (dataAdapter) {
448             dataAdapter->SetOffDays(offDays_);
449             dataAdapter->ParseCardCalendarData(calendarData_);
450         }
451         calendarController_->UpdateTheme();
452     } else {
453         calendarData_ = value;
454     }
455 }
456 
InitCardButton(bool isPreArrow)457 RefPtr<ButtonComponent> CalendarComponent::InitCardButton(bool isPreArrow)
458 {
459     auto Arrow = isPreArrow ? AceType::MakeRefPtr<ImageComponent>(InternalResource::ResourceId::LEFT_ARROW_SVG)
460                             : AceType::MakeRefPtr<ImageComponent>(InternalResource::ResourceId::RIGHT_ARROW_SVG);
461     isPreArrow ? calendarController_->SetLeftRowImage(Arrow) : calendarController_->SetRightRowImage(Arrow);
462     auto calendarTheme = theme_->GetCardCalendarTheme();
463     Arrow->SetWidth(calendarTheme.arrowWidth);
464     Arrow->SetHeight(calendarTheme.arrowHeight);
465     std::list<RefPtr<Component>> children;
466     children.emplace_back(Arrow);
467     auto button = AceType::MakeRefPtr<ButtonComponent>(children);
468     button->SetBackgroundColor(Color::TRANSPARENT);
469     button->SetClickedColor(calendarTheme.clickEffectColor);
470     button->SetWidth(calendarTheme.buttonWidth);
471     button->SetHeight(calendarTheme.buttonHeight);
472     button->SetRectRadius(CALENDAR_BUTTON_RADIUS);
473     isPreArrow ? preClickId_ = BackEndEventManager<void()>::GetInstance().GetAvailableMarker()
474                : nextClickId_ = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
475     isPreArrow ? button->SetClickedEventId(preClickId_) : button->SetClickedEventId(nextClickId_);
476 
477     return button;
478 }
479 
480 } // namespace OHOS::Ace
481