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