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