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