• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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/picker/picker_datetime_component.h"
17 
18 #include "base/i18n/localization.h"
19 
20 namespace OHOS::Ace {
21 
PickerDateTimeComponent()22 PickerDateTimeComponent::PickerDateTimeComponent() {}
23 
OnTitleBuilding()24 void PickerDateTimeComponent::OnTitleBuilding()
25 {
26     auto theme = GetTheme();
27     if (!theme) {
28         LOGE("theme is null.");
29         return;
30     }
31     SetHasTitle(theme->GetShowButtons());
32     SetHasButtons(theme->GetShowButtons());
33     SetHasTriangle(true); // triangle only for datetime picker.
34 
35     auto titleComponent = GetTitle();
36     if (!titleComponent) {
37         LOGE("title component is null.");
38         return;
39     }
40     titleComponent->SetData(currentDate_.ToString(false));
41 }
42 
OnColumnsBuilding()43 void PickerDateTimeComponent::OnColumnsBuilding()
44 {
45     PickerTimeComponent::OnColumnsBuilding();
46     FillSolarLunarDays(lunar_, selectedDate_);
47     InitDatePicker();
48 }
49 
OnSelectedSaving()50 void PickerDateTimeComponent::OnSelectedSaving()
51 {
52     PickerTimeComponent::OnSelectedSaving();
53     selectedDate_ = currentDate_;
54 }
55 
GetSelectedObject(bool isColumnChange,const std::string & changeColumnTag,int32_t status) const56 std::string PickerDateTimeComponent::GetSelectedObject(bool isColumnChange,
57     const std::string& changeColumnTag, int32_t status) const
58 {
59     if (isColumnChange) {
60         LOGE("datetime picker not support column change event.");
61         return "{}";
62     }
63 
64     auto date = selectedDate_;
65     // W3C's month is between 0 to 11, need to reduce one.
66     date.SetMonth(date.GetMonth() - 1);
67     PickerDateTime dateTime(date, GetSelectedTime());
68     return dateTime.ToString(true, status);
69 }
70 
OnLunarCallback(bool checked,std::vector<std::string> & resultTags)71 void PickerDateTimeComponent::OnLunarCallback(bool checked, std::vector<std::string>& resultTags)
72 {
73     FillSolarLunarDays(checked, currentDate_);
74     resultTags.emplace_back(PICKER_MONTHDAY_COLUMN);
75 }
76 
OnTriangleCallback(bool value)77 void PickerDateTimeComponent::OnTriangleCallback(bool value)
78 {
79     if (value) {
80         HideDatePicker();
81     } else {
82         ShowDatePicker();
83     }
84 }
85 
InitDatePicker()86 void PickerDateTimeComponent::InitDatePicker()
87 {
88     if (datePicker_) {
89         return; // already init.
90     }
91     datePicker_ = AceType::MakeRefPtr<PickerDateComponent>();
92     datePicker_->SetSubsidiary(true);
93     datePicker_->SetHasLunar(false);
94     datePicker_->SetIsDialog(true);
95     datePicker_->SetTextDirection(GetTextDirection());
96     datePicker_->SetTheme(GetTheme());
97     datePicker_->SetColumnHeight(GetColumnHeight());
98     datePicker_->SetOnDateChange([weak = WeakClaim(this)] (const PickerDate& date) {
99         auto refPtr = weak.Upgrade();
100         if (!refPtr) {
101             return;
102         }
103         refPtr->OnSubsidiaryChange(date);
104     });
105     auto controller = AceType::MakeRefPtr<PickerAnimationController>();
106     controller->SetOutStopCallback([weak = AceType::WeakClaim(AceType::RawPtr(datePicker_))] {
107         auto refPtr = weak.Upgrade();
108         if (!refPtr) {
109             return;
110         }
111         refPtr->HideDialog();
112     });
113     SetAnimationController(controller);
114     datePicker_->SetAnimationController(controller);
115 }
116 
OnSubsidiaryChange(const PickerDate & date)117 void PickerDateTimeComponent::OnSubsidiaryChange(const PickerDate& date)
118 {
119     auto days = date.ToDays();
120     days--;
121     currentDate_.FromDays(days);
122 
123     auto monthDay = GetColumn(PICKER_MONTHDAY_COLUMN);
124     if (!monthDay) {
125         return;
126     }
127 
128     monthDay->HandleChangeCallback(true, false);
129 }
130 
ShowDatePicker()131 void PickerDateTimeComponent::ShowDatePicker()
132 {
133     InitDatePicker();
134 #if defined(PREVIEW)
135     datePicker_->SetPickerBaseId(GetPickerBaseId());
136 #endif
137     datePicker_->SetShowLunar(lunar_);
138     datePicker_->SetSelectedDate(currentDate_);
139     datePicker_->SetMasterHasLunar(GetHasLunar());
140     datePicker_->ShowDialog(GetStack(), false);
141 }
142 
HideDatePicker()143 void PickerDateTimeComponent::HideDatePicker()
144 {
145     InitDatePicker();
146     auto controller = GetAnimationController();
147     if (!controller) {
148         LOGE("controller is null.");
149         return;
150     }
151 
152     controller->Play(false);
153 }
154 
OnColumnsCreating()155 void PickerDateTimeComponent::OnColumnsCreating()
156 {
157     RemoveColumn(PICKER_MONTHDAY_COLUMN);
158     auto monthDay = AceType::MakeRefPtr<PickerColumnComponent>();
159     monthDay->SetColumnTag(PICKER_MONTHDAY_COLUMN);
160     if (GetHour24()) {
161         monthDay->SetWidthRatio(3); // date:hour:minute:second = 3:2:2:2
162     } else {
163         monthDay->SetWidthRatio(4); // date:amPm:hour:minute:second = 4:2:2:2:2
164     }
165     AppendColumn(monthDay);
166 
167     PickerTimeComponent::OnColumnsCreating();
168 }
169 
GetMonthDayFormatString(bool lunar,uint32_t days) const170 std::string PickerDateTimeComponent::GetMonthDayFormatString(bool lunar, uint32_t days) const
171 {
172     PickerDate outDate;
173     outDate.FromDays(days);
174     auto nowadays = PickerDate::Current().ToDays();
175     if (days == nowadays) {
176         return Localization::GetInstance()->GetRelativeDateTime(0.0);
177     }
178     if (!lunar) {
179         DateTime dateTime;
180         dateTime.year = outDate.GetYear();
181         dateTime.month = outDate.GetMonth() - 1; // W3C's month start from 0 to 11
182         dateTime.day = outDate.GetDay();
183         return Localization::GetInstance()->FormatDateTime(dateTime, "MMMd");
184     }
185     Date date;
186     date.year = outDate.GetYear();
187     date.month = outDate.GetMonth();
188     date.day = outDate.GetDay();
189     auto lunarDate = Localization::GetInstance()->GetLunarDate(date);
190     return Localization::GetInstance()->GetLunarMonth(lunarDate.month, lunarDate.isLeapMonth) +
191         Localization::GetInstance()->GetLunarDay(lunarDate.day);
192 }
193 
FillSolarLunarDays(bool lunar,const PickerDate & currentDate)194 void PickerDateTimeComponent::FillSolarLunarDays(bool lunar, const PickerDate& currentDate)
195 {
196     auto monthDay = GetColumn(PICKER_MONTHDAY_COLUMN);
197     if (!monthDay) {
198         return;
199     }
200     monthDay->ClearOption();
201     monthDay->SetCurrentIndex(3); // total option is fixed 7. center index is 3 which is current.
202     uint32_t centerDays = currentDate.ToDays();
203     uint32_t startDays = centerDays - 3; // start day 3 days before center day.
204     uint32_t endDays = centerDays + 3; // end day 3 days after center day.
205     for (uint32_t days = startDays; days <= endDays; ++days) {
206         monthDay->AppendOption(GetMonthDayFormatString(lunar, days));
207     }
208     lunar_ = lunar;
209     currentDate_ = currentDate;
210 }
211 
OnDataLinking(const std::string & tag,bool isAdd,uint32_t index,std::vector<std::string> & resultTags)212 void PickerDateTimeComponent::OnDataLinking(const std::string& tag, bool isAdd, uint32_t index,
213     std::vector<std::string>& resultTags)
214 {
215     PickerTimeComponent::OnDataLinking(tag, isAdd, index, resultTags);
216     if (tag == PICKER_MONTHDAY_COLUMN) {
217         // linked by month day column itself.
218         auto days = currentDate_.ToDays();
219         days = (isAdd ? days + 1 : days - 1); // add one day or reduce one day.
220         PickerDate date;
221         date.FromDays(days);
222         FillSolarLunarDays(lunar_, date);
223         resultTags.emplace_back(PICKER_MONTHDAY_COLUMN);
224         return;
225     }
226     auto it = std::find(resultTags.begin(), resultTags.end(), PICKER_MONTHDAY_COLUMN);
227     if (it != resultTags.end()) {
228         // linked by other column
229         auto days = currentDate_.ToDays();
230         days = (isAdd ? days + 1 : days - 1);
231         PickerDate date;
232         date.FromDays(days);
233         FillSolarLunarDays(lunar_, date);
234     }
235 }
236 
237 } // namespace OHOS::Ace
238