• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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/calendar_picker/calendar_dialog_pattern.h"
17 
18 #include "base/i18n/localization.h"
19 #include "base/utils/date_util.h"
20 #include "core/components_ng/pattern/calendar/calendar_model_ng.h"
21 #include "core/components_ng/pattern/calendar/calendar_month_pattern.h"
22 #include "core/components_ng/pattern/calendar_picker/calendar_dialog_view.h"
23 #include "core/components_ng/pattern/calendar_picker/calendar_picker_event_hub.h"
24 #include "core/components_ng/pattern/calendar_picker/calendar_picker_pattern.h"
25 #include "core/components_ng/pattern/dialog/dialog_layout_property.h"
26 #include "core/components_ng/pattern/image/image_layout_property.h"
27 #include "core/components_ng/pattern/text/text_layout_property.h"
28 #include "core/components_ng/pattern/button/button_layout_property.h"
29 
30 namespace OHOS::Ace::NG {
31 namespace {
32 constexpr int32_t TITLE_NODE_INDEX = 0;
33 constexpr int32_t CALENDAR_NODE_INDEX = 2;
34 constexpr int32_t OPTIONS_NODE_INDEX = 3;
35 constexpr int32_t TITLE_LAST_YEAR_BUTTON_NODE_INDEX = 0;
36 constexpr int32_t TITLE_LAST_MONTH_BUTTON_NODE_INDEX = 1;
37 constexpr int32_t TITLE_TEXT_NODE_INDEX = 2;
38 constexpr int32_t TITLE_NEXT_MONTH_BUTTON_NODE_INDEX = 3;
39 constexpr int32_t TITLE_NEXT_YEAR_BUTTON_NODE_INDEX = 4;
40 constexpr int32_t OPTIONS_DIVIDER_NODE_INDEX = 1;
41 constexpr int32_t SWIPER_CHILDREN_SIZE = 3;
42 constexpr int32_t WEEK_DAYS = 7;
43 constexpr int32_t MAX_MONTH = 12;
44 constexpr int32_t MIN_YEAR = 1;
45 constexpr int32_t MAX_YEAR = 5000;
46 constexpr size_t CANCEL_BUTTON_FONT_COLOR_INDEX = 0;
47 constexpr size_t CANCEL_BUTTON_BACKGROUND_COLOR_INDEX = 1;
48 constexpr size_t ACCEPT_BUTTON_FONT_COLOR_INDEX = 2;
49 constexpr size_t ACCEPT_BUTTON_BACKGROUND_COLOR_INDEX = 3;
50 constexpr size_t OPTION_CANCEL_BUTTON_INDEX = 0;
51 constexpr size_t OPTION_ACCEPT_BUTTON_INDEX = 1;
52 } // namespace
53 
GetFocusPattern() const54 FocusPattern CalendarDialogPattern::GetFocusPattern() const
55 {
56     auto pipeline = PipelineBase::GetCurrentContext();
57     CHECK_NULL_RETURN(pipeline, FocusPattern());
58     auto pickerTheme = pipeline->GetTheme<PickerTheme>();
59     RefPtr<CalendarTheme> calendarTheme = pipeline->GetTheme<CalendarTheme>();
60     CHECK_NULL_RETURN(pickerTheme, FocusPattern());
61     CHECK_NULL_RETURN(calendarTheme, FocusPattern());
62     auto focusColor = pickerTheme->GetFocusColor();
63     FocusPaintParam focusPaintParams;
64     focusPaintParams.SetPaintColor(focusColor);
65     auto focusPaintWidth = calendarTheme->GetCalendarDayKeyFocusedPenWidth();
66     focusPaintParams.SetPaintWidth(focusPaintWidth);
67     return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParams };
68 }
69 
OnModifyDone()70 void CalendarDialogPattern::OnModifyDone()
71 {
72     LinearLayoutPattern::OnModifyDone();
73     UpdateCalendarLayout();
74 
75     InitClickEvent();
76     InitOnKeyEvent();
77     InitOnTouchEvent();
78     InitHoverEvent();
79     InitTitleArrowsEvent();
80     InitEntryChangeEvent();
81 
82     UpdateTitleArrowsImage();
83     UpdateOptionsButton();
84     UpdateDialogBackgroundColor();
85     UpdateTitleArrowsColor();
86     UpdateOptionsButtonColor();
87 }
88 
UpdateCalendarLayout()89 void CalendarDialogPattern::UpdateCalendarLayout()
90 {
91     auto entryNode = entryNode_.Upgrade();
92     CHECK_NULL_VOID(entryNode);
93     auto textDirection = entryNode->GetLayoutProperty()->GetNonAutoLayoutDirection();
94     auto calendarNode = GetCalendarFrameNode();
95     CHECK_NULL_VOID(calendarNode);
96     const auto& calendarLayoutProperty = calendarNode->GetLayoutProperty();
97     CHECK_NULL_VOID(calendarLayoutProperty);
98     calendarLayoutProperty->UpdateLayoutDirection(textDirection);
99 
100     auto host = GetHost();
101     CHECK_NULL_VOID(host);
102     auto hostNode = AceType::DynamicCast<FrameNode>(host);
103     CHECK_NULL_VOID(hostNode);
104     auto title = host->GetChildAtIndex(TITLE_NODE_INDEX);
105     CHECK_NULL_VOID(title);
106     auto titleNode = AceType::DynamicCast<FrameNode>(title);
107     CHECK_NULL_VOID(titleNode);
108     auto titleLayoutProperty = titleNode->GetLayoutProperty();
109     CHECK_NULL_VOID(titleLayoutProperty);
110     titleLayoutProperty->UpdateLayoutDirection(textDirection);
111 }
UpdateDialogBackgroundColor()112 void CalendarDialogPattern::UpdateDialogBackgroundColor()
113 {
114     auto host = GetHost();
115     CHECK_NULL_VOID(host);
116     auto wrapperNode = AceType::DynamicCast<FrameNode>(host->GetParent());
117     CHECK_NULL_VOID(wrapperNode);
118     auto pipelineContext = host->GetContext();
119     CHECK_NULL_VOID(pipelineContext);
120     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
121     auto contentRenderContext = wrapperNode->GetRenderContext();
122     CHECK_NULL_VOID(contentRenderContext);
123     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
124         contentRenderContext->UpdateBackgroundColor(theme->GetDialogBackgroundColor());
125     }
126 }
127 
UpdateTitleArrowsColor()128 void CalendarDialogPattern::UpdateTitleArrowsColor()
129 {
130     auto host = GetHost();
131     CHECK_NULL_VOID(host);
132     auto title = host->GetChildAtIndex(TITLE_NODE_INDEX);
133     CHECK_NULL_VOID(title);
134     auto pipelineContext = host->GetContext();
135     CHECK_NULL_VOID(pipelineContext);
136     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
137     CHECK_NULL_VOID(theme);
138 
139     for (const auto& child : title->GetChildren()) {
140         CHECK_NULL_VOID(child);
141         if (child->GetTag() == V2::BUTTON_ETS_TAG) {
142             auto buttonNode = AceType::DynamicCast<FrameNode>(child);
143             CHECK_NULL_VOID(buttonNode);
144             buttonNode->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
145             buttonNode->MarkModifyDone();
146 
147             auto image = buttonNode->GetChildren().front();
148             CHECK_NULL_VOID(image);
149             auto imageNode = AceType::DynamicCast<FrameNode>(image);
150             auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
151             CHECK_NULL_VOID(imageLayoutProperty);
152             auto imageInfo = imageLayoutProperty->GetImageSourceInfo();
153             CHECK_NULL_VOID(imageInfo);
154             imageInfo->SetFillColor(theme->GetEntryArrowColor());
155             imageLayoutProperty->UpdateImageSourceInfo(imageInfo.value());
156             imageNode->MarkModifyDone();
157         }
158     }
159 }
160 
UpdateTitleArrowsImage()161 void CalendarDialogPattern::UpdateTitleArrowsImage()
162 {
163     auto host = GetHost();
164     CHECK_NULL_VOID(host);
165     auto title = host->GetChildAtIndex(TITLE_NODE_INDEX);
166     CHECK_NULL_VOID(title);
167     auto titleNode = AceType::DynamicCast<FrameNode>(title);
168     CHECK_NULL_VOID(titleNode);
169     auto titleLayoutProperty = titleNode->GetLayoutProperty();
170     CHECK_NULL_VOID(titleLayoutProperty);
171     auto textDirection = titleLayoutProperty->GetNonAutoLayoutDirection();
172 
173     auto lastYearNode = AceType::DynamicCast<FrameNode>(title->GetChildAtIndex(TITLE_LAST_YEAR_BUTTON_NODE_INDEX));
174     CHECK_NULL_VOID(lastYearNode);
175     auto lastMonthNode = AceType::DynamicCast<FrameNode>(title->GetChildAtIndex(TITLE_LAST_MONTH_BUTTON_NODE_INDEX));
176     CHECK_NULL_VOID(lastMonthNode);
177     auto nextMonthNode = AceType::DynamicCast<FrameNode>(title->GetChildAtIndex(TITLE_NEXT_MONTH_BUTTON_NODE_INDEX));
178     CHECK_NULL_VOID(nextMonthNode);
179     auto nextYearNode = AceType::DynamicCast<FrameNode>(title->GetChildAtIndex(TITLE_NEXT_YEAR_BUTTON_NODE_INDEX));
180     CHECK_NULL_VOID(nextYearNode);
181 
182     if (textDirection == TextDirection::RTL) {
183         UpdateImage(lastYearNode, InternalResource::ResourceId::IC_PUBLIC_DOUBLE_ARROW_RIGHT_SVG);
184         UpdateImage(lastMonthNode, InternalResource::ResourceId::IC_PUBLIC_ARROW_RIGHT_SVG);
185         UpdateImage(nextMonthNode, InternalResource::ResourceId::IC_PUBLIC_ARROW_LEFT_SVG);
186         UpdateImage(nextYearNode, InternalResource::ResourceId::IC_PUBLIC_DOUBLE_ARROW_LEFT_SVG);
187     } else {
188         UpdateImage(lastYearNode, InternalResource::ResourceId::IC_PUBLIC_DOUBLE_ARROW_LEFT_SVG);
189         UpdateImage(lastMonthNode, InternalResource::ResourceId::IC_PUBLIC_ARROW_LEFT_SVG);
190         UpdateImage(nextMonthNode, InternalResource::ResourceId::IC_PUBLIC_ARROW_RIGHT_SVG);
191         UpdateImage(nextYearNode, InternalResource::ResourceId::IC_PUBLIC_DOUBLE_ARROW_RIGHT_SVG);
192     }
193 }
194 
UpdateImage(const RefPtr<FrameNode> & buttonNode,const InternalResource::ResourceId & resourceId)195 void CalendarDialogPattern::UpdateImage(
196     const RefPtr<FrameNode>& buttonNode, const InternalResource::ResourceId& resourceId)
197 {
198     auto image = buttonNode->GetChildren().front();
199     CHECK_NULL_VOID(image);
200     auto imageNode = AceType::DynamicCast<FrameNode>(image);
201     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
202     CHECK_NULL_VOID(imageLayoutProperty);
203 
204     ImageSourceInfo imageSourceInfo;
205     imageSourceInfo.SetResourceId(resourceId);
206     imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
207     imageNode->MarkModifyDone();
208 }
209 
UpdateOptionsButton()210 void CalendarDialogPattern::UpdateOptionsButton()
211 {
212     auto host = GetHost();
213     CHECK_NULL_VOID(host);
214     auto options = host->GetChildAtIndex(OPTIONS_NODE_INDEX);
215     CHECK_NULL_VOID(options);
216 
217     size_t buttonIndex = OPTION_CANCEL_BUTTON_INDEX;
218     for (const auto& child : options->GetChildren()) {
219         CHECK_NULL_VOID(child);
220         if (child->GetTag() == V2::BUTTON_ETS_TAG) {
221             auto button = AceType::DynamicCast<FrameNode>(child);
222             CHECK_NULL_VOID(button);
223             auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
224             CHECK_NULL_VOID(buttonLayoutProperty);
225             if (buttonIndex == OPTION_ACCEPT_BUTTON_INDEX) {
226                 buttonLayoutProperty->UpdateLabel(Localization::GetInstance()->GetEntryLetters("common.ok"));
227             } else {
228                 buttonLayoutProperty->UpdateLabel(Localization::GetInstance()->GetEntryLetters("common.cancel"));
229             }
230             button->MarkDirtyNode();
231             buttonIndex++;
232         }
233     }
234 }
235 
UpdateOptionsButtonColor()236 void CalendarDialogPattern::UpdateOptionsButtonColor()
237 {
238     auto host = GetHost();
239     CHECK_NULL_VOID(host);
240     auto options = host->GetChildAtIndex(OPTIONS_NODE_INDEX);
241     CHECK_NULL_VOID(options);
242     auto pipeline = host->GetContext();
243     CHECK_NULL_VOID(pipeline);
244     auto calendarTheme = pipeline->GetTheme<CalendarTheme>();
245     CHECK_NULL_VOID(calendarTheme);
246     auto pickerTheme = pipeline->GetTheme<PickerTheme>();
247     CHECK_NULL_VOID(pickerTheme);
248 
249     size_t buttonIndex = OPTION_CANCEL_BUTTON_INDEX;
250     for (const auto& child : options->GetChildren()) {
251         CHECK_NULL_VOID(child);
252         if (child->GetTag() == V2::BUTTON_ETS_TAG) {
253             auto button = AceType::DynamicCast<FrameNode>(child);
254             CHECK_NULL_VOID(button);
255             bool cancelNotUpdateBGColor =
256                 buttonIndex == OPTION_CANCEL_BUTTON_INDEX && !updateColorFlags[CANCEL_BUTTON_BACKGROUND_COLOR_INDEX];
257             bool acceptNotUpdateBGColor =
258                 buttonIndex == OPTION_ACCEPT_BUTTON_INDEX && !updateColorFlags[ACCEPT_BUTTON_BACKGROUND_COLOR_INDEX];
259             if (!(cancelNotUpdateBGColor || acceptNotUpdateBGColor)) {
260                 auto defaultBGColor = calendarTheme->GetIsButtonTransparent()
261                                           ? Color::TRANSPARENT
262                                           : calendarTheme->GetDialogButtonBackgroundColor();
263                 button->GetRenderContext()->UpdateBackgroundColor(defaultBGColor);
264             }
265             button->MarkModifyDone();
266 
267             auto text = button->GetChildren().front();
268             CHECK_NULL_VOID(text);
269             auto textNode = AceType::DynamicCast<FrameNode>(text);
270             auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
271             CHECK_NULL_VOID(textLayoutProperty);
272             bool cancelNotUpdateFontColor =
273                 buttonIndex == OPTION_CANCEL_BUTTON_INDEX && !updateColorFlags[CANCEL_BUTTON_FONT_COLOR_INDEX];
274             bool acceptNotUpdateFontColor =
275                 buttonIndex == OPTION_ACCEPT_BUTTON_INDEX && !updateColorFlags[ACCEPT_BUTTON_FONT_COLOR_INDEX];
276             if (!(cancelNotUpdateFontColor || acceptNotUpdateFontColor)) {
277                 textLayoutProperty->UpdateTextColor(pickerTheme->GetOptionStyle(true, false).GetTextColor());
278             }
279             textNode->MarkModifyDone();
280 
281             buttonIndex++;
282         }
283     }
284 }
285 
SetOptionsButtonUpdateColorFlags(size_t index,bool isUpdate)286 void CalendarDialogPattern::SetOptionsButtonUpdateColorFlags(size_t index, bool isUpdate)
287 {
288     if (index >= updateColorFlags.size()) {
289         return;
290     }
291 
292     updateColorFlags[index] = isUpdate;
293 }
294 
InitHoverEvent()295 void CalendarDialogPattern::InitHoverEvent()
296 {
297     CHECK_NULL_VOID(!hoverListener_);
298     auto host = GetHost();
299     CHECK_NULL_VOID(host);
300     auto inputHub = host->GetOrCreateInputEventHub();
301     CHECK_NULL_VOID(inputHub);
302 
303     auto mouseCallback = [weak = WeakClaim(this)](const MouseInfo& info) {
304         auto pattern = weak.Upgrade();
305         CHECK_NULL_VOID(pattern);
306         CHECK_NULL_VOID(pattern->GetHoverState());
307         pattern->HandleEntryNodeHoverEvent(
308             pattern->IsInEntryRegion(info.GetGlobalLocation()), info.GetGlobalLocation());
309     };
310     inputHub->SetMouseEvent(std::move(mouseCallback));
311 
312     auto hoverCallback = [weak = WeakClaim(this)](bool state) {
313         auto pattern = weak.Upgrade();
314         CHECK_NULL_VOID(pattern);
315         pattern->SetHoverState(state);
316         if (!state) {
317             Offset location;
318             pattern->HandleEntryNodeHoverEvent(false, location);
319         }
320     };
321     hoverListener_ = MakeRefPtr<InputEvent>(std::move(hoverCallback));
322     inputHub->AddOnHoverEvent(hoverListener_);
323 }
324 
IsInEntryRegion(const Offset & globalLocation)325 bool CalendarDialogPattern::IsInEntryRegion(const Offset& globalLocation)
326 {
327     auto entryNode = entryNode_.Upgrade();
328     CHECK_NULL_RETURN(entryNode, false);
329     return entryNode->GetTransformRectRelativeToWindow().IsInRegion(
330         PointF(globalLocation.GetX(), globalLocation.GetY()));
331 }
332 
HandleEntryNodeHoverEvent(bool state,const Offset & globalLocation)333 void CalendarDialogPattern::HandleEntryNodeHoverEvent(bool state, const Offset& globalLocation)
334 {
335     auto entryNode = entryNode_.Upgrade();
336     CHECK_NULL_VOID(entryNode);
337     auto pattern = entryNode->GetPattern<CalendarPickerPattern>();
338     CHECK_NULL_VOID(pattern);
339     pattern->HandleHoverEvent(state, globalLocation);
340 }
341 
HandleEntryNodeTouchEvent(bool isPressed,const Offset & globalLocation)342 void CalendarDialogPattern::HandleEntryNodeTouchEvent(bool isPressed, const Offset& globalLocation)
343 {
344     auto entryNode = entryNode_.Upgrade();
345     CHECK_NULL_VOID(entryNode);
346     if (IsInEntryRegion(globalLocation)) {
347         auto pattern = entryNode->GetPattern<CalendarPickerPattern>();
348         CHECK_NULL_VOID(pattern);
349         pattern->HandleTouchEvent(isPressed, globalLocation);
350     }
351 }
352 
InitClickEvent()353 void CalendarDialogPattern::InitClickEvent()
354 {
355     auto host = GetHost();
356     CHECK_NULL_VOID(host);
357     auto gesture = host->GetOrCreateGestureEventHub();
358     CHECK_NULL_VOID(gesture);
359     auto clickCallback = [weak = WeakClaim(this)](const GestureEvent& info) {
360         auto pattern = weak.Upgrade();
361         CHECK_NULL_VOID(pattern);
362         pattern->HandleClickEvent(info);
363     };
364     auto onClick = AceType::MakeRefPtr<ClickEvent>(clickCallback);
365     gesture->AddClickEvent(onClick);
366 }
367 
HandleClickEvent(const GestureEvent & info)368 void CalendarDialogPattern::HandleClickEvent(const GestureEvent& info)
369 {
370     auto entryNode = entryNode_.Upgrade();
371     CHECK_NULL_VOID(entryNode);
372     if (IsInEntryRegion(info.GetGlobalLocation())) {
373         auto pattern = entryNode->GetPattern<CalendarPickerPattern>();
374         CHECK_NULL_VOID(pattern);
375         pattern->HandleClickEvent(info.GetGlobalLocation());
376     }
377 }
378 
InitOnTouchEvent()379 void CalendarDialogPattern::InitOnTouchEvent()
380 {
381     if (touchListener_) {
382         return;
383     }
384     auto host = GetHost();
385     CHECK_NULL_VOID(host);
386     auto gesture = host->GetOrCreateGestureEventHub();
387     CHECK_NULL_VOID(gesture);
388     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
389         auto pattern = weak.Upgrade();
390         CHECK_NULL_VOID(pattern);
391         if (info.GetTouches().empty()) {
392             return;
393         }
394         if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
395             pattern->HandleEntryNodeTouchEvent(true, info.GetTouches().front().GetGlobalLocation());
396             if (!pattern->isFocused_) {
397                 return;
398             }
399             pattern->isFocused_ = false;
400             pattern->isCalendarFirstFocused_ = false;
401             pattern->ClearCalendarFocusedState();
402         }
403         if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
404             info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
405             pattern->HandleEntryNodeTouchEvent(false, info.GetTouches().front().GetGlobalLocation());
406         }
407     };
408     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
409     gesture->AddTouchEvent(touchListener_);
410 }
411 
InitOnKeyEvent()412 void CalendarDialogPattern::InitOnKeyEvent()
413 {
414     auto host = GetHost();
415     CHECK_NULL_VOID(host);
416     auto focusHub = host->GetOrCreateFocusHub();
417     CHECK_NULL_VOID(focusHub);
418 
419     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
420         auto pattern = wp.Upgrade();
421         CHECK_NULL_RETURN(pattern, false);
422         if (event.IsNumberKey() && event.action == KeyAction::DOWN) {
423             auto entryNode = pattern->entryNode_.Upgrade();
424             CHECK_NULL_RETURN(entryNode, false);
425             auto entryPattern = entryNode->GetPattern<CalendarPickerPattern>();
426             CHECK_NULL_RETURN(entryPattern, false);
427             entryPattern->HandleNumberKeyEvent(event);
428         }
429         if (pattern->isFocused_ && !pattern->isCalendarFirstFocused_ &&
430             pattern->focusAreaID_ == CALENDAR_NODE_INDEX) {
431             pattern->isCalendarFirstFocused_ = true;
432             pattern->FocusedLastFocusedDay();
433             return true;
434         }
435         if (pattern->isFocused_ && event.action == KeyAction::DOWN) {
436             return pattern->HandleKeyEvent(event);
437         }
438         if (!pattern->isFocused_ && !pattern->hasTabKeyDown_ && event.action == KeyAction::DOWN) {
439             pattern->OnEnterKeyEvent(event);
440         }
441         return false;
442     };
443     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
444 
445     auto blurTask = [weak = WeakClaim(this)]() {
446         auto pattern = weak.Upgrade();
447         CHECK_NULL_VOID(pattern);
448         pattern->isFocused_ = false;
449         pattern->isCalendarFirstFocused_ = false;
450         pattern->ClearCalendarFocusedState();
451     };
452     focusHub->SetOnBlurInternal(std::move(blurTask));
453 
454     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
455         auto pattern = wp.Upgrade();
456         CHECK_NULL_VOID(pattern);
457         pattern->GetInnerFocusPaintRect(paintRect);
458     };
459     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
460 }
461 
InitEntryChangeEvent()462 void CalendarDialogPattern::InitEntryChangeEvent()
463 {
464     auto entryNode = entryNode_.Upgrade();
465     CHECK_NULL_VOID(entryNode);
466     auto eventHub = entryNode->GetEventHub<CalendarPickerEventHub>();
467     CHECK_NULL_VOID(eventHub);
468     auto callback = [weak = WeakClaim(this)](const std::string& info) {
469         auto pattern = weak.Upgrade();
470         CHECK_NULL_VOID(pattern);
471         pattern->HandleEntryChange(info);
472     };
473     eventHub->SetInputChangeEvent(std::move(callback));
474     auto layoutChangeEvent = [weak = WeakClaim(this)]() {
475         auto pattern = weak.Upgrade();
476         CHECK_NULL_VOID(pattern);
477         pattern->HandleEntryLayoutChange();
478     };
479     eventHub->SetLayoutChangeEvent(layoutChangeEvent);
480 }
481 
HandleKeyEvent(const KeyEvent & event)482 bool CalendarDialogPattern::HandleKeyEvent(const KeyEvent& event)
483 {
484     auto host = GetHost();
485     CHECK_NULL_RETURN(host, false);
486 
487     if (event.code == KeyCode::KEY_TAB) {
488         return HandleTabKeyEvent(event);
489     }
490     if (focusAreaID_ == CALENDAR_NODE_INDEX) {
491         return HandleCalendarNodeKeyEvent(event);
492     }
493     if (focusAreaID_ != TITLE_NODE_INDEX && focusAreaID_ != OPTIONS_NODE_INDEX) {
494         return false;
495     }
496 
497     auto calendarNode = GetCalendarFrameNode();
498     CHECK_NULL_RETURN(calendarNode, false);
499     auto textDirection = calendarNode->GetLayoutProperty()->GetNonAutoLayoutDirection();
500     switch (event.code) {
501         case KeyCode::KEY_DPAD_LEFT: {
502             if (textDirection == TextDirection::RTL) {
503                 if ((focusAreaID_ == TITLE_NODE_INDEX && focusAreaChildID_ == TITLE_TEXT_NODE_INDEX - 1) ||
504                     (focusAreaID_ == OPTIONS_NODE_INDEX && focusAreaChildID_ == OPTIONS_DIVIDER_NODE_INDEX - 1)) {
505                     focusAreaChildID_++;
506                 }
507                 focusAreaChildID_++;
508                 auto childSize = static_cast<int32_t>(host->GetChildAtIndex(focusAreaID_)->GetChildren().size());
509                 if (focusAreaChildID_ > childSize - 1) {
510                     focusAreaChildID_ = childSize - 1;
511                 }
512             } else {
513                 if ((focusAreaID_ == TITLE_NODE_INDEX && focusAreaChildID_ == TITLE_TEXT_NODE_INDEX + 1) ||
514                     (focusAreaID_ == OPTIONS_NODE_INDEX && focusAreaChildID_ == OPTIONS_DIVIDER_NODE_INDEX + 1)) {
515                     focusAreaChildID_--;
516                 }
517                 focusAreaChildID_--;
518                 if (focusAreaChildID_ < 0) {
519                     focusAreaChildID_ = 0;
520                 }
521             }
522 
523             PaintFocusState();
524             ChangeEntryState();
525             return true;
526         }
527         case KeyCode::KEY_DPAD_RIGHT: {
528             if (textDirection == TextDirection::RTL) {
529                 if ((focusAreaID_ == TITLE_NODE_INDEX && focusAreaChildID_ == TITLE_TEXT_NODE_INDEX + 1) ||
530                     (focusAreaID_ == OPTIONS_NODE_INDEX && focusAreaChildID_ == OPTIONS_DIVIDER_NODE_INDEX + 1)) {
531                     focusAreaChildID_--;
532                 }
533 
534                 focusAreaChildID_--;
535                 if (focusAreaChildID_ < 0) {
536                     focusAreaChildID_ = 0;
537                 }
538             } else {
539                 if ((focusAreaID_ == TITLE_NODE_INDEX && focusAreaChildID_ == TITLE_TEXT_NODE_INDEX - 1) ||
540                     (focusAreaID_ == OPTIONS_NODE_INDEX && focusAreaChildID_ == OPTIONS_DIVIDER_NODE_INDEX - 1)) {
541                     focusAreaChildID_++;
542                 }
543 
544                 focusAreaChildID_++;
545                 auto childSize = static_cast<int32_t>(host->GetChildAtIndex(focusAreaID_)->GetChildren().size());
546                 if (focusAreaChildID_ > childSize - 1) {
547                     focusAreaChildID_ = childSize - 1;
548                 }
549             }
550 
551             PaintFocusState();
552             ChangeEntryState();
553             return true;
554         }
555         case KeyCode::KEY_MOVE_HOME: {
556             focusAreaChildID_ = 0;
557             PaintFocusState();
558             ChangeEntryState();
559             return true;
560         }
561         case KeyCode::KEY_MOVE_END: {
562             focusAreaChildID_ = static_cast<int32_t>(host->GetChildAtIndex(focusAreaID_)->GetChildren().size()) - 1;
563             PaintFocusState();
564             ChangeEntryState();
565             return true;
566         }
567         case KeyCode::KEY_SPACE:
568         case KeyCode::KEY_NUMPAD_ENTER:
569         case KeyCode::KEY_ENTER: {
570             return ActClick(focusAreaID_, focusAreaChildID_);
571         }
572         default:
573             break;
574     }
575     return false;
576 }
577 
HandleCalendarNodeKeyEvent(const KeyEvent & event)578 bool CalendarDialogPattern::HandleCalendarNodeKeyEvent(const KeyEvent& event)
579 {
580     auto swiperPattern = GetSwiperPattern();
581     CHECK_NULL_RETURN(swiperPattern, false);
582     auto swiperController = swiperPattern->GetSwiperController();
583     CHECK_NULL_RETURN(swiperController, false);
584     swiperController->FinishAnimation();
585     auto calendarPattern = GetCalendarPattern();
586     CHECK_NULL_RETURN(calendarPattern, false);
587     ObtainedMonth currentMonthData = calendarPattern->GetCurrentMonthData();
588     auto calendarNode = GetCalendarFrameNode();
589     CHECK_NULL_RETURN(calendarNode, false);
590     auto textDirection = calendarNode->GetLayoutProperty()->GetNonAutoLayoutDirection();
591     int32_t focusedDayIndex = GetIndexByFocusedDay();
592 
593     switch (event.code) {
594         case KeyCode::KEY_DPAD_LEFT: {
595             if (textDirection == TextDirection::RTL) {
596                 focusedDayIndex++;
597             } else {
598                 focusedDayIndex--;
599             }
600 
601             PaintMonthFocusState(focusedDayIndex);
602             return true;
603         }
604         case KeyCode::KEY_DPAD_RIGHT: {
605             if (textDirection == TextDirection::RTL) {
606                 focusedDayIndex--;
607             } else {
608                 focusedDayIndex++;
609             }
610 
611             PaintMonthFocusState(focusedDayIndex);
612             return true;
613         }
614         case KeyCode::KEY_DPAD_UP: {
615             focusedDayIndex -= WEEK_DAYS;
616             if (IsIndexInCurrentMonth(focusedDayIndex, currentMonthData)) {
617                 focusedDay_ = currentMonthData.days[focusedDayIndex];
618                 PaintCurrentMonthFocusState();
619                 return true;
620             }
621             break;
622         }
623         case KeyCode::KEY_DPAD_DOWN: {
624             focusedDayIndex += WEEK_DAYS;
625             if (IsIndexInCurrentMonth(focusedDayIndex, currentMonthData)) {
626                 focusedDay_ = currentMonthData.days[focusedDayIndex];
627                 PaintCurrentMonthFocusState();
628                 return true;
629             }
630             break;
631         }
632         case KeyCode::KEY_MOVE_HOME: {
633             auto it = std::find_if(currentMonthData.days.begin(), currentMonthData.days.end(),
634                 [currentMonthData](const CalendarDay& day) {
635                     return day.month.year == currentMonthData.year && day.month.month == currentMonthData.month;
636                 });
637             if (it != currentMonthData.days.end()) {
638                 focusedDay_ = currentMonthData.days[it->index];
639                 PaintCurrentMonthFocusState();
640                 return true;
641             }
642             break;
643         }
644         case KeyCode::KEY_MOVE_END: {
645             auto it = std::find_if(currentMonthData.days.rbegin(), currentMonthData.days.rend(),
646                 [currentMonthData](const CalendarDay& day) {
647                     return day.month.year == currentMonthData.year && day.month.month == currentMonthData.month;
648                 });
649             if (it != currentMonthData.days.rend()) {
650                 focusedDay_ = currentMonthData.days[it->index];
651                 PaintCurrentMonthFocusState();
652                 return true;
653             }
654             break;
655         }
656         case KeyCode::KEY_SPACE:
657         case KeyCode::KEY_NUMPAD_ENTER:
658         case KeyCode::KEY_ENTER: {
659             PickerDate selectedDay(focusedDay_.month.year, focusedDay_.month.month, focusedDay_.day);
660             calendarPattern->SetSelectedDay(selectedDay);
661             auto calendarFrameNode = GetCalendarFrameNode();
662             CHECK_NULL_RETURN(calendarFrameNode, false);
663             calendarFrameNode->MarkModifyDone();
664             FireChangeByKeyEvent(selectedDay);
665             return true;
666         }
667         default:
668             break;
669     }
670     return false;
671 }
672 
PaintMonthFocusState(int32_t focusedDayIndex)673 void CalendarDialogPattern::PaintMonthFocusState(int32_t focusedDayIndex)
674 {
675     auto calendarPattern = GetCalendarPattern();
676     CHECK_NULL_VOID(calendarPattern);
677     ObtainedMonth currentMonthData = calendarPattern->GetCurrentMonthData();
678     if (IsIndexInCurrentMonth(focusedDayIndex, currentMonthData)) {
679         focusedDay_ = currentMonthData.days[focusedDayIndex];
680         PaintCurrentMonthFocusState();
681     } else {
682         PaintNonCurrentMonthFocusState(focusedDayIndex);
683     }
684 }
685 
IsIndexInCurrentMonth(int32_t focusedDayIndex,const ObtainedMonth & currentMonthData)686 bool CalendarDialogPattern::IsIndexInCurrentMonth(int32_t focusedDayIndex, const ObtainedMonth& currentMonthData)
687 {
688     return focusedDayIndex >= 0 && focusedDayIndex < static_cast<int32_t>(currentMonthData.days.size()) &&
689            currentMonthData.days[focusedDayIndex].month.year == currentMonthData.year &&
690            currentMonthData.days[focusedDayIndex].month.month == currentMonthData.month;
691 }
692 
HandleTabKeyEvent(const KeyEvent & event)693 bool CalendarDialogPattern::HandleTabKeyEvent(const KeyEvent& event)
694 {
695     hasTabKeyDown_ = true;
696     auto host = GetHost();
697     CHECK_NULL_RETURN(host, false);
698     auto childSize = static_cast<int32_t>(host->GetChildren().size()) - 1;
699     if (event.IsShiftWith(KeyCode::KEY_TAB)) {
700         focusAreaIDWithoutWeek_ = (focusAreaIDWithoutWeek_ + childSize - 1) % childSize;
701     } else {
702         focusAreaIDWithoutWeek_ = (focusAreaIDWithoutWeek_ + 1) % childSize;
703     }
704 
705     if (focusAreaIDWithoutWeek_ == TITLE_NODE_INDEX) {
706         focusAreaID_ = focusAreaIDWithoutWeek_;
707     } else {
708         focusAreaID_ = focusAreaIDWithoutWeek_ + 1;
709     }
710 
711     if (focusAreaID_ == CALENDAR_NODE_INDEX) {
712         isCalendarFirstFocused_ = true;
713         FocusedLastFocusedDay();
714     } else {
715         ClearCalendarFocusedState();
716         focusAreaChildID_ = 0;
717         PaintFocusState();
718     }
719     ChangeEntryState();
720     return true;
721 }
722 
FocusedLastFocusedDay()723 void CalendarDialogPattern::FocusedLastFocusedDay()
724 {
725     auto calendarPattern = GetCalendarPattern();
726     CHECK_NULL_VOID(calendarPattern);
727     if (focusedDay_.day < 0) {
728         PickerDate selectedDay = calendarPattern->GetSelectedDay();
729         focusedDay_.month.year = static_cast<int32_t>(selectedDay.GetYear());
730         focusedDay_.month.month = static_cast<int32_t>(selectedDay.GetMonth());
731         focusedDay_.day = static_cast<int32_t>(selectedDay.GetDay());
732     }
733 
734     ObtainedMonth currentMonthData = calendarPattern->GetCurrentMonthData();
735     if (currentMonthData.year == focusedDay_.month.year && currentMonthData.month == focusedDay_.month.month) {
736         PaintCurrentMonthFocusState();
737         return;
738     }
739     ObtainedMonth monthData;
740     GetCalendarMonthData(focusedDay_.month.year, focusedDay_.month.month, monthData);
741     auto isPrev = currentMonthData.year > focusedDay_.month.year ||
742         (currentMonthData.year == focusedDay_.month.year && currentMonthData.month > focusedDay_.month.month);
743     auto it = std::find_if(monthData.days.begin(), monthData.days.end(),
744         [this](CalendarDay day) {
745             return day.day == focusedDay_.day && day.month == focusedDay_.month;
746         });
747     if (it != monthData.days.end()) {
748         focusedDay_ = *it;
749         it->isKeyFocused = true;
750         calendarPattern->SetDialogClickEventState(true);
751         UpdateSwiperNode(monthData, isPrev);
752     }
753 }
754 
UpdateSwiperNode(const ObtainedMonth & monthData,bool isPrev)755 void CalendarDialogPattern::UpdateSwiperNode(const ObtainedMonth& monthData, bool isPrev)
756 {
757     auto calendarPattern = GetCalendarPattern();
758     CHECK_NULL_VOID(calendarPattern);
759     auto swiperPattern = GetSwiperPattern();
760     CHECK_NULL_VOID(swiperPattern);
761     int32_t currentIndex = swiperPattern->GetCurrentIndex();
762     int32_t targetIndex = (currentIndex + SWIPER_CHILDREN_SIZE + (isPrev ? -1 : 1)) % SWIPER_CHILDREN_SIZE;
763 
764     auto swiperNode = GetSwiperFrameNode();
765     CHECK_NULL_VOID(swiperNode);
766     auto monthFrameNode = AceType::DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(targetIndex));
767     CHECK_NULL_VOID(monthFrameNode);
768     auto monthPattern = monthFrameNode->GetPattern<CalendarMonthPattern>();
769     CHECK_NULL_VOID(monthPattern);
770 
771     if (isPrev) {
772         monthPattern->SetMonthData(monthData, MonthState::PRE_MONTH);
773         calendarPattern->SetPreMonthData(monthData);
774     } else {
775         monthPattern->SetMonthData(monthData, MonthState::NEXT_MONTH);
776         calendarPattern->SetNextMonthData(monthData);
777     }
778 
779     monthFrameNode->MarkModifyDone();
780     monthFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
781     if (isPrev) {
782         swiperPattern->ShowPrevious();
783     } else {
784         swiperPattern->ShowNext();
785     }
786 }
787 
UpdateSwiperNodeFocusedDay(const CalendarDay & focusedDay,bool isPrev)788 void CalendarDialogPattern::UpdateSwiperNodeFocusedDay(const CalendarDay& focusedDay, bool isPrev)
789 {
790     auto calendarPattern = GetCalendarPattern();
791     CHECK_NULL_VOID(calendarPattern);
792     ObtainedMonth targetMonthData = isPrev ? calendarPattern->GetPreMonthData() : calendarPattern->GetNextMonthData();
793     if (focusedDay.month.year != targetMonthData.year || focusedDay.month.month != targetMonthData.month) {
794         return;
795     }
796 
797     auto it = std::find_if(targetMonthData.days.begin(), targetMonthData.days.end(),
798         [focusedDay](CalendarDay day) {
799             return day.day == focusedDay.day && day.month == focusedDay.month;
800         });
801     if (it != targetMonthData.days.end()) {
802         focusedDay_ = *it;
803         it->isKeyFocused = true;
804         auto swiperPattern = GetSwiperPattern();
805         CHECK_NULL_VOID(swiperPattern);
806         if (isPrev) {
807             calendarPattern->SetPreMonthData(targetMonthData);
808             swiperPattern->ShowPrevious();
809         } else {
810             calendarPattern->SetNextMonthData(targetMonthData);
811             swiperPattern->ShowNext();
812         }
813     }
814 }
815 
ActClick(int32_t focusAreaID,int32_t focusAreaChildID)816 bool CalendarDialogPattern::ActClick(int32_t focusAreaID, int32_t focusAreaChildID)
817 {
818     auto host = GetHost();
819     CHECK_NULL_RETURN(host, false);
820     auto focusArea = host->GetChildAtIndex(focusAreaID);
821     CHECK_NULL_RETURN(focusArea, false);
822     auto child = focusArea->GetChildAtIndex(focusAreaChildID);
823     CHECK_NULL_RETURN(child, false);
824     auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
825     CHECK_NULL_RETURN(childFrameNode, false);
826     auto gestureEventHub = childFrameNode->GetOrCreateGestureEventHub();
827     return gestureEventHub->ActClick();
828 }
829 
PaintCurrentMonthFocusState()830 void CalendarDialogPattern::PaintCurrentMonthFocusState()
831 {
832     auto calendarFrameNode = GetCalendarFrameNode();
833     CHECK_NULL_VOID(calendarFrameNode);
834     auto calendarPattern = calendarFrameNode->GetPattern<CalendarPattern>();
835     CHECK_NULL_VOID(calendarPattern);
836     ObtainedMonth currentMonthData = calendarPattern->GetCurrentMonthData();
837     for (auto& day : currentMonthData.days) {
838         day.isKeyFocused = currentMonthData.year == focusedDay_.month.year &&
839             currentMonthData.month == focusedDay_.month.month &&
840             day.month == focusedDay_.month && day.day == focusedDay_.day;
841     }
842     calendarPattern->SetCurrentMonthData(currentMonthData);
843     calendarFrameNode->MarkModifyDone();
844 }
845 
PaintNonCurrentMonthFocusState(int32_t focusedDayIndex)846 void CalendarDialogPattern::PaintNonCurrentMonthFocusState(int32_t focusedDayIndex)
847 {
848     auto calendarPattern = GetCalendarPattern();
849     CHECK_NULL_VOID(calendarPattern);
850     auto swiperPattern = GetSwiperPattern();
851     CHECK_NULL_VOID(swiperPattern);
852 
853     ObtainedMonth currentMonthData = calendarPattern->GetCurrentMonthData();
854     ObtainedMonth preMonthData = calendarPattern->GetPreMonthData();
855     ObtainedMonth nextMonthData = calendarPattern->GetNextMonthData();
856 
857     for (auto& day : currentMonthData.days) {
858         day.isKeyFocused = false;
859     }
860     calendarPattern->SetCurrentMonthData(currentMonthData);
861     calendarPattern->SetDialogClickEventState(true);
862     if (focusedDayIndex == -1) {
863         focusedDay_ = preMonthData.days[preMonthData.days.size() ? preMonthData.days.size() - 1 : 0];
864         preMonthData.days[preMonthData.days.size() ? preMonthData.days.size() - 1 : 0].isKeyFocused = true;
865         calendarPattern->SetPreMonthData(preMonthData);
866         swiperPattern->ShowPrevious();
867         return;
868     } else if (focusedDayIndex == static_cast<int32_t>(currentMonthData.days.size())) {
869         focusedDay_ = nextMonthData.days[0];
870         nextMonthData.days[0].isKeyFocused = true;
871         calendarPattern->SetNextMonthData(nextMonthData);
872         swiperPattern->ShowNext();
873         return;
874     }
875     UpdateNonCurrentMonthFocusedDay(focusedDayIndex);
876 }
877 
UpdateNonCurrentMonthFocusedDay(int32_t focusedDayIndex)878 void CalendarDialogPattern::UpdateNonCurrentMonthFocusedDay(int32_t focusedDayIndex)
879 {
880     auto calendarPattern = GetCalendarPattern();
881     CHECK_NULL_VOID(calendarPattern);
882 
883     ObtainedMonth currentMonthData = calendarPattern->GetCurrentMonthData();
884     ObtainedMonth preMonthData = calendarPattern->GetPreMonthData();
885     ObtainedMonth nextMonthData = calendarPattern->GetNextMonthData();
886 
887     if (focusedDayIndex < 0 || focusedDayIndex >= static_cast<int32_t>(currentMonthData.days.size())) {
888         return;
889     }
890 
891     CalendarDay focusedDay = currentMonthData.days[focusedDayIndex];
892     if (focusedDay.month.year == preMonthData.year && focusedDay.month.month == preMonthData.month) {
893         return UpdateSwiperNodeFocusedDay(focusedDay, true);
894     }
895 
896     if (focusedDay.month.year == nextMonthData.year && focusedDay.month.month == nextMonthData.month) {
897         return UpdateSwiperNodeFocusedDay(focusedDay, false);
898     }
899 }
900 
PaintFocusState()901 void CalendarDialogPattern::PaintFocusState()
902 {
903     auto host = GetHost();
904     CHECK_NULL_VOID(host);
905     RoundRect focusRect;
906     GetInnerFocusPaintRect(focusRect);
907     auto focusHub = host->GetFocusHub();
908     CHECK_NULL_VOID(focusHub);
909     focusHub->PaintInnerFocusState(focusRect);
910     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
911 }
912 
GetInnerFocusPaintRect(RoundRect & paintRect)913 void CalendarDialogPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
914 {
915     isFocused_ = true;
916     if (focusAreaID_ == CALENDAR_NODE_INDEX) {
917         paintRect.SetRect(RectF());
918         return;
919     }
920     auto host = GetHost();
921     CHECK_NULL_VOID(host);
922     auto focusArea = DynamicCast<FrameNode>(host->GetChildAtIndex(focusAreaID_));
923     CHECK_NULL_VOID(focusArea);
924     auto focusGeometryNode = focusArea->GetGeometryNode();
925     CHECK_NULL_VOID(focusGeometryNode);
926     auto focusAreaOffset = focusGeometryNode->GetFrameOffset();
927     auto child = DynamicCast<FrameNode>(focusArea->GetChildAtIndex(focusAreaChildID_));
928     CHECK_NULL_VOID(child);
929     auto childOffset = child->GetGeometryNode()->GetFrameOffset() + focusAreaOffset;
930     auto childSize = child->GetGeometryNode()->GetFrameSize();
931     paintRect.SetRect(RectF(childOffset, childSize));
932     auto renderContext = child->GetRenderContext();
933     CHECK_NULL_VOID(renderContext);
934     auto radius = renderContext->GetBorderRadius();
935     if (radius.has_value()) {
936         if (radius->radiusTopLeft.has_value()) {
937             paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS,
938                 static_cast<float>(radius->radiusTopLeft->ConvertToPx()),
939                 static_cast<float>(radius->radiusTopLeft->ConvertToPx()));
940         }
941         if (radius->radiusTopRight.has_value()) {
942             paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS,
943                 static_cast<float>(radius->radiusTopRight->ConvertToPx()),
944                 static_cast<float>(radius->radiusTopRight->ConvertToPx()));
945         }
946         if (radius->radiusBottomLeft.has_value()) {
947             paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS,
948                 static_cast<float>(radius->radiusBottomLeft->ConvertToPx()),
949                 static_cast<float>(radius->radiusBottomLeft->ConvertToPx()));
950         }
951         if (radius->radiusBottomRight.has_value()) {
952             paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS,
953                 static_cast<float>(radius->radiusBottomRight->ConvertToPx()),
954                 static_cast<float>(radius->radiusBottomRight->ConvertToPx()));
955         }
956     }
957     ChangeEntryState();
958 }
959 
ClearCalendarFocusedState()960 void CalendarDialogPattern::ClearCalendarFocusedState()
961 {
962     auto calendarFrameNode = GetCalendarFrameNode();
963     CHECK_NULL_VOID(calendarFrameNode);
964     auto calendarPattern = calendarFrameNode->GetPattern<CalendarPattern>();
965     CHECK_NULL_VOID(calendarPattern);
966     ObtainedMonth currentMonthData = calendarPattern->GetCurrentMonthData();
967     for (auto& day : currentMonthData.days) {
968         day.isKeyFocused = false;
969     }
970     calendarPattern->SetCurrentMonthData(currentMonthData);
971     calendarFrameNode->MarkModifyDone();
972 }
973 
ChangeEntryState()974 void CalendarDialogPattern::ChangeEntryState()
975 {
976     auto entryNode = entryNode_.Upgrade();
977     CHECK_NULL_VOID(entryNode);
978     auto enrtyPattern = entryNode->GetPattern<CalendarPickerPattern>();
979     CHECK_NULL_VOID(enrtyPattern);
980     if (focusAreaID_ == TITLE_NODE_INDEX) {
981         if (focusAreaChildID_ == TITLE_LAST_YEAR_BUTTON_NODE_INDEX ||
982             focusAreaChildID_ == TITLE_NEXT_YEAR_BUTTON_NODE_INDEX) {
983             enrtyPattern->SetSelectedType(CalendarPickerSelectedType::YEAR);
984         } else if (focusAreaChildID_ == TITLE_LAST_MONTH_BUTTON_NODE_INDEX ||
985                    focusAreaChildID_ == TITLE_NEXT_MONTH_BUTTON_NODE_INDEX) {
986             enrtyPattern->SetSelectedType(CalendarPickerSelectedType::MONTH);
987         }
988     } else if (focusAreaID_ == CALENDAR_NODE_INDEX) {
989         enrtyPattern->SetSelectedType(CalendarPickerSelectedType::DAY);
990     }
991 }
992 
InitTitleArrowsEvent()993 void CalendarDialogPattern::InitTitleArrowsEvent()
994 {
995     auto host = GetHost();
996     CHECK_NULL_VOID(host);
997     auto title = host->GetChildAtIndex(TITLE_NODE_INDEX);
998     CHECK_NULL_VOID(title);
999     for (const auto& child : title->GetChildren()) {
1000         CHECK_NULL_VOID(child);
1001         if (child->GetTag() == V2::TEXT_ETS_TAG) {
1002             continue;
1003         }
1004         int32_t childIndex = title->GetChildIndex(child);
1005         auto buttonNode = AceType::DynamicCast<FrameNode>(child);
1006         CHECK_NULL_VOID(buttonNode);
1007         auto event = [childIndex, wp = WeakClaim(this)](GestureEvent& /* info */) {
1008             auto pattern = wp.Upgrade();
1009             if (pattern) {
1010                 pattern->HandleTitleArrowsClickEvent(childIndex);
1011             }
1012         };
1013 
1014         auto buttonNodeId = buttonNode->GetId();
1015         if (clickEvents_.find(buttonNodeId) == clickEvents_.end()) {
1016             auto gestureHub = buttonNode->GetOrCreateGestureEventHub();
1017             CHECK_NULL_VOID(gestureHub);
1018             auto clickEvent = AceType::MakeRefPtr<ClickEvent>(std::move(event));
1019             clickEvents_[buttonNodeId] = clickEvent;
1020             gestureHub->AddClickEvent(clickEvent);
1021         }
1022     }
1023 }
1024 
HandleTitleArrowsClickEvent(int32_t nodeIndex)1025 void CalendarDialogPattern::HandleTitleArrowsClickEvent(int32_t nodeIndex)
1026 {
1027     auto swiperPattern = GetSwiperPattern();
1028     CHECK_NULL_VOID(swiperPattern);
1029     swiperPattern->GetSwiperController()->FinishAnimation();
1030 
1031     auto calendarPattern = GetCalendarPattern();
1032     CHECK_NULL_VOID(calendarPattern);
1033     ObtainedMonth currentObtainedMonth = calendarPattern->GetCurrentMonthData();
1034     CalendarMonth currentMonth { .year = currentObtainedMonth.year, .month = currentObtainedMonth.month };
1035 
1036     calendarPattern->SetDialogClickEventState(true);
1037     switch (nodeIndex) {
1038         case TITLE_LAST_YEAR_BUTTON_NODE_INDEX: {
1039             currentMonth.year = currentMonth.year == MIN_YEAR ? MAX_YEAR : currentMonth.year - 1;
1040             ObtainedMonth monthData;
1041             GetCalendarMonthData(currentMonth.year, currentMonth.month, monthData);
1042             UpdateSwiperNode(monthData, true);
1043             break;
1044         }
1045         case TITLE_LAST_MONTH_BUTTON_NODE_INDEX: {
1046             swiperPattern->ShowPrevious();
1047             break;
1048         }
1049         case TITLE_NEXT_MONTH_BUTTON_NODE_INDEX: {
1050             swiperPattern->ShowNext();
1051             break;
1052         }
1053         case TITLE_NEXT_YEAR_BUTTON_NODE_INDEX: {
1054             currentMonth.year = currentMonth.year == MAX_YEAR ? MIN_YEAR : currentMonth.year + 1;
1055             ObtainedMonth monthData;
1056             GetCalendarMonthData(currentMonth.year, currentMonth.month, monthData);
1057             UpdateSwiperNode(monthData, false);
1058             break;
1059         }
1060         default:
1061             break;
1062     }
1063 }
1064 
GetCalendarMonthData(int32_t year,int32_t month,ObtainedMonth & calendarMonthData)1065 void CalendarDialogPattern::GetCalendarMonthData(int32_t year, int32_t month, ObtainedMonth& calendarMonthData)
1066 {
1067     calendarMonthData.year = year;
1068     calendarMonthData.month = month;
1069     calendarMonthData.firstDayIndex = 0;
1070 
1071     CalendarMonth currentMonth { .year = year, .month = month };
1072 
1073     int32_t currentMonthMaxDay = static_cast<int32_t>(PickerDate::GetMaxDay(year, month));
1074     int32_t preMonthMaxDay =
1075         static_cast<int32_t>(PickerDate::GetMaxDay(GetLastMonth(currentMonth).year, GetLastMonth(currentMonth).month));
1076     int32_t preMonthDaysCount = (Date::CalculateWeekDay(year, month, 1) + 1) % WEEK_DAYS;
1077     int32_t nextMonthDaysCount = 6 - ((Date::CalculateWeekDay(year, month, currentMonthMaxDay) + 1) % WEEK_DAYS);
1078 
1079     int32_t index = 0;
1080     for (int32_t i = 0; i < preMonthDaysCount; i++, index++) {
1081         calendarMonthData.days.emplace_back(CalendarDay { .index = index,
1082             .day = preMonthMaxDay - preMonthDaysCount + index + 1,
1083             .month = GetLastMonth(currentMonth) });
1084     }
1085 
1086     for (int32_t i = 0; i < currentMonthMaxDay; i++, index++) {
1087         calendarMonthData.days.emplace_back(CalendarDay { .index = index, .day = i + 1, .month = currentMonth });
1088     }
1089 
1090     for (int32_t i = 0; i < nextMonthDaysCount; i++, index++) {
1091         calendarMonthData.days.emplace_back(
1092             CalendarDay { .index = index, .day = i + 1, .month = GetNextMonth(currentMonth) });
1093     }
1094 
1095     auto calendarPattern = GetCalendarPattern();
1096     CHECK_NULL_VOID(calendarPattern);
1097     PickerDate selectedDay = calendarPattern->GetSelectedDay();
1098     for (size_t i = 0; i < calendarMonthData.days.size(); i++) {
1099         calendarMonthData.days[i].isKeyFocused = isFocused_
1100                                                      ? ((focusedDay_.month.year == calendarMonthData.year) &&
1101                                                            (focusedDay_.month.month == calendarMonthData.month) &&
1102                                                            (focusedDay_.month == calendarMonthData.days[i].month) &&
1103                                                            (focusedDay_.day == calendarMonthData.days[i].day))
1104                                                      : false;
1105         calendarMonthData.days[i].isSelected =
1106             (selectedDay.GetYear() == static_cast<uint32_t>(calendarMonthData.year)) &&
1107             (selectedDay.GetMonth() == static_cast<uint32_t>(calendarMonthData.month)) &&
1108             (selectedDay.GetYear() == static_cast<uint32_t>(calendarMonthData.days[i].month.year)) &&
1109             (selectedDay.GetMonth() == static_cast<uint32_t>(calendarMonthData.days[i].month.month)) &&
1110             (selectedDay.GetDay() == static_cast<uint32_t>(calendarMonthData.days[i].day));
1111     }
1112 }
1113 
AddHotZoneRect()1114 void CalendarDialogPattern::AddHotZoneRect()
1115 {
1116     auto entryNode = entryNode_.Upgrade();
1117     CHECK_NULL_VOID(entryNode);
1118     auto rect = entryNode->GetPaintRectWithTransform();
1119     DimensionRect hotZoneRegion;
1120     hotZoneRegion.SetSize(DimensionSize(
1121         Dimension(rect.Width()), Dimension(rect.Height())));
1122     hotZoneRegion.SetOffset(DimensionOffset(
1123         Dimension(rect.Left() - dialogOffset_.GetX()), Dimension(rect.Top() - dialogOffset_.GetY())));
1124 
1125     auto host = GetHost();
1126     CHECK_NULL_VOID(host);
1127     auto geometryNode = host->GetGeometryNode();
1128     CHECK_NULL_VOID(geometryNode);
1129     DimensionRect hotZoneRegionHost;
1130     hotZoneRegionHost.SetSize(DimensionSize(
1131         Dimension(geometryNode->GetFrameRect().Width()), Dimension(geometryNode->GetFrameRect().Height())));
1132 
1133     host->AddHotZoneRect(hotZoneRegion);
1134     host->AddHotZoneRect(hotZoneRegionHost);
1135 }
1136 
FireChangeByKeyEvent(PickerDate & selectedDay)1137 void CalendarDialogPattern::FireChangeByKeyEvent(PickerDate& selectedDay)
1138 {
1139     auto calendarNode = GetCalendarFrameNode();
1140     CHECK_NULL_VOID(calendarNode);
1141 
1142     auto swiperNode = AceType::DynamicCast<FrameNode>(calendarNode->GetFirstChild());
1143     CHECK_NULL_VOID(swiperNode);
1144     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
1145     CHECK_NULL_VOID(swiperPattern);
1146     auto monthNode = AceType::DynamicCast<FrameNode>(swiperNode->GetChildAtIndex(swiperPattern->GetCurrentIndex()));
1147     CHECK_NULL_VOID(monthNode);
1148     auto eventHub = monthNode->GetEventHub<CalendarEventHub>();
1149     CHECK_NULL_VOID(eventHub);
1150     eventHub->UpdateSelectedChangeEvent(selectedDay.ToString(true));
1151 }
1152 
GetNextMonth(const CalendarMonth & calendarMonth)1153 CalendarMonth CalendarDialogPattern::GetNextMonth(const CalendarMonth& calendarMonth)
1154 {
1155     CalendarMonth nextMonth = calendarMonth;
1156     if (calendarMonth.month + 1 > MAX_MONTH) {
1157         nextMonth.month = 1;
1158         nextMonth.year = nextMonth.year == MAX_YEAR ? MIN_YEAR : nextMonth.year + 1;
1159     } else {
1160         ++nextMonth.month;
1161     }
1162     return nextMonth;
1163 }
1164 
GetLastMonth(const CalendarMonth & calendarMonth)1165 CalendarMonth CalendarDialogPattern::GetLastMonth(const CalendarMonth& calendarMonth)
1166 {
1167     CalendarMonth lastMonth = calendarMonth;
1168     if (calendarMonth.month - 1 <= 0) {
1169         lastMonth.month = MAX_MONTH;
1170         lastMonth.year = lastMonth.year == MIN_YEAR ? MAX_YEAR : lastMonth.year - 1;
1171     } else {
1172         --lastMonth.month;
1173     }
1174     return lastMonth;
1175 }
1176 
GetIndexByFocusedDay()1177 int32_t CalendarDialogPattern::GetIndexByFocusedDay()
1178 {
1179     ObtainedMonth monthData;
1180     GetCalendarMonthData(focusedDay_.month.year, focusedDay_.month.month, monthData);
1181     auto it = std::find_if(monthData.days.begin(), monthData.days.end(),
1182         [this](CalendarDay day) {
1183             return day.day == focusedDay_.day && day.month == focusedDay_.month;
1184         });
1185     if (it != monthData.days.end()) {
1186         return it->index;
1187     }
1188     return -1;
1189 }
1190 
HandleEntryLayoutChange()1191 void CalendarDialogPattern::HandleEntryLayoutChange()
1192 {
1193     auto entryNode = entryNode_.Upgrade();
1194     CHECK_NULL_VOID(entryNode);
1195     auto host = GetHost();
1196     CHECK_NULL_VOID(host);
1197     auto wrapperNode = host->GetParent();
1198     CHECK_NULL_VOID(wrapperNode);
1199     auto dialogNode = AceType::DynamicCast<FrameNode>(wrapperNode->GetParent());
1200     CHECK_NULL_VOID(dialogNode);
1201     auto pipeline = GetContext();
1202     if (pipeline) {
1203         pipeline->AddAfterRenderTask([weak = WeakClaim(this), entryNode, dialogNode]() {
1204             auto node = weak.Upgrade();
1205             CHECK_NULL_VOID(node);
1206             auto pattern = entryNode->GetPattern<CalendarPickerPattern>();
1207             CHECK_NULL_VOID(pattern);
1208             node->dialogOffset_ = pattern->CalculateDialogOffset();
1209             auto dialogLayoutProp = dialogNode->GetLayoutProperty<DialogLayoutProperty>();
1210             CHECK_NULL_VOID(dialogLayoutProp);
1211             dialogLayoutProp->UpdateDialogOffset(DimensionOffset(node->dialogOffset_));
1212             dialogNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1213         });
1214     }
1215     isFirstAddhotZoneRect_ = false;
1216 }
1217 
HandleEntryChange(const std::string & info)1218 void CalendarDialogPattern::HandleEntryChange(const std::string& info)
1219 {
1220     auto calendarNode = GetCalendarFrameNode();
1221     CHECK_NULL_VOID(calendarNode);
1222     auto calendarPattern = calendarNode->GetPattern<CalendarPattern>();
1223     CHECK_NULL_VOID(calendarPattern);
1224 
1225     auto calendarJson = JsonUtil::ParseJsonString(calendarPattern->GetSelectDate());
1226     auto entryJson = JsonUtil::ParseJsonString(info);
1227     auto entryYear = entryJson->GetUInt("year");
1228     auto entryMonth = entryJson->GetUInt("month");
1229     auto entryDay = entryJson->GetUInt("day");
1230 
1231     PickerDate selectedDay = PickerDate(entryYear, entryMonth, entryDay);
1232     if (entryYear != calendarJson->GetUInt("year") || entryMonth != calendarJson->GetUInt("month")) {
1233         CalendarData calendarData;
1234         CalendarMonth calendarMonth { .year = entryYear, .month = entryMonth };
1235 
1236         GetCalendarMonthData(entryYear, entryMonth, calendarData.currentData);
1237         calendarPattern->SetCurrentMonthData(calendarData.currentData);
1238         GetCalendarMonthData(
1239             GetLastMonth(calendarMonth).year, GetLastMonth(calendarMonth).month, calendarData.preData);
1240         calendarPattern->SetPreMonthData(calendarData.preData);
1241         GetCalendarMonthData(
1242             GetNextMonth(calendarMonth).year, GetNextMonth(calendarMonth).month, calendarData.nextData);
1243         calendarPattern->SetNextMonthData(calendarData.nextData);
1244     }
1245 
1246     calendarPattern->SetSelectedDay(selectedDay);
1247     calendarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1248     calendarNode->MarkModifyDone();
1249 }
1250 
GetCalendarFrameNode()1251 RefPtr<FrameNode> CalendarDialogPattern::GetCalendarFrameNode()
1252 {
1253     auto host = GetHost();
1254     CHECK_NULL_RETURN(host, nullptr);
1255     auto scrollNode = host->GetChildAtIndex(CALENDAR_NODE_INDEX);
1256     CHECK_NULL_RETURN(scrollNode, nullptr);
1257     auto calendarNode = scrollNode->GetChildren().front();
1258     return AceType::DynamicCast<FrameNode>(calendarNode);
1259 }
1260 
GetCalendarPattern()1261 RefPtr<CalendarPattern> CalendarDialogPattern::GetCalendarPattern()
1262 {
1263     auto calendarFrameNode = GetCalendarFrameNode();
1264     CHECK_NULL_RETURN(calendarFrameNode, nullptr);
1265     return calendarFrameNode->GetPattern<CalendarPattern>();
1266 }
1267 
GetSwiperFrameNode()1268 RefPtr<FrameNode> CalendarDialogPattern::GetSwiperFrameNode()
1269 {
1270     auto calendarFrameNode = GetCalendarFrameNode();
1271     CHECK_NULL_RETURN(calendarFrameNode, nullptr);
1272     if (calendarFrameNode->GetChildren().empty()) {
1273         return nullptr;
1274     }
1275     auto swiperNode = calendarFrameNode->GetChildren().front();
1276     CHECK_NULL_RETURN(swiperNode, nullptr);
1277     return AceType::DynamicCast<FrameNode>(swiperNode);
1278 }
1279 
GetSwiperPattern()1280 RefPtr<SwiperPattern> CalendarDialogPattern::GetSwiperPattern()
1281 {
1282     auto swiperFrameNode = GetSwiperFrameNode();
1283     CHECK_NULL_RETURN(swiperFrameNode, nullptr);
1284     return swiperFrameNode->GetPattern<SwiperPattern>();
1285 }
1286 
OnEnterKeyEvent(const KeyEvent & event)1287 void CalendarDialogPattern::OnEnterKeyEvent(const KeyEvent& event)
1288 {
1289     bool checkKeyCode = (event.code == KeyCode::KEY_ENTER || event.code == KeyCode::KEY_NUMPAD_ENTER ||
1290         event.code == KeyCode::KEY_SPACE);
1291     if (!checkKeyCode) {
1292         return;
1293     }
1294     auto host = GetHost();
1295     CHECK_NULL_VOID(host);
1296     auto options = host->GetChildAtIndex(OPTIONS_NODE_INDEX);
1297     CHECK_NULL_VOID(options);
1298 
1299     for (const auto& child : options->GetChildren()) {
1300         CHECK_NULL_VOID(child);
1301         if (child->GetTag() != V2::BUTTON_ETS_TAG) {
1302             continue;
1303         }
1304         auto button = AceType::DynamicCast<FrameNode>(child);
1305         CHECK_NULL_VOID(button);
1306         auto focusHub = button->GetOrCreateFocusHub();
1307         if (focusHub && focusHub->IsDefaultFocus()) {
1308             auto gesture = button->GetOrCreateGestureEventHub();
1309             CHECK_NULL_VOID(gesture);
1310             gesture->ActClick();
1311         }
1312     }
1313 }
1314 
OnLanguageConfigurationUpdate()1315 void CalendarDialogPattern::OnLanguageConfigurationUpdate()
1316 {
1317     auto host = GetHost();
1318     CHECK_NULL_VOID(host);
1319     auto scrollNode = host->GetChildAtIndex(CALENDAR_NODE_INDEX);
1320     CHECK_NULL_VOID(scrollNode);
1321     auto calendarNode = AceType::DynamicCast<FrameNode>(scrollNode->GetChildren().front());
1322     CHECK_NULL_VOID(calendarNode);
1323     auto swiperNode = AceType::DynamicCast<FrameNode>(calendarNode->GetFirstChild());
1324     CHECK_NULL_VOID(swiperNode);
1325 
1326     for (auto&& child : swiperNode->GetChildren()) {
1327         auto monthFrameNode = AceType::DynamicCast<FrameNode>(child);
1328         CHECK_NULL_VOID(monthFrameNode);
1329         auto pipelineContext = GetContext();
1330         CHECK_NULL_VOID(pipelineContext);
1331         RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
1332         CHECK_NULL_VOID(theme);
1333 
1334         auto fontSizeScale = pipelineContext->GetFontScale();
1335         auto fontSize = theme->GetCalendarDayFontSize();
1336         if (AceApplicationInfo::GetInstance().GetLanguage() != "zh") {
1337             ACE_UPDATE_NODE_PAINT_PROPERTY(
1338                 CalendarPaintProperty, WeekFontSize, theme->GetCalendarSmallDayFontSize(), monthFrameNode);
1339         } else {
1340             if (fontSizeScale < theme->GetCalendarPickerLargeScale() || CalendarDialogView::CheckOrientationChange()) {
1341                 ACE_UPDATE_NODE_PAINT_PROPERTY(CalendarPaintProperty, WeekFontSize, fontSize, monthFrameNode);
1342             } else {
1343                 fontSizeScale = fontSizeScale > theme->GetCalendarPickerLargerScale()
1344                                     ? theme->GetCalendarPickerLargerScale()
1345                                     : fontSizeScale;
1346                 ACE_UPDATE_NODE_PAINT_PROPERTY(
1347                     CalendarPaintProperty, WeekFontSize, fontSize * fontSizeScale, monthFrameNode);
1348             }
1349         }
1350         monthFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1351     }
1352 }
1353 
InitSurfaceChangedCallback()1354 void CalendarDialogPattern::InitSurfaceChangedCallback()
1355 {
1356     auto pipelineContext = GetContext();
1357     CHECK_NULL_VOID(pipelineContext);
1358     if (!HasSurfaceChangedCallback()) {
1359         auto callbackId = pipelineContext->RegisterSurfaceChangedCallback(
1360             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
1361                 WindowSizeChangeReason type) {
1362                 auto pattern = weak.Upgrade();
1363                 if (pattern) {
1364                     pattern->HandleSurfaceChanged(newWidth, newHeight, prevWidth, prevHeight);
1365                 }
1366             });
1367         UpdateSurfaceChangedCallbackId(callbackId);
1368     }
1369 }
1370 
HandleSurfaceChanged(int32_t newWidth,int32_t newHeight,int32_t prevWidth,int32_t prevHeight)1371 void CalendarDialogPattern::HandleSurfaceChanged(
1372     int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight)
1373 {
1374     if (newWidth == prevWidth && newHeight == prevHeight) {
1375         return;
1376     }
1377 
1378     auto tmpHost = GetHost();
1379     CHECK_NULL_VOID(tmpHost);
1380     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1381     UpdateCaretInfoToController();
1382 }
1383 
UpdateCaretInfoToController()1384 void CalendarDialogPattern::UpdateCaretInfoToController()
1385 {
1386     auto host = GetHost();
1387     CHECK_NULL_VOID(host);
1388     auto titleNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(TITLE_NODE_INDEX));
1389     CHECK_NULL_VOID(titleNode);
1390     auto layoutProps = titleNode->GetLayoutProperty<LinearLayoutProperty>();
1391     CHECK_NULL_VOID(layoutProps);
1392     auto pipelineContext = GetContext();
1393     CHECK_NULL_VOID(pipelineContext);
1394     auto calendarTheme = pipelineContext->GetTheme<CalendarTheme>();
1395     CHECK_NULL_VOID(calendarTheme);
1396     auto scrollNode = host->GetChildAtIndex(CALENDAR_NODE_INDEX);
1397     CHECK_NULL_VOID(calendarTheme);
1398     auto calendarNode = AceType::DynamicCast<FrameNode>(scrollNode->GetChildren().front());
1399     CHECK_NULL_VOID(calendarNode);
1400     auto calendarLayoutProperty = calendarNode->GetLayoutProperty();
1401     CHECK_NULL_VOID(calendarLayoutProperty);
1402     CalendarDialogView::UpdateIdealSize(calendarTheme, layoutProps, calendarLayoutProperty, calendarNode);
1403 
1404     auto swiperNode = AceType::DynamicCast<FrameNode>(calendarNode->GetFirstChild());
1405     CHECK_NULL_VOID(swiperNode);
1406     for (auto&& child : swiperNode->GetChildren()) {
1407         auto monthFrameNode = AceType::DynamicCast<FrameNode>(child);
1408         CHECK_NULL_VOID(monthFrameNode);
1409         auto monthPattern = monthFrameNode->GetPattern<CalendarMonthPattern>();
1410         CHECK_NULL_VOID(monthPattern);
1411         CalendarDialogView::UpdatePaintProperties(monthFrameNode, currentSettingData_);
1412         monthPattern->UpdateColRowSpace();
1413         monthFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1414     }
1415 
1416     if (host->GetTotalChildCount() > OPTIONS_NODE_INDEX) {
1417         auto contentRow = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(OPTIONS_NODE_INDEX));
1418         CHECK_NULL_VOID(contentRow);
1419         size_t buttonIndex = OPTION_CANCEL_BUTTON_INDEX;
1420         for (auto&& child : contentRow->GetChildren()) {
1421             auto buttonNode = AceType::DynamicCast<FrameNode>(child);
1422             CHECK_NULL_VOID(buttonNode);
1423             CalendarDialogView::UpdateButtons(buttonNode, buttonIndex, currentButtonInfos_);
1424             buttonIndex++;
1425         }
1426     }
1427 
1428     auto calendarPattern = GetCalendarPattern();
1429     CHECK_NULL_VOID(calendarPattern);
1430     calendarPattern->UpdateTitleNode();
1431 
1432     auto wrapperNode = host->GetParent();
1433     CHECK_NULL_VOID(wrapperNode);
1434     auto dialogNode = AceType::DynamicCast<FrameNode>(wrapperNode->GetParent());
1435     CHECK_NULL_VOID(dialogNode);
1436     dialogNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1437     CalendarDialogView::SetPreviousOrientation();
1438 }
1439 
CanReportChangeEvent(const PickerDate & pickerDate)1440 bool CalendarDialogPattern::CanReportChangeEvent(const PickerDate& pickerDate)
1441 {
1442     return CalendarDialogView::CanReportChangeEvent(reportedPickerDate_, pickerDate);
1443 }
1444 
OnColorConfigurationUpdate()1445 void CalendarDialogPattern::OnColorConfigurationUpdate()
1446 {
1447     auto titleNode = titleNode_.Upgrade();
1448     CHECK_NULL_VOID(titleNode);
1449     auto pipelineContext = titleNode->GetContextRefPtr();
1450     CHECK_NULL_VOID(pipelineContext);
1451     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
1452     CHECK_NULL_VOID(theme);
1453     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
1454     CHECK_NULL_VOID(textLayoutProperty);
1455 
1456     textLayoutProperty->UpdateTextColor(theme->GetCalendarTitleFontColor());
1457 }
1458 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1459 void CalendarDialogPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1460 {
1461     /* no fixed attr below, just return */
1462     if (filter.IsFastFilter()) {
1463         return;
1464     }
1465 
1466     json->PutExtAttr("markToday", currentSettingData_.markToday ? "true" : "false", filter);
1467     std::string disabledDateRangeStr = "";
1468     for (const auto& range : currentSettingData_.disabledDateRange) {
1469         disabledDateRangeStr += range.first.ToString(false) + "," + range.second.ToString(false) + ",";
1470     }
1471     if (!disabledDateRangeStr.empty() && disabledDateRangeStr.back() == ',') {
1472         disabledDateRangeStr.pop_back();
1473     }
1474     json->PutExtAttr("disabledDateRange", disabledDateRangeStr.c_str(), filter);
1475     if (currentSettingData_.startDate.ToDays() == PickerDate().ToDays()) {
1476         json->PutExtAttr("start", "undefined", filter);
1477     } else {
1478         json->PutExtAttr("start", currentSettingData_.startDate.ToString(false).c_str(), filter);
1479     }
1480     if (currentSettingData_.endDate.ToDays() == PickerDate().ToDays()) {
1481         json->PutExtAttr("end", "undefined", filter);
1482     } else {
1483         json->PutExtAttr("end", currentSettingData_.endDate.ToString(false).c_str(), filter);
1484     }
1485 }
1486 } // namespace OHOS::Ace::NG
1487