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 #include "base/memory/ace_type.h"
23 #include "base/utils/utils.h"
24 #include "core/components/picker/picker_base_component.h"
25 #include "core/components/theme/icon_theme.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/event/click_event.h"
28 #include "core/components_ng/pattern/button/button_pattern.h"
29 #include "core/components_ng/pattern/image/image_layout_property.h"
30 #include "core/components_ng/pattern/picker/datepicker_column_pattern.h"
31 #include "core/components_v2/inspector/inspector_constants.h"
32 #include "core/pipeline/pipeline_base.h"
33 #include "core/pipeline_ng/ui_task_scheduler.h"
34
35 namespace OHOS::Ace::NG {
36 namespace {
37 constexpr int32_t SINGLE_CHILD_SIZE = 1;
38 constexpr int32_t CHILD_SIZE = 3;
39 constexpr uint32_t MIN_MONTH = 1;
40 constexpr uint32_t MAX_MONTH = 12;
41 constexpr uint32_t MIN_DAY = 1;
42 const Dimension PRESS_INTERVAL = 4.0_vp;
43 const Dimension PRESS_RADIUS = 8.0_vp;
44 const int32_t UNOPTION_COUNT = 2;
45 } // namespace
46 bool DatePickerPattern::inited_ = false;
47 const std::string DatePickerPattern::empty_;
48 std::vector<std::string> DatePickerPattern::years_; // year from 1900 to 2100,count is 201
49 std::vector<std::string> DatePickerPattern::solarMonths_; // solar month from 1 to 12,count is 12
50 std::vector<std::string> DatePickerPattern::solarDays_; // solar day from 1 to 31, count is 31
51 std::vector<std::string> DatePickerPattern::lunarMonths_; // lunar month from 1 to 24, count is 24
52 std::vector<std::string> DatePickerPattern::lunarDays_; // lunar day from 1 to 30, count is 30
53 std::vector<std::string> DatePickerPattern::tagOrder_; // order of year month day
54
OnAttachToFrameNode()55 void DatePickerPattern::OnAttachToFrameNode()
56 {
57 auto host = GetHost();
58 CHECK_NULL_VOID(host);
59 host->GetRenderContext()->SetClipToFrame(true);
60 host->GetRenderContext()->UpdateClipEdge(true);
61 }
62
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)63 bool DatePickerPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
64 {
65 CHECK_NULL_RETURN_NOLOG(config.frameSizeChange, false);
66 CHECK_NULL_RETURN(dirty, false);
67 auto host = GetHost();
68 CHECK_NULL_RETURN(host, false);
69 auto context = host->GetContext();
70 CHECK_NULL_RETURN(context, false);
71 auto pickerTheme = context->GetTheme<PickerTheme>();
72 CHECK_NULL_RETURN(pickerTheme, false);
73 auto children = host->GetChildren();
74 auto heigth = pickerTheme->GetDividerSpacing();
75 for (const auto& child : children) {
76 auto columnNode = DynamicCast<FrameNode>(child->GetLastChild());
77 auto width = columnNode->GetGeometryNode()->GetFrameSize().Width();
78 auto buttonNode = DynamicCast<FrameNode>(child->GetFirstChild());
79 auto buttonConfirmLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
80 buttonConfirmLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
81 buttonConfirmLayoutProperty->UpdateType(ButtonType::NORMAL);
82 buttonConfirmLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(PRESS_RADIUS));
83 buttonConfirmLayoutProperty->UpdateUserDefinedIdealSize(
84 CalcSize(CalcLength(width - PRESS_INTERVAL.ConvertToPx()), CalcLength(heigth - PRESS_INTERVAL)));
85 auto buttonConfirmRenderContext = buttonNode->GetRenderContext();
86 buttonConfirmRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
87 buttonNode->MarkModifyDone();
88 }
89 return true;
90 }
91
OnModifyDone()92 void DatePickerPattern::OnModifyDone()
93 {
94 auto host = GetHost();
95 CHECK_NULL_VOID(host);
96 InitDisabled();
97 if (ShowMonthDays()) {
98 FlushMonthDaysColumn();
99 } else {
100 FlushColumn();
101 }
102 ShowTitle(GetTitleId());
103 SetChangeCallback([weak = WeakClaim(this)](const RefPtr<FrameNode>& tag, bool add, uint32_t index, bool notify) {
104 auto refPtr = weak.Upgrade();
105 CHECK_NULL_VOID_NOLOG(refPtr);
106 refPtr->HandleColumnChange(tag, add, index, notify);
107 });
108 SetEventCallback([weak = WeakClaim(this), titleId = GetTitleId()](bool refresh) {
109 auto refPtr = weak.Upgrade();
110 CHECK_NULL_VOID_NOLOG(refPtr);
111 refPtr->FireChangeEvent(refresh);
112 if (refresh) {
113 refPtr->ShowTitle(titleId);
114 }
115 });
116 auto focusHub = host->GetFocusHub();
117 if (focusHub) {
118 InitOnKeyEvent(focusHub);
119 }
120 }
121
InitDisabled()122 void DatePickerPattern::InitDisabled()
123 {
124 auto host = GetHost();
125 CHECK_NULL_VOID(host);
126 auto eventHub = host->GetEventHub<EventHub>();
127 CHECK_NULL_VOID(eventHub);
128 auto renderContext = host->GetRenderContext();
129 enabled_ = eventHub->IsEnabled();
130 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
131 }
132
OnLanguageConfigurationUpdate()133 void DatePickerPattern::OnLanguageConfigurationUpdate()
134 {
135 auto buttonConfirmNode = weakButtonConfirm_.Upgrade();
136 CHECK_NULL_VOID(buttonConfirmNode);
137 auto confirmNode = buttonConfirmNode->GetFirstChild();
138 auto confirmNodeLayout = AceType::DynamicCast<FrameNode>(confirmNode)->GetLayoutProperty<TextLayoutProperty>();
139 confirmNodeLayout->UpdateContent(Localization::GetInstance()->GetEntryLetters("common.ok"));
140
141 auto buttonCancelNode = weakButtonCancel_.Upgrade();
142 CHECK_NULL_VOID(buttonCancelNode);
143 auto cancelNode = buttonCancelNode->GetFirstChild();
144 auto cancelNodeLayout = AceType::DynamicCast<FrameNode>(cancelNode)->GetLayoutProperty<TextLayoutProperty>();
145 cancelNodeLayout->UpdateContent(Localization::GetInstance()->GetEntryLetters("common.cancel"));
146 }
147
HandleColumnChange(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,bool needNotify)148 void DatePickerPattern::HandleColumnChange(const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, bool needNotify)
149 {
150 CHECK_NULL_VOID(GetHost());
151 std::vector<RefPtr<FrameNode>> tags;
152 if (ShowMonthDays()) {
153 HandleMonthDaysChange(tag, isAdd, index, tags);
154 } else {
155 OnDataLinking(tag, isAdd, index, tags);
156 }
157 for (const auto& tag : tags) {
158 auto iter = std::find_if(datePickerColumns_.begin(), datePickerColumns_.end(),
159 [&tag](const RefPtr<FrameNode>& column) { return column->GetId() == tag->GetId(); });
160 if (iter != datePickerColumns_.end()) {
161 auto datePickerColumnPattern = (*iter)->GetPattern<DatePickerColumnPattern>();
162 CHECK_NULL_VOID(datePickerColumnPattern);
163 datePickerColumnPattern->FlushCurrentOptions(isAdd, true, false);
164 }
165 }
166 }
167
SetEventCallback(EventCallback && value)168 void DatePickerPattern::SetEventCallback(EventCallback&& value)
169 {
170 auto host = GetHost();
171 CHECK_NULL_VOID(host);
172 auto children = host->GetChildren();
173 for (const auto& child : children) {
174 auto stackNode = DynamicCast<FrameNode>(child);
175 CHECK_NULL_VOID(stackNode);
176 auto childNode = stackNode->GetChildAtIndex(1);
177 CHECK_NULL_VOID(childNode);
178 auto datePickerColumnPattern = DynamicCast<FrameNode>(childNode)->GetPattern<DatePickerColumnPattern>();
179 CHECK_NULL_VOID(datePickerColumnPattern);
180 datePickerColumnPattern->SetEventCallback(std::move(value));
181 }
182 }
183
SetChangeCallback(ColumnChangeCallback && value)184 void DatePickerPattern::SetChangeCallback(ColumnChangeCallback&& value)
185 {
186 auto host = GetHost();
187 CHECK_NULL_VOID(host);
188 auto children = host->GetChildren();
189 for (const auto& child : children) {
190 auto stackNode = DynamicCast<FrameNode>(child);
191 CHECK_NULL_VOID(stackNode);
192 auto childNode = stackNode->GetChildAtIndex(1);
193 CHECK_NULL_VOID(childNode);
194 auto datePickerColumnPattern = DynamicCast<FrameNode>(childNode)->GetPattern<DatePickerColumnPattern>();
195 CHECK_NULL_VOID(datePickerColumnPattern);
196 datePickerColumnPattern->SetChangeCallback(std::move(value));
197 }
198 }
199
OnColorConfigurationUpdate()200 void DatePickerPattern::OnColorConfigurationUpdate()
201 {
202 auto host = GetHost();
203 CHECK_NULL_VOID(host);
204 host->SetNeedCallChildrenUpdate(false);
205 auto context = host->GetContext();
206 CHECK_NULL_VOID(context);
207 auto pickerTheme = context->GetTheme<PickerTheme>();
208 CHECK_NULL_VOID(pickerTheme);
209 auto dialogTheme = context->GetTheme<DialogTheme>();
210 CHECK_NULL_VOID(dialogTheme);
211 auto disappearStyle = pickerTheme->GetDisappearOptionStyle();
212 auto normalStyle = pickerTheme->GetOptionStyle(false, false);
213 auto pickerProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
214 CHECK_NULL_VOID(pickerProperty);
215 pickerProperty->UpdateColor(normalStyle.GetTextColor());
216 pickerProperty->UpdateDisappearColor(disappearStyle.GetTextColor());
217 if (isPicker_) {
218 return;
219 }
220 SetBackgroundColor(dialogTheme->GetBackgroundColor());
221 CHECK_NULL_VOID(buttonTitleNode_);
222 auto titleLayoutRenderContext = buttonTitleNode_->GetRenderContext();
223 CHECK_NULL_VOID(titleLayoutRenderContext);
224 titleLayoutRenderContext->UpdateBackgroundColor(dialogTheme->GetButtonBackgroundColor());
225 auto childButton = buttonTitleNode_->GetFirstChild();
226 CHECK_NULL_VOID(childButton);
227 auto ButtonNode = DynamicCast<FrameNode>(childButton);
228 CHECK_NULL_VOID(ButtonNode);
229 auto buttonTitleRenderContext = ButtonNode->GetRenderContext();
230 CHECK_NULL_VOID(buttonTitleRenderContext);
231 buttonTitleRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
232 auto childText = ButtonNode->GetFirstChild();
233 CHECK_NULL_VOID(childText);
234 auto textTitleNode = DynamicCast<FrameNode>(childText);
235 CHECK_NULL_VOID(textTitleNode);
236 auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
237 CHECK_NULL_VOID(textLayoutProperty);
238 textLayoutProperty->UpdateTextColor(pickerTheme->GetTitleStyle().GetTextColor());
239 CHECK_NULL_VOID(contentRowNode_);
240 auto layoutRenderContext = contentRowNode_->GetRenderContext();
241 CHECK_NULL_VOID(layoutRenderContext);
242 layoutRenderContext->UpdateBackgroundColor(dialogTheme->GetButtonBackgroundColor());
243 OnModifyDone();
244 }
245
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)246 void DatePickerPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
247 {
248 auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
249 auto pattern = wp.Upgrade();
250 CHECK_NULL_RETURN_NOLOG(pattern, false);
251 return pattern->OnKeyEvent(event);
252 };
253 focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
254
255 auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
256 auto pattern = wp.Upgrade();
257 if (pattern) {
258 pattern->GetInnerFocusPaintRect(paintRect);
259 }
260 };
261 focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
262 }
263
PaintFocusState()264 void DatePickerPattern::PaintFocusState()
265 {
266 auto host = GetHost();
267 CHECK_NULL_VOID(host);
268
269 RoundRect focusRect;
270 GetInnerFocusPaintRect(focusRect);
271
272 auto focusHub = host->GetFocusHub();
273 CHECK_NULL_VOID(focusHub);
274 focusHub->PaintInnerFocusState(focusRect);
275
276 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
277 }
278
GetInnerFocusPaintRect(RoundRect & paintRect)279 void DatePickerPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
280 {
281 auto host = GetHost();
282 CHECK_NULL_VOID(host);
283 auto childSize = 1.0f;
284 if (!ShowMonthDays()) {
285 childSize = static_cast<float>(host->GetChildren().size());
286 }
287 auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
288 CHECK_NULL_VOID(stackChild);
289 auto pickerChild = DynamicCast<FrameNode>(stackChild->GetLastChild());
290 CHECK_NULL_VOID(pickerChild);
291 auto columnWidth = pickerChild->GetGeometryNode()->GetFrameSize().Width();
292 auto pipeline = PipelineBase::GetCurrentContext();
293 CHECK_NULL_VOID(pipeline);
294 auto pickerTheme = pipeline->GetTheme<PickerTheme>();
295 CHECK_NULL_VOID(pickerTheme);
296 auto frameWidth = host->GetGeometryNode()->GetFrameSize().Width();
297 auto dividerSpacing = pickerTheme->GetDividerSpacing().ConvertToPx();
298 auto pickerThemeWidth = dividerSpacing * 2;
299
300 auto centerX = (frameWidth / childSize - pickerThemeWidth) / 2 +
301 pickerChild->GetGeometryNode()->GetFrameRect().Width() * focusKeyID_ +
302 PRESS_INTERVAL.ConvertToPx() * 2;
303 auto centerY =
304 (host->GetGeometryNode()->GetFrameSize().Height() - dividerSpacing) / 2 + PRESS_INTERVAL.ConvertToPx();
305 float piantRectWidth = (dividerSpacing - PRESS_INTERVAL.ConvertToPx()) * 2;
306 float piantRectHeight = dividerSpacing - PRESS_INTERVAL.ConvertToPx() * 2;
307 if (piantRectWidth > columnWidth) {
308 piantRectWidth = columnWidth;
309 centerX = focusKeyID_ * columnWidth;
310 }
311 paintRect.SetRect(RectF(centerX, centerY, piantRectWidth, piantRectHeight));
312 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
313 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
314 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
315 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
316 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
317 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
318 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
319 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
320 }
321
OnKeyEvent(const KeyEvent & event)322 bool DatePickerPattern::OnKeyEvent(const KeyEvent& event)
323 {
324 if (event.action != KeyAction::DOWN) {
325 return false;
326 }
327 if (event.code == KeyCode::KEY_DPAD_UP || event.code == KeyCode::KEY_DPAD_DOWN ||
328 event.code == KeyCode::KEY_DPAD_LEFT || event.code == KeyCode::KEY_DPAD_RIGHT ||
329 event.code == KeyCode::KEY_MOVE_HOME || event.code == KeyCode::KEY_MOVE_END) {
330 return HandleDirectionKey(event.code);
331 }
332 return false;
333 }
334
HandleDirectionKey(KeyCode code)335 bool DatePickerPattern::HandleDirectionKey(KeyCode code)
336 {
337 auto host = GetHost();
338 CHECK_NULL_RETURN(host, false);
339
340 auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
341 auto pickerChild = DynamicCast<FrameNode>(stackChild->GetChildAtIndex(1));
342 auto pattern = pickerChild->GetPattern<DatePickerColumnPattern>();
343 auto totalOptionCount = GetOptionCount(pickerChild);
344 if (totalOptionCount == 0) {
345 return false;
346 }
347 if (code == KeyCode::KEY_DPAD_UP) {
348 pattern->InnerHandleScroll(false, false);
349 return true;
350 }
351 if (code == KeyCode::KEY_DPAD_DOWN) {
352 pattern->InnerHandleScroll(true, false);
353 return true;
354 }
355 if (code == KeyCode::KEY_MOVE_HOME) {
356 pattern->SetCurrentIndex(1);
357 pattern->InnerHandleScroll(false, false);
358 return true;
359 }
360 if (code == KeyCode::KEY_MOVE_END) {
361 pattern->SetCurrentIndex(totalOptionCount - UNOPTION_COUNT);
362 pattern->InnerHandleScroll(true, false);
363 return true;
364 }
365 if (code == KeyCode::KEY_DPAD_LEFT) {
366 focusKeyID_ -= 1;
367 if (focusKeyID_ < 0) {
368 focusKeyID_ = 0;
369 return false;
370 }
371 PaintFocusState();
372 return true;
373 }
374 if (code == KeyCode::KEY_DPAD_RIGHT) {
375 focusKeyID_ += 1;
376 auto childSize = 1.0f;
377 if (!ShowMonthDays()) {
378 childSize = static_cast<float>(host->GetChildren().size());
379 }
380 if (focusKeyID_ > childSize -1) {
381 focusKeyID_ = childSize -1;
382 return false;
383 }
384 PaintFocusState();
385 return true;
386 }
387 return false;
388 }
389
GetAllChildNode()390 std::unordered_map<std::string, RefPtr<FrameNode>> DatePickerPattern::GetAllChildNode()
391 {
392 std::unordered_map<std::string, RefPtr<FrameNode>> allChildNode;
393 auto host = GetHost();
394 CHECK_NULL_RETURN(host, allChildNode);
395 auto children = host->GetChildren();
396 if (children.size() != CHILD_SIZE) {
397 return allChildNode;
398 }
399 auto iter = children.begin();
400 auto year = (*iter);
401 CHECK_NULL_RETURN(year, allChildNode);
402 iter++;
403 auto month = *iter;
404 CHECK_NULL_RETURN(month, allChildNode);
405 iter++;
406 auto day = *iter;
407 CHECK_NULL_RETURN(day, allChildNode);
408 auto stackYear = DynamicCast<FrameNode>(year);
409 auto yearNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
410 auto stackMonth = DynamicCast<FrameNode>(month);
411 auto monthNode = DynamicCast<FrameNode>(stackMonth->GetChildAtIndex(1));
412 auto stackDay = DynamicCast<FrameNode>(day);
413 auto dayNode = DynamicCast<FrameNode>(stackDay->GetChildAtIndex(1));
414
415 CHECK_NULL_RETURN(yearNode, allChildNode);
416 CHECK_NULL_RETURN(monthNode, allChildNode);
417 CHECK_NULL_RETURN(dayNode, allChildNode);
418 allChildNode["year"] = yearNode;
419 allChildNode["month"] = monthNode;
420 allChildNode["day"] = dayNode;
421 return allChildNode;
422 }
423
FlushColumn()424 void DatePickerPattern::FlushColumn()
425 {
426 auto host = GetHost();
427 CHECK_NULL_VOID(host);
428 auto allChildNode = GetAllChildNode();
429
430 auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
431 CHECK_NULL_VOID(dataPickerRowLayoutProperty);
432 auto lunarDate = dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate()));
433 AdjustLunarDate(lunarDate);
434 if (dataPickerRowLayoutProperty->GetLunar().value_or(false)) {
435 LunarColumnsBuilding(lunarDate);
436 } else {
437 SolarColumnsBuilding(LunarToSolar(lunarDate));
438 }
439
440 auto yearNode = allChildNode["year"];
441 auto monthNode = allChildNode["month"];
442 auto dayNode = allChildNode["day"];
443 CHECK_NULL_VOID(yearNode);
444 CHECK_NULL_VOID(monthNode);
445 CHECK_NULL_VOID(dayNode);
446 auto yearColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
447 CHECK_NULL_VOID(yearColumnPattern);
448 auto monthColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
449 CHECK_NULL_VOID(monthColumnPattern);
450 auto dayColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
451 CHECK_NULL_VOID(dayColumnPattern);
452
453 yearColumnPattern->SetShowCount(GetShowCount());
454 monthColumnPattern->SetShowCount(GetShowCount());
455 dayColumnPattern->SetShowCount(GetShowCount());
456 yearColumnPattern->FlushCurrentOptions();
457 monthColumnPattern->FlushCurrentOptions();
458 dayColumnPattern->FlushCurrentOptions();
459 }
460
FlushMonthDaysColumn()461 void DatePickerPattern::FlushMonthDaysColumn()
462 {
463 auto host = GetHost();
464 CHECK_NULL_VOID(host);
465
466 auto children = host->GetChildren();
467 if (children.size() <= SINGLE_CHILD_SIZE) {
468 return;
469 }
470 auto iter = children.begin();
471 auto monthDays = (*iter);
472 CHECK_NULL_VOID(monthDays);
473 iter++;
474 auto year = *iter;
475 CHECK_NULL_VOID(year);
476 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
477 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
478 auto stackYear = DynamicCast<FrameNode>(year);
479 auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
480 CHECK_NULL_VOID(monthDaysNode);
481 CHECK_NULL_VOID(yearDaysNode);
482 auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
483 CHECK_NULL_VOID(dataPickerRowLayoutProperty);
484 if (dataPickerRowLayoutProperty->GetLunar().value_or(false)) {
485 LunarMonthDaysColumnBuilding(
486 dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate())));
487 } else {
488 SolarMonthDaysColumnsBuilding(
489 LunarToSolar(dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate()))));
490 }
491
492 auto monthDaysColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
493 auto yearColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
494 CHECK_NULL_VOID(monthDaysColumnPattern);
495 CHECK_NULL_VOID(yearColumnPattern);
496
497 monthDaysColumnPattern->SetShowCount(GetShowCount());
498 yearColumnPattern->SetShowCount(GetShowCount());
499 monthDaysColumnPattern->FlushCurrentOptions();
500 yearColumnPattern->FlushCurrentOptions();
501 }
502
FireChangeEvent(bool refresh) const503 void DatePickerPattern::FireChangeEvent(bool refresh) const
504 {
505 if (refresh) {
506 auto datePickerEventHub = GetEventHub<DatePickerEventHub>();
507 CHECK_NULL_VOID(datePickerEventHub);
508 auto str = GetSelectedObject(true);
509 auto info = std::make_shared<DatePickerChangeEvent>(str);
510 datePickerEventHub->FireChangeEvent(info.get());
511 datePickerEventHub->FireDialogChangeEvent(str);
512 }
513 }
514
ShowTitle(int32_t titleId)515 void DatePickerPattern::ShowTitle(int32_t titleId)
516 {
517 if (HasTitleNode()) {
518 auto textTitleNode = FrameNode::GetOrCreateFrameNode(
519 V2::TEXT_ETS_TAG, titleId, []() { return AceType::MakeRefPtr<TextPattern>(); });
520 auto dateStr = GetCurrentDate();
521 CHECK_NULL_VOID(textTitleNode);
522 auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
523 CHECK_NULL_VOID(textLayoutProperty);
524 textLayoutProperty->UpdateContent(dateStr.ToString(false));
525 textTitleNode->MarkModifyDone();
526 textTitleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
527 }
528 }
529
OnDataLinking(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)530 void DatePickerPattern::OnDataLinking(
531 const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
532 {
533 auto allChildNode = GetAllChildNode();
534 auto yearNode = allChildNode["year"];
535 auto monthNode = allChildNode["month"];
536 auto dayNode = allChildNode["day"];
537 CHECK_NULL_VOID(yearNode);
538 CHECK_NULL_VOID(monthNode);
539 CHECK_NULL_VOID(dayNode);
540 if (tag == yearNode) {
541 HandleYearChange(isAdd, index, resultTags);
542 return;
543 }
544
545 if (tag == monthNode) {
546 HandleMonthChange(isAdd, index, resultTags);
547 return;
548 }
549
550 if (tag == dayNode) {
551 HandleDayChange(isAdd, index, resultTags);
552 return;
553 }
554 LOGE("unknown tag[%{private}d] of column.", tag->GetId());
555 }
556
HandleMonthDaysChange(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)557 void DatePickerPattern::HandleMonthDaysChange(
558 const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
559 {
560 auto host = GetHost();
561 CHECK_NULL_VOID(host);
562
563 auto children = host->GetChildren();
564 if (children.size() <= SINGLE_CHILD_SIZE) {
565 return;
566 }
567 auto iter = children.begin();
568 auto monthDays = (*iter);
569 CHECK_NULL_VOID(monthDays);
570
571 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
572 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
573 if (tag != monthDaysNode) {
574 LOGE("unknown tag[%{private}d] of column.", tag->GetId());
575 return;
576 }
577
578 if (IsShowLunar()) {
579 HandleLunarMonthDaysChange(isAdd, index);
580 } else {
581 HandleSolarMonthDaysChange(isAdd, index);
582 }
583
584 resultTags.emplace_back(monthDaysNode);
585 }
586
GetSelectedObject(bool isColumnChange,int status) const587 std::string DatePickerPattern::GetSelectedObject(bool isColumnChange, int status) const
588 {
589 auto date = selectedDate_;
590 if (isColumnChange) {
591 date = GetCurrentDate();
592 }
593 // W3C's month is between 0 to 11, need to reduce one.
594 date.SetMonth(date.GetMonth() - 1);
595
596 auto dateTimeString = std::string("{\"year\":") + std::to_string(date.GetYear()) + ",\"month\":" +
597 std::to_string(date.GetMonth()) + ",\"day\":" + std::to_string(date.GetDay());
598 auto pickTime = PickerTime::Current();
599 if (showTime_) {
600 auto host = GetHost();
601 CHECK_NULL_RETURN(host, date.ToString(true, status));
602 if (showMonthDays_) {
603 auto pickerRow = host->GetParent();
604 CHECK_NULL_RETURN(pickerRow, date.ToString(true, status));
605 auto timeNode = AceType::DynamicCast<FrameNode>(pickerRow->GetChildAtIndex(1));
606 CHECK_NULL_RETURN(timeNode, date.ToString(true, status));
607 auto timePickerPattern = timeNode->GetPattern<TimePickerRowPattern>();
608 CHECK_NULL_RETURN(timePickerPattern, date.ToString(true, status));
609 pickTime = timePickerPattern->GetCurrentTime();
610 } else {
611 auto pickerStack = host->GetParent();
612 CHECK_NULL_RETURN(pickerStack, date.ToString(true, status));
613 auto pickerRow = pickerStack->GetLastChild();
614 CHECK_NULL_RETURN(pickerRow, date.ToString(true, status));
615 auto timeNode = AceType::DynamicCast<FrameNode>(pickerRow->GetChildAtIndex(1));
616 CHECK_NULL_RETURN(timeNode, date.ToString(true, status));
617 auto timePickerPattern = timeNode->GetPattern<TimePickerRowPattern>();
618 CHECK_NULL_RETURN(timePickerPattern, date.ToString(true, status));
619 pickTime = timePickerPattern->GetCurrentTime();
620 }
621 }
622 dateTimeString += std::string(",\"hour\":") + std::to_string(pickTime.GetHour()) + ",\"minute\":" +
623 std::to_string(pickTime.GetMinute()) + ",\"status\":" + std::to_string(status) + "}";
624 return dateTimeString;
625 }
626
HandleDayChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)627 void DatePickerPattern::HandleDayChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
628 {
629 auto allChildNode = GetAllChildNode();
630 auto yearNode = allChildNode["year"];
631 auto monthNode = allChildNode["month"];
632 auto dayNode = allChildNode["day"];
633 CHECK_NULL_VOID(yearNode);
634 CHECK_NULL_VOID(monthNode);
635 CHECK_NULL_VOID(dayNode);
636 if (IsShowLunar()) {
637 HandleLunarDayChange(isAdd, index);
638 } else {
639 HandleSolarDayChange(isAdd, index);
640 }
641 resultTags.emplace_back(yearNode);
642 resultTags.emplace_back(monthNode);
643 resultTags.emplace_back(dayNode);
644 }
645
HandleSolarDayChange(bool isAdd,uint32_t index)646 void DatePickerPattern::HandleSolarDayChange(bool isAdd, uint32_t index)
647 {
648 auto allChildNode = GetAllChildNode();
649 auto yearNode = allChildNode["year"];
650 auto monthNode = allChildNode["month"];
651 auto dayNode = allChildNode["day"];
652
653 CHECK_NULL_VOID(yearNode);
654 CHECK_NULL_VOID(monthNode);
655 CHECK_NULL_VOID(dayNode);
656 auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
657 auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
658 auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
659 if (!yearDatePickerColumnPattern || !monthDatePickerColumnPattern || !dayDatePickerColumnPattern) {
660 LOGE("year or month or day column pattern is null.");
661 return;
662 }
663
664 auto date = GetCurrentDate();
665 if (isAdd && index == 0) {
666 date.SetMonth(date.GetMonth() + 1); // add to next month
667 if (date.GetMonth() > 12) { // invalidate month, max month is 12
668 date.SetMonth(1); // first month is 1
669 date.SetYear(date.GetYear() + 1); // add to next year
670 if (date.GetYear() > endDateSolar_.GetYear()) {
671 date.SetYear(startDateSolar_.GetYear());
672 }
673 }
674 }
675 if (!isAdd &&
676 dayDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(dayNode) - 1) { // last index is count - 1
677 date.SetMonth(date.GetMonth() - 1); // reduce to previous month
678 if (date.GetMonth() == 0) { // min month is 1, invalidate
679 date.SetMonth(12); // set to be the last month
680 date.SetYear(date.GetYear() - 1); // reduce to previous year
681 if (date.GetYear() < startDateSolar_.GetYear()) {
682 date.SetYear(endDateSolar_.GetYear());
683 }
684 }
685 date.SetDay(PickerDate::GetMaxDay(date.GetYear(), date.GetMonth())); // reduce to previous month's last day
686 }
687 uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
688 if (date.GetDay() > maxDay) {
689 date.SetDay(maxDay);
690 }
691 AdjustSolarDate(date);
692 SolarColumnsBuilding(date);
693 }
694
HandleLunarDayChange(bool isAdd,uint32_t index)695 void DatePickerPattern::HandleLunarDayChange(bool isAdd, uint32_t index)
696 {
697 if (isAdd) {
698 HandleAddLunarDayChange(index);
699 } else {
700 HandleReduceLunarDayChange(index);
701 }
702 }
703
HandleReduceLunarDayChange(uint32_t index)704 void DatePickerPattern::HandleReduceLunarDayChange(uint32_t index)
705 {
706 auto allChildNode = GetAllChildNode();
707 auto yearNode = allChildNode["year"];
708 auto monthNode = allChildNode["month"];
709 auto dayNode = allChildNode["day"];
710
711 CHECK_NULL_VOID(yearNode);
712 CHECK_NULL_VOID(monthNode);
713 CHECK_NULL_VOID(dayNode);
714
715 auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
716 auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
717 auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
718
719 uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
720 auto lunarDate = GetCurrentLunarDate(nowLunarYear);
721 uint32_t lunarLeapMonth = 0;
722 bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
723 if (dayDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(dayNode) - 1) { // max index is count - 1
724 if (monthDatePickerColumnPattern->GetCurrentIndex() == 0) {
725 lunarDate.year = lunarDate.year - 1; // reduce to previous year
726 if (lunarDate.year < startDateLunar_.year) {
727 lunarDate.year = endDateLunar_.year;
728 }
729 lunarDate.month = 12; // set to be previous year's max month
730 lunarDate.isLeapMonth = false;
731 if (LunarCalculator::GetLunarLeapMonth(lunarDate.year) == 12) { // leap 12th month
732 lunarDate.isLeapMonth = true;
733 }
734 lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
735 } else {
736 if (lunarDate.isLeapMonth) {
737 lunarDate.isLeapMonth = false;
738 } else if (!hasLeapMonth) {
739 lunarDate.month = lunarDate.month - 1; // reduce to previous month
740 } else if (lunarLeapMonth == lunarDate.month - 1) { // leap month is previous month
741 lunarDate.isLeapMonth = true;
742 lunarDate.month = lunarLeapMonth;
743 } else {
744 lunarDate.month = lunarDate.month - 1; // reduce to previous month
745 }
746 lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
747 }
748 }
749
750 AdjustLunarDate(lunarDate);
751 LunarColumnsBuilding(lunarDate);
752 }
753
HandleAddLunarDayChange(uint32_t index)754 void DatePickerPattern::HandleAddLunarDayChange(uint32_t index)
755 {
756 auto allChildNode = GetAllChildNode();
757 auto yearNode = allChildNode["year"];
758 auto monthNode = allChildNode["month"];
759 auto dayNode = allChildNode["day"];
760
761 CHECK_NULL_VOID(yearNode);
762 CHECK_NULL_VOID(monthNode);
763 CHECK_NULL_VOID(dayNode);
764
765 auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
766 auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
767 auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
768
769 uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
770 auto lunarDate = GetCurrentLunarDate(nowLunarYear);
771 uint32_t lunarLeapMonth = 0;
772 bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
773 if (index == 0) {
774 if (monthDatePickerColumnPattern->GetCurrentIndex() ==
775 GetOptionCount(monthNode) - 1) { // max index is count - 1
776 lunarDate.year = lunarDate.year + 1; // add to next year
777 if (lunarDate.year > endDateLunar_.year) {
778 lunarDate.year = startDateLunar_.year;
779 }
780 lunarDate.month = 1; // first month
781 lunarDate.isLeapMonth = false;
782 } else {
783 if (lunarDate.isLeapMonth) {
784 lunarDate.month = lunarDate.month + 1; // add to next month
785 lunarDate.isLeapMonth = false;
786 } else if (!hasLeapMonth) {
787 lunarDate.month = lunarDate.month + 1; // add to next month
788 } else if (lunarLeapMonth == lunarDate.month) {
789 lunarDate.isLeapMonth = true;
790 } else {
791 lunarDate.month = lunarDate.month + 1; // add to next month
792 }
793 }
794 }
795
796 AdjustLunarDate(lunarDate);
797 LunarColumnsBuilding(lunarDate);
798 }
799
HandleSolarMonthDaysChange(bool isAdd,uint32_t index)800 void DatePickerPattern::HandleSolarMonthDaysChange(bool isAdd, uint32_t index)
801 {
802 auto host = GetHost();
803 CHECK_NULL_VOID(host);
804
805 auto children = host->GetChildren();
806 if (children.size() <= SINGLE_CHILD_SIZE) {
807 return;
808 }
809 auto iter = children.begin();
810 auto monthDays = (*iter);
811 CHECK_NULL_VOID(monthDays);
812 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
813 CHECK_NULL_VOID(stackMonthDays);
814 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
815 CHECK_NULL_VOID(monthDaysNode);
816 auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
817 CHECK_NULL_VOID(monthDaysDatePickerColumnPattern);
818
819 auto date = GetCurrentDate();
820
821 if (isAdd && index == 0) {
822 // add to next year
823 date.SetYear(date.GetYear() + 1); // add to next year
824 if (date.GetYear() > endDateSolar_.GetYear()) {
825 date.SetYear(startDateSolar_.GetYear());
826 }
827 }
828 if (!isAdd && monthDaysDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(monthDaysNode) - 1) {
829 // reduce to previous year
830 date.SetYear(date.GetYear() - 1);
831 if (date.GetYear() < startDateSolar_.GetYear()) {
832 date.SetYear(endDateSolar_.GetYear());
833 }
834 // reduce to previous year's last day
835 date.SetMonth(MAX_MONTH);
836 date.SetDay(PickerDate::GetMaxDay(date.GetYear(), date.GetMonth()));
837 }
838 uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
839 if (date.GetDay() > maxDay) {
840 date.SetDay(maxDay);
841 }
842 AdjustSolarDate(date);
843 SolarMonthDaysColumnsBuilding(date);
844 }
845
HandleLunarMonthDaysChange(bool isAdd,uint32_t index)846 void DatePickerPattern::HandleLunarMonthDaysChange(bool isAdd, uint32_t index)
847 {
848 if (isAdd) {
849 HandleAddLunarMonthDaysChange(index);
850 } else {
851 HandleReduceLunarMonthDaysChange(index);
852 }
853 }
854
HandleAddLunarMonthDaysChange(uint32_t index)855 void DatePickerPattern::HandleAddLunarMonthDaysChange(uint32_t index)
856 {
857 auto host = GetHost();
858 CHECK_NULL_VOID(host);
859
860 auto children = host->GetChildren();
861 if (children.size() <= SINGLE_CHILD_SIZE) {
862 return;
863 }
864 auto iter = children.begin();
865 auto monthDays = (*iter);
866 CHECK_NULL_VOID(monthDays);
867 iter++;
868 auto year = *iter;
869 CHECK_NULL_VOID(year);
870 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
871 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
872 auto stackYear = DynamicCast<FrameNode>(year);
873 auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
874 CHECK_NULL_VOID(monthDaysNode);
875 CHECK_NULL_VOID(yearDaysNode);
876
877 auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
878 auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
879
880 uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
881 auto lunarDate = GetCurrentLunarDateByMonthDaysColumn(nowLunarYear);
882 if (index == 0) {
883 lunarDate.year = lunarDate.year + 1; // add to next year
884 if (lunarDate.year > endDateLunar_.year) {
885 lunarDate.year = startDateLunar_.year;
886 }
887 lunarDate.month = 1;
888 lunarDate.isLeapMonth = false;
889 }
890
891 AdjustLunarDate(lunarDate);
892 LunarMonthDaysColumnBuilding(lunarDate);
893 }
894
HandleReduceLunarMonthDaysChange(uint32_t index)895 void DatePickerPattern::HandleReduceLunarMonthDaysChange(uint32_t index)
896 {
897 auto host = GetHost();
898 CHECK_NULL_VOID(host);
899
900 auto children = host->GetChildren();
901 if (children.size() <= SINGLE_CHILD_SIZE) {
902 return;
903 }
904 auto iter = children.begin();
905 auto monthDays = (*iter);
906 CHECK_NULL_VOID(monthDays);
907 iter++;
908 auto year = *iter;
909 CHECK_NULL_VOID(year);
910 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
911 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
912 auto stackYear = DynamicCast<FrameNode>(year);
913 auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
914 CHECK_NULL_VOID(monthDaysNode);
915 CHECK_NULL_VOID(yearDaysNode);
916
917 auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
918 auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
919 CHECK_NULL_VOID(monthDaysDatePickerColumnPattern);
920 CHECK_NULL_VOID(yearDatePickerColumnPattern);
921
922 uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
923 auto lunarDate = GetCurrentLunarDateByMonthDaysColumn(nowLunarYear);
924 if (monthDaysDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(monthDaysNode) - 1) {
925 lunarDate.year = lunarDate.year - 1; // reduce to previous year
926 if (lunarDate.year < startDateLunar_.year) {
927 lunarDate.year = endDateLunar_.year;
928 }
929 lunarDate.month = MAX_MONTH; // set to be previous year's max month
930 lunarDate.isLeapMonth = false;
931 if (LunarCalculator::GetLunarLeapMonth(lunarDate.year) == 12) { // leap 12th month
932 lunarDate.isLeapMonth = true;
933 }
934 lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
935 }
936
937 AdjustLunarDate(lunarDate);
938 LunarMonthDaysColumnBuilding(lunarDate);
939 }
940
HandleYearChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)941 void DatePickerPattern::HandleYearChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
942 {
943 auto allChildNode = GetAllChildNode();
944 auto yearNode = allChildNode["year"];
945 auto monthNode = allChildNode["month"];
946 auto dayNode = allChildNode["day"];
947
948 CHECK_NULL_VOID(yearNode);
949 CHECK_NULL_VOID(monthNode);
950 CHECK_NULL_VOID(dayNode);
951 if (IsShowLunar()) {
952 HandleLunarYearChange(isAdd, index);
953 } else {
954 HandleSolarYearChange(isAdd, index);
955 }
956 resultTags.emplace_back(yearNode);
957 resultTags.emplace_back(monthNode);
958 resultTags.emplace_back(dayNode);
959 }
960
HandleMonthChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)961 void DatePickerPattern::HandleMonthChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
962 {
963 auto allChildNode = GetAllChildNode();
964 auto yearNode = allChildNode["year"];
965 auto monthNode = allChildNode["month"];
966 auto dayNode = allChildNode["day"];
967
968 CHECK_NULL_VOID(yearNode);
969 CHECK_NULL_VOID(monthNode);
970 CHECK_NULL_VOID(dayNode);
971 if (IsShowLunar()) {
972 HandleLunarMonthChange(isAdd, index);
973 } else {
974 HandleSolarMonthChange(isAdd, index);
975 }
976 resultTags.emplace_back(yearNode);
977 resultTags.emplace_back(monthNode);
978 resultTags.emplace_back(dayNode);
979 }
980
HandleSolarMonthChange(bool isAdd,uint32_t index)981 void DatePickerPattern::HandleSolarMonthChange(bool isAdd, uint32_t index)
982 {
983 auto date = GetCurrentDate();
984 if (isAdd && date.GetMonth() == 1) { // first month is 1
985 date.SetYear(date.GetYear() + 1); // add 1 year, the next year
986 if (date.GetYear() > endDateSolar_.GetYear()) {
987 date.SetYear(startDateSolar_.GetYear());
988 }
989 }
990 if (!isAdd && date.GetMonth() == 12) { // the last month is 12
991 date.SetYear(date.GetYear() - 1); // reduce 1 year, the previous year
992 if (date.GetYear() < startDateSolar_.GetYear()) {
993 date.SetYear(endDateSolar_.GetYear());
994 }
995 }
996 uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
997 if (date.GetDay() > maxDay) {
998 date.SetDay(maxDay);
999 }
1000 AdjustSolarDate(date);
1001 SolarColumnsBuilding(date);
1002 }
1003
HandleLunarMonthChange(bool isAdd,uint32_t index)1004 void DatePickerPattern::HandleLunarMonthChange(bool isAdd, uint32_t index)
1005 {
1006 auto allChildNode = GetAllChildNode();
1007 auto yearNode = allChildNode["year"];
1008 auto monthNode = allChildNode["month"];
1009 auto dayNode = allChildNode["day"];
1010
1011 CHECK_NULL_VOID(yearNode);
1012 CHECK_NULL_VOID(monthNode);
1013 CHECK_NULL_VOID(dayNode);
1014
1015 auto yearColumn = yearNode->GetPattern<DatePickerColumnPattern>();
1016 CHECK_NULL_VOID(yearColumn);
1017 uint32_t nowLunarYear = startDateLunar_.year + yearColumn->GetCurrentIndex();
1018 auto lunarDate = GetCurrentLunarDate(nowLunarYear);
1019 if (isAdd && index == 0) {
1020 lunarDate.year = lunarDate.year + 1; // add to next year
1021 if (lunarDate.year > endDateLunar_.year) {
1022 lunarDate.year = startDateLunar_.year;
1023 }
1024 }
1025 if (!isAdd && index == GetOptionCount(monthNode) - 1) {
1026 lunarDate.year = lunarDate.year - 1; // reduce to previous year
1027 if (lunarDate.year < startDateLunar_.year) {
1028 lunarDate.year = endDateLunar_.year;
1029 }
1030 }
1031 uint32_t lunarLeapMonth = 0;
1032 bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
1033 if (!hasLeapMonth && lunarDate.isLeapMonth) {
1034 lunarDate.isLeapMonth = false;
1035 }
1036 uint32_t maxDay = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1037 if (lunarDate.day > maxDay) {
1038 lunarDate.day = maxDay;
1039 }
1040
1041 AdjustLunarDate(lunarDate);
1042 LunarColumnsBuilding(lunarDate);
1043 }
1044
HandleLunarYearChange(bool isAdd,uint32_t index)1045 void DatePickerPattern::HandleLunarYearChange(bool isAdd, uint32_t index)
1046 {
1047 auto allChildNode = GetAllChildNode();
1048 auto yearNode = allChildNode["year"];
1049 CHECK_NULL_VOID(yearNode);
1050 auto yearColumn = DynamicCast<FrameNode>(yearNode);
1051 uint32_t lastYearIndex = index;
1052 auto optionCount = GetOptionCount(yearColumn);
1053 if (isAdd) { // need reduce one index
1054 lastYearIndex = optionCount != 0 ? (GetOptionCount(yearColumn) + lastYearIndex - 1) % optionCount : 0;
1055 } else { // need add one index
1056 lastYearIndex = optionCount != 0 ? (GetOptionCount(yearColumn) + lastYearIndex + 1) % optionCount : 0;
1057 }
1058 uint32_t lastLunarYear = startDateLunar_.year + lastYearIndex;
1059 auto lunarDate = GetCurrentLunarDate(lastLunarYear);
1060 uint32_t nowLeapMonth = 0;
1061 bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, nowLeapMonth);
1062 if (!hasLeapMonth && lunarDate.isLeapMonth) {
1063 lunarDate.isLeapMonth = false;
1064 }
1065 uint32_t nowMaxDay = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1066 if (lunarDate.day > nowMaxDay) {
1067 lunarDate.day = nowMaxDay;
1068 }
1069
1070 AdjustLunarDate(lunarDate);
1071 LunarColumnsBuilding(lunarDate);
1072 }
1073
GetCurrentLunarDate(uint32_t lunarYear) const1074 LunarDate DatePickerPattern::GetCurrentLunarDate(uint32_t lunarYear) const
1075 {
1076 LunarDate lunarResult;
1077 auto host = GetHost();
1078 CHECK_NULL_RETURN(host, lunarResult);
1079 auto children = host->GetChildren();
1080 auto iter = children.begin();
1081 auto year = (*iter);
1082 CHECK_NULL_RETURN(year, lunarResult);
1083 std::advance(iter, 1);
1084 auto month = *iter;
1085 CHECK_NULL_RETURN(month, lunarResult);
1086 std::advance(iter, 1);
1087 auto day = *iter;
1088 CHECK_NULL_RETURN(day, lunarResult);
1089
1090 auto stackYear = DynamicCast<FrameNode>(year);
1091 auto yearColumn = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1092 auto stackMonth = DynamicCast<FrameNode>(month);
1093 auto monthColumn = DynamicCast<FrameNode>(stackMonth->GetChildAtIndex(1));
1094 auto stackDay = DynamicCast<FrameNode>(day);
1095 auto dayColumn = DynamicCast<FrameNode>(stackDay->GetChildAtIndex(1));
1096 CHECK_NULL_RETURN_NOLOG(yearColumn, lunarResult);
1097 CHECK_NULL_RETURN_NOLOG(monthColumn, lunarResult);
1098 CHECK_NULL_RETURN_NOLOG(dayColumn, lunarResult);
1099
1100 auto yearDatePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1101 auto monthDatePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1102 auto dayDatePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1103
1104 if (!yearDatePickerColumnPattern || !monthDatePickerColumnPattern || !dayDatePickerColumnPattern) {
1105 LOGE("year or month or day pattern is null.");
1106 return lunarResult;
1107 }
1108
1109 uint32_t lunarLeapMonth = 0;
1110 bool hasLeapMonth = GetLunarLeapMonth(lunarYear, lunarLeapMonth);
1111 lunarResult.isLeapMonth = false;
1112 if (!hasLeapMonth) {
1113 lunarResult.month =
1114 monthDatePickerColumnPattern->GetCurrentIndex() + 1; // month from 1 to 12, index from 0 to 11
1115 } else {
1116 if (monthDatePickerColumnPattern->GetCurrentIndex() == lunarLeapMonth) {
1117 lunarResult.isLeapMonth = true;
1118 lunarResult.month = lunarLeapMonth;
1119 } else if (monthDatePickerColumnPattern->GetCurrentIndex() < lunarLeapMonth) {
1120 lunarResult.month =
1121 monthDatePickerColumnPattern->GetCurrentIndex() + 1; // month start from 1, index start from 0
1122 } else {
1123 lunarResult.month = monthDatePickerColumnPattern->GetCurrentIndex();
1124 }
1125 }
1126 lunarResult.year = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1127 lunarResult.day = dayDatePickerColumnPattern->GetCurrentIndex() + 1; // day start form 1, index start from 0
1128 return lunarResult;
1129 }
1130
HandleSolarYearChange(bool isAdd,uint32_t index)1131 void DatePickerPattern::HandleSolarYearChange(bool isAdd, uint32_t index)
1132 {
1133 auto date = GetCurrentDate();
1134 bool leapYear = PickerDate::IsLeapYear(date.GetYear());
1135
1136 if (date.GetMonth() == 2 && !leapYear && date.GetDay() > 28) { // invalidate of 2th month
1137 date.SetDay(28); // the max day of the 2th month of none leap year is 28
1138 }
1139
1140 AdjustSolarDate(date);
1141 SolarColumnsBuilding(date);
1142 }
1143
GetCurrentDate() const1144 PickerDate DatePickerPattern::GetCurrentDate() const
1145 {
1146 if (ShowMonthDays()) {
1147 return GetCurrentDateByMonthDaysColumn();
1148 } else {
1149 return GetCurrentDateByYearMonthDayColumn();
1150 }
1151 }
1152
GetCurrentDateByYearMonthDayColumn() const1153 PickerDate DatePickerPattern::GetCurrentDateByYearMonthDayColumn() const
1154 {
1155 PickerDate currentDate;
1156 auto host = GetHost();
1157 CHECK_NULL_RETURN(host, currentDate);
1158 auto children = host->GetChildren();
1159 if (children.size() != CHILD_SIZE) {
1160 return currentDate;
1161 }
1162 auto iter = children.begin();
1163 auto year = (*iter);
1164 CHECK_NULL_RETURN(year, currentDate);
1165 iter++;
1166 auto month = *iter;
1167 CHECK_NULL_RETURN(month, currentDate);
1168 iter++;
1169 auto day = *iter;
1170 CHECK_NULL_RETURN(day, currentDate);
1171
1172 auto stackYear = DynamicCast<FrameNode>(year);
1173 auto yearColumn = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1174 auto stackMonth = DynamicCast<FrameNode>(month);
1175 auto monthColumn = DynamicCast<FrameNode>(stackMonth->GetChildAtIndex(1));
1176 auto stackDay = DynamicCast<FrameNode>(day);
1177 auto dayColumn = DynamicCast<FrameNode>(stackDay->GetChildAtIndex(1));
1178 CHECK_NULL_RETURN_NOLOG(yearColumn, currentDate);
1179 CHECK_NULL_RETURN_NOLOG(monthColumn, currentDate);
1180 CHECK_NULL_RETURN_NOLOG(dayColumn, currentDate);
1181 auto yearDatePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1182 auto monthDatePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1183 auto dayDatePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1184
1185 if (!yearDatePickerColumnPattern || !monthDatePickerColumnPattern || !dayDatePickerColumnPattern) {
1186 LOGE("year or month or day pattern is null.");
1187 return currentDate;
1188 }
1189 if (!IsShowLunar()) {
1190 currentDate.SetYear(startDateSolar_.GetYear() + yearDatePickerColumnPattern->GetCurrentIndex());
1191 currentDate.SetMonth(
1192 monthDatePickerColumnPattern->GetCurrentIndex() + 1); // month from 1 to 12, index from 0 to 11.
1193 currentDate.SetDay(dayDatePickerColumnPattern->GetCurrentIndex() + 1); // day from 1 to 31, index from 0 to 30.
1194 return currentDate;
1195 }
1196
1197 uint32_t lunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1198 return LunarToSolar(GetCurrentLunarDate(lunarYear));
1199 }
1200
GetCurrentDateByMonthDaysColumn() const1201 PickerDate DatePickerPattern::GetCurrentDateByMonthDaysColumn() const
1202 {
1203 PickerDate currentDate;
1204 auto host = GetHost();
1205 CHECK_NULL_RETURN(host, currentDate);
1206
1207 auto children = host->GetChildren();
1208 if (children.size() <= SINGLE_CHILD_SIZE) {
1209 return currentDate;
1210 }
1211 auto iter = children.begin();
1212 auto monthDays = (*iter);
1213 CHECK_NULL_RETURN(monthDays, currentDate);
1214 iter++;
1215 auto year = *iter;
1216 CHECK_NULL_RETURN(year, currentDate);
1217 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1218 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1219 auto stackYear = DynamicCast<FrameNode>(year);
1220 auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1221 CHECK_NULL_RETURN_NOLOG(monthDaysNode, currentDate);
1222 CHECK_NULL_RETURN_NOLOG(yearDaysNode, currentDate);
1223
1224 auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1225 auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1226 if (!yearDatePickerColumnPattern || !monthDaysDatePickerColumnPattern) {
1227 LOGE("year or monthDays pattern is null.");
1228 return currentDate;
1229 }
1230
1231 if (!IsShowLunar()) {
1232 currentDate.SetYear(startDateSolar_.GetYear() + yearDatePickerColumnPattern->GetCurrentIndex());
1233 auto monthDaysIndex = monthDaysDatePickerColumnPattern->GetCurrentIndex();
1234
1235 uint32_t month = 1;
1236 for (; month <= 12; ++month) { // month start from 1 to 12
1237 uint32_t daysInMonth = PickerDate::GetMaxDay(currentDate.GetYear(), month);
1238 if (monthDaysIndex < daysInMonth) {
1239 break;
1240 } else {
1241 monthDaysIndex -= daysInMonth;
1242 }
1243 }
1244 currentDate.SetMonth(month);
1245 currentDate.SetDay(monthDaysIndex + 1); // days is index start form 0 and day start form 1.
1246 return currentDate;
1247 }
1248
1249 uint32_t lunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1250 return LunarToSolar(GetCurrentLunarDateByMonthDaysColumn(lunarYear));
1251 }
1252
GetCurrentLunarDateByMonthDaysColumn(uint32_t lunarYear) const1253 LunarDate DatePickerPattern::GetCurrentLunarDateByMonthDaysColumn(uint32_t lunarYear) const
1254 {
1255 LunarDate lunarResult;
1256 auto host = GetHost();
1257 CHECK_NULL_RETURN(host, lunarResult);
1258
1259 auto children = host->GetChildren();
1260 if (children.size() <= SINGLE_CHILD_SIZE) {
1261 return lunarResult;
1262 }
1263 auto iter = children.begin();
1264 auto monthDays = (*iter);
1265 CHECK_NULL_RETURN(monthDays, lunarResult);
1266 iter++;
1267 auto year = *iter;
1268 CHECK_NULL_RETURN(year, lunarResult);
1269 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1270 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1271 auto stackYear = DynamicCast<FrameNode>(year);
1272 auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1273 CHECK_NULL_RETURN_NOLOG(monthDaysNode, lunarResult);
1274 CHECK_NULL_RETURN_NOLOG(yearDaysNode, lunarResult);
1275
1276 auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1277 auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1278 if (!yearDatePickerColumnPattern || !monthDaysDatePickerColumnPattern) {
1279 LOGE("year or month or day pattern is null.");
1280 return lunarResult;
1281 }
1282
1283 uint32_t lunarLeapMonth = 0;
1284 bool hasLeapMonth = GetLunarLeapMonth(lunarYear, lunarLeapMonth);
1285 auto monthDaysIndex = monthDaysDatePickerColumnPattern->GetCurrentIndex();
1286 uint32_t month = 1;
1287 for (; month <= 12; ++month) { // month start from 1 to 12
1288 auto flag = hasLeapMonth && lunarLeapMonth == month;
1289 uint32_t daysInMonth = GetLunarMaxDay(lunarYear, month, flag && lunarResult.isLeapMonth);
1290 if (monthDaysIndex < daysInMonth) {
1291 break;
1292 } else {
1293 monthDaysIndex -= daysInMonth;
1294 }
1295 if (flag && !lunarResult.isLeapMonth) {
1296 --month;
1297 lunarResult.isLeapMonth = true;
1298 }
1299 }
1300 lunarResult.month = month;
1301 lunarResult.isLeapMonth = (lunarResult.month == lunarLeapMonth && hasLeapMonth);
1302 lunarResult.day = monthDaysIndex + 1; // day start form 1, index start from 0
1303 lunarResult.year = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1304
1305 return lunarResult;
1306 }
1307
AdjustLunarDate(LunarDate & date)1308 void DatePickerPattern::AdjustLunarDate(LunarDate& date)
1309 {
1310 auto host = GetHost();
1311 CHECK_NULL_VOID(host);
1312
1313 auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
1314 CHECK_NULL_VOID(dataPickerRowLayoutProperty);
1315 startDateLunar_ = dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_));
1316 endDateLunar_ = dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_));
1317
1318 if (LunarDateCompare(date, startDateLunar_) < 0) {
1319 date = startDateLunar_;
1320 return;
1321 }
1322 if (LunarDateCompare(date, endDateLunar_) > 0) {
1323 date = endDateLunar_;
1324 }
1325 }
1326
LunarDateCompare(const LunarDate & left,const LunarDate & right) const1327 int DatePickerPattern::LunarDateCompare(const LunarDate& left, const LunarDate& right) const
1328 {
1329 static const int leftEqualRight = 0; // means left = right
1330 static const int leftGreatRight = 1; // means left > right
1331 static const int leftLessRight = -1; // means left < right
1332 static const double addingValue = 0.5; // adding value for leap month.
1333 if (left.year > right.year) {
1334 return leftGreatRight;
1335 }
1336 if (left.year < right.year) {
1337 return leftLessRight;
1338 }
1339 double leftMonth = (left.isLeapMonth ? left.month + addingValue : left.month);
1340 double rightMonth = (right.isLeapMonth ? right.month + addingValue : right.month);
1341 if (GreatNotEqual(leftMonth, rightMonth)) {
1342 return leftGreatRight;
1343 }
1344 if (LessNotEqual(leftMonth, rightMonth)) {
1345 return leftLessRight;
1346 }
1347 if (left.day > right.day) {
1348 return leftGreatRight;
1349 }
1350 if (left.day < right.day) {
1351 return leftLessRight;
1352 }
1353 return leftEqualRight;
1354 }
1355
LunarColumnsBuilding(const LunarDate & current)1356 void DatePickerPattern::LunarColumnsBuilding(const LunarDate& current)
1357 {
1358 RefPtr<FrameNode> yearColumn;
1359 RefPtr<FrameNode> monthColumn;
1360 RefPtr<FrameNode> dayColumn;
1361 auto host = GetHost();
1362 CHECK_NULL_VOID(host);
1363 int index = 0;
1364 for (const auto& stackChild : host->GetChildren()) {
1365 CHECK_NULL_VOID(stackChild);
1366 auto child = stackChild->GetChildAtIndex(1);
1367 CHECK_NULL_VOID(child);
1368 if (index == 0) {
1369 yearColumn = GetColumn(child->GetId());
1370 }
1371 if (index == 1) {
1372 monthColumn = GetColumn(child->GetId());
1373 }
1374 if (index == 2) {
1375 dayColumn = GetColumn(child->GetId());
1376 }
1377 index++;
1378 }
1379 CHECK_NULL_VOID(yearColumn);
1380 CHECK_NULL_VOID(monthColumn);
1381 CHECK_NULL_VOID(dayColumn);
1382
1383 AdjustLunarStartEndDate();
1384 auto startYear = startDateLunar_.year;
1385 auto endYear = endDateLunar_.year;
1386 auto startMonth = startDateLunar_.month;
1387 auto endMonth = endDateLunar_.month;
1388 auto startDay = startDateLunar_.day;
1389 auto endDay = endDateLunar_.day;
1390 uint32_t maxDay = GetLunarMaxDay(current.year, current.month, current.isLeapMonth);
1391 if (startYear < endYear) {
1392 startMonth = 1;
1393 endMonth = 12;
1394 startDay = 1;
1395 endDay = maxDay;
1396 }
1397 if (startYear == endYear && startMonth < endMonth) {
1398 startDay = 1;
1399 endDay = maxDay;
1400 }
1401
1402 options_[yearColumn].clear();
1403 for (uint32_t index = startYear; index <= endYear; ++index) {
1404 if (current.year == index) {
1405 auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1406 CHECK_NULL_VOID(datePickerColumnPattern);
1407 datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1408 }
1409 auto yearTextValue = GetYearFormatString(index);
1410 options_[yearColumn].emplace_back(yearTextValue);
1411 }
1412
1413 uint32_t lunarLeapMonth = 0;
1414 bool hasLeapMonth = GetLunarLeapMonth(current.year, lunarLeapMonth);
1415 options_[monthColumn].clear();
1416 if (startYear == endYear) {
1417 options_[monthColumn].resize(startMonth - 1, "");
1418 }
1419 // lunar's month start form startMonth to endMonth
1420 for (uint32_t index = startMonth; index <= endMonth; ++index) {
1421 if (!current.isLeapMonth && current.month == index) {
1422 auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1423 CHECK_NULL_VOID(datePickerColumnPattern);
1424 datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
1425 }
1426 auto monthTextValue = GetMonthFormatString(index, true, false);
1427 options_[monthColumn].emplace_back(monthTextValue);
1428
1429 if (hasLeapMonth && lunarLeapMonth == index) {
1430 if (current.isLeapMonth && current.month == index) {
1431 auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1432 CHECK_NULL_VOID(datePickerColumnPattern);
1433 datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
1434 }
1435 auto monthTextValue = GetMonthFormatString(index, true, true);
1436 options_[monthColumn].emplace_back(monthTextValue);
1437 }
1438 }
1439
1440 options_[dayColumn].clear();
1441 if (startYear == endYear && startMonth == endMonth) {
1442 options_[dayColumn].resize(startDay - 1, "");
1443 }
1444 // lunar's day start from startDay
1445 for (uint32_t index = startDay; index <= endDay; ++index) {
1446 if (current.day == index) {
1447 auto datePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1448 CHECK_NULL_VOID(datePickerColumnPattern);
1449 datePickerColumnPattern->SetCurrentIndex(options_[dayColumn].size());
1450 }
1451 auto dayTextValue = GetDayFormatString(index, true);
1452 options_[dayColumn].emplace_back(dayTextValue);
1453 }
1454 auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1455 CHECK_NULL_VOID(yearColumnPattern);
1456 auto monthColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1457 CHECK_NULL_VOID(monthColumnPattern);
1458 auto dayColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1459 CHECK_NULL_VOID(dayColumnPattern);
1460 yearColumnPattern->SetOptions(GetOptions());
1461 monthColumnPattern->SetOptions(GetOptions());
1462 dayColumnPattern->SetOptions(GetOptions());
1463
1464 SetShowLunar(true);
1465 }
1466
SolarColumnsBuilding(const PickerDate & current)1467 void DatePickerPattern::SolarColumnsBuilding(const PickerDate& current)
1468 {
1469 RefPtr<FrameNode> yearColumn;
1470 RefPtr<FrameNode> monthColumn;
1471 RefPtr<FrameNode> dayColumn;
1472 auto host = GetHost();
1473 CHECK_NULL_VOID(host);
1474 int index = 0;
1475 for (const auto& stackChild : host->GetChildren()) {
1476 CHECK_NULL_VOID(stackChild);
1477 auto child = stackChild->GetChildAtIndex(1);
1478 if (index == 0) {
1479 yearColumn = GetColumn(child->GetId());
1480 }
1481 if (index == 1) {
1482 monthColumn = GetColumn(child->GetId());
1483 }
1484 if (index == 2) {
1485 dayColumn = GetColumn(child->GetId());
1486 }
1487 index++;
1488 }
1489 CHECK_NULL_VOID(yearColumn);
1490 CHECK_NULL_VOID(monthColumn);
1491 CHECK_NULL_VOID(dayColumn);
1492
1493 AdjustSolarStartEndDate();
1494 auto startYear = startDateSolar_.GetYear();
1495 auto endYear = endDateSolar_.GetYear();
1496 auto startMonth = startDateSolar_.GetMonth();
1497 auto endMonth = endDateSolar_.GetMonth();
1498 auto startDay = startDateSolar_.GetDay();
1499 auto endDay = endDateSolar_.GetDay();
1500
1501 uint32_t maxDay = PickerDate::GetMaxDay(current.GetYear(), current.GetMonth());
1502 if (startYear < endYear) {
1503 startMonth = 1;
1504 endMonth = 12;
1505 startDay = 1;
1506 endDay = maxDay;
1507 }
1508 if (startYear == endYear && startMonth < endMonth) {
1509 startDay = 1;
1510 endDay = maxDay;
1511 }
1512
1513 options_[yearColumn].clear();
1514 for (uint32_t year = startYear; year <= endYear; ++year) {
1515 if (year == current.GetYear()) {
1516 auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1517 CHECK_NULL_VOID(datePickerColumnPattern);
1518 datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1519 }
1520 auto yearTextValue = GetYearFormatString(year);
1521 options_[yearColumn].emplace_back(yearTextValue);
1522 }
1523
1524 options_[monthColumn].clear();
1525 if (startYear == endYear) {
1526 options_[monthColumn].resize(startMonth - 1, "");
1527 }
1528 // solar's month start form 1 to 12
1529 for (uint32_t month = startMonth; month <= endMonth; month++) {
1530 if (month == current.GetMonth()) {
1531 auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1532 CHECK_NULL_VOID(datePickerColumnPattern);
1533 // back index = size - 1
1534 datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
1535 }
1536
1537 auto monthTextValue = GetMonthFormatString(month, false, false);
1538 options_[monthColumn].emplace_back(monthTextValue);
1539 }
1540
1541 options_[dayColumn].clear();
1542 if (startYear == endYear && startMonth == endMonth) {
1543 options_[dayColumn].resize(startDay - 1, "");
1544 }
1545 // solar's day start from 1
1546 for (uint32_t day = startDay; day <= endDay; day++) {
1547 if (day == current.GetDay()) {
1548 auto datePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1549 CHECK_NULL_VOID(datePickerColumnPattern);
1550 datePickerColumnPattern->SetCurrentIndex(options_[dayColumn].size());
1551 }
1552 auto dayTextValue = GetDayFormatString(day, false);
1553 options_[dayColumn].emplace_back(dayTextValue);
1554 }
1555
1556 auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1557 CHECK_NULL_VOID(yearColumnPattern);
1558 auto monthColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1559 CHECK_NULL_VOID(monthColumnPattern);
1560 auto dayColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1561 CHECK_NULL_VOID(dayColumnPattern);
1562 yearColumnPattern->SetOptions(GetOptions());
1563 monthColumnPattern->SetOptions(GetOptions());
1564 dayColumnPattern->SetOptions(GetOptions());
1565
1566 SetShowLunar(false);
1567 }
1568
LunarMonthDaysColumnBuilding(const LunarDate & current)1569 void DatePickerPattern::LunarMonthDaysColumnBuilding(const LunarDate& current)
1570 {
1571 RefPtr<FrameNode> monthDaysColumn;
1572 RefPtr<FrameNode> yearColumn;
1573 auto host = GetHost();
1574 CHECK_NULL_VOID(host);
1575
1576 auto children = host->GetChildren();
1577 if (children.size() <= SINGLE_CHILD_SIZE) {
1578 return;
1579 }
1580
1581 auto iter = children.begin();
1582 auto monthDays = (*iter);
1583 CHECK_NULL_VOID(monthDays);
1584 iter++;
1585 auto year = *iter;
1586 CHECK_NULL_VOID(year);
1587 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1588 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1589 auto stackYear = DynamicCast<FrameNode>(year);
1590 auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1591 CHECK_NULL_VOID(monthDaysNode);
1592 CHECK_NULL_VOID(yearDaysNode);
1593
1594 monthDaysColumn = GetColumn(monthDaysNode->GetId());
1595 yearColumn = GetColumn(yearDaysNode->GetId());
1596 CHECK_NULL_VOID(monthDaysColumn);
1597 CHECK_NULL_VOID(yearColumn);
1598
1599 AdjustLunarStartEndDate();
1600
1601 auto startYear = startDateLunar_.year;
1602 auto endYear = endDateLunar_.year;
1603
1604 options_[yearColumn].clear();
1605 for (uint32_t index = startYear; index <= endYear; ++index) {
1606 if (current.year == index) {
1607 auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1608 CHECK_NULL_VOID(datePickerColumnPattern);
1609 datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1610 }
1611 auto yearTextValue = GetYearFormatString(index);
1612 options_[yearColumn].emplace_back(yearTextValue);
1613 }
1614
1615 FillLunarMonthDaysOptions(current, monthDaysColumn);
1616
1617 auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1618 auto monthDaysColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1619 CHECK_NULL_VOID(yearColumnPattern);
1620 CHECK_NULL_VOID(monthDaysColumnPattern);
1621 yearColumnPattern->SetOptions(GetOptions());
1622 monthDaysColumnPattern->SetOptions(GetOptions());
1623
1624 SetShowLunar(true);
1625 }
1626
SolarMonthDaysColumnsBuilding(const PickerDate & current)1627 void DatePickerPattern::SolarMonthDaysColumnsBuilding(const PickerDate& current)
1628 {
1629 RefPtr<FrameNode> monthDaysColumn;
1630 RefPtr<FrameNode> yearColumn;
1631 auto host = GetHost();
1632 CHECK_NULL_VOID(host);
1633
1634 auto children = host->GetChildren();
1635 if (children.size() <= SINGLE_CHILD_SIZE) {
1636 return;
1637 }
1638 auto iter = children.begin();
1639 auto monthDays = (*iter);
1640 CHECK_NULL_VOID(monthDays);
1641 iter++;
1642 auto year = *iter;
1643 CHECK_NULL_VOID(year);
1644 auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1645 auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1646 auto stackYear = DynamicCast<FrameNode>(year);
1647 auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1648 monthDaysColumn = GetColumn(monthDaysNode->GetId());
1649 yearColumn = GetColumn(yearDaysNode->GetId());
1650 CHECK_NULL_VOID(monthDaysColumn);
1651 CHECK_NULL_VOID(yearColumn);
1652
1653 AdjustSolarStartEndDate();
1654 FillSolarYearOptions(current, yearColumn);
1655
1656 options_[monthDaysColumn].clear();
1657 for (uint32_t index = MIN_MONTH; index <= MAX_MONTH; ++index) {
1658 uint32_t maxDay = PickerDate::GetMaxDay(current.GetYear(), index);
1659 auto monthTextValue = GetMonthFormatString(index, false, false);
1660 for (uint32_t dayIndex = MIN_DAY; dayIndex <= maxDay; ++dayIndex) {
1661 if (index == current.GetMonth() && dayIndex == current.GetDay()) {
1662 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1663 CHECK_NULL_VOID(datePickerColumnPattern);
1664 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
1665 }
1666 auto dayTextValue = GetDayFormatString(dayIndex, false);
1667 options_[monthDaysColumn].emplace_back(monthTextValue + dayTextValue);
1668 }
1669 }
1670
1671 auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1672 auto monthDaysColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1673 CHECK_NULL_VOID(yearColumnPattern);
1674 CHECK_NULL_VOID(monthDaysColumnPattern);
1675 yearColumnPattern->SetOptions(GetOptions());
1676 monthDaysColumnPattern->SetOptions(GetOptions());
1677
1678 SetShowLunar(false);
1679 }
1680
FillSolarYearOptions(const PickerDate & current,RefPtr<FrameNode> & yearColumn)1681 void DatePickerPattern::FillSolarYearOptions(const PickerDate& current, RefPtr<FrameNode>& yearColumn)
1682 {
1683 options_[yearColumn].clear();
1684 for (uint32_t year = startDateSolar_.GetYear(); year <= endDateSolar_.GetYear(); ++year) {
1685 if (year == current.GetYear()) {
1686 auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1687 CHECK_NULL_VOID(datePickerColumnPattern);
1688 datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1689 }
1690 auto yearTextValue = GetYearFormatString(year);
1691 options_[yearColumn].emplace_back(yearTextValue);
1692 }
1693 }
1694
FillLunarMonthDaysOptions(const LunarDate & current,RefPtr<FrameNode> & monthDaysColumn)1695 void DatePickerPattern::FillLunarMonthDaysOptions(const LunarDate& current, RefPtr<FrameNode>& monthDaysColumn)
1696 {
1697 uint32_t startMonth = 1;
1698 uint32_t endMonth = 12;
1699 uint32_t startDay = 1;
1700
1701 uint32_t lunarLeapMonth = 0;
1702 bool hasLeapMonth = GetLunarLeapMonth(current.year, lunarLeapMonth);
1703 options_[monthDaysColumn].clear();
1704
1705 for (uint32_t index = startMonth; index <= endMonth; ++index) {
1706 uint32_t maxDay = GetLunarMaxDay(current.year, index, false);
1707 auto monthTextValue = GetMonthFormatString(index, true, false);
1708 for (uint32_t dayIndex = startDay; dayIndex <= maxDay; ++dayIndex) {
1709 if (!current.isLeapMonth && current.month == index && current.day == dayIndex) {
1710 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1711 CHECK_NULL_VOID(datePickerColumnPattern);
1712 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
1713 }
1714 auto dayTextValue = GetDayFormatString(dayIndex, true);
1715 options_[monthDaysColumn].emplace_back(monthTextValue + dayTextValue);
1716 }
1717
1718 if (!hasLeapMonth || lunarLeapMonth != index) {
1719 continue;
1720 }
1721
1722 maxDay = GetLunarMaxDay(current.year, index, true);
1723 monthTextValue = GetMonthFormatString(index, true, true);
1724 for (uint32_t dayIndex = startDay; dayIndex <= maxDay; ++dayIndex) {
1725 if (current.isLeapMonth && current.month == index && current.day == dayIndex) {
1726 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1727 CHECK_NULL_VOID(datePickerColumnPattern);
1728 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
1729 }
1730 auto dayTextValue = GetDayFormatString(dayIndex, true);
1731 options_[monthDaysColumn].emplace_back(monthTextValue + dayTextValue);
1732 }
1733 }
1734 }
1735
AdjustSolarStartEndDate()1736 void DatePickerPattern::AdjustSolarStartEndDate()
1737 {
1738 auto host = GetHost();
1739 CHECK_NULL_VOID(host);
1740
1741 auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
1742 CHECK_NULL_VOID(dataPickerRowLayoutProperty);
1743 startDateSolar_ = LunarToSolar(dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_)));
1744 endDateSolar_ = LunarToSolar(dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_)));
1745
1746 if (startDateSolar_.GetYear() > endDateSolar_.GetYear()) {
1747 startDateSolar_ = startDefaultDateSolar_;
1748 endDateSolar_ = endDefaultDateSolar_;
1749 }
1750 if (startDateSolar_.GetYear() == endDateSolar_.GetYear() && startDateSolar_.GetMonth() > endDateSolar_.GetMonth()) {
1751 startDateSolar_ = startDefaultDateSolar_;
1752 endDateSolar_ = endDefaultDateSolar_;
1753 }
1754 if (startDateSolar_.GetYear() == endDateSolar_.GetYear() &&
1755 startDateSolar_.GetMonth() == endDateSolar_.GetMonth() && startDateSolar_.GetDay() > endDateSolar_.GetDay()) {
1756 startDateSolar_ = startDefaultDateSolar_;
1757 endDateSolar_ = endDefaultDateSolar_;
1758 }
1759 }
1760
AdjustLunarStartEndDate()1761 void DatePickerPattern::AdjustLunarStartEndDate()
1762 {
1763 auto host = GetHost();
1764 CHECK_NULL_VOID(host);
1765
1766 auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
1767 CHECK_NULL_VOID(dataPickerRowLayoutProperty);
1768 startDateLunar_ = dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_));
1769 endDateLunar_ = dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_));
1770
1771 if (GetStartDateLunar().year > GetEndDateLunar().year) {
1772 startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
1773 endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
1774 }
1775 if (GetStartDateLunar().year == GetEndDateLunar().year && GetStartDateLunar().month > GetEndDateLunar().month) {
1776 startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
1777 endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
1778 }
1779 if (GetStartDateLunar().year == GetEndDateLunar().year && GetStartDateLunar().month == GetEndDateLunar().month &&
1780 GetStartDateLunar().day > GetEndDateLunar().day) {
1781 startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
1782 endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
1783 }
1784 }
1785
GetLunarLeapMonth(uint32_t year,uint32_t & outLeapMonth) const1786 bool DatePickerPattern::GetLunarLeapMonth(uint32_t year, uint32_t& outLeapMonth) const
1787 {
1788 auto leapMonth = LunarCalculator::GetLunarLeapMonth(year);
1789 if (leapMonth <= 0) {
1790 return false;
1791 }
1792
1793 outLeapMonth = static_cast<uint32_t>(leapMonth);
1794 return true;
1795 }
1796
GetLunarMaxDay(uint32_t year,uint32_t month,bool isLeap) const1797 uint32_t DatePickerPattern::GetLunarMaxDay(uint32_t year, uint32_t month, bool isLeap) const
1798 {
1799 if (isLeap) {
1800 return static_cast<uint32_t>(LunarCalculator::GetLunarLeapDays(year));
1801 } else {
1802 return static_cast<uint32_t>(LunarCalculator::GetLunarMonthDays(year, month));
1803 }
1804 }
1805
SolarToLunar(const PickerDate & date) const1806 LunarDate DatePickerPattern::SolarToLunar(const PickerDate& date) const
1807 {
1808 Date result;
1809 result.year = date.GetYear();
1810 result.month = date.GetMonth();
1811 result.day = date.GetDay();
1812 return Localization::GetInstance()->GetLunarDate(result);
1813 }
1814
LunarToSolar(const LunarDate & date) const1815 PickerDate DatePickerPattern::LunarToSolar(const LunarDate& date) const
1816 {
1817 uint32_t days = date.day - 1; // calculate days from 1900.1.1 to this date
1818 if (date.isLeapMonth) {
1819 days += LunarCalculator::GetLunarMonthDays(date.year, date.month);
1820 } else {
1821 uint32_t leapMonth = LunarCalculator::GetLunarLeapMonth(date.year);
1822 if (leapMonth < date.month) {
1823 days += LunarCalculator::GetLunarLeapDays(date.year);
1824 }
1825 }
1826 for (uint32_t month = 1; month < date.month; ++month) { // month start from 1
1827 days += LunarCalculator::GetLunarMonthDays(date.year, month);
1828 }
1829 for (uint32_t year = 1900; year < date.year; ++year) { // year start from 1900
1830 days += LunarCalculator::GetLunarYearDays(year);
1831 }
1832 days += 30; // days from solar's 1900.1.1 to lunar's 1900.1.1 is 30
1833 PickerDate result;
1834 result.FromDays(days);
1835 return result;
1836 }
1837
Init()1838 void DatePickerPattern::Init()
1839 {
1840 CHECK_NULL_VOID_NOLOG(!inited_);
1841 years_.resize(201); // year from 1900 to 2100,count is 201
1842 solarMonths_.resize(12); // solar month from 1 to 12,count is 12
1843 solarDays_.resize(31); // solar day from 1 to 31, count is 31
1844 lunarMonths_.resize(24); // lunar month from 1 to 24, count is 24
1845 lunarDays_.resize(30); // lunar day from 1 to 30, count is 30
1846 // init year from 1900 to 2100
1847 for (uint32_t year = 1900; year <= 2100; ++year) {
1848 DateTime date;
1849 date.year = year;
1850 years_[year - 1900] = Localization::GetInstance()->FormatDateTime(date, "y"); // index start from 0
1851 }
1852 // init solar month from 1 to 12
1853 auto months = Localization::GetInstance()->GetMonths(true);
1854 for (uint32_t month = 1; month <= 12; ++month) {
1855 if (month - 1 < months.size()) {
1856 solarMonths_[month - 1] = months[month - 1];
1857 continue;
1858 }
1859 DateTime date;
1860 date.month = month - 1; // W3C's month start from 0 to 11
1861 solarMonths_[month - 1] = Localization::GetInstance()->FormatDateTime(date, "M"); // index start from 0
1862 }
1863 // init solar day from 1 to 31
1864 for (uint32_t day = 1; day <= 31; ++day) {
1865 DateTime date;
1866 date.day = day;
1867 solarDays_[day - 1] = Localization::GetInstance()->FormatDateTime(date, "d"); // index start from 0
1868 }
1869 // init lunar month from 1 to 24 which is 1th, 2th, ... leap 1th, leap 2th ...
1870 for (uint32_t index = 1; index <= 24; ++index) {
1871 uint32_t month = (index > 12 ? index - 12 : index);
1872 bool isLeap = (index > 12);
1873 lunarMonths_[index - 1] = Localization::GetInstance()->GetLunarMonth(month, isLeap); // index start from 0
1874 }
1875 // init lunar day from 1 to 30
1876 for (uint32_t day = 1; day <= 30; ++day) {
1877 lunarDays_[day - 1] = Localization::GetInstance()->GetLunarDay(day); // index start from 0
1878 }
1879 inited_ = true;
1880 Localization::GetInstance()->SetOnChange([]() { inited_ = false; });
1881 }
1882
GetYear(uint32_t year)1883 const std::string& DatePickerPattern::GetYear(uint32_t year)
1884 {
1885 Init();
1886 if (!(1900 <= year && year <= 2100)) { // year in [1900,2100]
1887 return empty_;
1888 }
1889 return years_[year - 1900]; // index in [0, 200]
1890 }
1891
GetSolarMonth(uint32_t month)1892 const std::string& DatePickerPattern::GetSolarMonth(uint32_t month)
1893 {
1894 Init();
1895 if (!(1 <= month && month <= 12)) { // solar month in [1,12]
1896 return empty_;
1897 }
1898 return solarMonths_[month - 1]; // index in [0,11]
1899 }
1900
GetSolarDay(uint32_t day)1901 const std::string& DatePickerPattern::GetSolarDay(uint32_t day)
1902 {
1903 Init();
1904 if (!(1 <= day && day <= 31)) { // solar day in [1,31]
1905 return empty_;
1906 }
1907 return solarDays_[day - 1]; // index in [0,30]
1908 }
1909
GetLunarMonth(uint32_t month,bool isLeap)1910 const std::string& DatePickerPattern::GetLunarMonth(uint32_t month, bool isLeap)
1911 {
1912 Init();
1913 uint32_t index = (isLeap ? month + 12 : month); // leap month is behind 12 index
1914 if (!(1 <= index && index <= 24)) { // lunar month need in [1,24]
1915 return empty_;
1916 }
1917 return lunarMonths_[index - 1]; // index in [0,23]
1918 }
1919
GetLunarDay(uint32_t day)1920 const std::string& DatePickerPattern::GetLunarDay(uint32_t day)
1921 {
1922 Init();
1923 if (!(1 <= day && day <= 30)) { // lunar day need in [1,30]
1924 return empty_;
1925 }
1926 return lunarDays_[day - 1]; // index in [0,29]
1927 }
1928
ToJsonValue(std::unique_ptr<JsonValue> & json) const1929 void DatePickerPattern::ToJsonValue(std::unique_ptr<JsonValue>& json) const
1930 {
1931 auto GetDateString = [](const PickerDate& pickerDate) {
1932 std::string ret;
1933 ret += std::to_string(pickerDate.GetYear());
1934 ret += "-";
1935 ret += std::to_string(pickerDate.GetMonth());
1936 ret += "-";
1937 ret += std::to_string(pickerDate.GetDay());
1938 return ret;
1939 };
1940 auto rowLayoutProperty = GetLayoutProperty<DataPickerRowLayoutProperty>();
1941 CHECK_NULL_VOID(rowLayoutProperty);
1942 auto jsonConstructor = JsonUtil::Create(true);
1943 auto isLunar = rowLayoutProperty->GetLunarValue(false);
1944 if (isLunar) {
1945 jsonConstructor->Put("start", rowLayoutProperty->GetDateStart().c_str());
1946 jsonConstructor->Put("end", rowLayoutProperty->GetDateEnd().c_str());
1947 jsonConstructor->Put("selected", rowLayoutProperty->GetDateSelected().c_str());
1948 } else {
1949 jsonConstructor->Put("start", GetDateString(startDateSolar_).c_str());
1950 jsonConstructor->Put("end", GetDateString(endDateSolar_).c_str());
1951 jsonConstructor->Put("selected", GetDateString(selectedDate_).c_str());
1952 }
1953 json->Put("constructor", jsonConstructor);
1954 }
1955
SetFocusDisable()1956 void DatePickerPattern::SetFocusDisable()
1957 {
1958 auto host = GetHost();
1959 CHECK_NULL_VOID(host);
1960
1961 auto focusHub = host->GetFocusHub();
1962 CHECK_NULL_VOID(focusHub);
1963
1964 focusHub->SetFocusable(false);
1965 }
1966
SetFocusEnable()1967 void DatePickerPattern::SetFocusEnable()
1968 {
1969 auto host = GetHost();
1970 CHECK_NULL_VOID(host);
1971
1972 auto focusHub = host->GetFocusHub();
1973 CHECK_NULL_VOID(focusHub);
1974
1975 focusHub->SetFocusable(true);
1976 }
1977 } // namespace OHOS::Ace::NG
1978