• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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/picker/datepicker_pattern.h"
17 
18 #include <stdint.h>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "base/i18n/date_time_sequence.h"
24 #include "base/memory/ace_type.h"
25 #include "base/utils/utils.h"
26 #include "core/components/picker/picker_base_component.h"
27 #include "core/components/theme/icon_theme.h"
28 #include "core/components_ng/base/frame_node.h"
29 #include "core/components_ng/base/inspector_filter.h"
30 #include "core/components_ng/event/click_event.h"
31 #include "core/components_ng/pattern/button/button_pattern.h"
32 #include "core/components_ng/pattern/image/image_layout_property.h"
33 #include "core/components_ng/pattern/picker/datepicker_column_pattern.h"
34 #include "core/components_v2/inspector/inspector_constants.h"
35 #include "core/pipeline/pipeline_base.h"
36 #include "core/pipeline_ng/ui_task_scheduler.h"
37 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
38 
39 namespace OHOS::Ace::NG {
40 namespace {
41 constexpr int32_t SINGLE_CHILD_SIZE = 1;
42 constexpr int32_t CHILD_SIZE = 3;
43 constexpr uint32_t MIN_MONTH = 1;
44 constexpr uint32_t MAX_MONTH = 12;
45 constexpr uint32_t MIN_DAY = 1;
46 const Dimension PRESS_INTERVAL = 4.0_vp;
47 const Dimension FOCUS_INTERVAL = 2.0_vp;
48 const Dimension LINE_WIDTH = 1.5_vp;
49 const Dimension PRESS_RADIUS = 8.0_vp;
50 const int32_t UNOPTION_COUNT = 2;
51 const int32_t COLUMNS_SIZE = 3;
52 const int32_t COLUMNS_ZERO = 0;
53 const int32_t COLUMNS_ONE = 1;
54 const int32_t COLUMNS_TWO = 2;
55 const int32_t INDEX_YEAR = 0;
56 const int32_t INDEX_MONTH = 1;
57 const int32_t INDEX_DAY = 2;
58 constexpr float DISABLE_ALPHA = 0.6f;
59 const int32_t RATE = 2;
60 const int32_t MONTH_DECEMBER = 12;
61 constexpr int32_t RATIO_ZERO = 0;
62 constexpr int32_t RATIO_ONE = 1;
63 constexpr int32_t SECOND_PAGE = 1;
64 } // namespace
65 bool DatePickerPattern::inited_ = false;
66 const std::string DatePickerPattern::empty_;
67 const PickerDateF DatePickerPattern::emptyPickerDate_;
68 std::unordered_map<uint32_t, std::string> DatePickerPattern::years_;       // year from 1900 to 2100,count is 201
69 std::unordered_map<uint32_t, std::string> DatePickerPattern::solarMonths_; // solar month from 1 to 12,count is 12
70 std::unordered_map<uint32_t, std::string> DatePickerPattern::solarDays_;   // solar day from 1 to 31, count is 31
71 std::unordered_map<uint32_t, std::string> DatePickerPattern::lunarMonths_; // lunar month from 1 to 24, count is 24
72 std::unordered_map<uint32_t, std::string> DatePickerPattern::lunarDays_;   // lunar day from 1 to 30, count is 30
73 std::vector<std::string> DatePickerPattern::tagOrder_;    // order of year month day
74 std::vector<std::string> DatePickerPattern::localizedMonths_;
75 
OnAttachToFrameNode()76 void DatePickerPattern::OnAttachToFrameNode()
77 {
78     auto host = GetHost();
79     CHECK_NULL_VOID(host);
80     host->GetRenderContext()->SetClipToFrame(true);
81     host->GetRenderContext()->UpdateClipEdge(true);
82 }
83 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)84 bool DatePickerPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
85 {
86     CHECK_NULL_RETURN(dirty, false);
87     auto host = GetHost();
88     CHECK_NULL_RETURN(host, false);
89     auto context = host->GetContext();
90     CHECK_NULL_RETURN(context, false);
91     auto pickerTheme = context->GetTheme<PickerTheme>();
92     CHECK_NULL_RETURN(pickerTheme, false);
93     auto children = host->GetChildren();
94     auto height = pickerTheme->GetDividerSpacing();
95     auto buttonSpace = pickerTheme->GetSelectorItemSpace();
96     auto currentFocusStackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
97     CHECK_NULL_RETURN(currentFocusStackChild, false);
98     auto currentFocusButtonNode = DynamicCast<FrameNode>(currentFocusStackChild->GetFirstChild());
99     CHECK_NULL_RETURN(currentFocusButtonNode, false);
100     for (const auto& child : children) {
101         auto columnNode = DynamicCast<FrameNode>(child->GetLastChild()->GetLastChild());
102         CHECK_NULL_RETURN(columnNode, false);
103         auto width = columnNode->GetGeometryNode()->GetFrameSize().Width();
104         auto datePickerColumnNode = DynamicCast<FrameNode>(child->GetLastChild());
105         CHECK_NULL_RETURN(datePickerColumnNode, false);
106         auto buttonNode = DynamicCast<FrameNode>(child->GetFirstChild());
107         CHECK_NULL_RETURN(buttonNode, false);
108         auto buttonConfirmLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
109         buttonConfirmLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
110         buttonConfirmLayoutProperty->UpdateType(ButtonType::NORMAL);
111         buttonConfirmLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(selectorItemRadius_));
112         auto standardButtonHeight = static_cast<float>((height - PRESS_INTERVAL).ConvertToPx());
113         auto maxButtonHeight = static_cast<float>(datePickerColumnNode->GetGeometryNode()->GetFrameSize().Height());
114         auto buttonHeight = Dimension(std::min(standardButtonHeight, maxButtonHeight), DimensionUnit::PX);
115         buttonConfirmLayoutProperty->UpdateUserDefinedIdealSize(
116             CalcSize(CalcLength(width - buttonSpace.ConvertToPx()), CalcLength(buttonHeight)));
117         auto buttonConfirmRenderContext = buttonNode->GetRenderContext();
118         if (!useButtonFocusArea_) {
119             buttonConfirmRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
120         } else {
121             auto isFocusButton = haveFocus_ && (currentFocusButtonNode == buttonNode);
122             UpdateColumnButtonStyles(columnNode, isFocusButton, false);
123         }
124         buttonNode->MarkModifyDone();
125         buttonNode->MarkDirtyNode();
126         if (GetIsShowInDialog() && GreatNotEqual(standardButtonHeight, maxButtonHeight) &&
127             GreatNotEqual(maxButtonHeight, 0.0f)) {
128             auto parentNode = DynamicCast<FrameNode>(host->GetParent());
129             CHECK_NULL_RETURN(parentNode, false);
130             parentNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
131         }
132     }
133     return true;
134 }
135 
InitSelectorProps()136 void DatePickerPattern::InitSelectorProps()
137 {
138     auto host = GetHost();
139     CHECK_NULL_VOID(host);
140     auto context = host->GetContextRefPtr();
141     CHECK_NULL_VOID(context);
142     auto pickerTheme = context->GetTheme<PickerTheme>();
143     CHECK_NULL_VOID(pickerTheme);
144 
145     selectorItemRadius_ = pickerTheme->GetSelectorItemRadius();
146     useButtonFocusArea_ = pickerTheme->NeedButtonFocusAreaType();
147 }
148 
InitFocusEvent()149 void DatePickerPattern::InitFocusEvent()
150 {
151     CHECK_NULL_VOID(!focusEventInitialized_);
152     auto host = GetHost();
153     CHECK_NULL_VOID(host);
154     auto context = host->GetContextRefPtr();
155     CHECK_NULL_VOID(context);
156     auto pickerTheme = context->GetTheme<PickerTheme>();
157     CHECK_NULL_VOID(pickerTheme);
158     auto focusHub = host->GetOrCreateFocusHub();
159     CHECK_NULL_VOID(focusHub);
160     auto focusTask = [weak = WeakClaim(this)]() {
161         auto pattern = weak.Upgrade();
162         CHECK_NULL_VOID(pattern);
163         pattern->HandleFocusEvent();
164     };
165     focusHub->SetOnFocusInternal(focusTask);
166 
167     auto blurTask = [weak = WeakClaim(this)]() {
168         auto pattern = weak.Upgrade();
169         CHECK_NULL_VOID(pattern);
170         pattern->HandleBlurEvent();
171     };
172     focusHub->SetOnBlurInternal(blurTask);
173 
174     focusEventInitialized_ = true;
175 }
176 
AddIsFocusActiveUpdateEvent()177 void DatePickerPattern::AddIsFocusActiveUpdateEvent()
178 {
179     if (!isFocusActiveUpdateEvent_) {
180         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
181             auto pickerPattern = weak.Upgrade();
182             CHECK_NULL_VOID(pickerPattern);
183             pickerPattern->SetHaveFocus(isFocusAcitve);
184             pickerPattern->UpdateFocusButtonState();
185         };
186     }
187 
188     auto context = GetContext();
189     CHECK_NULL_VOID(context);
190     context->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
191 }
192 
RemoveIsFocusActiveUpdateEvent()193 void DatePickerPattern::RemoveIsFocusActiveUpdateEvent()
194 {
195     auto host = GetHost();
196     CHECK_NULL_VOID(host);
197     auto pipeline = host->GetContext();
198     CHECK_NULL_VOID(pipeline);
199     pipeline->RemoveIsFocusActiveUpdateEvent(host);
200 }
201 
SetHaveFocus(bool haveFocus)202 void DatePickerPattern::SetHaveFocus(bool haveFocus)
203 {
204     haveFocus_ = haveFocus;
205 }
206 
HandleFocusEvent()207 void DatePickerPattern::HandleFocusEvent()
208 {
209     auto host = GetHost();
210     CHECK_NULL_VOID(host);
211     auto context = host->GetContextRefPtr();
212     CHECK_NULL_VOID(context);
213 
214     AddIsFocusActiveUpdateEvent();
215     if (context->GetIsFocusActive()) {
216         SetHaveFocus(true);
217         UpdateFocusButtonState();
218     }
219 }
220 
HandleBlurEvent()221 void DatePickerPattern::HandleBlurEvent()
222 {
223     SetHaveFocus(false);
224     RemoveIsFocusActiveUpdateEvent();
225     UpdateFocusButtonState();
226 }
227 
UpdateFocusButtonState()228 void DatePickerPattern::UpdateFocusButtonState()
229 {
230     auto host = GetHost();
231     CHECK_NULL_VOID(host);
232     if (useButtonFocusArea_) {
233         auto currentFocusStackNode = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
234         CHECK_NULL_VOID(currentFocusStackNode);
235         auto blendColumnNode = currentFocusStackNode->GetLastChild();
236         CHECK_NULL_VOID(blendColumnNode);
237         auto currentFocusColumnNode = DynamicCast<FrameNode>(blendColumnNode->GetLastChild());
238         CHECK_NULL_VOID(currentFocusColumnNode);
239 
240         UpdateColumnButtonStyles(currentFocusColumnNode, haveFocus_, true);
241     }
242 }
243 
UpdateColumnButtonStyles(const RefPtr<FrameNode> & columnNode,bool haveFocus,bool needMarkDirty)244 void DatePickerPattern::UpdateColumnButtonStyles(
245     const RefPtr<FrameNode>& columnNode, bool haveFocus, bool needMarkDirty)
246 {
247     CHECK_NULL_VOID(columnNode);
248 
249     auto datePickerColumnPattern = columnNode->GetPattern<DatePickerColumnPattern>();
250     CHECK_NULL_VOID(datePickerColumnPattern);
251     datePickerColumnPattern->UpdateColumnButtonFocusState(haveFocus, needMarkDirty);
252 }
253 
GetInnerFocusButtonPaintRect(RoundRect & paintRect,float focusButtonXOffset)254 void DatePickerPattern::GetInnerFocusButtonPaintRect(RoundRect& paintRect, float focusButtonXOffset)
255 {
256     auto host = GetHost();
257     CHECK_NULL_VOID(host);
258 
259     auto geometryNode = host->GetGeometryNode();
260     CHECK_NULL_VOID(geometryNode);
261     auto context = host->GetContext();
262     CHECK_NULL_VOID(context);
263     auto pickerTheme = context->GetTheme<PickerTheme>();
264     CHECK_NULL_VOID(pickerTheme);
265     auto stackNode = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
266     CHECK_NULL_VOID(stackNode);
267     auto buttonNode = DynamicCast<FrameNode>(stackNode->GetFirstChild());
268     CHECK_NULL_VOID(buttonNode);
269     auto focusButtonRect = buttonNode->GetGeometryNode()->GetFrameRect();
270     auto focusSpace = pickerTheme->GetFocusPadding().ConvertToPx();
271     auto stackRenderContext = stackNode->GetRenderContext();
272     CHECK_NULL_VOID(stackRenderContext);
273     auto leftPadding = 0.0f;
274     if (geometryNode->GetPadding()) {
275         leftPadding = geometryNode->GetPadding()->left.value_or(0.0f);
276     }
277     focusButtonRect -=
278         OffsetF(focusSpace - leftPadding, focusSpace - stackRenderContext->GetPaintRectWithoutTransform().GetY());
279     focusButtonRect += SizeF(focusSpace + focusSpace, focusSpace + focusSpace);
280     focusButtonRect += OffsetF(focusButtonXOffset, 0);
281 
282     paintRect.SetRect(focusButtonRect);
283     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS,
284         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()),
285         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()));
286     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS,
287         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()),
288         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()));
289     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS,
290         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()),
291         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()));
292     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS,
293         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()),
294         static_cast<RSScalar>(selectorItemRadius_.ConvertToPx()));
295 }
296 
ColumnPatternInitHapticController()297 void DatePickerPattern::ColumnPatternInitHapticController()
298 {
299     if (!isHapticChanged_) {
300         return;
301     }
302     isHapticChanged_ = false;
303     auto frameNodes = GetAllChildNode();
304     for (auto iter : frameNodes) {
305         auto columnNode = iter.second;
306         if (!columnNode) {
307             continue;
308         }
309         auto columnPattern = columnNode->GetPattern<DatePickerColumnPattern>();
310         if (!columnPattern) {
311             continue;
312         }
313         columnPattern->InitHapticController();
314     }
315 }
316 
ColumnPatternInitHapticController(const RefPtr<FrameNode> & columnNode)317 void DatePickerPattern::ColumnPatternInitHapticController(const RefPtr<FrameNode>& columnNode)
318 {
319     CHECK_NULL_VOID(columnNode);
320     if (!isHapticChanged_) {
321         return;
322     }
323     isHapticChanged_ = false;
324     auto columnPattern = columnNode->GetPattern<DatePickerColumnPattern>();
325     CHECK_NULL_VOID(columnPattern);
326     columnPattern->InitHapticController();
327 }
328 
ColumnPatternStopHaptic()329 void DatePickerPattern::ColumnPatternStopHaptic()
330 {
331     if (!isEnableHaptic_) {
332         return;
333     }
334     auto host = GetHost();
335     CHECK_NULL_VOID(host);
336     auto children = host->GetChildren();
337     for (const auto& child : children) {
338         auto stackNode = DynamicCast<FrameNode>(child);
339         CHECK_NULL_VOID(stackNode);
340         auto blendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
341         CHECK_NULL_VOID(blendNode);
342         auto childNode = blendNode->GetLastChild();
343         CHECK_NULL_VOID(childNode);
344         auto datePickerColumnPattern = DynamicCast<FrameNode>(childNode)->GetPattern<DatePickerColumnPattern>();
345         CHECK_NULL_VOID(datePickerColumnPattern);
346         datePickerColumnPattern->StopHaptic();
347     }
348 }
349 
InitFocusKeyEvent()350 void DatePickerPattern::InitFocusKeyEvent()
351 {
352     auto host = GetHost();
353     CHECK_NULL_VOID(host);
354     auto focusHub = host->GetFocusHub();
355     if (focusHub) {
356         InitOnKeyEvent(focusHub);
357 #ifdef SUPPORT_DIGITAL_CROWN
358         InitOnCrownEvent(focusHub);
359 #endif
360     }
361 }
362 
FlushChildNodes()363 void DatePickerPattern::FlushChildNodes()
364 {
365     auto frameNodes = GetAllChildNode();
366     for (auto it : frameNodes) {
367         CHECK_NULL_VOID(it.second);
368         it.second->MarkModifyDone();
369         it.second->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
370     }
371 }
372 
OnModifyDone()373 void DatePickerPattern::OnModifyDone()
374 {
375     Pattern::CheckLocalized();
376     auto host = GetHost();
377     CHECK_NULL_VOID(host);
378     auto datePickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
379     CHECK_NULL_VOID(datePickerRowLayoutProperty);
380     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
381         ColumnPatternInitHapticController();
382         isHapticChanged_ = false;
383     }
384     if (isFiredDateChange_ && !isForceUpdate_ && (lunar_ == datePickerRowLayoutProperty->GetLunar().value_or(false)) &&
385         !isDateOrderChange_) {
386         isFiredDateChange_ = false;
387         return;
388     }
389     ClearFocus();
390     isForceUpdate_ = false;
391     isDateOrderChange_ = false;
392     InitDisabled();
393     if (ShowMonthDays()) {
394         FlushMonthDaysColumn();
395     } else {
396         FlushColumn();
397     }
398     ShowTitle(GetTitleId());
399     SetChangeCallback([weak = WeakClaim(this)](const RefPtr<FrameNode>& tag, bool add, uint32_t index, bool notify) {
400         auto refPtr = weak.Upgrade();
401         CHECK_NULL_VOID(refPtr);
402         refPtr->HandleColumnChange(tag, add, index, notify);
403     });
404     SetEventCallback([weak = WeakClaim(this), titleId = GetTitleId()](bool refresh) {
405         auto refPtr = weak.Upgrade();
406         CHECK_NULL_VOID(refPtr);
407         refPtr->FireChangeEvent(refresh);
408         if (refresh) {
409             refPtr->ShowTitle(titleId);
410         }
411     });
412     InitFocusKeyEvent();
413     SetDefaultFocus();
414     InitFocusEvent();
415     InitSelectorProps();
416     FlushChildNodes();
417 }
418 
InitDisabled()419 void DatePickerPattern::InitDisabled()
420 {
421     auto host = GetHost();
422     CHECK_NULL_VOID(host);
423     auto eventHub = host->GetEventHub<EventHub>();
424     CHECK_NULL_VOID(eventHub);
425     enabled_ = eventHub->IsEnabled();
426     auto renderContext = host->GetRenderContext();
427     CHECK_NULL_VOID(renderContext);
428     auto opacity = curOpacity_;
429     if (!enabled_) {
430         opacity *= DISABLE_ALPHA;
431         renderContext->UpdateOpacity(opacity);
432     } else if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
433         renderContext->UpdateOpacity(opacity);
434     }
435 
436     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
437         for (const auto& child : host->GetChildren()) {
438             auto stackNode = DynamicCast<FrameNode>(child);
439             CHECK_NULL_VOID(stackNode);
440             auto renderContext = stackNode->GetRenderContext();
441             CHECK_NULL_VOID(renderContext);
442             renderContext->UpdateOpacity(opacity);
443         }
444     }
445     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
446 }
447 
UpdateButtonMargin(const RefPtr<FrameNode> & buttonNode,const RefPtr<DialogTheme> & dialogTheme,const bool isConfirmNode)448 void DatePickerPattern::UpdateButtonMargin(
449     const RefPtr<FrameNode>& buttonNode, const RefPtr<DialogTheme>& dialogTheme, const bool isConfirmNode)
450 {
451     MarginProperty margin;
452     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
453     isRtl = isConfirmNode ? isRtl : !isRtl;
454     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
455         DialogTypeMargin::UpdateDialogMargin(isRtl, margin, dialogTheme, true, ModuleDialogType::DATEPICKER_DIALOG);
456     } else {
457         DialogTypeMargin::UpdateDialogMargin(isRtl, margin, dialogTheme, false, ModuleDialogType::DATEPICKER_DIALOG);
458     }
459     buttonNode->GetLayoutProperty()->UpdateMargin(margin);
460 }
461 
OnFontConfigurationUpdate()462 void DatePickerPattern::OnFontConfigurationUpdate()
463 {
464     CHECK_NULL_VOID(closeDialogEvent_);
465     closeDialogEvent_();
466 }
467 
OnFontScaleConfigurationUpdate()468 void DatePickerPattern::OnFontScaleConfigurationUpdate()
469 {
470     CHECK_NULL_VOID(closeDialogEvent_);
471     closeDialogEvent_();
472 }
473 
UpdateButtonNode(const RefPtr<FrameNode> & buttonNode,const bool isConfirmNode)474 void DatePickerPattern::UpdateButtonNode(const RefPtr<FrameNode>& buttonNode, const bool isConfirmNode)
475 {
476     CHECK_NULL_VOID(buttonNode);
477     auto updateNode = AceType::DynamicCast<FrameNode>(buttonNode->GetFirstChild());
478     CHECK_NULL_VOID(updateNode);
479     auto updateNodeLayout = updateNode->GetLayoutProperty<TextLayoutProperty>();
480     CHECK_NULL_VOID(updateNodeLayout);
481 
482     std::string lettersStr = isConfirmNode ? "common.ok" : "common.cancel";
483     updateNodeLayout->UpdateContent(Localization::GetInstance()->GetEntryLetters(lettersStr));
484 
485     auto pipeline = updateNode->GetContextRefPtr();
486     CHECK_NULL_VOID(pipeline);
487     auto dialogTheme = pipeline->GetTheme<DialogTheme>();
488     CHECK_NULL_VOID(dialogTheme);
489     UpdateButtonMargin(buttonNode, dialogTheme, isConfirmNode);
490     updateNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
491 }
492 
UpdateLunarSwitch()493 void DatePickerPattern::UpdateLunarSwitch()
494 {
495     auto lunarSwitchNode = weakLunarSwitchText_.Upgrade();
496     CHECK_NULL_VOID(lunarSwitchNode);
497     auto context = lunarSwitchNode->GetContextRefPtr();
498     CHECK_NULL_VOID(context);
499     auto pickerTheme = context->GetTheme<PickerTheme>();
500     CHECK_NULL_VOID(pickerTheme);
501 
502     auto lunarSwitchTextLayoutProperty = lunarSwitchNode->GetLayoutProperty<TextLayoutProperty>();
503     CHECK_NULL_VOID(lunarSwitchTextLayoutProperty);
504     lunarSwitchTextLayoutProperty->UpdateContent(
505         Localization::GetInstance()->GetEntryLetters("datepicker.lunarSwitch"));
506     lunarSwitchTextLayoutProperty->UpdateTextColor(pickerTheme->GetLunarSwitchTextColor());
507     lunarSwitchNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
508 }
509 
UpdateDateOrder()510 void DatePickerPattern::UpdateDateOrder()
511 {
512     auto language = AceApplicationInfo::GetInstance().GetLanguage();
513     std::string dateOrder = "y-d-M";
514     if (language != "ug") {
515         DateTimeSequence sequence;
516         OrderResult orderResult = sequence.GetDateOrder(language);
517         dateOrder = orderResult.dateOrder;
518     }
519     SetDateOrder(dateOrder);
520 }
521 
OnLanguageConfigurationUpdate()522 void DatePickerPattern::OnLanguageConfigurationUpdate()
523 {
524     auto buttonConfirmNode = weakButtonConfirm_.Upgrade();
525     UpdateButtonNode(buttonConfirmNode, true);
526 
527     auto buttonCancelNode = weakButtonCancel_.Upgrade();
528     UpdateButtonNode(buttonCancelNode, false);
529 
530     UpdateLunarSwitch();
531     UpdateDateOrder();
532 }
533 
HandleColumnChange(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,bool needNotify)534 void DatePickerPattern::HandleColumnChange(const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, bool needNotify)
535 {
536     CHECK_NULL_VOID(GetHost());
537     std::vector<RefPtr<FrameNode>> tags;
538     if (ShowMonthDays()) {
539         HandleMonthDaysChange(tag, isAdd, index, tags);
540     } else {
541         OnDataLinking(tag, isAdd, index, tags);
542     }
543     for (const auto& tag : tags) {
544         auto iter = std::find_if(datePickerColumns_.begin(), datePickerColumns_.end(), [&tag](const auto& c) {
545             auto column = c.Upgrade();
546             return column && column->GetId() == tag->GetId();
547         });
548         if (iter != datePickerColumns_.end()) {
549             auto datePickerColumn = (*iter).Upgrade();
550             CHECK_NULL_VOID(datePickerColumn);
551             auto datePickerColumnPattern = datePickerColumn->GetPattern<DatePickerColumnPattern>();
552             CHECK_NULL_VOID(datePickerColumnPattern);
553             datePickerColumnPattern->FlushCurrentOptions(isAdd, true, false);
554         }
555     }
556 }
557 
SetEventCallback(EventCallback && value)558 void DatePickerPattern::SetEventCallback(EventCallback&& value)
559 {
560     auto host = GetHost();
561     CHECK_NULL_VOID(host);
562     auto children = host->GetChildren();
563     for (const auto& child : children) {
564         auto stackNode = DynamicCast<FrameNode>(child);
565         CHECK_NULL_VOID(stackNode);
566         auto blendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
567         CHECK_NULL_VOID(blendNode);
568         auto childNode = blendNode->GetLastChild();
569         CHECK_NULL_VOID(childNode);
570         auto datePickerColumnPattern = DynamicCast<FrameNode>(childNode)->GetPattern<DatePickerColumnPattern>();
571         CHECK_NULL_VOID(datePickerColumnPattern);
572         datePickerColumnPattern->SetEventCallback(std::move(value));
573     }
574 }
575 
SetChangeCallback(ColumnChangeCallback && value)576 void DatePickerPattern::SetChangeCallback(ColumnChangeCallback&& value)
577 {
578     auto host = GetHost();
579     CHECK_NULL_VOID(host);
580     auto children = host->GetChildren();
581     for (const auto& child : children) {
582         auto stackNode = DynamicCast<FrameNode>(child);
583         CHECK_NULL_VOID(stackNode);
584         auto blendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
585         CHECK_NULL_VOID(blendNode);
586         auto childNode = blendNode->GetLastChild();
587         CHECK_NULL_VOID(childNode);
588         auto datePickerColumnPattern = DynamicCast<FrameNode>(childNode)->GetPattern<DatePickerColumnPattern>();
589         CHECK_NULL_VOID(datePickerColumnPattern);
590         datePickerColumnPattern->SetChangeCallback(std::move(value));
591     }
592 }
593 
OnColorConfigurationUpdate()594 void DatePickerPattern::OnColorConfigurationUpdate()
595 {
596     auto host = GetHost();
597     CHECK_NULL_VOID(host);
598     host->SetNeedCallChildrenUpdate(false);
599     auto context = host->GetContext();
600     CHECK_NULL_VOID(context);
601     auto pickerTheme = context->GetTheme<PickerTheme>(host->GetThemeScopeId());
602     CHECK_NULL_VOID(pickerTheme);
603     auto dialogTheme = context->GetTheme<DialogTheme>();
604     CHECK_NULL_VOID(dialogTheme);
605     auto disappearStyle = pickerTheme->GetDisappearOptionStyle();
606     auto normalStyle = pickerTheme->GetOptionStyle(false, false);
607     auto pickerProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
608     CHECK_NULL_VOID(pickerProperty);
609     pickerProperty->UpdateColor(GetTextProperties().normalTextStyle_.textColor.value_or(normalStyle.GetTextColor()));
610     pickerProperty->UpdateDisappearColor(
611         GetTextProperties().disappearTextStyle_.textColor.value_or(disappearStyle.GetTextColor()));
612     if (isPicker_) {
613         OnModifyDone();
614         return;
615     }
616     SetBackgroundColor(dialogTheme->GetBackgroundColor());
617     auto buttonTitleNode = buttonTitleNode_.Upgrade();
618     CHECK_NULL_VOID(buttonTitleNode);
619     auto titleLayoutRenderContext = buttonTitleNode->GetRenderContext();
620     CHECK_NULL_VOID(titleLayoutRenderContext);
621     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) ||
622         !titleLayoutRenderContext->IsUniRenderEnabled()) {
623         titleLayoutRenderContext->UpdateBackgroundColor(dialogTheme->GetButtonBackgroundColor());
624     }
625     UpdateTitleTextColor(buttonTitleNode, pickerTheme);
626     UpdateLunarSwitch();
627     OnModifyDone();
628 }
629 
OnThemeScopeUpdate(int32_t themeScopeId)630 bool DatePickerPattern::OnThemeScopeUpdate(int32_t themeScopeId)
631 {
632     bool result = false;
633     auto host = GetHost();
634     CHECK_NULL_RETURN(host, result);
635     host->SetNeedCallChildrenUpdate(false);
636     auto pickerProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
637     CHECK_NULL_RETURN(pickerProperty, result);
638     // The following three attributes will be affected by withTheme.
639     // If they are setted by user, then use the value by user set; Otherwise use the value from withTheme
640     // When the "result" is true, mean to notify the framework to Re-render
641     if ((!pickerProperty->HasColor()) || (!pickerProperty->HasDisappearColor()) ||
642         (!pickerProperty->HasSelectedColor())) {
643         result = true;
644     }
645     OnModifyDone();
646     return result;
647 }
648 
UpdateTitleTextColor(const RefPtr<FrameNode> & buttonTitleNode,const RefPtr<PickerTheme> & pickerTheme)649 void DatePickerPattern::UpdateTitleTextColor(
650     const RefPtr<FrameNode>& buttonTitleNode, const RefPtr<PickerTheme>& pickerTheme)
651 {
652     auto childButton = buttonTitleNode->GetFirstChild();
653     CHECK_NULL_VOID(childButton);
654     auto ButtonNode = DynamicCast<FrameNode>(childButton);
655     CHECK_NULL_VOID(ButtonNode);
656     auto buttonTitleRenderContext = ButtonNode->GetRenderContext();
657     CHECK_NULL_VOID(buttonTitleRenderContext);
658     buttonTitleRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
659     auto childColumn = ButtonNode->GetFirstChild();
660     CHECK_NULL_VOID(childColumn);
661     auto childText = childColumn->GetFirstChild();
662     CHECK_NULL_VOID(childText);
663     auto textTitleNode = DynamicCast<FrameNode>(childText);
664     CHECK_NULL_VOID(textTitleNode);
665     auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
666     CHECK_NULL_VOID(textLayoutProperty);
667     textLayoutProperty->UpdateTextColor(pickerTheme->GetTitleStyle().GetTextColor());
668     if (childColumn->GetChildren().size() > 1) {
669         auto spinner = childColumn->GetLastChild();
670         CHECK_NULL_VOID(spinner);
671         auto spinnerNode = DynamicCast<FrameNode>(spinner);
672         CHECK_NULL_VOID(spinnerNode);
673         auto spinnerRenderProperty = spinnerNode->GetPaintProperty<ImageRenderProperty>();
674         CHECK_NULL_VOID(spinnerRenderProperty);
675         spinnerRenderProperty->UpdateSvgFillColor(pickerTheme->GetTitleStyle().GetTextColor());
676     }
677 }
678 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)679 void DatePickerPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
680 {
681     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
682         auto pattern = wp.Upgrade();
683         CHECK_NULL_RETURN(pattern, false);
684         return pattern->OnKeyEvent(event);
685     };
686     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
687 
688     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
689         auto pattern = wp.Upgrade();
690         if (pattern) {
691             pattern->GetInnerFocusPaintRect(paintRect);
692         }
693     };
694     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
695 }
696 
PaintFocusState()697 void DatePickerPattern::PaintFocusState()
698 {
699     auto host = GetHost();
700     CHECK_NULL_VOID(host);
701 
702     RoundRect focusRect;
703     GetInnerFocusPaintRect(focusRect);
704 
705     auto focusHub = host->GetFocusHub();
706     CHECK_NULL_VOID(focusHub);
707     focusHub->PaintInnerFocusState(focusRect);
708     UpdateFocusButtonState();
709     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
710 }
711 
CalcLeftTotalColumnWidth(const RefPtr<FrameNode> & host,float & leftTotalColumnWidth,float childSize)712 void DatePickerPattern::CalcLeftTotalColumnWidth(
713     const RefPtr<FrameNode>& host, float& leftTotalColumnWidth, float childSize)
714 {
715     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
716     if (isRtl) {
717         for (int32_t index = childSize - 1; index > focusKeyID_; --index) {
718             auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(index));
719             CHECK_NULL_VOID(stackChild);
720             auto geometryNode = stackChild->GetGeometryNode();
721             CHECK_NULL_VOID(geometryNode);
722             leftTotalColumnWidth += geometryNode->GetFrameSize().Width();
723         }
724     } else {
725         for (int32_t index = 0; index < focusKeyID_; ++index) {
726             auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(index));
727             CHECK_NULL_VOID(stackChild);
728             auto geometryNode = stackChild->GetGeometryNode();
729             CHECK_NULL_VOID(geometryNode);
730             leftTotalColumnWidth += geometryNode->GetFrameSize().Width();
731         }
732     }
733 }
734 
GetInnerFocusPaintRect(RoundRect & paintRect)735 void DatePickerPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
736 {
737     auto host = GetHost();
738     CHECK_NULL_VOID(host);
739     auto childSize = 1.0f;
740     if (!ShowMonthDays()) {
741         childSize = static_cast<float>(host->GetChildren().size());
742     }
743     auto leftTotalColumnWidth = 0.0f;
744     CalcLeftTotalColumnWidth(host, leftTotalColumnWidth, childSize);
745     auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
746     CHECK_NULL_VOID(stackChild);
747     auto blendChild = DynamicCast<FrameNode>(stackChild->GetLastChild());
748     CHECK_NULL_VOID(blendChild);
749     auto pickerChild = DynamicCast<FrameNode>(blendChild->GetLastChild());
750     CHECK_NULL_VOID(pickerChild);
751     auto columnWidth = pickerChild->GetGeometryNode()->GetFrameSize().Width();
752     auto pipeline = PipelineBase::GetCurrentContext();
753     CHECK_NULL_VOID(pipeline);
754     auto pickerTheme = pipeline->GetTheme<PickerTheme>();
755     CHECK_NULL_VOID(pickerTheme);
756     if (useButtonFocusArea_) {
757         return GetInnerFocusButtonPaintRect(paintRect, leftTotalColumnWidth);
758     }
759 
760     auto dividerSpacing = pickerTheme->GetDividerSpacing().ConvertToPx();
761     float paintRectWidth = columnWidth - FOCUS_INTERVAL.ConvertToPx() * RATE - LINE_WIDTH.ConvertToPx() * RATE;
762     float paintRectHeight = dividerSpacing - FOCUS_INTERVAL.ConvertToPx() * RATE - LINE_WIDTH.ConvertToPx() * RATE;
763     auto centerX = leftTotalColumnWidth + FOCUS_INTERVAL.ConvertToPx() + LINE_WIDTH.ConvertToPx();
764     auto centerY = (host->GetGeometryNode()->GetFrameSize().Height() - dividerSpacing) / RATE +
765         FOCUS_INTERVAL.ConvertToPx() + LINE_WIDTH.ConvertToPx();
766 
767     paintRect.SetRect(RectF(centerX, centerY, paintRectWidth, paintRectHeight));
768     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
769         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
770     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
771         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
772     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
773         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
774     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
775         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
776 }
777 
OnKeyEvent(const KeyEvent & event)778 bool DatePickerPattern::OnKeyEvent(const KeyEvent& event)
779 {
780     if (event.action != KeyAction::DOWN) {
781         return false;
782     }
783     if (event.code == KeyCode::KEY_DPAD_UP || event.code == KeyCode::KEY_DPAD_DOWN ||
784         event.code == KeyCode::KEY_DPAD_LEFT || event.code == KeyCode::KEY_DPAD_RIGHT ||
785         event.code == KeyCode::KEY_MOVE_HOME || event.code == KeyCode::KEY_MOVE_END) {
786         return HandleDirectionKey(event.code);
787     }
788     return false;
789 }
790 
CheckFocusID(int32_t childSize)791 bool DatePickerPattern::CheckFocusID(int32_t childSize)
792 {
793     int32_t startIndex = 0;
794     int32_t endIndex = 0;
795 
796     if (showTime_ || datePickerMode_ == DatePickerMode::DATE) {
797         startIndex = INDEX_YEAR;
798         endIndex = INDEX_DAY;
799     } else if (datePickerMode_ == DatePickerMode::YEAR_AND_MONTH) {
800         startIndex = INDEX_YEAR;
801         endIndex = INDEX_MONTH;
802     } else if (datePickerMode_ == DatePickerMode::MONTH_AND_DAY) {
803         startIndex = INDEX_MONTH;
804         endIndex = INDEX_DAY;
805     }
806 
807     if (NeedAdaptForAging()) {
808         if (GetCurrentPage() == SECOND_PAGE) {
809             startIndex = INDEX_MONTH;
810             endIndex = INDEX_DAY;
811         } else {
812             if (datePickerMode_ == DatePickerMode::DATE) {
813                 startIndex = INDEX_YEAR;
814                 endIndex = INDEX_YEAR;
815             }
816         }
817     }
818 
819     if (focusKeyID_ < startIndex) {
820         focusKeyID_ = startIndex;
821         return false;
822     } else if (focusKeyID_ > childSize - 1) {
823         focusKeyID_ = childSize - 1;
824         return false;
825     } else if (focusKeyID_ > endIndex) {
826         focusKeyID_ = endIndex;
827         return false;
828     }
829 
830     return true;
831 }
832 
ParseDirectionKey(RefPtr<DatePickerColumnPattern> & pattern,KeyCode & code,uint32_t totalOptionCount,int32_t childSize)833 bool DatePickerPattern::ParseDirectionKey(
834     RefPtr<DatePickerColumnPattern>& pattern, KeyCode& code, uint32_t totalOptionCount, int32_t childSize)
835 {
836     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
837     if (code == KeyCode::KEY_DPAD_UP) {
838         pattern->InnerHandleScroll(false, false);
839         return true;
840     }
841     if (code == KeyCode::KEY_DPAD_DOWN) {
842         pattern->InnerHandleScroll(true, false);
843         return true;
844     }
845     if (code == KeyCode::KEY_MOVE_HOME) {
846         pattern->SetCurrentIndex(1);
847         pattern->InnerHandleScroll(false, false);
848         return true;
849     }
850     if (code == KeyCode::KEY_MOVE_END) {
851         pattern->SetCurrentIndex(totalOptionCount - UNOPTION_COUNT);
852         pattern->InnerHandleScroll(true, false);
853         return true;
854     }
855     if (code == KeyCode::KEY_DPAD_LEFT) {
856         focusKeyID_ = isRtl ? (focusKeyID_ + 1) : (focusKeyID_ - 1);
857         if (!CheckFocusID(childSize)) {
858             return false;
859         }
860         PaintFocusState();
861         return true;
862     }
863     if (code == KeyCode::KEY_DPAD_RIGHT) {
864         focusKeyID_ = isRtl ? (focusKeyID_ - 1) : (focusKeyID_ + 1);
865         if (ShowMonthDays()) {
866             childSize = 1;
867         }
868         if (!CheckFocusID(childSize)) {
869             return false;
870         }
871         PaintFocusState();
872         return true;
873     }
874     return false;
875 }
876 
HandleDirectionKey(KeyCode code)877 bool DatePickerPattern::HandleDirectionKey(KeyCode code)
878 {
879     auto host = GetHost();
880     CHECK_NULL_RETURN(host, false);
881     auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
882     CHECK_NULL_RETURN(stackChild, false);
883     auto childSize = host->GetChildren().size();
884     auto pickerChild = DynamicCast<FrameNode>(stackChild->GetLastChild()->GetLastChild());
885     CHECK_NULL_RETURN(pickerChild, false);
886     auto pattern = pickerChild->GetPattern<DatePickerColumnPattern>();
887     CHECK_NULL_RETURN(pattern, false);
888     auto totalOptionCount = GetOptionCount(pickerChild);
889     if (totalOptionCount == 0) {
890         return false;
891     }
892     return ParseDirectionKey(pattern, code, totalOptionCount, static_cast<int32_t>(childSize));
893 }
894 
GetAllChildNode()895 std::unordered_map<std::string, RefPtr<FrameNode>> DatePickerPattern::GetAllChildNode()
896 {
897     std::unordered_map<std::string, RefPtr<FrameNode>> allChildNode;
898     RefPtr<FrameNode> stackYear;
899     RefPtr<FrameNode> stackMonth;
900     RefPtr<FrameNode> stackDay;
901     OrderAllChildNode(stackYear, stackMonth, stackDay);
902     CHECK_NULL_RETURN(stackYear, allChildNode);
903     CHECK_NULL_RETURN(stackMonth, allChildNode);
904     CHECK_NULL_RETURN(stackDay, allChildNode);
905     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
906     CHECK_NULL_RETURN(blendYear, allChildNode);
907     auto blendMonth = DynamicCast<FrameNode>(stackMonth->GetLastChild());
908     CHECK_NULL_RETURN(blendMonth, allChildNode);
909     auto blendDay = DynamicCast<FrameNode>(stackDay->GetLastChild());
910     CHECK_NULL_RETURN(blendDay, allChildNode);
911     auto yearNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
912     CHECK_NULL_RETURN(yearNode, allChildNode);
913     auto monthNode = DynamicCast<FrameNode>(blendMonth->GetLastChild());
914     CHECK_NULL_RETURN(monthNode, allChildNode);
915     auto dayNode = DynamicCast<FrameNode>(blendDay->GetLastChild());
916     CHECK_NULL_RETURN(dayNode, allChildNode);
917     allChildNode["year"] = yearNode;
918     allChildNode["month"] = monthNode;
919     allChildNode["day"] = dayNode;
920     return allChildNode;
921 }
922 
OrderAllChildNode(RefPtr<FrameNode> & stackYear,RefPtr<FrameNode> & stackMonth,RefPtr<FrameNode> & stackDay)923 void DatePickerPattern::OrderAllChildNode(
924     RefPtr<FrameNode>& stackYear, RefPtr<FrameNode>& stackMonth, RefPtr<FrameNode>& stackDay)
925 {
926     auto host = GetHost();
927     CHECK_NULL_VOID(host);
928     auto children = host->GetChildren();
929     if (children.size() != CHILD_SIZE) {
930         return;
931     }
932 
933     auto processDateNode = [&children](RefPtr<UINode>& first, RefPtr<UINode>& second, RefPtr<UINode>& third) {
934         auto iter = children.begin();
935         first = *iter++;
936         CHECK_NULL_VOID(first);
937         second = *iter++;
938         CHECK_NULL_VOID(second);
939         third = *iter;
940         CHECK_NULL_VOID(third);
941     };
942 
943     RefPtr<UINode> year;
944     RefPtr<UINode> month;
945     RefPtr<UINode> day;
946     if (dateOrder_ == "M-d-y") {
947         processDateNode(month, day, year);
948     } else if (dateOrder_ == "y-d-M") {
949         processDateNode(year, day, month);
950     } else {
951         processDateNode(year, month, day);
952     }
953     stackYear = DynamicCast<FrameNode>(year);
954     stackMonth = DynamicCast<FrameNode>(month);
955     stackDay = DynamicCast<FrameNode>(day);
956 }
957 
FlushColumn()958 void DatePickerPattern::FlushColumn()
959 {
960     auto host = GetHost();
961     CHECK_NULL_VOID(host);
962     auto allChildNode = GetAllChildNode();
963 
964     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
965     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
966     auto lunarDate = dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate()));
967     AdjustLunarDate(lunarDate);
968     std::string language = Localization::GetInstance()->GetLanguage();
969     if (dataPickerRowLayoutProperty->GetLunar().value_or(false) && (strcmp(language.c_str(), "zh") == 0)) {
970         LunarColumnsBuilding(lunarDate);
971     } else {
972         SolarColumnsBuilding(LunarToSolar(lunarDate));
973     }
974 
975     auto yearNode = allChildNode["year"];
976     auto monthNode = allChildNode["month"];
977     auto dayNode = allChildNode["day"];
978     CHECK_NULL_VOID(yearNode);
979     CHECK_NULL_VOID(monthNode);
980     CHECK_NULL_VOID(dayNode);
981     auto yearColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
982     CHECK_NULL_VOID(yearColumnPattern);
983     auto monthColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
984     CHECK_NULL_VOID(monthColumnPattern);
985     auto dayColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
986     CHECK_NULL_VOID(dayColumnPattern);
987 
988     yearColumnPattern->SetShowCount(GetShowCount());
989     monthColumnPattern->SetShowCount(GetShowCount());
990     dayColumnPattern->SetShowCount(GetShowCount());
991     yearColumnPattern->FlushCurrentOptions();
992     monthColumnPattern->FlushCurrentOptions();
993     dayColumnPattern->FlushCurrentOptions();
994     yearNode->MarkModifyDone();
995     monthNode->MarkModifyDone();
996     dayNode->MarkModifyDone();
997     yearNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
998     monthNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
999     dayNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1000 
1001     ShowColumnByDatePickMode();
1002 }
1003 
ShowColumnByDatePickMode()1004 void DatePickerPattern::ShowColumnByDatePickMode()
1005 {
1006     if (GetIsShowInDialog() && (showTime_ || datePickerMode_ == DatePickerMode::DATE)) {
1007         return;
1008     }
1009     RefPtr<FrameNode> stackYear;
1010     RefPtr<FrameNode> stackMonth;
1011     RefPtr<FrameNode> stackDay;
1012     OrderAllChildNode(stackYear, stackMonth, stackDay);
1013     CHECK_NULL_VOID(stackYear);
1014     CHECK_NULL_VOID(stackMonth);
1015     CHECK_NULL_VOID(stackDay);
1016 
1017     if (datePickerMode_ == DatePickerMode::DATE) {
1018         UpdateStackPropVisibility(stackYear, VisibleType::VISIBLE, RATIO_ONE);
1019         UpdateStackPropVisibility(stackMonth, VisibleType::VISIBLE, RATIO_ONE);
1020         UpdateStackPropVisibility(stackDay, VisibleType::VISIBLE, RATIO_ONE);
1021         focusKeyID_ = INDEX_YEAR;
1022     } else if (datePickerMode_ == DatePickerMode::YEAR_AND_MONTH) {
1023         UpdateStackPropVisibility(stackYear, VisibleType::VISIBLE, RATIO_ONE);
1024         UpdateStackPropVisibility(stackMonth, VisibleType::VISIBLE, RATIO_ONE);
1025         UpdateStackPropVisibility(stackDay, VisibleType::GONE, RATIO_ZERO);
1026         focusKeyID_ = INDEX_YEAR;
1027     } else if (datePickerMode_ == DatePickerMode::MONTH_AND_DAY) {
1028         UpdateStackPropVisibility(stackYear, VisibleType::GONE, RATIO_ZERO);
1029         UpdateStackPropVisibility(stackMonth, VisibleType::VISIBLE, RATIO_ONE);
1030         UpdateStackPropVisibility(stackDay, VisibleType::VISIBLE, RATIO_ONE);
1031         focusKeyID_ = INDEX_MONTH;
1032     }
1033 }
1034 
UpdateStackPropVisibility(const RefPtr<FrameNode> & stackNode,const VisibleType visibleType,const int32_t weight)1035 void DatePickerPattern::UpdateStackPropVisibility(const RefPtr<FrameNode>& stackNode,
1036     const VisibleType visibleType, const int32_t weight)
1037 {
1038     for (const auto& child : stackNode->GetChildren()) {
1039         auto frameNodeChild = AceType::DynamicCast<NG::FrameNode>(child);
1040         CHECK_NULL_VOID(frameNodeChild);
1041         auto layoutProperty = frameNodeChild->GetLayoutProperty();
1042         layoutProperty->UpdateVisibility(visibleType);
1043     }
1044     auto stackNodeLayoutProperty = stackNode->GetLayoutProperty<LayoutProperty>();
1045     CHECK_NULL_VOID(stackNodeLayoutProperty);
1046     if ((datePickerMode_ != DatePickerMode::DATE) || !GetIsShowInDialog()) {
1047         stackNodeLayoutProperty->UpdateLayoutWeight(weight);
1048     }
1049 }
1050 
FlushMonthDaysColumn()1051 void DatePickerPattern::FlushMonthDaysColumn()
1052 {
1053     auto host = GetHost();
1054     CHECK_NULL_VOID(host);
1055 
1056     auto children = host->GetChildren();
1057     if (children.size() <= SINGLE_CHILD_SIZE) {
1058         return;
1059     }
1060     auto iter = children.begin();
1061     auto monthDays = (*iter);
1062     CHECK_NULL_VOID(monthDays);
1063     iter++;
1064     auto year = *iter;
1065     CHECK_NULL_VOID(year);
1066     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1067     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
1068     CHECK_NULL_VOID(blendMonthDays);
1069     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
1070     auto stackYear = DynamicCast<FrameNode>(year);
1071     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
1072     CHECK_NULL_VOID(blendYear);
1073     auto yearDaysNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
1074     CHECK_NULL_VOID(monthDaysNode);
1075     CHECK_NULL_VOID(yearDaysNode);
1076     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
1077     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
1078     std::string language = Localization::GetInstance()->GetLanguage();
1079     if (dataPickerRowLayoutProperty->GetLunar().value_or(false) && (strcmp(language.c_str(), "zh") == 0)) {
1080         LunarMonthDaysColumnBuilding(
1081             dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate())));
1082     } else {
1083         SolarMonthDaysColumnsBuilding(
1084             LunarToSolar(dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate()))));
1085     }
1086 
1087     auto monthDaysColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1088     auto yearColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1089     CHECK_NULL_VOID(monthDaysColumnPattern);
1090     CHECK_NULL_VOID(yearColumnPattern);
1091 
1092     monthDaysColumnPattern->SetShowCount(GetShowCount());
1093     yearColumnPattern->SetShowCount(GetShowCount());
1094     monthDaysColumnPattern->FlushCurrentOptions();
1095     yearColumnPattern->FlushCurrentOptions();
1096     monthDaysNode->MarkModifyDone();
1097     yearDaysNode->MarkModifyDone();
1098     monthDaysNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1099     yearDaysNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1100 }
1101 
ReportDateChangeEvent(int32_t nodeId,const std::string & compName,const std::string & eventName,const std::string & eventData)1102 bool DatePickerPattern::ReportDateChangeEvent(int32_t nodeId, const std::string& compName,
1103     const std::string& eventName, const std::string& eventData)
1104 {
1105     auto dataJson = JsonUtil::ParseJsonString(eventData);
1106     CHECK_NULL_RETURN(dataJson, false);
1107     auto params = JsonUtil::Create();
1108     CHECK_NULL_RETURN(params, false);
1109     params->Put("year", static_cast<int32_t>(dataJson->GetUInt("year")));
1110     params->Put("month", static_cast<int32_t>(dataJson->GetUInt("month") + 1)); // month: 1-12
1111     params->Put("day", static_cast<int32_t>(dataJson->GetUInt("day")));
1112     params->Put("hour", static_cast<int32_t>(dataJson->GetUInt("hour")));
1113     params->Put("minute", static_cast<int32_t>(dataJson->GetUInt("minute")));
1114     auto value = JsonUtil::Create();
1115     CHECK_NULL_RETURN(value, false);
1116     value->Put("nodeId", nodeId);
1117     value->Put(compName.c_str(), eventName.c_str());
1118     value->Put("params", params);
1119     UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", value->ToString());
1120     return true;
1121 }
1122 
ReportDateChangeEvent(const std::string & compName,const std::string & eventName,const std::string & eventData)1123 bool DatePickerPattern::ReportDateChangeEvent(const std::string& compName,
1124     const std::string& eventName, const std::string& eventData)
1125 {
1126     if (GetIsShowInDialog()) {
1127         return false;
1128     }
1129     auto host = GetHost();
1130     CHECK_NULL_RETURN(host, false);
1131     return ReportDateChangeEvent(host->GetId(), compName, eventName, eventData);
1132 }
1133 
FireChangeEvent(bool refresh)1134 void DatePickerPattern::FireChangeEvent(bool refresh)
1135 {
1136     if (refresh) {
1137         ReportDateChangeEvent("DatePicker", "onDateChange", GetSelectedObject(true));
1138         auto datePickerEventHub = GetEventHub<DatePickerEventHub>();
1139         CHECK_NULL_VOID(datePickerEventHub);
1140         auto str = GetSelectedObject(true);
1141         auto info = std::make_shared<DatePickerChangeEvent>(str);
1142         datePickerEventHub->FireChangeEvent(info.get());
1143         datePickerEventHub->FireDialogChangeEvent(str);
1144         firedDateStr_ = str;
1145     }
1146 }
1147 
ShowTitle(int32_t titleId)1148 void DatePickerPattern::ShowTitle(int32_t titleId)
1149 {
1150     if (HasTitleNode() && isFocus_) {
1151         auto textTitleNode = FrameNode::GetOrCreateFrameNode(
1152             V2::TEXT_ETS_TAG, titleId, []() { return AceType::MakeRefPtr<TextPattern>(); });
1153         CHECK_NULL_VOID(textTitleNode);
1154         auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
1155         CHECK_NULL_VOID(textLayoutProperty);
1156 
1157         if (!showTime_ && (datePickerMode_ != DatePickerMode::DATE)) {
1158             auto dateStr = GetVisibleColumnsText();
1159             textLayoutProperty->UpdateContent(dateStr);
1160         } else {
1161             auto dateStr = GetCurrentDate();
1162             textLayoutProperty->UpdateContent(dateStr.ToString(false));
1163         }
1164         textTitleNode->MarkModifyDone();
1165         textTitleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1166     }
1167 }
1168 
GetVisibleColumnsText()1169 std::string DatePickerPattern::GetVisibleColumnsText()
1170 {
1171     std::string result = "";
1172     auto allChildNode = GetAllChildNode();
1173     auto yearNode = allChildNode["year"];
1174     auto monthNode = allChildNode["month"];
1175     auto dayNode = allChildNode["day"];
1176     CHECK_NULL_RETURN(yearNode, "");
1177     CHECK_NULL_RETURN(monthNode, "");
1178     CHECK_NULL_RETURN(dayNode, "");
1179     if (datePickerMode_ == DatePickerMode::YEAR_AND_MONTH) {
1180         GetColumnText(yearNode, result);
1181     }
1182     GetColumnText(monthNode, result);
1183     if (datePickerMode_ == DatePickerMode::MONTH_AND_DAY) {
1184         GetColumnText(dayNode, result);
1185     }
1186     return result;
1187 }
1188 
GetColumnText(const RefPtr<FrameNode> & columnNode,std::string & result)1189 void DatePickerPattern::GetColumnText(const RefPtr<FrameNode>& columnNode, std::string& result)
1190 {
1191     auto columnPattern = columnNode->GetPattern<DatePickerColumnPattern>();
1192     CHECK_NULL_VOID(columnPattern);
1193     auto index = columnPattern->GetCurrentIndex();
1194     auto options = columnPattern->GetOptions();
1195     auto it = options.find(columnNode);
1196     if (it != options.end() && index >= 0 && index < it->second.size()) {
1197         auto date = it->second.at(index);
1198         result.append(GetFormatString(date));
1199     }
1200 }
1201 
OnDataLinking(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)1202 void DatePickerPattern::OnDataLinking(
1203     const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
1204 {
1205     auto allChildNode = GetAllChildNode();
1206     auto yearNode = allChildNode["year"];
1207     auto monthNode = allChildNode["month"];
1208     auto dayNode = allChildNode["day"];
1209     CHECK_NULL_VOID(yearNode);
1210     CHECK_NULL_VOID(monthNode);
1211     CHECK_NULL_VOID(dayNode);
1212     if (tag == yearNode) {
1213         HandleYearChange(isAdd, index, resultTags);
1214         return;
1215     }
1216 
1217     if (tag == monthNode) {
1218         HandleMonthChange(isAdd, index, resultTags);
1219         return;
1220     }
1221 
1222     if (tag == dayNode) {
1223         HandleDayChange(isAdd, index, resultTags);
1224         return;
1225     }
1226 }
1227 
HandleMonthDaysChange(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)1228 void DatePickerPattern::HandleMonthDaysChange(
1229     const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
1230 {
1231     auto host = GetHost();
1232     CHECK_NULL_VOID(host);
1233 
1234     auto children = host->GetChildren();
1235     if (children.size() <= SINGLE_CHILD_SIZE) {
1236         return;
1237     }
1238     auto iter = children.begin();
1239     auto monthDays = (*iter);
1240     CHECK_NULL_VOID(monthDays);
1241 
1242     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1243     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
1244     CHECK_NULL_VOID(blendMonthDays);
1245     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
1246     if (tag != monthDaysNode) {
1247         return;
1248     }
1249 
1250     if (IsShowLunar()) {
1251         HandleLunarMonthDaysChange(isAdd, index);
1252     } else {
1253         HandleSolarMonthDaysChange(isAdd, index);
1254     }
1255 
1256     resultTags.emplace_back(monthDaysNode);
1257 }
1258 
GetSelectedObject(bool isColumnChange,int status) const1259 std::string DatePickerPattern::GetSelectedObject(bool isColumnChange, int status) const
1260 {
1261     auto date = selectedDate_;
1262     if (isColumnChange) {
1263         date = GetCurrentDate();
1264     }
1265     // W3C's month is between 0 to 11, need to reduce one.
1266     auto getMonth = date.GetMonth();
1267     getMonth = getMonth > 0 ? getMonth - 1 : 0;
1268     date.SetMonth(getMonth);
1269 
1270     auto dateTimeString = std::string("{\"year\":") + std::to_string(date.GetYear()) +
1271                           ",\"month\":" + std::to_string(date.GetMonth()) + ",\"day\":" + std::to_string(date.GetDay());
1272     auto pickTime = PickerTime::Current();
1273     if (showTime_) {
1274         auto host = GetHost();
1275         CHECK_NULL_RETURN(host, date.ToString(true, status));
1276         if (showMonthDays_) {
1277             auto pickerRow = host->GetParent();
1278             CHECK_NULL_RETURN(pickerRow, date.ToString(true, status));
1279             auto timeNode = AceType::DynamicCast<FrameNode>(pickerRow->GetChildAtIndex(1));
1280             CHECK_NULL_RETURN(timeNode, date.ToString(true, status));
1281             auto timePickerPattern = timeNode->GetPattern<TimePickerRowPattern>();
1282             CHECK_NULL_RETURN(timePickerPattern, date.ToString(true, status));
1283             pickTime = timePickerPattern->GetCurrentTime();
1284         } else {
1285             auto pickerStack = host->GetParent();
1286             CHECK_NULL_RETURN(pickerStack, date.ToString(true, status));
1287             auto pickerRow = pickerStack->GetLastChild();
1288             CHECK_NULL_RETURN(pickerRow, date.ToString(true, status));
1289             auto timeNode = AceType::DynamicCast<FrameNode>(pickerRow->GetChildAtIndex(1));
1290             CHECK_NULL_RETURN(timeNode, date.ToString(true, status));
1291             auto timePickerPattern = timeNode->GetPattern<TimePickerRowPattern>();
1292             CHECK_NULL_RETURN(timePickerPattern, date.ToString(true, status));
1293             pickTime = timePickerPattern->GetCurrentTime();
1294         }
1295     }
1296     dateTimeString += std::string(",\"hour\":") + std::to_string(pickTime.GetHour()) +
1297                       ",\"minute\":" + std::to_string(pickTime.GetMinute()) + ",\"status\":" + std::to_string(status) +
1298                       "}";
1299     return dateTimeString;
1300 }
1301 
HandleDayChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)1302 void DatePickerPattern::HandleDayChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
1303 {
1304     auto allChildNode = GetAllChildNode();
1305     auto yearNode = allChildNode["year"];
1306     auto monthNode = allChildNode["month"];
1307     auto dayNode = allChildNode["day"];
1308     CHECK_NULL_VOID(yearNode);
1309     CHECK_NULL_VOID(monthNode);
1310     CHECK_NULL_VOID(dayNode);
1311     if (IsShowLunar()) {
1312         HandleLunarDayChange(isAdd, index);
1313     } else {
1314         HandleSolarDayChange(isAdd, index);
1315     }
1316     resultTags.emplace_back(yearNode);
1317     resultTags.emplace_back(monthNode);
1318     resultTags.emplace_back(dayNode);
1319 }
1320 
HandleSolarDayChange(bool isAdd,uint32_t index)1321 void DatePickerPattern::HandleSolarDayChange(bool isAdd, uint32_t index)
1322 {
1323     auto allChildNode = GetAllChildNode();
1324     auto yearNode = allChildNode["year"];
1325     auto monthNode = allChildNode["month"];
1326     auto dayNode = allChildNode["day"];
1327 
1328     CHECK_NULL_VOID(yearNode);
1329     CHECK_NULL_VOID(monthNode);
1330     CHECK_NULL_VOID(dayNode);
1331     auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
1332     auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
1333     auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
1334     CHECK_NULL_VOID(yearDatePickerColumnPattern);
1335     CHECK_NULL_VOID(monthDatePickerColumnPattern);
1336     CHECK_NULL_VOID(dayDatePickerColumnPattern);
1337 
1338     auto date = GetCurrentDate();
1339     if (isAdd && index == 0) {
1340         IncreaseLinkageYearMonth(date);
1341     }
1342     auto getOptionCount = GetOptionCount(dayNode);
1343     getOptionCount = getOptionCount > 0 ? getOptionCount - 1 : 0;
1344     if (!isAdd &&
1345         dayDatePickerColumnPattern->GetCurrentIndex() == getOptionCount) { // last index is count - 1
1346         ReduceLinkageYearMonth(date);
1347     }
1348     uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
1349     if (date.GetDay() > maxDay) {
1350         date.SetDay(maxDay);
1351     }
1352     AdjustSolarDate(date);
1353     SolarColumnsBuilding(date);
1354 }
1355 
HandleLunarDayChange(bool isAdd,uint32_t index)1356 void DatePickerPattern::HandleLunarDayChange(bool isAdd, uint32_t index)
1357 {
1358     if (isAdd) {
1359         HandleAddLunarDayChange(index);
1360     } else {
1361         HandleReduceLunarDayChange(index);
1362     }
1363 }
1364 
IncreaseLinkageYearMonth(PickerDate & date)1365 void DatePickerPattern::IncreaseLinkageYearMonth(PickerDate& date)
1366 {
1367     date.SetMonth(date.GetMonth() + 1); // add to next month
1368     if (date.GetMonth() > 12) {         // invalidate month, max month is 12
1369         date.SetMonth(1);               // first month is 1
1370         if (datePickerMode_ != DatePickerMode::MONTH_AND_DAY) {
1371             date.SetYear(date.GetYear() + 1); // add to next year
1372             if (date.GetYear() > endDateSolar_.GetYear()) {
1373                 date.SetYear(startDateSolar_.GetYear());
1374             }
1375         }
1376     }
1377 }
1378 
ReduceLinkageYearMonth(PickerDate & date)1379 void DatePickerPattern::ReduceLinkageYearMonth(PickerDate& date)
1380 {
1381     auto getMonth = date.GetMonth();
1382     getMonth = getMonth > 0 ? getMonth - 1 : 0;
1383     date.SetMonth(getMonth);           // reduce to previous month
1384     if (date.GetMonth() == 0) {        // min month is 1, invalidate
1385         date.SetMonth(MONTH_DECEMBER); // set to be the last month
1386         if (datePickerMode_ != DatePickerMode::MONTH_AND_DAY) {
1387             auto getYear = date.GetYear();
1388             getYear = getYear > 0 ? getYear - 1 : 0;
1389             date.SetYear(getYear); // reduce to previous year
1390             if (date.GetYear() < startDateSolar_.GetYear()) {
1391                 date.SetYear(endDateSolar_.GetYear());
1392             }
1393         }
1394     }
1395     date.SetDay(PickerDate::GetMaxDay(date.GetYear(), date.GetMonth())); // reduce to previous month's last day
1396 }
1397 
HandleReduceLunarDayChange(uint32_t index)1398 void DatePickerPattern::HandleReduceLunarDayChange(uint32_t index)
1399 {
1400     auto allChildNode = GetAllChildNode();
1401     auto yearNode = allChildNode["year"];
1402     auto monthNode = allChildNode["month"];
1403     auto dayNode = allChildNode["day"];
1404 
1405     CHECK_NULL_VOID(yearNode);
1406     CHECK_NULL_VOID(monthNode);
1407     CHECK_NULL_VOID(dayNode);
1408 
1409     auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
1410     auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
1411     auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
1412 
1413     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1414     auto lunarDate = GetCurrentLunarDate(nowLunarYear);
1415     uint32_t lunarLeapMonth = 0;
1416     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
1417     auto getOptionCount = GetOptionCount(dayNode);
1418     getOptionCount = getOptionCount > 0 ? getOptionCount - 1 : 0;
1419     if (dayDatePickerColumnPattern->GetCurrentIndex() == getOptionCount) { // max index is count - 1
1420         if (monthDatePickerColumnPattern->GetCurrentIndex() == 0) {
1421             lunarDate.year = lunarDate.year > 0 ? lunarDate.year - 1 : 0; // reduce to previous year
1422             if (lunarDate.year < startDateLunar_.year) {
1423                 lunarDate.year = endDateLunar_.year;
1424             }
1425             lunarDate.month = 12; // set to be previous year's max month
1426             lunarDate.isLeapMonth = false;
1427             if (LunarCalculator::GetLunarLeapMonth(lunarDate.year) == 12) { // leap 12th month
1428                 lunarDate.isLeapMonth = true;
1429             }
1430             lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1431         } else {
1432             if (lunarDate.isLeapMonth) {
1433                 lunarDate.isLeapMonth = false;
1434             } else if (!hasLeapMonth) {
1435                 lunarDate.month = lunarDate.month - 1;          // reduce to previous month
1436             } else if (lunarLeapMonth == lunarDate.month - 1) { // leap month is previous month
1437                 lunarDate.isLeapMonth = true;
1438                 lunarDate.month = lunarLeapMonth;
1439             } else {
1440                 lunarDate.month = lunarDate.month - 1; // reduce to previous month
1441             }
1442             lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1443         }
1444     }
1445 
1446     AdjustLunarDate(lunarDate);
1447     LunarColumnsBuilding(lunarDate);
1448 }
1449 
HandleAddLunarDayChange(uint32_t index)1450 void DatePickerPattern::HandleAddLunarDayChange(uint32_t index)
1451 {
1452     auto allChildNode = GetAllChildNode();
1453     auto yearNode = allChildNode["year"];
1454     auto monthNode = allChildNode["month"];
1455     auto dayNode = allChildNode["day"];
1456 
1457     CHECK_NULL_VOID(yearNode);
1458     CHECK_NULL_VOID(monthNode);
1459     CHECK_NULL_VOID(dayNode);
1460 
1461     auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
1462     auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
1463     auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
1464 
1465     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1466     auto lunarDate = GetCurrentLunarDate(nowLunarYear);
1467     uint32_t lunarLeapMonth = 0;
1468     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
1469     if (index == 0) {
1470         auto getOptionCount = GetOptionCount(monthNode);
1471         getOptionCount = getOptionCount > 0 ? getOptionCount - 1 : 0;
1472         if (monthDatePickerColumnPattern->GetCurrentIndex() == getOptionCount) {     // max index is count - 1
1473             lunarDate.year = lunarDate.year + 1; // add to next year
1474             if (lunarDate.year > endDateLunar_.year) {
1475                 lunarDate.year = startDateLunar_.year;
1476             }
1477             lunarDate.month = 1; // first month
1478             lunarDate.isLeapMonth = false;
1479         } else {
1480             if (lunarDate.isLeapMonth) {
1481                 lunarDate.month = lunarDate.month + 1; // add to next month
1482                 lunarDate.isLeapMonth = false;
1483             } else if (!hasLeapMonth) {
1484                 lunarDate.month = lunarDate.month + 1; // add to next month
1485             } else if (lunarLeapMonth == lunarDate.month) {
1486                 lunarDate.isLeapMonth = true;
1487             } else {
1488                 lunarDate.month = lunarDate.month + 1; // add to next month
1489             }
1490         }
1491     }
1492 
1493     AdjustLunarDate(lunarDate);
1494     LunarColumnsBuilding(lunarDate);
1495 }
1496 
HandleSolarMonthDaysChange(bool isAdd,uint32_t index)1497 void DatePickerPattern::HandleSolarMonthDaysChange(bool isAdd, uint32_t index)
1498 {
1499     auto host = GetHost();
1500     CHECK_NULL_VOID(host);
1501 
1502     auto children = host->GetChildren();
1503     if (children.size() <= SINGLE_CHILD_SIZE) {
1504         return;
1505     }
1506     auto iter = children.begin();
1507     auto monthDays = (*iter);
1508     CHECK_NULL_VOID(monthDays);
1509     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1510     CHECK_NULL_VOID(stackMonthDays);
1511     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
1512     CHECK_NULL_VOID(blendMonthDays);
1513     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
1514     CHECK_NULL_VOID(monthDaysNode);
1515     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1516     CHECK_NULL_VOID(monthDaysDatePickerColumnPattern);
1517 
1518     auto date = GetCurrentDate();
1519 
1520     if (isAdd && index == 0) {
1521         // add to next year
1522         date.SetYear(date.GetYear() + 1); // add to next year
1523         if (date.GetYear() > endDateSolar_.GetYear()) {
1524             date.SetYear(startDateSolar_.GetYear());
1525         }
1526     }
1527     auto getOptionCount = GetOptionCount(monthDaysNode);
1528     getOptionCount = getOptionCount > 0 ? getOptionCount - 1 : 0;
1529     if (!isAdd && monthDaysDatePickerColumnPattern->GetCurrentIndex() == getOptionCount) {
1530         // reduce to previous year
1531         auto getYear = date.GetYear();
1532         getYear = getYear > 0 ? getYear - 1 : 0;
1533         date.SetYear(getYear);
1534         if (date.GetYear() < startDateSolar_.GetYear()) {
1535             date.SetYear(endDateSolar_.GetYear());
1536         }
1537         // reduce to previous year's last day
1538         date.SetMonth(MAX_MONTH);
1539         date.SetDay(PickerDate::GetMaxDay(date.GetYear(), date.GetMonth()));
1540     }
1541     uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
1542     if (date.GetDay() > maxDay) {
1543         date.SetDay(maxDay);
1544     }
1545     AdjustSolarDate(date);
1546     SolarMonthDaysColumnsBuilding(date);
1547 }
1548 
HandleLunarMonthDaysChange(bool isAdd,uint32_t index)1549 void DatePickerPattern::HandleLunarMonthDaysChange(bool isAdd, uint32_t index)
1550 {
1551     if (isAdd) {
1552         HandleAddLunarMonthDaysChange(index);
1553     } else {
1554         HandleReduceLunarMonthDaysChange(index);
1555     }
1556 }
1557 
HandleAddLunarMonthDaysChange(uint32_t index)1558 void DatePickerPattern::HandleAddLunarMonthDaysChange(uint32_t index)
1559 {
1560     auto host = GetHost();
1561     CHECK_NULL_VOID(host);
1562 
1563     auto children = host->GetChildren();
1564     if (children.size() <= SINGLE_CHILD_SIZE) {
1565         return;
1566     }
1567     auto iter = children.begin();
1568     auto monthDays = (*iter);
1569     CHECK_NULL_VOID(monthDays);
1570     iter++;
1571     auto year = *iter;
1572     CHECK_NULL_VOID(year);
1573     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1574     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
1575     CHECK_NULL_VOID(blendMonthDays);
1576     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
1577     auto stackYear = DynamicCast<FrameNode>(year);
1578     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
1579     CHECK_NULL_VOID(blendYear);
1580     auto yearDaysNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
1581     CHECK_NULL_VOID(monthDaysNode);
1582     CHECK_NULL_VOID(yearDaysNode);
1583 
1584     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1585     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1586 
1587     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1588     auto lunarDate = GetCurrentLunarDateByMonthDaysColumn(nowLunarYear);
1589     if (index == 0) {
1590         lunarDate.year = lunarDate.year + 1; // add to next year
1591         if (lunarDate.year > endDateLunar_.year) {
1592             lunarDate.year = startDateLunar_.year;
1593         }
1594         lunarDate.month = 1;
1595         lunarDate.isLeapMonth = false;
1596     }
1597 
1598     AdjustLunarDate(lunarDate);
1599     LunarMonthDaysColumnBuilding(lunarDate);
1600 }
1601 
HandleReduceLunarMonthDaysChange(uint32_t index)1602 void DatePickerPattern::HandleReduceLunarMonthDaysChange(uint32_t index)
1603 {
1604     auto host = GetHost();
1605     CHECK_NULL_VOID(host);
1606 
1607     auto children = host->GetChildren();
1608     if (children.size() <= SINGLE_CHILD_SIZE) {
1609         return;
1610     }
1611     auto iter = children.begin();
1612     auto monthDays = (*iter);
1613     CHECK_NULL_VOID(monthDays);
1614     iter++;
1615     auto year = *iter;
1616     CHECK_NULL_VOID(year);
1617     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1618     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
1619     CHECK_NULL_VOID(blendMonthDays);
1620     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
1621     auto stackYear = DynamicCast<FrameNode>(year);
1622     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
1623     CHECK_NULL_VOID(blendYear);
1624     auto yearDaysNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
1625     CHECK_NULL_VOID(monthDaysNode);
1626     CHECK_NULL_VOID(yearDaysNode);
1627 
1628     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1629     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1630     CHECK_NULL_VOID(monthDaysDatePickerColumnPattern);
1631     CHECK_NULL_VOID(yearDatePickerColumnPattern);
1632 
1633     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1634     auto lunarDate = GetCurrentLunarDateByMonthDaysColumn(nowLunarYear);
1635     auto getOptionCount = GetOptionCount(monthDaysNode);
1636     getOptionCount = getOptionCount > 0 ? getOptionCount - 1 : 0;
1637     if (monthDaysDatePickerColumnPattern->GetCurrentIndex() == getOptionCount) {
1638         lunarDate.year = lunarDate.year > 0 ? lunarDate.year - 1 : 0; // reduce to previous year
1639         if (lunarDate.year < startDateLunar_.year) {
1640             lunarDate.year = endDateLunar_.year;
1641         }
1642         lunarDate.month = MAX_MONTH; // set to be previous year's max month
1643         lunarDate.isLeapMonth = false;
1644         if (LunarCalculator::GetLunarLeapMonth(lunarDate.year) == 12) { // leap 12th month
1645             lunarDate.isLeapMonth = true;
1646         }
1647         lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1648     }
1649 
1650     AdjustLunarDate(lunarDate);
1651     LunarMonthDaysColumnBuilding(lunarDate);
1652 }
1653 
HandleYearChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)1654 void DatePickerPattern::HandleYearChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
1655 {
1656     auto allChildNode = GetAllChildNode();
1657     auto yearNode = allChildNode["year"];
1658     auto monthNode = allChildNode["month"];
1659     auto dayNode = allChildNode["day"];
1660 
1661     CHECK_NULL_VOID(yearNode);
1662     CHECK_NULL_VOID(monthNode);
1663     CHECK_NULL_VOID(dayNode);
1664     if (IsShowLunar()) {
1665         HandleLunarYearChange(isAdd, index);
1666     } else {
1667         HandleSolarYearChange(isAdd, index);
1668     }
1669     resultTags.emplace_back(yearNode);
1670     resultTags.emplace_back(monthNode);
1671     resultTags.emplace_back(dayNode);
1672 }
1673 
HandleMonthChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)1674 void DatePickerPattern::HandleMonthChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
1675 {
1676     auto allChildNode = GetAllChildNode();
1677     auto yearNode = allChildNode["year"];
1678     auto monthNode = allChildNode["month"];
1679     auto dayNode = allChildNode["day"];
1680 
1681     CHECK_NULL_VOID(yearNode);
1682     CHECK_NULL_VOID(monthNode);
1683     CHECK_NULL_VOID(dayNode);
1684     if (IsShowLunar()) {
1685         HandleLunarMonthChange(isAdd, index);
1686     } else {
1687         HandleSolarMonthChange(isAdd, index);
1688     }
1689     resultTags.emplace_back(yearNode);
1690     resultTags.emplace_back(monthNode);
1691     resultTags.emplace_back(dayNode);
1692 }
1693 
HandleSolarMonthChange(bool isAdd,uint32_t index)1694 void DatePickerPattern::HandleSolarMonthChange(bool isAdd, uint32_t index)
1695 {
1696     auto date = GetCurrentDate();
1697     if (datePickerMode_ != DatePickerMode::MONTH_AND_DAY) {
1698         if (isAdd && date.GetMonth() == 1) {  // first month is 1
1699             date.SetYear(date.GetYear() + 1); // add 1 year, the next year
1700             if (date.GetYear() > endDateSolar_.GetYear()) {
1701                 date.SetYear(startDateSolar_.GetYear());
1702             }
1703         }
1704         if (!isAdd && date.GetMonth() == 12) { // the last month is 12
1705             auto getYear = date.GetYear();
1706             getYear = getYear > 0 ? getYear - 1 : 0;
1707             date.SetYear(getYear);  // reduce 1 year, the previous year
1708             if (date.GetYear() < startDateSolar_.GetYear()) {
1709                 date.SetYear(endDateSolar_.GetYear());
1710             }
1711         }
1712     }
1713     uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
1714     if (date.GetDay() > maxDay) {
1715         date.SetDay(maxDay);
1716     }
1717     AdjustSolarDate(date);
1718     SolarColumnsBuilding(date);
1719 }
1720 
HandleLunarMonthChange(bool isAdd,uint32_t index)1721 void DatePickerPattern::HandleLunarMonthChange(bool isAdd, uint32_t index)
1722 {
1723     auto allChildNode = GetAllChildNode();
1724     auto yearNode = allChildNode["year"];
1725     auto monthNode = allChildNode["month"];
1726     auto dayNode = allChildNode["day"];
1727 
1728     CHECK_NULL_VOID(yearNode);
1729     CHECK_NULL_VOID(monthNode);
1730     CHECK_NULL_VOID(dayNode);
1731 
1732     auto yearColumn = yearNode->GetPattern<DatePickerColumnPattern>();
1733     CHECK_NULL_VOID(yearColumn);
1734     uint32_t nowLunarYear = startDateLunar_.year + yearColumn->GetCurrentIndex();
1735     auto lunarDate = GetCurrentLunarDate(nowLunarYear);
1736     if (isAdd && index == 0) {
1737         lunarDate.year = lunarDate.year + 1; // add to next year
1738         if (lunarDate.year > endDateLunar_.year) {
1739             lunarDate.year = startDateLunar_.year;
1740         }
1741     }
1742     auto getOptionCount = GetOptionCount(monthNode);
1743     getOptionCount = getOptionCount > 0 ? getOptionCount - 1 : 0;
1744     if (!isAdd && index == getOptionCount) {
1745         lunarDate.year = lunarDate.year > 0 ? lunarDate.year - 1 : 0; // reduce to previous year
1746         if (lunarDate.year < startDateLunar_.year) {
1747             lunarDate.year = endDateLunar_.year;
1748         }
1749     }
1750     uint32_t lunarLeapMonth = 0;
1751     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
1752     if (!hasLeapMonth && lunarDate.isLeapMonth) {
1753         lunarDate.isLeapMonth = false;
1754     }
1755     uint32_t maxDay = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1756     if (lunarDate.day > maxDay) {
1757         lunarDate.day = maxDay;
1758     }
1759 
1760     AdjustLunarDate(lunarDate);
1761     LunarColumnsBuilding(lunarDate);
1762 }
1763 
HandleLunarYearChange(bool isAdd,uint32_t index)1764 void DatePickerPattern::HandleLunarYearChange(bool isAdd, uint32_t index)
1765 {
1766     auto allChildNode = GetAllChildNode();
1767     auto yearNode = allChildNode["year"];
1768     CHECK_NULL_VOID(yearNode);
1769     auto yearColumn = DynamicCast<FrameNode>(yearNode);
1770     uint32_t lastYearIndex = index;
1771     auto optionCount = GetOptionCount(yearColumn);
1772     if (isAdd) { // need reduce one index
1773         auto countAndIndex = optionCount + lastYearIndex;
1774         countAndIndex = countAndIndex > 0 ? countAndIndex - 1 : 0;
1775         lastYearIndex = optionCount != 0 ? countAndIndex % optionCount : 0;
1776     } else { // need add one index
1777         lastYearIndex = optionCount != 0 ? (GetOptionCount(yearColumn) + lastYearIndex + 1) % optionCount : 0;
1778     }
1779     uint32_t lastLunarYear = startDateLunar_.year + lastYearIndex;
1780     auto lunarDate = GetCurrentLunarDate(lastLunarYear);
1781     uint32_t nowLeapMonth = 0;
1782     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, nowLeapMonth);
1783     if (!hasLeapMonth && lunarDate.isLeapMonth) {
1784         lunarDate.isLeapMonth = false;
1785     }
1786     uint32_t nowMaxDay = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1787     if (lunarDate.day > nowMaxDay) {
1788         lunarDate.day = nowMaxDay;
1789     }
1790 
1791     AdjustLunarDate(lunarDate);
1792     LunarColumnsBuilding(lunarDate);
1793 }
1794 
GetCurrentLunarDate(uint32_t lunarYear) const1795 LunarDate DatePickerPattern::GetCurrentLunarDate(uint32_t lunarYear) const
1796 {
1797     LunarDate lunarResult;
1798     RefPtr<FrameNode> stackYear;
1799     RefPtr<FrameNode> stackMonth;
1800     RefPtr<FrameNode> stackDay;
1801     OrderCurrentLunarDate(stackYear, stackMonth, stackDay);
1802     CHECK_NULL_RETURN(stackYear, lunarResult);
1803     CHECK_NULL_RETURN(stackMonth, lunarResult);
1804     CHECK_NULL_RETURN(stackDay, lunarResult);
1805     auto yearColumn = DynamicCast<FrameNode>(stackYear->GetLastChild()->GetLastChild());
1806     CHECK_NULL_RETURN(yearColumn, lunarResult);
1807     auto monthColumn = DynamicCast<FrameNode>(stackMonth->GetLastChild()->GetLastChild());
1808     CHECK_NULL_RETURN(monthColumn, lunarResult);
1809     auto dayColumn = DynamicCast<FrameNode>(stackDay->GetLastChild()->GetLastChild());
1810     CHECK_NULL_RETURN(dayColumn, lunarResult);
1811     auto yearDatePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1812     CHECK_NULL_RETURN(yearDatePickerColumnPattern, lunarResult);
1813     auto monthDatePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1814     CHECK_NULL_RETURN(monthDatePickerColumnPattern, lunarResult);
1815     auto dayDatePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1816     CHECK_NULL_RETURN(dayDatePickerColumnPattern, lunarResult);
1817     uint32_t lunarLeapMonth = 0;
1818     bool hasLeapMonth = GetLunarLeapMonth(lunarYear, lunarLeapMonth);
1819     lunarResult.isLeapMonth = false;
1820     if (!hasLeapMonth) {
1821         lunarResult.month =
1822             monthDatePickerColumnPattern->GetCurrentIndex() + 1; // month from 1 to 12, index from 0 to 11
1823     } else {
1824         if (monthDatePickerColumnPattern->GetCurrentIndex() == lunarLeapMonth) {
1825             lunarResult.isLeapMonth = true;
1826             lunarResult.month = lunarLeapMonth;
1827         } else if (monthDatePickerColumnPattern->GetCurrentIndex() < lunarLeapMonth) {
1828             lunarResult.month =
1829                 monthDatePickerColumnPattern->GetCurrentIndex() + 1; // month start from 1, index start from 0
1830         } else {
1831             lunarResult.month = monthDatePickerColumnPattern->GetCurrentIndex();
1832         }
1833     }
1834     lunarResult.year = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1835     lunarResult.day = dayDatePickerColumnPattern->GetCurrentIndex() + 1; // day start form 1, index start from 0
1836     return lunarResult;
1837 }
1838 
OrderCurrentLunarDate(RefPtr<FrameNode> & stackYear,RefPtr<FrameNode> & stackMonth,RefPtr<FrameNode> & stackDay) const1839 void DatePickerPattern::OrderCurrentLunarDate(
1840     RefPtr<FrameNode>& stackYear, RefPtr<FrameNode>& stackMonth, RefPtr<FrameNode>& stackDay) const
1841 {
1842     auto host = GetHost();
1843     CHECK_NULL_VOID(host);
1844     auto children = host->GetChildren();
1845     auto processDateNode = [&children](RefPtr<UINode>& first, RefPtr<UINode>& second, RefPtr<UINode>& third) {
1846         auto iter = children.begin();
1847         first = *iter++;
1848         CHECK_NULL_VOID(first);
1849         second = *iter++;
1850         CHECK_NULL_VOID(second);
1851         third = *iter;
1852         CHECK_NULL_VOID(third);
1853     };
1854     RefPtr<UINode> year;
1855     RefPtr<UINode> month;
1856     RefPtr<UINode> day;
1857     if (dateOrder_ == "M-d-y") {
1858         processDateNode(month, day, year);
1859     } else if (dateOrder_ == "y-d-M") {
1860         processDateNode(year, day, month);
1861     } else {
1862         processDateNode(year, month, day);
1863     }
1864     stackYear = DynamicCast<FrameNode>(year);
1865     stackMonth = DynamicCast<FrameNode>(month);
1866     stackDay = DynamicCast<FrameNode>(day);
1867 }
1868 
HandleSolarYearChange(bool isAdd,uint32_t index)1869 void DatePickerPattern::HandleSolarYearChange(bool isAdd, uint32_t index)
1870 {
1871     auto date = GetCurrentDate();
1872     bool leapYear = PickerDate::IsLeapYear(date.GetYear());
1873     if (date.GetMonth() == 2 && !leapYear && date.GetDay() > 28) { // invalidate of 2th month
1874         date.SetDay(28); // the max day of the 2th month of none leap year is 28
1875     }
1876 
1877     AdjustSolarDate(date);
1878     SolarColumnsBuilding(date);
1879 }
1880 
GetCurrentDate() const1881 PickerDate DatePickerPattern::GetCurrentDate() const
1882 {
1883     if (ShowMonthDays()) {
1884         return GetCurrentDateByMonthDaysColumn();
1885     } else {
1886         return GetCurrentDateByYearMonthDayColumn();
1887     }
1888 }
1889 
GetCurrentDateByYearMonthDayColumn() const1890 PickerDate DatePickerPattern::GetCurrentDateByYearMonthDayColumn() const
1891 {
1892     PickerDate currentDate;
1893     RefPtr<FrameNode> stackYear;
1894     RefPtr<FrameNode> stackMonth;
1895     RefPtr<FrameNode> stackDay;
1896     OrderCurrentDateByYearMonthDayColumn(stackYear, stackMonth, stackDay);
1897     CHECK_NULL_RETURN(stackYear, currentDate);
1898     CHECK_NULL_RETURN(stackMonth, currentDate);
1899     CHECK_NULL_RETURN(stackDay, currentDate);
1900     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
1901     CHECK_NULL_RETURN(blendYear, currentDate);
1902     auto yearColumn = DynamicCast<FrameNode>(blendYear->GetLastChild());
1903     CHECK_NULL_RETURN(yearColumn, currentDate);
1904     auto blendMonth = DynamicCast<FrameNode>(stackMonth->GetLastChild());
1905     CHECK_NULL_RETURN(blendMonth, currentDate);
1906     auto monthColumn = DynamicCast<FrameNode>(blendMonth->GetLastChild());
1907     CHECK_NULL_RETURN(monthColumn, currentDate);
1908     auto blendDay = DynamicCast<FrameNode>(stackDay->GetLastChild());
1909     CHECK_NULL_RETURN(blendDay, currentDate);
1910     auto dayColumn = DynamicCast<FrameNode>(blendDay->GetLastChild());
1911     CHECK_NULL_RETURN(dayColumn, currentDate);
1912     auto yearDatePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1913     auto monthDatePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1914     auto dayDatePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1915     CHECK_NULL_RETURN(yearDatePickerColumnPattern, currentDate);
1916     CHECK_NULL_RETURN(monthDatePickerColumnPattern, currentDate);
1917     CHECK_NULL_RETURN(dayDatePickerColumnPattern, currentDate);
1918     if (!IsShowLunar()) {
1919         currentDate.SetYear(startDateSolar_.GetYear() + yearDatePickerColumnPattern->GetCurrentIndex());
1920         currentDate.SetMonth(
1921             monthDatePickerColumnPattern->GetCurrentIndex() + 1); // month from 1 to 12, index from 0 to 11.
1922         currentDate.SetDay(dayDatePickerColumnPattern->GetCurrentIndex() + 1); // day from 1 to 31, index from 0 to 30.
1923         return currentDate;
1924     }
1925     uint32_t lunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1926     return LunarToSolar(GetCurrentLunarDate(lunarYear));
1927 }
1928 
OrderCurrentDateByYearMonthDayColumn(RefPtr<FrameNode> & stackYear,RefPtr<FrameNode> & stackMonth,RefPtr<FrameNode> & stackDay) const1929 void DatePickerPattern::OrderCurrentDateByYearMonthDayColumn(
1930     RefPtr<FrameNode>& stackYear, RefPtr<FrameNode>& stackMonth, RefPtr<FrameNode>& stackDay) const
1931 {
1932     auto host = GetHost();
1933     CHECK_NULL_VOID(host);
1934     auto children = host->GetChildren();
1935     if (children.size() != CHILD_SIZE) {
1936         return;
1937     }
1938     auto processDateNode = [&children](RefPtr<UINode>& first, RefPtr<UINode>& second, RefPtr<UINode>& third) {
1939         auto iter = children.begin();
1940         first = *iter++;
1941         CHECK_NULL_VOID(first);
1942         second = *iter++;
1943         CHECK_NULL_VOID(second);
1944         third = *iter;
1945         CHECK_NULL_VOID(third);
1946     };
1947     RefPtr<UINode> year;
1948     RefPtr<UINode> month;
1949     RefPtr<UINode> day;
1950     if (dateOrder_ == "M-d-y") {
1951         processDateNode(month, day, year);
1952     } else if (dateOrder_ == "y-d-M") {
1953         processDateNode(year, day, month);
1954     } else {
1955         processDateNode(year, month, day);
1956     }
1957     stackYear = DynamicCast<FrameNode>(year);
1958     stackMonth = DynamicCast<FrameNode>(month);
1959     stackDay = DynamicCast<FrameNode>(day);
1960 }
1961 
GetCurrentDateByMonthDaysColumn() const1962 PickerDate DatePickerPattern::GetCurrentDateByMonthDaysColumn() const
1963 {
1964     PickerDate currentDate;
1965     auto host = GetHost();
1966     CHECK_NULL_RETURN(host, currentDate);
1967 
1968     auto children = host->GetChildren();
1969     if (children.size() <= SINGLE_CHILD_SIZE) {
1970         return currentDate;
1971     }
1972     auto iter = children.begin();
1973     auto monthDays = (*iter);
1974     CHECK_NULL_RETURN(monthDays, currentDate);
1975     iter++;
1976     auto year = *iter;
1977     CHECK_NULL_RETURN(year, currentDate);
1978     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1979     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
1980     CHECK_NULL_RETURN(blendMonthDays, currentDate);
1981     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
1982     auto stackYear = DynamicCast<FrameNode>(year);
1983     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
1984     CHECK_NULL_RETURN(blendYear, currentDate);
1985     auto yearDaysNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
1986     CHECK_NULL_RETURN(monthDaysNode, currentDate);
1987     CHECK_NULL_RETURN(yearDaysNode, currentDate);
1988 
1989     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1990     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1991     CHECK_NULL_RETURN(yearDatePickerColumnPattern, currentDate);
1992     CHECK_NULL_RETURN(monthDaysDatePickerColumnPattern, currentDate);
1993 
1994     if (!IsShowLunar()) {
1995         currentDate.SetYear(startDateSolar_.GetYear() + yearDatePickerColumnPattern->GetCurrentIndex());
1996         auto monthDaysIndex = monthDaysDatePickerColumnPattern->GetCurrentIndex();
1997 
1998         uint32_t month = 1;
1999         for (; month <= 12; ++month) { // month start from 1 to 12
2000             uint32_t daysInMonth = PickerDate::GetMaxDay(currentDate.GetYear(), month);
2001             if (monthDaysIndex < daysInMonth) {
2002                 break;
2003             } else {
2004                 monthDaysIndex -= daysInMonth;
2005             }
2006         }
2007         currentDate.SetMonth(month);
2008         currentDate.SetDay(monthDaysIndex + 1); // days is index start form 0 and day start form 1.
2009         return currentDate;
2010     }
2011 
2012     uint32_t lunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
2013     return LunarToSolar(GetCurrentLunarDateByMonthDaysColumn(lunarYear));
2014 }
2015 
GetCurrentLunarDateByMonthDaysColumn(uint32_t lunarYear) const2016 LunarDate DatePickerPattern::GetCurrentLunarDateByMonthDaysColumn(uint32_t lunarYear) const
2017 {
2018     LunarDate lunarResult;
2019     auto host = GetHost();
2020     CHECK_NULL_RETURN(host, lunarResult);
2021 
2022     auto children = host->GetChildren();
2023     if (children.size() <= SINGLE_CHILD_SIZE) {
2024         return lunarResult;
2025     }
2026     auto iter = children.begin();
2027     auto monthDays = (*iter);
2028     CHECK_NULL_RETURN(monthDays, lunarResult);
2029     iter++;
2030     auto year = *iter;
2031     CHECK_NULL_RETURN(year, lunarResult);
2032     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
2033     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetLastChild()->GetLastChild());
2034     auto stackYear = DynamicCast<FrameNode>(year);
2035     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
2036     CHECK_NULL_RETURN(blendYear, lunarResult);
2037     auto yearDaysNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
2038     CHECK_NULL_RETURN(monthDaysNode, lunarResult);
2039     CHECK_NULL_RETURN(yearDaysNode, lunarResult);
2040 
2041     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
2042     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
2043     CHECK_NULL_RETURN(monthDaysDatePickerColumnPattern, lunarResult);
2044     CHECK_NULL_RETURN(yearDatePickerColumnPattern, lunarResult);
2045 
2046 
2047     uint32_t lunarLeapMonth = 0;
2048     bool hasLeapMonth = GetLunarLeapMonth(lunarYear, lunarLeapMonth);
2049     auto monthDaysIndex = monthDaysDatePickerColumnPattern->GetCurrentIndex();
2050     uint32_t month = 1;
2051     for (; month <= 12; ++month) { // month start from 1 to 12
2052         auto flag = hasLeapMonth && lunarLeapMonth == month;
2053         uint32_t daysInMonth = GetLunarMaxDay(lunarYear, month, flag && lunarResult.isLeapMonth);
2054         if (monthDaysIndex < daysInMonth) {
2055             break;
2056         } else {
2057             monthDaysIndex -= daysInMonth;
2058         }
2059         if (flag && !lunarResult.isLeapMonth) {
2060             --month;
2061             lunarResult.isLeapMonth = true;
2062         }
2063     }
2064     lunarResult.month = month;
2065     lunarResult.isLeapMonth = (lunarResult.month == lunarLeapMonth && hasLeapMonth);
2066     lunarResult.day = monthDaysIndex + 1; // day start form 1, index start from 0
2067     lunarResult.year = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
2068 
2069     return lunarResult;
2070 }
2071 
AdjustLunarDate(LunarDate & date)2072 void DatePickerPattern::AdjustLunarDate(LunarDate& date)
2073 {
2074     auto host = GetHost();
2075     CHECK_NULL_VOID(host);
2076 
2077     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
2078     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
2079     startDateLunar_ = dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_));
2080     endDateLunar_ = dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_));
2081 
2082     if (LunarDateCompare(date, startDateLunar_) < 0) {
2083         date = startDateLunar_;
2084         return;
2085     }
2086     if (LunarDateCompare(date, endDateLunar_) > 0) {
2087         date = endDateLunar_;
2088     }
2089 }
2090 
LunarDateCompare(const LunarDate & left,const LunarDate & right) const2091 int DatePickerPattern::LunarDateCompare(const LunarDate& left, const LunarDate& right) const
2092 {
2093     static const int leftEqualRight = 0;   // means left = right
2094     static const int leftGreatRight = 1;   // means left > right
2095     static const int leftLessRight = -1;   // means left < right
2096     static const double addingValue = 0.5; // adding value for leap month.
2097     if (left.year > right.year) {
2098         return leftGreatRight;
2099     }
2100     if (left.year < right.year) {
2101         return leftLessRight;
2102     }
2103     double leftMonth = (left.isLeapMonth ? left.month + addingValue : left.month);
2104     double rightMonth = (right.isLeapMonth ? right.month + addingValue : right.month);
2105     if (GreatNotEqual(leftMonth, rightMonth)) {
2106         return leftGreatRight;
2107     }
2108     if (LessNotEqual(leftMonth, rightMonth)) {
2109         return leftLessRight;
2110     }
2111     if (left.day > right.day) {
2112         return leftGreatRight;
2113     }
2114     if (left.day < right.day) {
2115         return leftLessRight;
2116     }
2117     return leftEqualRight;
2118 }
2119 
LunarColumnsBuilding(const LunarDate & current)2120 void DatePickerPattern::LunarColumnsBuilding(const LunarDate& current)
2121 {
2122     RefPtr<FrameNode> yearColumn;
2123     RefPtr<FrameNode> monthColumn;
2124     RefPtr<FrameNode> dayColumn;
2125     RefPtr<FrameNode> columns[COLUMNS_SIZE];
2126     auto host = GetHost();
2127     CHECK_NULL_VOID(host);
2128     int index = 0;
2129     int order[COLUMNS_SIZE];
2130     if (dateOrder_ == "M-d-y") {
2131         order[COLUMNS_ZERO] = INDEX_MONTH;
2132         order[COLUMNS_ONE] = INDEX_DAY;
2133         order[COLUMNS_TWO] = INDEX_YEAR;
2134     } else if (dateOrder_ == "y-d-M") {
2135         order[COLUMNS_ZERO] = INDEX_YEAR;
2136         order[COLUMNS_ONE] = INDEX_DAY;
2137         order[COLUMNS_TWO] = INDEX_MONTH;
2138     } else {
2139         order[COLUMNS_ZERO] = INDEX_YEAR;
2140         order[COLUMNS_ONE] = INDEX_MONTH;
2141         order[COLUMNS_TWO] = INDEX_DAY;
2142     }
2143     for (const auto& stackChild : host->GetChildren()) {
2144         CHECK_NULL_VOID(stackChild);
2145         auto blendChild = stackChild->GetLastChild();
2146         CHECK_NULL_VOID(blendChild);
2147         auto child = blendChild->GetLastChild();
2148         columns[order[index]] = GetColumn(child->GetId());
2149         index++;
2150     }
2151     yearColumn = columns[COLUMNS_ZERO];
2152     monthColumn = columns[COLUMNS_ONE];
2153     dayColumn = columns[COLUMNS_TWO];
2154     CHECK_NULL_VOID(yearColumn);
2155     CHECK_NULL_VOID(monthColumn);
2156     CHECK_NULL_VOID(dayColumn);
2157 
2158     AdjustLunarStartEndDate();
2159     auto startYear = startDateLunar_.year;
2160     auto endYear = endDateLunar_.year;
2161     auto startMonth = startDateLunar_.month;
2162     auto endMonth = endDateLunar_.month;
2163     auto startDay = startDateLunar_.day;
2164     auto endDay = endDateLunar_.day;
2165     uint32_t maxDay = GetLunarMaxDay(current.year, current.month, current.isLeapMonth);
2166     if (startYear < endYear) {
2167         startMonth = 1;
2168         endMonth = 12;
2169         startDay = 1;
2170         endDay = maxDay;
2171     }
2172     if (startYear == endYear && startMonth < endMonth) {
2173         startDay = 1;
2174         endDay = maxDay;
2175     }
2176 
2177     options_[yearColumn].clear();
2178     for (uint32_t index = startYear; index <= endYear; ++index) {
2179         if (current.year == index) {
2180             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2181             CHECK_NULL_VOID(datePickerColumnPattern);
2182             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
2183         }
2184         options_[yearColumn].emplace_back(PickerDateF::CreateYear(index));
2185     }
2186 
2187     uint32_t lunarLeapMonth = 0;
2188     bool hasLeapMonth = GetLunarLeapMonth(current.year, lunarLeapMonth);
2189     options_[monthColumn].clear();
2190     if (startYear == endYear) {
2191         options_[monthColumn].resize(startMonth > 0 ? startMonth - 1 : 0, emptyPickerDate_);
2192     }
2193     // lunar's month start form startMonth to endMonth
2194     for (uint32_t index = startMonth; index <= endMonth; ++index) {
2195         if (!current.isLeapMonth && current.month == index) {
2196             auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
2197             CHECK_NULL_VOID(datePickerColumnPattern);
2198             datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
2199         }
2200         options_[monthColumn].emplace_back(PickerDateF::CreateMonth(index, true, false));
2201 
2202         if (hasLeapMonth && lunarLeapMonth == index) {
2203             if (current.isLeapMonth && current.month == index) {
2204                 auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
2205                 CHECK_NULL_VOID(datePickerColumnPattern);
2206                 datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
2207             }
2208             options_[monthColumn].emplace_back(PickerDateF::CreateMonth(index, true, true));
2209         }
2210     }
2211 
2212     options_[dayColumn].clear();
2213     if (startYear == endYear && startMonth == endMonth) {
2214         options_[dayColumn].resize(startDay > 0 ? startDay - 1 : 0, emptyPickerDate_);
2215     }
2216     // lunar's day start from startDay
2217     for (uint32_t index = startDay; index <= endDay; ++index) {
2218         if (current.day == index) {
2219             auto datePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
2220             CHECK_NULL_VOID(datePickerColumnPattern);
2221             datePickerColumnPattern->SetCurrentIndex(options_[dayColumn].size());
2222         }
2223         options_[dayColumn].emplace_back(PickerDateF::CreateDay(index, true));
2224     }
2225     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2226     CHECK_NULL_VOID(yearColumnPattern);
2227     auto monthColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
2228     CHECK_NULL_VOID(monthColumnPattern);
2229     auto dayColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
2230     CHECK_NULL_VOID(dayColumnPattern);
2231     yearColumnPattern->SetOptions(GetOptions());
2232     monthColumnPattern->SetOptions(GetOptions());
2233     dayColumnPattern->SetOptions(GetOptions());
2234 
2235     SetShowLunar(true);
2236 }
2237 
SolarColumnsBuilding(const PickerDate & current)2238 void DatePickerPattern::SolarColumnsBuilding(const PickerDate& current)
2239 {
2240     RefPtr<FrameNode> yearColumn;
2241     RefPtr<FrameNode> monthColumn;
2242     RefPtr<FrameNode> dayColumn;
2243 
2244     RefPtr<FrameNode> columns[COLUMNS_SIZE];
2245     auto host = GetHost();
2246     CHECK_NULL_VOID(host);
2247     int index = 0;
2248     int order[COLUMNS_SIZE];
2249     if (dateOrder_ == "M-d-y") {
2250         order[COLUMNS_ZERO] = INDEX_MONTH;
2251         order[COLUMNS_ONE] = INDEX_DAY;
2252         order[COLUMNS_TWO] = INDEX_YEAR;
2253     } else if (dateOrder_ == "y-d-M") {
2254         order[COLUMNS_ZERO] = INDEX_YEAR;
2255         order[COLUMNS_ONE] = INDEX_DAY;
2256         order[COLUMNS_TWO] = INDEX_MONTH;
2257     } else {
2258         order[COLUMNS_ZERO] = INDEX_YEAR;
2259         order[COLUMNS_ONE] = INDEX_MONTH;
2260         order[COLUMNS_TWO] = INDEX_DAY;
2261     }
2262     for (const auto& stackChild : host->GetChildren()) {
2263         CHECK_NULL_VOID(stackChild);
2264         auto blendChild = stackChild->GetLastChild();
2265         CHECK_NULL_VOID(blendChild);
2266         auto child = blendChild->GetLastChild();
2267         columns[order[index]] = GetColumn(child->GetId());
2268         index++;
2269     }
2270     yearColumn = columns[COLUMNS_ZERO];
2271     monthColumn = columns[COLUMNS_ONE];
2272     dayColumn = columns[COLUMNS_TWO];
2273 
2274     CHECK_NULL_VOID(yearColumn);
2275     CHECK_NULL_VOID(monthColumn);
2276     CHECK_NULL_VOID(dayColumn);
2277 
2278     AdjustSolarStartEndDate();
2279     auto startYear = startDateSolar_.GetYear();
2280     auto endYear = endDateSolar_.GetYear();
2281     auto startMonth = startDateSolar_.GetMonth();
2282     auto endMonth = endDateSolar_.GetMonth();
2283     auto startDay = startDateSolar_.GetDay();
2284     auto endDay = endDateSolar_.GetDay();
2285 
2286     uint32_t maxDay = PickerDate::GetMaxDay(current.GetYear(), current.GetMonth());
2287     if (startYear < endYear) {
2288         startMonth = 1;
2289         endMonth = 12;
2290         startDay = 1;
2291         endDay = maxDay;
2292     }
2293     if (startYear == endYear && startMonth < endMonth) {
2294         startDay = 1;
2295         endDay = maxDay;
2296     }
2297 
2298     options_[yearColumn].clear();
2299     for (uint32_t year = startYear; year <= endYear; ++year) {
2300         if (year == current.GetYear()) {
2301             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2302             CHECK_NULL_VOID(datePickerColumnPattern);
2303             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
2304         }
2305         options_[yearColumn].emplace_back(PickerDateF::CreateYear(year));
2306     }
2307 
2308     options_[monthColumn].clear();
2309     if (startYear == endYear) {
2310         options_[monthColumn].resize(startMonth > 0 ? startMonth - 1 : 0, emptyPickerDate_);
2311     }
2312     // solar's month start form 1 to 12
2313     for (uint32_t month = startMonth; month <= endMonth; month++) {
2314         if (month == current.GetMonth()) {
2315             auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
2316             CHECK_NULL_VOID(datePickerColumnPattern);
2317             // back index = size - 1
2318             datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
2319         }
2320 
2321         options_[monthColumn].emplace_back(PickerDateF::CreateMonth(month, false, false));
2322     }
2323 
2324     options_[dayColumn].clear();
2325     if (startYear == endYear && startMonth == endMonth) {
2326         options_[dayColumn].resize(startDay - 1, emptyPickerDate_);
2327     }
2328     // solar's day start from 1
2329     for (uint32_t day = startDay; day <= endDay; day++) {
2330         if (day == current.GetDay()) {
2331             auto datePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
2332             CHECK_NULL_VOID(datePickerColumnPattern);
2333             datePickerColumnPattern->SetCurrentIndex(options_[dayColumn].size());
2334         }
2335         options_[dayColumn].emplace_back(PickerDateF::CreateDay(day, false));
2336     }
2337 
2338     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2339     CHECK_NULL_VOID(yearColumnPattern);
2340     auto monthColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
2341     CHECK_NULL_VOID(monthColumnPattern);
2342     auto dayColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
2343     CHECK_NULL_VOID(dayColumnPattern);
2344     yearColumnPattern->SetOptions(GetOptions());
2345     monthColumnPattern->SetOptions(GetOptions());
2346     dayColumnPattern->SetOptions(GetOptions());
2347 
2348     SetShowLunar(false);
2349 }
2350 
LunarMonthDaysColumnBuilding(const LunarDate & current)2351 void DatePickerPattern::LunarMonthDaysColumnBuilding(const LunarDate& current)
2352 {
2353     RefPtr<FrameNode> monthDaysColumn;
2354     RefPtr<FrameNode> yearColumn;
2355     auto host = GetHost();
2356     CHECK_NULL_VOID(host);
2357 
2358     auto children = host->GetChildren();
2359     if (children.size() <= SINGLE_CHILD_SIZE) {
2360         return;
2361     }
2362 
2363     auto iter = children.begin();
2364     auto monthDays = (*iter);
2365     CHECK_NULL_VOID(monthDays);
2366     iter++;
2367     auto year = *iter;
2368     CHECK_NULL_VOID(year);
2369     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
2370     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
2371     CHECK_NULL_VOID(blendMonthDays);
2372     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
2373     auto stackYear = DynamicCast<FrameNode>(year);
2374     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
2375     CHECK_NULL_VOID(blendYear);
2376     auto yearDaysNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
2377     CHECK_NULL_VOID(monthDaysNode);
2378     CHECK_NULL_VOID(yearDaysNode);
2379 
2380     monthDaysColumn = GetColumn(monthDaysNode->GetId());
2381     yearColumn = GetColumn(yearDaysNode->GetId());
2382     CHECK_NULL_VOID(monthDaysColumn);
2383     CHECK_NULL_VOID(yearColumn);
2384 
2385     AdjustLunarStartEndDate();
2386 
2387     auto startYear = startDateLunar_.year;
2388     auto endYear = endDateLunar_.year;
2389 
2390     options_[yearColumn].clear();
2391     for (uint32_t index = startYear; index <= endYear; ++index) {
2392         if (current.year == index) {
2393             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2394             CHECK_NULL_VOID(datePickerColumnPattern);
2395             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
2396         }
2397         options_[yearColumn].emplace_back(PickerDateF::CreateYear(index));
2398     }
2399 
2400     FillLunarMonthDaysOptions(current, monthDaysColumn);
2401 
2402     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2403     auto monthDaysColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
2404     CHECK_NULL_VOID(yearColumnPattern);
2405     CHECK_NULL_VOID(monthDaysColumnPattern);
2406     yearColumnPattern->SetOptions(GetOptions());
2407     monthDaysColumnPattern->SetOptions(GetOptions());
2408 
2409     SetShowLunar(true);
2410 }
2411 
SolarMonthDaysColumnsBuilding(const PickerDate & current)2412 void DatePickerPattern::SolarMonthDaysColumnsBuilding(const PickerDate& current)
2413 {
2414     RefPtr<FrameNode> monthDaysColumn;
2415     RefPtr<FrameNode> yearColumn;
2416     auto host = GetHost();
2417     CHECK_NULL_VOID(host);
2418 
2419     auto children = host->GetChildren();
2420     if (children.size() <= SINGLE_CHILD_SIZE) {
2421         return;
2422     }
2423     auto iter = children.begin();
2424     auto monthDays = (*iter);
2425     CHECK_NULL_VOID(monthDays);
2426     iter++;
2427     auto year = *iter;
2428     CHECK_NULL_VOID(year);
2429     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
2430     auto blendMonthDays = DynamicCast<FrameNode>(stackMonthDays->GetLastChild());
2431     CHECK_NULL_VOID(blendMonthDays);
2432     auto monthDaysNode = DynamicCast<FrameNode>(blendMonthDays->GetLastChild());
2433     auto stackYear = DynamicCast<FrameNode>(year);
2434     auto blendYear = DynamicCast<FrameNode>(stackYear->GetLastChild());
2435     CHECK_NULL_VOID(blendYear);
2436     auto yearDaysNode = DynamicCast<FrameNode>(blendYear->GetLastChild());
2437     monthDaysColumn = GetColumn(monthDaysNode->GetId());
2438     yearColumn = GetColumn(yearDaysNode->GetId());
2439     CHECK_NULL_VOID(monthDaysColumn);
2440     CHECK_NULL_VOID(yearColumn);
2441 
2442     AdjustSolarStartEndDate();
2443     FillSolarYearOptions(current, yearColumn);
2444 
2445     options_[monthDaysColumn].clear();
2446     for (uint32_t index = MIN_MONTH; index <= MAX_MONTH; ++index) {
2447         uint32_t maxDay = PickerDate::GetMaxDay(current.GetYear(), index);
2448         for (uint32_t dayIndex = MIN_DAY; dayIndex <= maxDay; ++dayIndex) {
2449             if (index == current.GetMonth() && dayIndex == current.GetDay()) {
2450                 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
2451                 CHECK_NULL_VOID(datePickerColumnPattern);
2452                 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
2453             }
2454             options_[monthDaysColumn].emplace_back(PickerDateF::CreateMonthDay(index, dayIndex, false, false));
2455         }
2456     }
2457 
2458     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2459     auto monthDaysColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
2460     CHECK_NULL_VOID(yearColumnPattern);
2461     CHECK_NULL_VOID(monthDaysColumnPattern);
2462     yearColumnPattern->SetOptions(GetOptions());
2463     monthDaysColumnPattern->SetOptions(GetOptions());
2464 
2465     SetShowLunar(false);
2466 }
2467 
FillSolarYearOptions(const PickerDate & current,RefPtr<FrameNode> & yearColumn)2468 void DatePickerPattern::FillSolarYearOptions(const PickerDate& current, RefPtr<FrameNode>& yearColumn)
2469 {
2470     options_[yearColumn].clear();
2471     for (uint32_t year = startDateSolar_.GetYear(); year <= endDateSolar_.GetYear(); ++year) {
2472         if (year == current.GetYear()) {
2473             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
2474             CHECK_NULL_VOID(datePickerColumnPattern);
2475             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
2476         }
2477         options_[yearColumn].emplace_back(PickerDateF::CreateYear(year));
2478     }
2479 }
2480 
FillLunarMonthDaysOptions(const LunarDate & current,RefPtr<FrameNode> & monthDaysColumn)2481 void DatePickerPattern::FillLunarMonthDaysOptions(const LunarDate& current, RefPtr<FrameNode>& monthDaysColumn)
2482 {
2483     uint32_t startMonth = 1;
2484     uint32_t endMonth = 12;
2485     uint32_t startDay = 1;
2486 
2487     uint32_t lunarLeapMonth = 0;
2488     bool hasLeapMonth = GetLunarLeapMonth(current.year, lunarLeapMonth);
2489     options_[monthDaysColumn].clear();
2490 
2491     for (uint32_t index = startMonth; index <= endMonth; ++index) {
2492         uint32_t maxDay = GetLunarMaxDay(current.year, index, false);
2493         for (uint32_t dayIndex = startDay; dayIndex <= maxDay; ++dayIndex) {
2494             if (!current.isLeapMonth && current.month == index && current.day == dayIndex) {
2495                 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
2496                 CHECK_NULL_VOID(datePickerColumnPattern);
2497                 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
2498             }
2499             options_[monthDaysColumn].emplace_back(PickerDateF::CreateMonthDay(index, dayIndex, true, false));
2500         }
2501 
2502         if (!hasLeapMonth || lunarLeapMonth != index) {
2503             continue;
2504         }
2505 
2506         maxDay = GetLunarMaxDay(current.year, index, true);
2507         for (uint32_t dayIndex = startDay; dayIndex <= maxDay; ++dayIndex) {
2508             if (current.isLeapMonth && current.month == index && current.day == dayIndex) {
2509                 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
2510                 CHECK_NULL_VOID(datePickerColumnPattern);
2511                 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
2512             }
2513             options_[monthDaysColumn].emplace_back(PickerDateF::CreateMonthDay(index, dayIndex, true, true));
2514         }
2515     }
2516 }
2517 
AdjustSolarStartEndDate()2518 void DatePickerPattern::AdjustSolarStartEndDate()
2519 {
2520     auto host = GetHost();
2521     CHECK_NULL_VOID(host);
2522 
2523     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
2524     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
2525     startDateSolar_ = LunarToSolar(dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_)));
2526     endDateSolar_ = LunarToSolar(dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_)));
2527 
2528     if (startDateSolar_.GetYear() > endDateSolar_.GetYear()) {
2529         startDateSolar_ = startDefaultDateSolar_;
2530         endDateSolar_ = endDefaultDateSolar_;
2531     }
2532     if (startDateSolar_.GetYear() == endDateSolar_.GetYear() && startDateSolar_.GetMonth() > endDateSolar_.GetMonth()) {
2533         startDateSolar_ = startDefaultDateSolar_;
2534         endDateSolar_ = endDefaultDateSolar_;
2535     }
2536     if (startDateSolar_.GetYear() == endDateSolar_.GetYear() &&
2537         startDateSolar_.GetMonth() == endDateSolar_.GetMonth() && startDateSolar_.GetDay() > endDateSolar_.GetDay()) {
2538         startDateSolar_ = startDefaultDateSolar_;
2539         endDateSolar_ = endDefaultDateSolar_;
2540     }
2541 }
2542 
AdjustLunarStartEndDate()2543 void DatePickerPattern::AdjustLunarStartEndDate()
2544 {
2545     auto host = GetHost();
2546     CHECK_NULL_VOID(host);
2547 
2548     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
2549     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
2550     startDateLunar_ = dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_));
2551     endDateLunar_ = dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_));
2552 
2553     if (GetStartDateLunar().year > GetEndDateLunar().year) {
2554         startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
2555         endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
2556     }
2557     if (GetStartDateLunar().year == GetEndDateLunar().year && GetStartDateLunar().month > GetEndDateLunar().month) {
2558         startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
2559         endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
2560     }
2561     if (GetStartDateLunar().year == GetEndDateLunar().year && GetStartDateLunar().month == GetEndDateLunar().month &&
2562         GetStartDateLunar().day > GetEndDateLunar().day) {
2563         startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
2564         endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
2565     }
2566 }
2567 
GetLunarLeapMonth(uint32_t year,uint32_t & outLeapMonth) const2568 bool DatePickerPattern::GetLunarLeapMonth(uint32_t year, uint32_t& outLeapMonth) const
2569 {
2570     auto leapMonth = LunarCalculator::GetLunarLeapMonth(year);
2571     if (leapMonth <= 0) {
2572         return false;
2573     }
2574 
2575     outLeapMonth = static_cast<uint32_t>(leapMonth);
2576     return true;
2577 }
2578 
GetLunarMaxDay(uint32_t year,uint32_t month,bool isLeap) const2579 uint32_t DatePickerPattern::GetLunarMaxDay(uint32_t year, uint32_t month, bool isLeap) const
2580 {
2581     if (isLeap) {
2582         return static_cast<uint32_t>(LunarCalculator::GetLunarLeapDays(year));
2583     } else {
2584         return static_cast<uint32_t>(LunarCalculator::GetLunarMonthDays(year, month));
2585     }
2586 }
2587 
SolarToLunar(const PickerDate & date) const2588 LunarDate DatePickerPattern::SolarToLunar(const PickerDate& date) const
2589 {
2590     Date result;
2591     result.year = date.GetYear();
2592     result.month = date.GetMonth();
2593     result.day = date.GetDay();
2594     return Localization::GetInstance()->GetLunarDate(result);
2595 }
2596 
LunarToSolar(const LunarDate & date) const2597 PickerDate DatePickerPattern::LunarToSolar(const LunarDate& date) const
2598 {
2599     uint32_t days = date.day > 0 ? date.day - 1 : 0; // calculate days from 1900.1.1 to this date
2600     if (date.isLeapMonth) {
2601         days += LunarCalculator::GetLunarMonthDays(date.year, date.month);
2602     } else {
2603         uint32_t leapMonth = LunarCalculator::GetLunarLeapMonth(date.year);
2604         if (leapMonth < date.month) {
2605             days += LunarCalculator::GetLunarLeapDays(date.year);
2606         }
2607     }
2608     for (uint32_t month = 1; month < date.month; ++month) { // month start from 1
2609         days += LunarCalculator::GetLunarMonthDays(date.year, month);
2610     }
2611     for (uint32_t year = 1900; year < date.year; ++year) { // year start from 1900
2612         days += LunarCalculator::GetLunarYearDays(year);
2613     }
2614     days += 30; // days from solar's 1900.1.1 to lunar's 1900.1.1 is 30
2615     PickerDate result;
2616     result.FromDays(days);
2617     return result;
2618 }
2619 
Init()2620 void DatePickerPattern::Init()
2621 {
2622     if (inited_) {
2623         return;
2624     }
2625     years_.clear();
2626     solarMonths_.clear();
2627     solarDays_.clear();
2628     lunarMonths_.clear();
2629     lunarDays_.clear();
2630     localizedMonths_ = Localization::GetInstance()->GetMonths(true);
2631 
2632     inited_ = true;
2633     Localization::GetInstance()->SetOnChange([]() { inited_ = false; });
2634 }
2635 
GetYear(uint32_t year)2636 const std::string& DatePickerPattern::GetYear(uint32_t year)
2637 {
2638     Init();
2639     if (!(1900 <= year && year <= 2100)) { // year in [1900,2100]
2640         return empty_;
2641     }
2642     auto index = year - 1900;
2643     auto it = years_.find(index);
2644     if (it == years_.end()) {
2645         DateTime date;
2646         date.year = year;
2647         auto& dateYear = years_[index];
2648         dateYear = Localization::GetInstance()->FormatDateTime(date, "y");
2649         return dateYear;
2650     }
2651     return it->second; // index in [0, 200]
2652 }
2653 
GetSolarMonth(uint32_t month)2654 const std::string& DatePickerPattern::GetSolarMonth(uint32_t month)
2655 {
2656     Init();
2657     if (!(1 <= month && month <= 12)) { // solar month in [1,12]
2658         return empty_;
2659     }
2660     auto index = month - 1;
2661     auto it = solarMonths_.find(index);
2662     if (it == solarMonths_.end()) {
2663         auto& dateMonth = solarMonths_[index];
2664         if (index < localizedMonths_.size()) {
2665             dateMonth = localizedMonths_[index];
2666         } else {
2667             DateTime date;
2668             date.month = month - 1; // W3C's month start from 0 to 11
2669             dateMonth = Localization::GetInstance()->FormatDateTime(date, "M");
2670         }
2671         return dateMonth;
2672     }
2673     return it->second; // index in [0,11]
2674 }
2675 
GetSolarDay(uint32_t day)2676 const std::string& DatePickerPattern::GetSolarDay(uint32_t day)
2677 {
2678     Init();
2679     if (!(1 <= day && day <= 31)) { // solar day in [1,31]
2680         return empty_;
2681     }
2682     auto index = day - 1;
2683     auto it = solarDays_.find(index);
2684     if (it == solarDays_.end()) {
2685         auto& dateDay = solarDays_[index];
2686         DateTime date;
2687         date.day = day;
2688         dateDay = Localization::GetInstance()->FormatDateTime(date, "d");
2689         return dateDay;
2690     }
2691     return it->second; // index in [0,30]
2692 }
2693 
GetLunarMonth(uint32_t month,bool isLeap)2694 const std::string& DatePickerPattern::GetLunarMonth(uint32_t month, bool isLeap)
2695 {
2696     Init();
2697     uint32_t index = (isLeap ? month + 12 : month); // leap month is behind 12 index
2698     if (!(1 <= index && index <= 24)) {             // lunar month need in [1,24]
2699         return empty_;
2700     }
2701     auto it = lunarMonths_.find(index - 1);
2702     if (it == lunarMonths_.end()) {
2703         auto& dateMonth = lunarMonths_[index - 1];
2704         dateMonth = Localization::GetInstance()->GetLunarMonth(month, isLeap);
2705         return dateMonth;
2706     }
2707     return it->second; // index in [0,23]
2708 }
2709 
GetLunarDay(uint32_t day)2710 const std::string& DatePickerPattern::GetLunarDay(uint32_t day)
2711 {
2712     Init();
2713     if (!(1 <= day && day <= 30)) { // lunar day need in [1,30]
2714         return empty_;
2715     }
2716     auto index = day - 1;
2717     auto it = lunarDays_.find(index);
2718     if (it == lunarDays_.end()) {
2719         auto& dateDay = lunarDays_[index];
2720         dateDay = Localization::GetInstance()->GetLunarDay(day);
2721         return dateDay;
2722     }
2723     return it->second; // index in [0,29]
2724 }
2725 
GetText()2726 const std::string DatePickerPattern::GetText()
2727 {
2728     auto pickerDate = GetCurrentDate();
2729     std::string result = std::to_string(pickerDate.GetYear()) + "-" + std::to_string(pickerDate.GetMonth()) + "-" +
2730                      std::to_string(pickerDate.GetDay());
2731     return result;
2732 }
2733 
GetFormatString(PickerDateF date)2734 const std::string DatePickerPattern::GetFormatString(PickerDateF date)
2735 {
2736     if (date.year.has_value()) {
2737         return GetYear(date.year.value());
2738     }
2739 
2740     std::string monthStr;
2741     if (date.month.has_value()) {
2742         monthStr = date.lunar ? GetLunarMonth(date.month.value(), date.leap) : GetSolarMonth(date.month.value());
2743         if (!date.day.has_value()) {
2744             return monthStr;
2745         }
2746     }
2747 
2748     std::string dayStr;
2749     if (date.day.has_value()) {
2750         dayStr = date.lunar ? GetLunarDay(date.day.value()) : GetSolarDay(date.day.value());
2751         DateTimeSequence sequence;
2752         auto language = AceApplicationInfo::GetInstance().GetLanguage();
2753         OrderResult orderResult = sequence.GetDateOrder(language);
2754         if (language == "ug") {
2755             return date.month.has_value() ? (dayStr + "-" + monthStr) : dayStr;
2756         } else if (language == "en") {
2757             return date.month.has_value() ? (monthStr + " " + dayStr) : dayStr;
2758         } else {
2759             return date.month.has_value() ? (monthStr + dayStr) : dayStr;
2760         }
2761     }
2762 
2763     return "";
2764 }
2765 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const2766 void DatePickerPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
2767 {
2768     /* no fixed attr below, just return */
2769     if (filter.IsFastFilter()) {
2770         return;
2771     }
2772     auto GetDateString = [](const PickerDate& pickerDate) {
2773         std::string ret;
2774         ret += std::to_string(pickerDate.GetYear());
2775         ret += "-";
2776         ret += std::to_string(pickerDate.GetMonth());
2777         ret += "-";
2778         ret += std::to_string(pickerDate.GetDay());
2779         return ret;
2780     };
2781     auto GetModeString = [](const DatePickerMode& datePickerMode) {
2782         std::string ret;
2783         if (datePickerMode == DatePickerMode::DATE) {
2784             ret = "DatePickerMode.DATE";
2785         } else if (datePickerMode == DatePickerMode::YEAR_AND_MONTH) {
2786             ret = "DatePickerMode.YEAR_AND_MONTH";
2787         } else if (datePickerMode == DatePickerMode::MONTH_AND_DAY) {
2788             ret = "DatePickerMode.MONTH_AND_DAY";
2789         }
2790         return ret;
2791     };
2792     auto rowLayoutProperty = GetLayoutProperty<DataPickerRowLayoutProperty>();
2793     CHECK_NULL_VOID(rowLayoutProperty);
2794     auto jsonConstructor = JsonUtil::Create(true);
2795     auto isLunar = rowLayoutProperty->GetLunarValue(false);
2796     if (isLunar) {
2797         jsonConstructor->Put("start", rowLayoutProperty->GetDateStart().c_str());
2798         jsonConstructor->Put("end", rowLayoutProperty->GetDateEnd().c_str());
2799         jsonConstructor->Put("selected", rowLayoutProperty->GetDateSelected().c_str());
2800         jsonConstructor->Put("mode", rowLayoutProperty->GetDatePickerMode().c_str());
2801     } else {
2802         jsonConstructor->Put("start", GetDateString(startDateSolar_).c_str());
2803         jsonConstructor->Put("end", GetDateString(endDateSolar_).c_str());
2804         jsonConstructor->Put("selected", GetDateString(selectedDate_).c_str());
2805         jsonConstructor->Put("mode", GetModeString(datePickerMode_).c_str());
2806     }
2807     json->PutExtAttr("constructor", jsonConstructor, filter);
2808     json->PutExtAttr("enableHapticFeedback", isEnableHaptic_, filter);
2809 }
2810 
SetFocusDisable()2811 void DatePickerPattern::SetFocusDisable()
2812 {
2813     auto host = GetHost();
2814     CHECK_NULL_VOID(host);
2815 
2816     auto focusHub = host->GetFocusHub();
2817     CHECK_NULL_VOID(focusHub);
2818 
2819     isFocus_ = false;
2820     focusHub->SetFocusable(false);
2821 }
2822 
SetFocusEnable()2823 void DatePickerPattern::SetFocusEnable()
2824 {
2825     auto host = GetHost();
2826     CHECK_NULL_VOID(host);
2827 
2828     auto focusHub = host->GetFocusHub();
2829     CHECK_NULL_VOID(focusHub);
2830 
2831     isFocus_ = true;
2832     focusHub->SetFocusable(true);
2833 }
2834 
NeedAdaptForAging()2835 bool DatePickerPattern::NeedAdaptForAging()
2836 {
2837     auto host = GetHost();
2838     CHECK_NULL_RETURN(host, false);
2839     auto pipeline = host->GetContext();
2840     CHECK_NULL_RETURN(pipeline, false);
2841     auto pickerTheme = pipeline->GetTheme<PickerTheme>();
2842     CHECK_NULL_RETURN(pickerTheme, false);
2843 
2844     if (GreatOrEqual(pipeline->GetFontScale(), pickerTheme->GetMaxOneFontScale()) &&
2845         GreatOrEqual(Dimension(pipeline->GetRootHeight()).ConvertToVp(), pickerTheme->GetDeviceHeightLimit())) {
2846         return true;
2847     }
2848     return false;
2849 }
2850 
2851 #ifdef SUPPORT_DIGITAL_CROWN
InitOnCrownEvent(const RefPtr<FocusHub> & focusHub)2852 void DatePickerPattern::InitOnCrownEvent(const RefPtr<FocusHub>& focusHub)
2853 {
2854     CHECK_NULL_VOID(focusHub);
2855     auto onCrowEvent = [wp = WeakClaim(this)](const CrownEvent& event)->bool {
2856         auto pattern = wp.Upgrade();
2857         if (pattern) {
2858             return pattern->OnCrownEvent(event);
2859         }
2860         return false;
2861     };
2862 
2863     focusHub->SetOnCrownEventInternal(std::move(onCrowEvent));
2864 }
2865 
OnCrownEvent(const CrownEvent & event)2866 bool DatePickerPattern::OnCrownEvent(const CrownEvent& event)
2867 {
2868     if (event.action == OHOS::Ace::CrownAction::BEGIN ||
2869         event.action == OHOS::Ace::CrownAction::UPDATE ||
2870         event.action == OHOS::Ace::CrownAction::END) {
2871         RefPtr<DatePickerColumnPattern> crownPickerColumnPattern;
2872         for (auto& iter : datePickerColumns_) {
2873             auto column = iter.Upgrade();
2874             if (!column) {
2875                 continue;
2876             }
2877             auto pickerColumnPattern = column->GetPattern<DatePickerColumnPattern>();
2878             if (!pickerColumnPattern) {
2879                 continue;
2880             }
2881             auto columnID =  pickerColumnPattern->GetSelectedColumnId();
2882             if (!pickerColumnPattern->IsCrownEventEnded()) {
2883                 crownPickerColumnPattern = pickerColumnPattern;
2884                 break;
2885             } else if (columnID == selectedColumnId_) {
2886                 crownPickerColumnPattern = pickerColumnPattern;
2887             }
2888         }
2889         if (crownPickerColumnPattern) {
2890             return crownPickerColumnPattern->OnCrownEvent(event);
2891         }
2892     }
2893 
2894     return false;
2895 }
2896 #endif
2897 
IsCircle()2898 bool DatePickerPattern::IsCircle()
2899 {
2900     auto host = GetHost();
2901     CHECK_NULL_RETURN(host, false);
2902     auto context = host->GetContext();
2903     CHECK_NULL_RETURN(context, false);
2904     auto pickerTheme = context->GetTheme<PickerTheme>();
2905     CHECK_NULL_RETURN(pickerTheme, false);
2906 
2907     return pickerTheme->IsCircleDial();
2908 }
2909 
ClearFocus()2910 void DatePickerPattern::ClearFocus()
2911 {
2912     CHECK_EQUAL_VOID(IsCircle(), false);
2913     CHECK_EQUAL_VOID(isFirstTimeSetFocus_, true);
2914     CHECK_EQUAL_VOID(lastTimeIsLuanar_, CurrentIsLunar());
2915     if (!selectedColumnId_.empty()) {
2916         const auto& allChildNode = GetAllChildNode();
2917         auto it = allChildNode.find(selectedColumnId_);
2918         if (it != allChildNode.end()) {
2919             auto tmpPattern = it->second->GetPattern<DatePickerColumnPattern>();
2920             if (tmpPattern) {
2921                 tmpPattern->SetSelectedMark(false, false);
2922             }
2923         }
2924         selectedColumnId_ = "";
2925     }
2926 }
2927 
SetDefaultFocus()2928 void DatePickerPattern::SetDefaultFocus()
2929 {
2930     CHECK_EQUAL_VOID(IsCircle(), false);
2931     if (!isFirstTimeSetFocus_ && (lastTimeIsLuanar_ == CurrentIsLunar())) {
2932         return;
2933     }
2934     isFirstTimeSetFocus_ = false;
2935     lastTimeIsLuanar_ = CurrentIsLunar();
2936     std::function<void(std::string& focusId)> call =  [weak = WeakClaim(this)](std::string& focusId) {
2937         auto pattern = weak.Upgrade();
2938         CHECK_NULL_VOID(pattern);
2939         if (pattern->selectedColumnId_.empty()) {
2940             pattern->selectedColumnId_ = focusId;
2941             return;
2942         }
2943         const auto& allChildNode = pattern->GetAllChildNode();
2944         auto it = allChildNode.find(pattern->selectedColumnId_);
2945         if (it != allChildNode.end()) {
2946             auto tmpPattern = it->second->GetPattern<DatePickerColumnPattern>();
2947             tmpPattern->SetSelectedMark(false, false);
2948         }
2949 
2950         pattern->selectedColumnId_ = focusId;
2951     };
2952 
2953     const auto& allChildNode = GetAllChildNode();
2954     static const std::string columnName[] = {"year", "month", "day"};
2955     bool setFocus = true;
2956     for (size_t i = 0; i < sizeof(columnName) / sizeof(columnName[0]); i++) {
2957         auto it = allChildNode.find(columnName[i]);
2958         if (it != allChildNode.end()) {
2959             auto tmpPattern = it->second->GetPattern<DatePickerColumnPattern>();
2960             CHECK_NULL_VOID(tmpPattern);
2961             tmpPattern->SetSelectedMarkId(columnName[i]);
2962             tmpPattern->SetSelectedMarkListener(call);
2963             if (setFocus) {
2964                 selectedColumnId_ = columnName[i];
2965             }
2966             tmpPattern->SetSelectedMark(setFocus, false);
2967             setFocus = false;
2968         }
2969     }
2970 }
2971 
SetDigitalCrownSensitivity(int32_t crownSensitivity)2972 void DatePickerPattern::SetDigitalCrownSensitivity(int32_t crownSensitivity)
2973 {
2974 #ifdef SUPPORT_DIGITAL_CROWN
2975     auto host = GetHost();
2976     CHECK_NULL_VOID(host);
2977     auto&& children = host->GetChildren();
2978     for (const auto& child : children) {
2979         auto stackNode = DynamicCast<FrameNode>(child);
2980         CHECK_NULL_VOID(stackNode);
2981         auto blendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
2982         CHECK_NULL_VOID(blendNode);
2983         auto childNode = DynamicCast<FrameNode>(blendNode->GetLastChild());
2984         CHECK_NULL_VOID(childNode);
2985         auto pickerColumnPattern = childNode->GetPattern<DatePickerColumnPattern>();
2986         CHECK_NULL_VOID(pickerColumnPattern);
2987         pickerColumnPattern->SetDigitalCrownSensitivity(crownSensitivity);
2988     }
2989 #endif
2990 }
2991 
UpdateUserSetSelectColor()2992 void DatePickerPattern::UpdateUserSetSelectColor()
2993 {
2994     CHECK_EQUAL_VOID(IsCircle(), false);
2995     auto host = GetHost();
2996     CHECK_NULL_VOID(host);
2997     auto&& children = host->GetChildren();
2998     for (const auto& child : children) {
2999         auto stackNode = DynamicCast<FrameNode>(child);
3000         CHECK_NULL_VOID(stackNode);
3001         auto blendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
3002         CHECK_NULL_VOID(blendNode);
3003         auto childNode = DynamicCast<FrameNode>(blendNode->GetLastChild());
3004         CHECK_NULL_VOID(childNode);
3005         auto pickerColumnPattern = childNode->GetPattern<DatePickerColumnPattern>();
3006         CHECK_NULL_VOID(pickerColumnPattern);
3007         pickerColumnPattern->UpdateUserSetSelectColor();
3008     }
3009 }
3010 
CurrentIsLunar()3011 bool DatePickerPattern::CurrentIsLunar()
3012 {
3013     auto rowLayoutProperty = GetLayoutProperty<DataPickerRowLayoutProperty>();
3014     CHECK_NULL_RETURN(rowLayoutProperty, true);
3015     return rowLayoutProperty->GetLunarValue(false);
3016 }
3017 
3018 } // namespace OHOS::Ace::NG
3019