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