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