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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_DATE_PICKER_DATE_PICKER_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_DATE_PICKER_DATE_PICKER_PATTERN_H 18 19 #include <optional> 20 21 #include "core/components/common/layout/constants.h" 22 #include "core/components/picker/picker_data.h" 23 #include "core/components/picker/picker_theme.h" 24 #include "core/components_ng/base/frame_node.h" 25 #include "core/components_ng/event/event_hub.h" 26 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" 27 #include "core/components_ng/pattern/pattern.h" 28 #include "core/components_ng/pattern/picker/datepicker_accessibility_property.h" 29 #include "core/components_ng/pattern/picker/datepicker_column_pattern.h" 30 #include "core/components_ng/pattern/picker/datepicker_event_hub.h" 31 #include "core/components_ng/pattern/picker/datepicker_layout_property.h" 32 #include "core/components_ng/pattern/picker/datepicker_row_layout_property.h" 33 #include "core/components_ng/pattern/text/text_pattern.h" 34 #include "core/components_ng/pattern/picker/datepicker_dialog_view.h" 35 36 namespace OHOS::Ace::NG { 37 namespace { 38 const Dimension FOCUS_PAINT_WIDTH = 2.0_vp; 39 } 40 41 class DatePickerPattern : public LinearLayoutPattern { 42 DECLARE_ACE_TYPE(DatePickerPattern, LinearLayoutPattern); 43 44 public: DatePickerPattern()45 DatePickerPattern() : LinearLayoutPattern(false) {}; 46 47 ~DatePickerPattern() override = default; 48 IsAtomicNode()49 bool IsAtomicNode() const override 50 { 51 return true; 52 } 53 CreateEventHub()54 RefPtr<EventHub> CreateEventHub() override 55 { 56 return MakeRefPtr<DatePickerEventHub>(); 57 } 58 CreateLayoutAlgorithm()59 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override 60 { 61 return MakeRefPtr<LinearLayoutAlgorithm>(); 62 } 63 CreateLayoutProperty()64 RefPtr<LayoutProperty> CreateLayoutProperty() override 65 { 66 return MakeRefPtr<DataPickerRowLayoutProperty>(); 67 } 68 CreateNodePaintMethod()69 RefPtr<NodePaintMethod> CreateNodePaintMethod() override 70 { 71 auto paintMethod = MakeRefPtr<DatePickerPaintMethod>(WeakClaim(this)); 72 paintMethod->SetEnabled(enabled_); 73 paintMethod->SetBackgroundColor(backgroundColor_); 74 return paintMethod; 75 } 76 CreateAccessibilityProperty()77 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 78 { 79 return MakeRefPtr<DatePickerAccessibilityProperty>(); 80 } 81 SetConfirmNode(WeakPtr<FrameNode> buttonConfirmNode)82 void SetConfirmNode(WeakPtr<FrameNode> buttonConfirmNode) 83 { 84 weakButtonConfirm_ = buttonConfirmNode; 85 } 86 SetCancelNode(WeakPtr<FrameNode> buttonCancelNode)87 void SetCancelNode(WeakPtr<FrameNode> buttonCancelNode) 88 { 89 weakButtonCancel_ = buttonCancelNode; 90 } 91 92 void OnLanguageConfigurationUpdate() override; 93 94 void OnColorConfigurationUpdate() override; 95 96 void SetChangeCallback(ColumnChangeCallback&& value); 97 98 void HandleColumnChange(const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, bool needNotify); 99 100 void SolarColumnsBuilding(const PickerDate& current); 101 102 void LunarColumnsBuilding(const LunarDate& current); 103 104 void SolarMonthDaysColumnsBuilding(const PickerDate& current); 105 106 void LunarMonthDaysColumnBuilding(const LunarDate& current); 107 108 void HandleYearChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags); 109 110 void HandleMonthChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags); 111 112 void HandleLunarMonthChange(bool isAdd, uint32_t index); 113 114 void HandleLunarYearChange(bool isAdd, uint32_t index); 115 116 void HandleSolarYearChange(bool isAdd, uint32_t index); 117 118 LunarDate GetCurrentLunarDate(uint32_t lunarYear) const; 119 120 void HandleSolarMonthChange(bool isAdd, uint32_t index); 121 122 void HandleDayChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags); 123 124 void HandleReduceLunarDayChange(uint32_t index); 125 126 void HandleLunarDayChange(bool isAdd, uint32_t index); 127 128 void HandleAddLunarDayChange(uint32_t index); 129 130 void HandleSolarDayChange(bool isAdd, uint32_t index); 131 132 void HandleSolarMonthDaysChange(bool isAdd, uint32_t index); 133 134 void HandleLunarMonthDaysChange(bool isAdd, uint32_t index); 135 136 void HandleAddLunarMonthDaysChange(uint32_t index); 137 138 void HandleReduceLunarMonthDaysChange(uint32_t index); 139 140 LunarDate GetCurrentLunarDateByMonthDaysColumn(uint32_t lunarYear) const; 141 142 PickerDate GetCurrentDate() const; 143 144 void SetEventCallback(EventCallback&& value); 145 146 void FireChangeEvent(bool refresh) const; 147 148 void FlushColumn(); 149 150 void FlushMonthDaysColumn(); 151 152 void AdjustLunarDate(LunarDate& date); 153 154 int LunarDateCompare(const LunarDate& left, const LunarDate& right) const; 155 156 std::unordered_map<std::string, RefPtr<FrameNode>> GetAllChildNode(); 157 GetColumn(const int32_t & tag)158 RefPtr<FrameNode> GetColumn(const int32_t& tag) const 159 { 160 auto iter = std::find_if(datePickerColumns_.begin(), datePickerColumns_.end(), 161 [&tag](const RefPtr<FrameNode>& column) { return column->GetId() == tag; }); 162 return (iter == datePickerColumns_.end()) ? nullptr : *iter; 163 } 164 SetColumn(const RefPtr<FrameNode> & value)165 void SetColumn(const RefPtr<FrameNode>& value) 166 { 167 datePickerColumns_.emplace_back(value); 168 } 169 ClearColumn()170 void ClearColumn() 171 { 172 datePickerColumns_.clear(); 173 } 174 SetShowLunar(bool value)175 void SetShowLunar(bool value) 176 { 177 lunar_ = value; 178 } 179 IsShowLunar()180 bool IsShowLunar() const 181 { 182 return lunar_; 183 } 184 SetShowMonthDaysFlag(bool value)185 void SetShowMonthDaysFlag(bool value) 186 { 187 showMonthDays_ = value; 188 } 189 ShowMonthDays()190 bool ShowMonthDays() const 191 { 192 return showMonthDays_; 193 } 194 SetShowTimeFlag(bool value)195 void SetShowTimeFlag(bool value) 196 { 197 showTime_ = value; 198 } 199 GetDialogAcceptEvent()200 const EventMarker& GetDialogAcceptEvent() const 201 { 202 return OnDialogAccept_; 203 } SetDialogAcceptEvent(const EventMarker & value)204 void SetDialogAcceptEvent(const EventMarker& value) 205 { 206 OnDialogAccept_ = value; 207 } 208 GetDialogCancelEvent()209 const EventMarker& GetDialogCancelEvent() const 210 { 211 return OnDialogCancel_; 212 } SetDialogCancelEvent(const EventMarker & value)213 void SetDialogCancelEvent(const EventMarker& value) 214 { 215 OnDialogCancel_ = value; 216 } 217 GetDialogChangeEvent()218 const EventMarker& GetDialogChangeEvent() const 219 { 220 return OnDialogChange_; 221 } SetDialogChangeEvent(const EventMarker & value)222 void SetDialogChangeEvent(const EventMarker& value) 223 { 224 OnDialogChange_ = value; 225 } 226 SetResizePickerItemHeight(double resizePickerItemHeight)227 void SetResizePickerItemHeight(double resizePickerItemHeight) 228 { 229 resizePickerItemHeight_ = resizePickerItemHeight; 230 } 231 GetResizePickerItemHeight()232 double GetResizePickerItemHeight() const 233 { 234 return resizePickerItemHeight_; 235 } 236 SetResizeFlag(bool resizeFlag)237 void SetResizeFlag(bool resizeFlag) 238 { 239 resizeFlag_ = resizeFlag; 240 } 241 GetResizeFlag()242 bool GetResizeFlag() const 243 { 244 return resizeFlag_; 245 } 246 SetIsShowInDialog(bool isShowInDialog)247 void SetIsShowInDialog(bool isShowInDialog) 248 { 249 isShowInDialog_ = isShowInDialog; 250 } 251 GetIsShowInDialog()252 bool GetIsShowInDialog() const 253 { 254 return isShowInDialog_; 255 } 256 GetOptionCount(RefPtr<FrameNode> & frmeNode)257 uint32_t GetOptionCount(RefPtr<FrameNode>& frmeNode) 258 { 259 return options_[frmeNode].size(); 260 } 261 GetOptionValue(RefPtr<FrameNode> & frmeNode,uint32_t index)262 std::string GetOptionValue(RefPtr<FrameNode>& frmeNode, uint32_t index) 263 { 264 if (index >= GetOptionCount(frmeNode)) { 265 LOGE("index out of range."); 266 return nullptr; 267 } 268 return options_[frmeNode][index]; 269 } 270 GetAllOptions(RefPtr<FrameNode> & frmeNode)271 const std::vector<std::string>& GetAllOptions(RefPtr<FrameNode>& frmeNode) 272 { 273 return options_[frmeNode]; 274 } 275 GetOptions()276 const std::map<RefPtr<FrameNode>, std::vector<std::string>>& GetOptions() const 277 { 278 return options_; 279 } 280 GetShowCount()281 uint32_t GetShowCount() const 282 { 283 return showCount_; 284 } 285 SetShowCount(uint32_t showCount)286 void SetShowCount(uint32_t showCount) 287 { 288 showCount_ = showCount; 289 } 290 GetYearFormatString(uint32_t year)291 static std::string GetYearFormatString(uint32_t year) 292 { 293 return PickerStringFormatter::GetYear(year); 294 } 295 GetMonthFormatString(uint32_t month,bool isLunar,bool isLeap)296 static std::string GetMonthFormatString(uint32_t month, bool isLunar, bool isLeap) 297 { 298 if (isLunar) { 299 return PickerStringFormatter::GetLunarMonth(month, isLeap); 300 } 301 return PickerStringFormatter::GetSolarMonth(month); 302 } 303 GetDayFormatString(uint32_t day,bool isLunar)304 static std::string GetDayFormatString(uint32_t day, bool isLunar) 305 { 306 if (isLunar) { 307 return PickerStringFormatter::GetLunarDay(day); 308 } 309 return PickerStringFormatter::GetSolarDay(day); 310 } 311 312 uint32_t GetLunarMaxDay(uint32_t year, uint32_t month, bool isLeap) const; 313 314 bool GetLunarLeapMonth(uint32_t year, uint32_t& outLeapMonth) const; 315 316 LunarDate SolarToLunar(const PickerDate& date) const; 317 318 PickerDate LunarToSolar(const LunarDate& date) const; 319 320 void UpdateCurrentOffset(float offset); 321 322 void OnDataLinking( 323 const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags); 324 325 void HandleMonthDaysChange( 326 const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags); 327 328 std::string GetSelectedObject(bool isColumnChange, int status = -1) const; 329 GetSelectDate()330 const LunarDate& GetSelectDate() 331 { 332 return selectedLunar_; 333 } 334 SetSelectDate(const PickerDate & value)335 void SetSelectDate(const PickerDate& value) 336 { 337 selectedDate_ = value; 338 if (selectedDate_.GetYear() <= 0) { 339 LOGW("selectedDate error"); 340 selectedDate_ = PickerDate::Current(); 341 } 342 AdjustSolarDate(selectedDate_, startDateSolar_, endDateSolar_); 343 selectedLunar_ = SolarToLunar(selectedDate_); 344 } 345 GetSelectedDate()346 const PickerDate& GetSelectedDate() 347 { 348 return selectedDate_; 349 } 350 SetStartDate(const PickerDate & value)351 void SetStartDate(const PickerDate& value) 352 { 353 startDateSolar_ = value; 354 AdjustSolarDate(startDateSolar_, limitStartDate_, limitEndDate_); 355 startDateLunar_ = SolarToLunar(startDateSolar_); 356 } 357 GetStartDateLunar()358 const LunarDate& GetStartDateLunar() 359 { 360 return startDateLunar_; 361 } 362 SetEndDate(const PickerDate & value)363 void SetEndDate(const PickerDate& value) 364 { 365 endDateSolar_ = value; 366 AdjustSolarDate(endDateSolar_, limitStartDate_, limitEndDate_); 367 endDateLunar_ = SolarToLunar(endDateSolar_); 368 } 369 GetEndDateLunar()370 const LunarDate& GetEndDateLunar() 371 { 372 return endDateLunar_; 373 } 374 AdjustSolarDate(PickerDate & date,const PickerDate & start,const PickerDate & end)375 void AdjustSolarDate(PickerDate& date, const PickerDate& start, const PickerDate& end) const 376 { 377 if (SolarDateCompare(date, start) < 0) { 378 date = start; 379 return; 380 } 381 if (SolarDateCompare(date, end) > 0) { 382 date = end; 383 } 384 } 385 AdjustSolarDate(PickerDate & date)386 void AdjustSolarDate(PickerDate& date) const 387 { 388 AdjustSolarDate(date, startDateSolar_, endDateSolar_); 389 } 390 SolarDateCompare(const PickerDate & left,const PickerDate & right)391 static int SolarDateCompare(const PickerDate& left, const PickerDate& right) 392 { 393 static const int leftEqualRight = 0; // means left = right 394 static const int leftGreatRight = 1; // means left > right 395 static const int leftLessRight = -1; // means left < right 396 if (left.GetYear() > right.GetYear()) { 397 return leftGreatRight; 398 } 399 if (left.GetYear() < right.GetYear()) { 400 return leftLessRight; 401 } 402 if (left.GetMonth() > right.GetMonth()) { 403 return leftGreatRight; 404 } 405 if (left.GetMonth() < right.GetMonth()) { 406 return leftLessRight; 407 } 408 if (left.GetDay() > right.GetDay()) { 409 return leftGreatRight; 410 } 411 if (left.GetDay() < right.GetDay()) { 412 return leftLessRight; 413 } 414 return leftEqualRight; 415 } 416 HasYearNode()417 bool HasYearNode() const 418 { 419 return yearId_.has_value(); 420 } 421 GetYearId()422 int32_t GetYearId() 423 { 424 if (!yearId_.has_value()) { 425 yearId_ = ElementRegister::GetInstance()->MakeUniqueId(); 426 } 427 return yearId_.value(); 428 } 429 HasMonthNode()430 bool HasMonthNode() const 431 { 432 return monthId_.has_value(); 433 } 434 GetMonthId()435 int32_t GetMonthId() 436 { 437 if (!monthId_.has_value()) { 438 monthId_ = ElementRegister::GetInstance()->MakeUniqueId(); 439 } 440 return monthId_.value(); 441 } 442 HasDayNode()443 bool HasDayNode() const 444 { 445 return dayId_.has_value(); 446 } 447 GetDayId()448 int32_t GetDayId() 449 { 450 if (!dayId_.has_value()) { 451 dayId_ = ElementRegister::GetInstance()->MakeUniqueId(); 452 } 453 return dayId_.value(); 454 } 455 HasMonthDaysNode()456 bool HasMonthDaysNode() const 457 { 458 return monthDaysId_.has_value(); 459 } 460 GetMonthDaysId()461 int32_t GetMonthDaysId() 462 { 463 if (!monthDaysId_.has_value()) { 464 monthDaysId_ = ElementRegister::GetInstance()->MakeUniqueId(); 465 } 466 return monthDaysId_.value(); 467 } 468 HasTitleNode()469 bool HasTitleNode() const 470 { 471 return titleId_.has_value(); 472 } 473 SetTitleId(const int32_t id)474 bool SetTitleId(const int32_t id) 475 { 476 if (HasTitleNode()) { 477 return false; 478 } 479 titleId_ = id; 480 return true; 481 } 482 GetTitleId()483 int32_t GetTitleId() 484 { 485 if (!titleId_.has_value()) { 486 titleId_ = ElementRegister::GetInstance()->MakeUniqueId(); 487 } 488 return titleId_.value(); 489 } 490 HasButtonTitleNode()491 bool HasButtonTitleNode() const 492 { 493 return ButtonTitleId_.has_value(); 494 } 495 GetButtonTitleId()496 int32_t GetButtonTitleId() 497 { 498 if (!ButtonTitleId_.has_value()) { 499 ButtonTitleId_ = ElementRegister::GetInstance()->MakeUniqueId(); 500 } 501 return ButtonTitleId_.value(); 502 } 503 HasDividerNode()504 bool HasDividerNode() const 505 { 506 return DividerId_.has_value(); 507 } 508 GetDividerId()509 int32_t GetDividerId() 510 { 511 if (!DividerId_.has_value()) { 512 DividerId_ = ElementRegister::GetInstance()->MakeUniqueId(); 513 } 514 return DividerId_.value(); 515 } 516 SetBackgroundColor(const Color & color)517 void SetBackgroundColor(const Color& color) 518 { 519 backgroundColor_ = color; 520 } 521 522 static const std::string& GetYear(uint32_t year); 523 524 static const std::string& GetSolarMonth(uint32_t month); 525 526 static const std::string& GetSolarDay(uint32_t day); 527 528 static const std::string& GetLunarMonth(uint32_t month, bool isLeap); 529 530 static const std::string& GetLunarDay(uint32_t day); 531 GetFocusPattern()532 FocusPattern GetFocusPattern() const override 533 { 534 auto pipeline = PipelineBase::GetCurrentContext(); 535 CHECK_NULL_RETURN(pipeline, FocusPattern()); 536 auto pickerTheme = pipeline->GetTheme<PickerTheme>(); 537 CHECK_NULL_RETURN(pickerTheme, FocusPattern()); 538 auto focusColor = pickerTheme->GetFocusColor(); 539 FocusPaintParam focusPaintParams; 540 focusPaintParams.SetPaintColor(focusColor); 541 focusPaintParams.SetPaintWidth(FOCUS_PAINT_WIDTH); 542 return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParams }; 543 } 544 545 void ShowTitle(int32_t titleId); 546 void ToJsonValue(std::unique_ptr<JsonValue>& json) const override; SetContentRowNode(RefPtr<FrameNode> & contentRowNode)547 void SetContentRowNode(RefPtr<FrameNode>& contentRowNode) 548 { 549 contentRowNode_ = contentRowNode; 550 } SetbuttonTitleNode(RefPtr<FrameNode> & buttonTitleNode)551 void SetbuttonTitleNode(RefPtr<FrameNode>& buttonTitleNode) 552 { 553 buttonTitleNode_ = buttonTitleNode; 554 } 555 SetPickerTag(bool isPicker)556 void SetPickerTag(bool isPicker) 557 { 558 isPicker_ = isPicker; 559 } 560 561 void SetFocusDisable(); 562 void SetFocusEnable(); 563 564 private: 565 void OnModifyDone() override; 566 void OnAttachToFrameNode() override; 567 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 568 static void Init(); 569 void InitDisabled(); 570 void GetInnerFocusPaintRect(RoundRect& paintRect); 571 void PaintFocusState(); 572 void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub); 573 bool OnKeyEvent(const KeyEvent& event); 574 bool HandleDirectionKey(KeyCode code); 575 PickerDate GetCurrentDateByMonthDaysColumn() const; 576 PickerDate GetCurrentDateByYearMonthDayColumn() const; 577 void FillSolarYearOptions(const PickerDate& current, RefPtr<FrameNode>& yearColumn); 578 void FillLunarMonthDaysOptions(const LunarDate& current, RefPtr<FrameNode>& monthDaysColumn); 579 void AdjustSolarStartEndDate(); 580 void AdjustLunarStartEndDate(); 581 RefPtr<ClickEvent> clickEventListener_; 582 bool enabled_ = true; 583 int32_t focusKeyID_ = 0; 584 std::map<RefPtr<FrameNode>, std::vector<std::string>> options_; 585 uint32_t showCount_ = 0; 586 std::vector<RefPtr<FrameNode>> datePickerColumns_; 587 bool lunar_ = false; 588 bool showMonthDays_ = false; 589 bool showTime_ = false; 590 Color backgroundColor_ = Color::WHITE; 591 std::optional<int32_t> yearId_; 592 std::optional<int32_t> monthId_; 593 std::optional<int32_t> dayId_; 594 std::optional<int32_t> monthDaysId_; 595 std::optional<int32_t> dateNodeId_; 596 std::optional<int32_t> titleId_; 597 std::optional<int32_t> ButtonTitleId_; 598 std::optional<int32_t> DividerId_; 599 double resizePickerItemHeight_; 600 bool resizeFlag_ = false; 601 bool isShowInDialog_ = false; 602 EventMarker OnDialogAccept_; 603 EventMarker OnDialogCancel_; 604 EventMarker OnDialogChange_; 605 WeakPtr<FrameNode> weakButtonConfirm_; 606 WeakPtr<FrameNode> weakButtonCancel_; 607 PickerDate startDateSolar_ = PickerDate(1970, 1, 1); // default start date is 1970-1-1 from FA document. 608 LunarDate startDateLunar_; 609 PickerDate endDateSolar_ = PickerDate(2100, 12, 31); // default end date is 2100-12-31 from FA document. 610 LunarDate endDateLunar_; 611 PickerDate selectedDate_ = PickerDate::Current(); 612 LunarDate selectedLunar_; 613 PickerDate startDefaultDateSolar_ = PickerDate(1970, 1, 1); // default start date is 1970-1-1 from FA document. 614 PickerDate endDefaultDateSolar_ = PickerDate(2100, 12, 31); // default end date is 2100-12-31 from FA document. 615 const PickerDate limitStartDate_ = PickerDate(1900, 1, 31); 616 const PickerDate limitEndDate_ = PickerDate(2100, 12, 31); 617 static bool inited_; 618 static const std::string empty_; 619 static std::vector<std::string> years_; // year from 1900 to 2100,count is 201 620 static std::vector<std::string> solarMonths_; // solar month from 1 to 12,count is 12 621 static std::vector<std::string> solarDays_; // solar day from 1 to 31, count is 31 622 static std::vector<std::string> lunarMonths_; // lunar month from 1 to 24, count is 24 623 static std::vector<std::string> lunarDays_; // lunar day from 1 to 30, count is 30 624 static std::vector<std::string> tagOrder_; // year month day tag order 625 RefPtr<FrameNode> contentRowNode_; 626 RefPtr<FrameNode> buttonTitleNode_; 627 bool isPicker_ = false; 628 ACE_DISALLOW_COPY_AND_MOVE(DatePickerPattern); 629 }; 630 } // namespace OHOS::Ace::NG 631 632 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_DATE_PICKER_DATE_PICKER_PATTERN_H 633