• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_element.h"
17 
18 #include "base/i18n/localization.h"
19 #include "core/common/ace_application_info.h"
20 #include "core/components/calendar/calendar_component.h"
21 #include "core/components/calendar/calendar_component_v2.h"
22 #include "core/components/calendar/render_calendar.h"
23 #include "core/components/display/render_display.h"
24 #include "core/components/swiper/swiper_element.h"
25 #include "core/components/text/text_element.h"
26 
27 namespace OHOS::Ace {
28 namespace {
29 
30 constexpr int REGISTER_CHANGE_LISTENER_ID = 1003;
31 
32 }
33 
PerformBuild()34 void CalendarElement::PerformBuild()
35 {
36     RefPtr<CalendarComponent> calendar = AceType::DynamicCast<CalendarComponent>(component_);
37     if (!calendar) {
38         LOGE("Can not dynamicCast to CalendarComponent!");
39         return;
40     }
41 
42     if (!calendarController_) {
43         calendarController_ = AceType::MakeRefPtr<CalendarController>(calendar->GetDataAdapterAction(), context_);
44         UpdateAttr(calendar);
45         calendarController_->Initialize();
46         auto calendarV2 = AceType::DynamicCast<CalendarComponentV2>(calendar);
47         if (calendarV2) {
48             auto controllerV2 = calendarV2->GetControllerV2();
49             if (controllerV2) {
50                 controllerV2->SetCalendarController(calendarController_);
51             }
52         }
53     } else {
54         auto calendarV2 = AceType::DynamicCast<CalendarComponentV2>(calendar);
55         if (calendarV2) {
56             auto dataAdapter = calendarController_->GetDataAdapter();
57             dataAdapter->ParseCalendarData(calendarV2->GetObtainedMonths());
58             auto controllerV2 = calendarV2->GetControllerV2();
59             if (controllerV2) {
60                 controllerV2->SetCalendarController(calendarController_);
61             }
62         }
63         calendarController_->UpdateTheme();
64         UpdateAttr(calendar);
65         return;
66     }
67 
68     const auto& child = children_.empty() ? nullptr : children_.front();
69     auto newComponent = calendar->Build(GetContext(), calendarController_);
70     auto childElement = UpdateChild(child, newComponent);
71     auto element = childElement;
72     if (calendar->IsCardCalendar()) {
73         BuildCardCalendar(calendar, childElement);
74         element = childElement->GetChildren().back();
75     }
76 
77     auto swiperElement = AceType::DynamicCast<SwiperElement>(element);
78 
79     calendarController_->SetRequestFocusImpl([weak = WeakClaim(this)]() {
80         auto element = weak.Upgrade();
81         if (!element) {
82             return;
83         }
84         element->RequestFocus();
85     });
86     if (swiperElement) {
87         renderSwiper_ = AceType::DynamicCast<RenderSwiper>(swiperElement->GetRenderNode());
88         if (renderSwiper_) {
89             calendarController_->SetRenderSwiper(renderSwiper_);
90         }
91     }
92     RegisterChangeEndListener(calendar, childElement);
93     RequestFocusImmediately();
94 }
95 
RegisterChangeEndListener(const RefPtr<CalendarComponent> & calendar,const RefPtr<Element> & element)96 void CalendarElement::RegisterChangeEndListener(
97     const RefPtr<CalendarComponent>& calendar, const RefPtr<Element>& element)
98 {
99     if (!calendar->IsCardCalendar()) {
100         return;
101     }
102     auto children = element->GetChildren().front()->GetChildren();
103     int32_t index = 0;
104     RefPtr<Element> flex;
105     for (const auto& item : children) {
106         if (index == 1) {
107             flex = item;
108             break;
109         }
110         ++index;
111     }
112 
113     auto text = GetTextElement(flex);
114     CHECK_NULL_VOID(text);
115     auto renderText = AceType::DynamicCast<RenderText>(text->GetRenderNode());
116     CHECK_NULL_VOID(renderSwiper_);
117     auto onChanged = [text = WeakClaim(RawPtr(renderText)), weakController = WeakClaim(RawPtr(calendarController_))](
118                          bool index) {
119         auto controller = weakController.Upgrade();
120         CHECK_NULL_VOID(controller);
121         auto renderText = text.Upgrade();
122         CHECK_NULL_VOID(renderText);
123         auto currentDate = controller->GetCurrentMonth();
124         DateTime dateTime;
125         dateTime.year = currentDate.year;
126         dateTime.month = currentDate.month;
127         auto date = Localization::GetInstance()->FormatDateTime(dateTime, "yyyyMMM");
128         auto textComponent = AceType::MakeRefPtr<TextComponent>(date);
129         auto cardTheme = renderText->GetTheme<CalendarTheme>();
130         CHECK_NULL_VOID(cardTheme);
131         TextStyle style;
132         style.SetFontSize(cardTheme->GetCardCalendarTheme().titleFontSize);
133         style.SetTextColor(cardTheme->GetCardCalendarTheme().titleTextColor);
134         style.SetFontWeight(FontWeight::W500);
135         style.SetAllowScale(false);
136         textComponent->SetTextStyle(style);
137         renderText->Update(textComponent);
138         renderText->MarkNeedLayout();
139     };
140     renderSwiper_->RegisterChangeEndListener(REGISTER_CHANGE_LISTENER_ID, onChanged);
141 }
142 
BuildCardCalendar(const RefPtr<CalendarComponent> & calendar,const RefPtr<Element> & element)143 void CalendarElement::BuildCardCalendar(const RefPtr<CalendarComponent>& calendar, const RefPtr<Element>& element)
144 {
145     if (!element || !element->GetChildren().front()) {
146         return;
147     }
148     auto children = element->GetChildren().front()->GetChildren();
149     int32_t index = 0;
150     RefPtr<Element> flex;
151     for (const auto& item : children) {
152         if (index == 0) {
153             SetArrowImage(item, true);
154         }
155         if (index == 1) {
156             flex = item;
157         }
158         if (index == 2) {
159             SetArrowImage(item, false);
160         }
161         ++index;
162     }
163     auto text = GetTextElement(flex);
164     if (!text) {
165         LOGE("Get text element error");
166         return;
167     }
168     auto renderText = AceType::DynamicCast<RenderText>(text->GetRenderNode());
169     calendarController_->SetCardTitle(renderText);
170     auto buttonCallback = [weak = WeakClaim(RawPtr(calendar)), text = WeakClaim(RawPtr(renderText)),
171                               weakController = WeakClaim(RawPtr(calendarController_))](bool pre) {
172         auto calendar = weak.Upgrade();
173         auto controller = weakController.Upgrade();
174         if (!controller || !calendar) {
175             LOGE("build arrow callback error");
176             return;
177         }
178         auto swiper = controller->GetRenderSwiper();
179         if (!swiper) {
180             return;
181         }
182         if (swiper->GetMoveStatus()) {
183             return;
184         }
185         if (controller->GetCurrentIndex() != swiper->GetCurrentIndex()) {
186             return;
187         }
188         pre ? controller->GoToPrevMonth(1) : controller->GoToNextMonth(1);
189     };
190     BackEndEventManager<void()>::GetInstance().BindBackendEvent(calendar->GetPreClickId(), [buttonCallback]() {
191         AceApplicationInfo::GetInstance().IsRightToLeft() ? buttonCallback(false) : buttonCallback(true);
192     });
193     BackEndEventManager<void()>::GetInstance().BindBackendEvent(calendar->GetNextClickId(), [buttonCallback]() {
194         AceApplicationInfo::GetInstance().IsRightToLeft() ? buttonCallback(true) : buttonCallback(false);
195     });
196     dateEvent_ = AceAsyncEvent<void(const std::string&)>::Create(calendar->GetSelectedChangeEvent(), context_);
197     BackEndEventManager<void()>::GetInstance().BindBackendEvent(calendar->GetDateClickId(),
198         [date = dateEvent_, weakController = WeakPtr<CalendarController>(calendarController_)]() {
199             auto controller = weakController.Upgrade();
200             if (!controller) {
201                 LOGE("build calendar title callback error");
202                 return;
203             }
204             if (!date) {
205                 return;
206             }
207             auto currentDate = controller->GetCurrentMonth();
208             auto today = controller->GetToday();
209             auto json = JsonUtil::Create(true);
210             today.month == currentDate ? json->Put("day", today.day) : json->Put("day", 1);
211             json->Put("month", currentDate.month);
212             json->Put("year", currentDate.year);
213             date(json->ToString());
214         });
215 }
216 
UpdateAttr(const RefPtr<CalendarComponent> & calendar)217 void CalendarElement::UpdateAttr(const RefPtr<CalendarComponent>& calendar)
218 {
219     auto dataAdapter = calendarController_->GetDataAdapter();
220     if (!dataAdapter) {
221         return;
222     }
223     if (calendar->IsSetToday()) {
224         auto today = dataAdapter->GetToday();
225         auto date = calendar->GetDate();
226         if (today.day != date.day || today.month != date.month) {
227             calendarController_->SetToday(date);
228             calendarController_->GoTo(date.month.year, date.month.month, date.day);
229             calendarController_->UpdateTitle(date);
230         }
231     }
232     CardCalendarAttr attr;
233     attr.startDayOfWeek = calendar->GetStartDayOfWeek();
234     attr.showLunar = calendar->IsShowLunar();
235     attr.textDirection = calendar->GetTextDirection();
236     attr.cardCalendar = calendar->IsCardCalendar();
237     attr.requestData = calendar->GetRequestDataEvent();
238     attr.showHoliday = calendar->GetShowHoliday();
239     attr.needSlide = calendar->IsNeedSlide();
240     attr.offDays = calendar->GetOffDays();
241     attr.holidays = calendar->GetHolidays();
242     attr.workDays = calendar->GetWorkDays();
243     attr.axis = calendar->GetAxis();
244 
245     auto calendarV2 = AceType::DynamicCast<CalendarComponentV2>(calendar);
246     if (calendarV2) {
247         attr.isV2Component = true;
248     }
249     attr.calendarTheme = calendar->GetCalendarTheme();
250     attr.type = calendar->GetCalendarType();
251     dataAdapter->UpdateCardCalendarAttr(std::move(attr));
252 }
253 
SetArrowImage(const RefPtr<Element> & element,bool isLeft)254 void CalendarElement::SetArrowImage(const RefPtr<Element>& element, bool isLeft)
255 {
256     if (!element) {
257         return;
258     }
259     auto imageElement = element->GetChildren().front();
260     if (!imageElement) {
261         return;
262     }
263     auto image = AceType::DynamicCast<RenderImage>(imageElement->GetRenderNode());
264     if (image) {
265         isLeft ? calendarController_->SetLeftRowImage(image) : calendarController_->SetRightRowImage(image);
266     }
267 }
268 
GetTextElement(const RefPtr<Element> & flex)269 RefPtr<TextElement> CalendarElement::GetTextElement(const RefPtr<Element>& flex)
270 {
271     auto element = flex;
272     while (element && element->GetChildren().front()) {
273         element = element->GetChildren().front();
274     }
275     return AceType::DynamicCast<TextElement>(element);
276 }
277 
Update()278 void CalendarMonthElement::Update()
279 {
280     RenderElement::Update();
281 }
282 
OnKeyEvent(const KeyEvent & keyEvent)283 bool CalendarMonthElement::OnKeyEvent(const KeyEvent& keyEvent)
284 {
285     if (keyEvent.action != KeyAction::UP) {
286         return false;
287     }
288 
289     auto display = AceType::DynamicCast<RenderDisplay>(renderNode_->GetParent().Upgrade());
290     if (display) {
291         auto swiper = AceType::DynamicCast<RenderSwiper>(display->GetParent().Upgrade());
292         if (swiper) {
293             if (swiper->GetMoveStatus()) {
294                 return true;
295             }
296         }
297     }
298 
299     switch (keyEvent.code) {
300         case KeyCode::TV_CONTROL_UP:
301             return RequestNextFocus(true, true, GetRect());
302         case KeyCode::TV_CONTROL_DOWN:
303             return RequestNextFocus(true, false, GetRect());
304         case KeyCode::TV_CONTROL_LEFT:
305             return RequestNextFocus(false, true, GetRect());
306         case KeyCode::TV_CONTROL_RIGHT:
307             return RequestNextFocus(false, false, GetRect());
308         case KeyCode::KEY_TAB:
309             return RequestNextFocus(false, false, GetRect()) || RequestNextFocus(true, false, GetRect());
310         default:
311             return false;
312     }
313 }
314 
RequestNextFocus(bool vertical,bool reverse,const Rect & rect)315 bool CalendarMonthElement::RequestNextFocus(bool vertical, bool reverse, const Rect& rect)
316 {
317     RefPtr<FocusableGrid> focusableGrid = AceType::DynamicCast<FocusableGrid>(renderNode_);
318     if (!focusableGrid) {
319         LOGE("focusable grid is null.");
320         return false;
321     }
322     bool needFocus = focusableGrid->RequestNextFocus(vertical, reverse) >= 0;
323     if (needFocus) {
324         auto calendar = DynamicCast<RenderCalendar>(renderNode_);
325         if (!calendar) {
326             LOGE("get render node failed");
327             return false;
328         }
329         calendar->MarkNeedRender();
330     }
331     return needFocus;
332 }
333 
OnFocus()334 void CalendarMonthElement::OnFocus()
335 {
336     if (renderNode_) {
337         renderNode_->ChangeStatus(RenderStatus::FOCUS);
338     }
339 }
340 
OnBlur()341 void CalendarMonthElement::OnBlur()
342 {
343     if (renderNode_) {
344         renderNode_->ChangeStatus(RenderStatus::BLUR);
345     }
346 }
347 
348 } // namespace OHOS::Ace
349