1 /*
2 * Copyright (c) 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_ng/pattern/time_picker/timepicker_row_pattern.h"
17 #include <cstdint>
18
19 #include "base/geometry/ng/size_t.h"
20 #include "base/utils/utils.h"
21 #include "core/components/picker/picker_theme.h"
22 #include "core/components_ng/pattern/button/button_pattern.h"
23 #include "core/components_ng/pattern/stack/stack_pattern.h"
24 #include "core/components_ng/pattern/text/text_pattern.h"
25 #include "core/components_ng/pattern/time_picker/toss_animation_controller.h"
26 #include "core/components_v2/inspector/inspector_constants.h"
27 #include "core/pipeline_ng/ui_task_scheduler.h"
28
29 namespace OHOS::Ace::NG {
30 namespace {
31 constexpr int32_t CHILD_WITH_AMPM_SIZE = 3;
32 constexpr int32_t CHILD_WITHOUT_AMPM_SIZE = 2;
33 constexpr uint32_t AM_PM_HOUR_12 = 12;
34 constexpr uint32_t AM_PM_HOUR_11 = 11;
35 constexpr uint32_t MINUTE_10 = 10;
36 const int32_t AM_PM_COUNT = 3;
37 const Dimension PRESS_INTERVAL = 4.0_vp;
38 const Dimension PRESS_RADIUS = 8.0_vp;
39 const int32_t UNOPTION_COUNT = 2;
40 const int32_t AMPMDEFAULTPOSITION = 0;
41 const int32_t AMPM_FORWARD_WITHSECOND = 3;
42 const int32_t AMPM_FORWARD_WITHOUTSECOND = 2;
43 const int32_t AMPM_BACKWARD_WITHSECOND = -3;
44 const int32_t AMPM_BACKWARD_WITHOUTSECOND = -2;
45 const int32_t CHILD_INDEX_FIRST = 0;
46 const int32_t CHILD_INDEX_SECOND = 1;
47 const int32_t CHILD_INDEX_THIRD = 2;
48 const int32_t CHILD_INDEX_FOURTH = 3;
49 constexpr float DISABLE_ALPHA = 0.6f;
50 const Dimension FOCUS_INTERVAL = 2.0_vp;
51 const Dimension LINE_WIDTH = 1.5_vp;
52 const int32_t RATE = 2;
53 const PickerTime START_DEFAULT_TIME = PickerTime(0, 0, 0);
54 const PickerTime END_DEFAULT_TIME = PickerTime(23, 59, 59);
55 const uint32_t INDEX_AM_0 = 0;
56 const uint32_t INDEX_PM_1 = 1;
57 const uint32_t INDEX_HOUR_STRAT = 0;
58 const uint32_t INDEX_MINUTE_STRAT = 0;
59 const uint32_t INDEX_MINUTE_END = 59;
60 const uint32_t INDEX_SECOND_STRAT = 0;
61 const uint32_t INDEX_SECOND_ADD_ZERO = 10;
62 const uint32_t INDEX_SECOND_END = 59;
63 const uint32_t SIZE_OF_AMPM_COLUMN_OPTION = 2;
64 } // namespace
65
OnAttachToFrameNode()66 void TimePickerRowPattern::OnAttachToFrameNode()
67 {
68 auto host = GetHost();
69 CHECK_NULL_VOID(host);
70 host->GetRenderContext()->SetClipToFrame(true);
71 host->GetRenderContext()->UpdateClipEdge(true);
72 }
73
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)74 bool TimePickerRowPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
75 {
76 CHECK_NULL_RETURN(dirty, false);
77 SetButtonIdeaSize();
78 return true;
79 }
80
SetButtonIdeaSize()81 void TimePickerRowPattern::SetButtonIdeaSize()
82 {
83 auto host = GetHost();
84 CHECK_NULL_VOID(host);
85 auto context = host->GetContext();
86 CHECK_NULL_VOID(context);
87 auto pickerTheme = context->GetTheme<PickerTheme>();
88 CHECK_NULL_VOID(pickerTheme);
89 auto children = host->GetChildren();
90 auto height = pickerTheme->GetDividerSpacing();
91 for (const auto& child : children) {
92 auto childNode = DynamicCast<FrameNode>(child);
93 CHECK_NULL_VOID(childNode);
94 auto width = childNode->GetGeometryNode()->GetFrameSize().Width();
95 auto defaultWidth = height.ConvertToPx() * 2;
96 if (width > defaultWidth) {
97 width = static_cast<float>(defaultWidth);
98 }
99 auto timePickerColumnNode = DynamicCast<FrameNode>(childNode->GetLastChild());
100 CHECK_NULL_VOID(timePickerColumnNode);
101 auto columnNodeHeight = timePickerColumnNode->GetGeometryNode()->GetFrameSize().Height();
102 auto buttonNode = DynamicCast<FrameNode>(child->GetFirstChild());
103 auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
104 buttonLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
105 buttonLayoutProperty->UpdateType(ButtonType::NORMAL);
106 buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(PRESS_RADIUS));
107 auto standardButtonHeight = static_cast<float>((height - PRESS_INTERVAL).ConvertToPx());
108 auto maxButtonHeight = static_cast<float>(columnNodeHeight);
109 auto buttonHeight = Dimension(std::min(standardButtonHeight, maxButtonHeight), DimensionUnit::PX);
110 buttonLayoutProperty->UpdateUserDefinedIdealSize(
111 CalcSize(CalcLength(width - PRESS_INTERVAL.ConvertToPx()), CalcLength(buttonHeight)));
112 auto buttonConfirmRenderContext = buttonNode->GetRenderContext();
113 buttonConfirmRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
114 buttonNode->MarkModifyDone();
115 buttonNode->MarkDirtyNode();
116 if (GetIsShowInDialog() && GreatNotEqual(standardButtonHeight, maxButtonHeight) &&
117 GreatNotEqual(maxButtonHeight, 0.0f)) {
118 auto parentNode = DynamicCast<FrameNode>(host->GetParent());
119 CHECK_NULL_VOID(parentNode);
120 parentNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
121 }
122 }
123 }
124
ColumnPatternInitHapticController()125 void TimePickerRowPattern::ColumnPatternInitHapticController()
126 {
127 if (!isHapticChanged_) {
128 return;
129 }
130
131 isHapticChanged_ = false;
132 for (auto iter = allChildNode_.begin(); iter != allChildNode_.end(); iter++) {
133 auto columnNode = iter->second.Upgrade();
134 if (!columnNode) {
135 continue;
136 }
137 auto pattern = columnNode->GetPattern<TimePickerColumnPattern>();
138 if (!pattern) {
139 continue;
140 }
141 pattern->InitHapticController(columnNode);
142 }
143 }
144
ColumnPatternStopHaptic()145 void TimePickerRowPattern::ColumnPatternStopHaptic()
146 {
147 if (!isEnableHaptic_) {
148 return;
149 }
150 for (auto iter = allChildNode_.begin(); iter != allChildNode_.end(); iter++) {
151 auto columnNode = iter->second.Upgrade();
152 if (!columnNode) {
153 continue;
154 }
155 auto timePickerColumnPattern = columnNode->GetPattern<TimePickerColumnPattern>();
156 if (!timePickerColumnPattern) {
157 continue;
158 }
159 timePickerColumnPattern->StopHaptic();
160 }
161 }
162
IsCircle()163 bool TimePickerRowPattern::IsCircle()
164 {
165 auto host = GetHost();
166 CHECK_NULL_RETURN(host, false);
167 auto context = host->GetContext();
168 CHECK_NULL_RETURN(context, false);
169 auto pickerTheme = context->GetTheme<PickerTheme>();
170 CHECK_NULL_RETURN(pickerTheme, false);
171
172 return pickerTheme->IsCircleDial();
173 }
174
SetDefaultColoumnFocus(std::unordered_map<std::string,WeakPtr<FrameNode>>::iterator & it,const std::string & id,bool & focus,const std::function<void (const std::string &)> & call)175 void TimePickerRowPattern::SetDefaultColoumnFocus(std::unordered_map<std::string, WeakPtr<FrameNode>>::iterator& it,
176 const std::string &id, bool& focus, const std::function<void(const std::string&)>& call)
177 {
178 auto column = it->second.Upgrade();
179 CHECK_NULL_VOID(column);
180 auto tmpPattern = column->GetPattern<TimePickerColumnPattern>();
181 CHECK_NULL_VOID(tmpPattern);
182 tmpPattern->SetSelectedMarkId(id);
183 tmpPattern->SetSelectedMarkListener(call);
184 if (focus) {
185 tmpPattern->SetSelectedMark(true, false);
186 selectedColumnId_ = id;
187 focus = false;
188 }
189 }
190
ClearFocus()191 void TimePickerRowPattern::ClearFocus()
192 {
193 CHECK_EQUAL_VOID(IsCircle(), false);
194 if (!isClearFocus_ && (HasSecondNode() == hasSecond_)) {
195 return ;
196 }
197 isClearFocus_ = true;
198 if (!selectedColumnId_.empty()) {
199 auto it = allChildNode_.find(selectedColumnId_);
200 if (it != allChildNode_.end()) {
201 auto column = it->second.Upgrade();
202 CHECK_NULL_VOID(column);
203 auto tmpPattern = column->GetPattern<TimePickerColumnPattern>();
204 CHECK_NULL_VOID(tmpPattern);
205 tmpPattern->SetSelectedMark(false, false);
206 }
207
208 selectedColumnId_ = "";
209 }
210 }
211
SetDefaultFocus()212 void TimePickerRowPattern::SetDefaultFocus()
213 {
214 CHECK_EQUAL_VOID(IsCircle(), false);
215 CHECK_EQUAL_VOID(isClearFocus_, false);
216 isClearFocus_ = false;
217 std::function<void(const std::string &focusId)> call = [weak = WeakClaim(this)](const std::string &focusId) {
218 auto pattern = weak.Upgrade();
219 CHECK_NULL_VOID(pattern);
220 if (pattern->selectedColumnId_.empty()) {
221 pattern->selectedColumnId_ = focusId;
222 return;
223 }
224 auto it = pattern->allChildNode_.find(pattern->selectedColumnId_);
225 if (it != pattern->allChildNode_.end()) {
226 auto tmpColumn = it->second.Upgrade();
227 if (tmpColumn) {
228 auto tmpPattern = tmpColumn->GetPattern<TimePickerColumnPattern>();
229 CHECK_NULL_VOID(tmpPattern);
230 tmpPattern->SetSelectedMark(false, false);
231 }
232 }
233 pattern->selectedColumnId_ = focusId;
234 };
235 static const std::string columnName[] = {"amPm", "hour", "minute", "second"};
236 bool setFocus = true;
237 for (size_t i = 0; i < sizeof(columnName) / sizeof(columnName[0]); i++) {
238 auto it = allChildNode_.find(columnName[i]);
239 if (it != allChildNode_.end()) {
240 SetDefaultColoumnFocus(it, columnName[i], setFocus, call);
241 }
242 }
243 }
244
245 #ifdef SUPPORT_DIGITAL_CROWN
InitOnCrownEvent(const RefPtr<FocusHub> & focusHub)246 void TimePickerRowPattern::InitOnCrownEvent(const RefPtr<FocusHub>& focusHub)
247 {
248 CHECK_NULL_VOID(focusHub);
249 auto onCrowEvent = [wp = WeakClaim(this)](const CrownEvent& event) -> bool {
250 auto pattern = wp.Upgrade();
251 CHECK_NULL_RETURN(pattern, false);
252 return pattern->OnCrownEvent(event);
253 };
254 focusHub->SetOnCrownEventInternal(std::move(onCrowEvent));
255 }
256
OnCrownEvent(const CrownEvent & event)257 bool TimePickerRowPattern::OnCrownEvent(const CrownEvent& event)
258 {
259 if (event.action == OHOS::Ace::CrownAction::BEGIN ||
260 event.action == OHOS::Ace::CrownAction::UPDATE ||
261 event.action == OHOS::Ace::CrownAction::END) {
262 RefPtr<TimePickerColumnPattern> crownPickerColumnPattern;
263 for (auto& iter : timePickerColumns_) {
264 auto column = iter.Upgrade();
265 if (!column) {
266 continue;
267 }
268 auto pickerColumnPattern = column->GetPattern<TimePickerColumnPattern>();
269 CHECK_NULL_RETURN(pickerColumnPattern, false);
270 auto columnID = pickerColumnPattern->GetSelectedColumnId();
271 if (!pickerColumnPattern->IsCrownEventEnded()) {
272 crownPickerColumnPattern = pickerColumnPattern;
273 break;
274 } else if (columnID == selectedColumnId_) {
275 crownPickerColumnPattern = pickerColumnPattern;
276 }
277 }
278 if (crownPickerColumnPattern != nullptr) {
279 return crownPickerColumnPattern->OnCrownEvent(event);
280 }
281 }
282 return false;
283 }
284 #endif
285
InitFocusEvent()286 void TimePickerRowPattern::InitFocusEvent()
287 {
288 auto host = GetHost();
289 CHECK_NULL_VOID(host);
290 auto focusHub = host->GetFocusHub();
291 if (focusHub) {
292 InitOnKeyEvent(focusHub);
293 #ifdef SUPPORT_DIGITAL_CROWN
294 InitOnCrownEvent(focusHub);
295 #endif
296 }
297 }
298
UpdateTitleNodeContent()299 void TimePickerRowPattern::UpdateTitleNodeContent()
300 {
301 if (HasTitleNode()) {
302 auto textTitleNode = FrameNode::GetOrCreateFrameNode(
303 V2::TEXT_ETS_TAG, GetTitleId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
304 auto str = GetDialogTitleDate();
305 CHECK_NULL_VOID(textTitleNode);
306 auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
307 CHECK_NULL_VOID(textLayoutProperty);
308 textLayoutProperty->UpdateContent(str.ToString(false));
309 }
310 }
311
SetCallBack()312 void TimePickerRowPattern::SetCallBack()
313 {
314 SetChangeCallback([weak = WeakClaim(this)](const RefPtr<FrameNode>& tag, bool add, uint32_t index, bool notify) {
315 auto refPtr = weak.Upgrade();
316 CHECK_NULL_VOID(refPtr);
317 refPtr->HandleColumnChange(tag, add, index, notify);
318 });
319 SetEventCallback([weak = WeakClaim(this)](bool refresh) {
320 auto refPtr = weak.Upgrade();
321 CHECK_NULL_VOID(refPtr);
322 refPtr->FireChangeEvent(refresh);
323 });
324 SetEnterSelectedAreaEventCallback([weak = WeakClaim(this)](bool refresh) {
325 auto refPtr = weak.Upgrade();
326 CHECK_NULL_VOID(refPtr);
327 refPtr->FireEnterSelectedAreaEvent(refresh);
328 });
329 }
330
OnModifyDone()331 void TimePickerRowPattern::OnModifyDone()
332 {
333 Pattern::CheckLocalized();
334 if (isFiredTimeChange_ && !isForceUpdate_ && !isDateTimeOptionUpdate_) {
335 isFiredTimeChange_ = false;
336 ColumnPatternInitHapticController();
337 return;
338 }
339 LimitSelectedTimeInRange();
340 isHapticChanged_ = false;
341 isForceUpdate_ = false;
342 isDateTimeOptionUpdate_ = false;
343 ClearFocus();
344 auto host = GetHost();
345 CHECK_NULL_VOID(host);
346 auto pickerProperty = host->GetLayoutProperty<TimePickerLayoutProperty>();
347 CHECK_NULL_VOID(pickerProperty);
348 wheelModeEnabled_ = pickerProperty->GetLoopValue(true);
349 UpdateLanguageAndAmPmTimeOrder();
350 CreateOrDeleteSecondNode();
351 CreateAmPmNode();
352 OnColumnsBuilding();
353 FlushColumn();
354 InitDisabled();
355 SetCallBack();
356 InitFocusEvent();
357 UpdateTitleNodeContent();
358 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
359 if (isUserSetSelectColor_) {
360 UpdateUserSetSelectColor();
361 }
362 SetDefaultFocus();
363 }
364
LimitSelectedTimeInRange()365 void TimePickerRowPattern::LimitSelectedTimeInRange()
366 {
367 if (IsStartEndTimeDefined()) {
368 selectedTime_ = AdjustTime(selectedTime_);
369 }
370 }
371
InitDisabled()372 void TimePickerRowPattern::InitDisabled()
373 {
374 auto host = GetHost();
375 CHECK_NULL_VOID(host);
376 auto eventHub = host->GetEventHub<EventHub>();
377 CHECK_NULL_VOID(eventHub);
378 enabled_ = eventHub->IsEnabled();
379 auto renderContext = host->GetRenderContext();
380 CHECK_NULL_VOID(renderContext);
381 auto opacity = curOpacity_;
382 if (!enabled_) {
383 opacity *= DISABLE_ALPHA;
384 renderContext->UpdateOpacity(opacity);
385 } else if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
386 renderContext->UpdateOpacity(opacity);
387 }
388
389 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
390 for (const auto& child : host->GetChildren()) {
391 auto stackNode = DynamicCast<FrameNode>(child);
392 CHECK_NULL_VOID(stackNode);
393 auto renderContext = stackNode->GetRenderContext();
394 CHECK_NULL_VOID(renderContext);
395 renderContext->UpdateOpacity(opacity);
396 }
397 }
398 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
399 }
400
CreateAmPmNode()401 void TimePickerRowPattern::CreateAmPmNode()
402 {
403 auto host = GetHost();
404 CHECK_NULL_VOID(host);
405 auto context = host->GetContext();
406 CHECK_NULL_VOID(context);
407 auto pickerTheme = context->GetTheme<PickerTheme>();
408 CHECK_NULL_VOID(pickerTheme);
409 auto height = pickerTheme->GetDividerSpacing();
410 if (!GetHour24() && !HasAmPmNode()) {
411 auto amPmColumnNode = FrameNode::GetOrCreateFrameNode(
412 V2::COLUMN_ETS_TAG, GetAmPmId(), []() { return AceType::MakeRefPtr<TimePickerColumnPattern>(); });
413 CHECK_NULL_VOID(amPmColumnNode);
414 for (uint32_t index = 0; index < AM_PM_COUNT; index++) {
415 auto textNode = FrameNode::CreateFrameNode(
416 V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
417 CHECK_NULL_VOID(textNode);
418 textNode->MountToParent(amPmColumnNode);
419 }
420 SetColumn(amPmColumnNode);
421 auto stackAmPmNode = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG,
422 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<StackPattern>(); });
423 auto buttonNode = FrameNode::GetOrCreateFrameNode(V2::BUTTON_ETS_TAG,
424 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
425 auto blendNodeId = ElementRegister::GetInstance()->MakeUniqueId();
426 auto columnBlendNode = FrameNode::GetOrCreateFrameNode(
427 V2::COLUMN_ETS_TAG, blendNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
428 buttonNode->MountToParent(stackAmPmNode);
429 auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
430 amPmColumnNode->MountToParent(columnBlendNode);
431 columnBlendNode->MountToParent(stackAmPmNode);
432 auto layoutProperty = stackAmPmNode->GetLayoutProperty<LayoutProperty>();
433 layoutProperty->UpdateAlignment(Alignment::CENTER);
434 layoutProperty->UpdateLayoutWeight(1);
435 amPmTimeOrder_ == "01" ? stackAmPmNode->MountToParent(host) : stackAmPmNode->MountToParent(host, 0);
436 if (SetAmPmButtonIdeaSize() > 0) {
437 auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
438 buttonLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
439 buttonLayoutProperty->UpdateType(ButtonType::NORMAL);
440 buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(PRESS_RADIUS));
441 buttonLayoutProperty->UpdateUserDefinedIdealSize(
442 CalcSize(CalcLength(SetAmPmButtonIdeaSize()), CalcLength(height - PRESS_INTERVAL)));
443 buttonNode->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
444 buttonNode->MarkModifyDone();
445 buttonNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
446 }
447 host->MarkModifyDone();
448 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
449 }
450 }
451
CreateOrDeleteSecondNode()452 void TimePickerRowPattern::CreateOrDeleteSecondNode()
453 {
454 auto host = GetHost();
455 CHECK_NULL_VOID(host);
456 if (!HasSecondNode()) {
457 if (hasSecond_) {
458 auto secondColumnNode = FrameNode::GetOrCreateFrameNode(
459 V2::COLUMN_ETS_TAG, GetSecondId(), []() { return AceType::MakeRefPtr<TimePickerColumnPattern>(); });
460 CHECK_NULL_VOID(secondColumnNode);
461 for (uint32_t index = 0; index < GetShowCount(); index++) {
462 auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG,
463 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
464 CHECK_NULL_VOID(textNode);
465 textNode->MarkModifyDone();
466 textNode->MountToParent(secondColumnNode);
467 }
468 SetColumn(secondColumnNode);
469 auto stackSecondNode = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG,
470 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<StackPattern>(); });
471 auto buttonSecondNode = FrameNode::GetOrCreateFrameNode(V2::BUTTON_ETS_TAG,
472 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
473 auto blendNodeId = ElementRegister::GetInstance()->MakeUniqueId();
474 auto columnBlendNode = FrameNode::GetOrCreateFrameNode(
475 V2::COLUMN_ETS_TAG, blendNodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(true); });
476 buttonSecondNode->MarkModifyDone();
477 buttonSecondNode->MountToParent(stackSecondNode);
478 secondColumnNode->MarkModifyDone();
479 secondColumnNode->MountToParent(columnBlendNode);
480 columnBlendNode->MarkModifyDone();
481 columnBlendNode->MountToParent(stackSecondNode);
482 auto layoutProperty = stackSecondNode->GetLayoutProperty<LayoutProperty>();
483 layoutProperty->UpdateAlignment(Alignment::CENTER);
484 layoutProperty->UpdateLayoutWeight(1);
485 stackSecondNode->MarkModifyDone();
486 MountSecondNode(stackSecondNode);
487 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
488 }
489 } else {
490 if (!hasSecond_) {
491 RemoveSecondNode();
492 secondId_.reset();
493 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
494 }
495 }
496 }
497
MountSecondNode(const RefPtr<FrameNode> & stackSecondNode)498 void TimePickerRowPattern::MountSecondNode(const RefPtr<FrameNode>& stackSecondNode)
499 {
500 auto host = GetHost();
501 CHECK_NULL_VOID(host);
502 int32_t secondNodePosition = static_cast<int32_t>(host->GetChildren().size()) - 1;
503 if (!HasAmPmNode()) {
504 if (language_ == "ug") {
505 secondNodePosition = CHILD_INDEX_FIRST;
506 }
507 } else {
508 if (amPmTimeOrder_ == "01") {
509 secondNodePosition = CHILD_INDEX_THIRD;
510 } else if (language_ == "ug") {
511 secondNodePosition = CHILD_INDEX_SECOND;
512 }
513 }
514 stackSecondNode->MountToParent(host, secondNodePosition);
515 }
516
RemoveSecondNode()517 void TimePickerRowPattern::RemoveSecondNode()
518 {
519 auto host = GetHost();
520 CHECK_NULL_VOID(host);
521 int32_t secondNodePosition = static_cast<int32_t>(host->GetChildren().size()) - 1;
522 if (!HasAmPmNode()) {
523 if (language_ == "ug") {
524 secondNodePosition = CHILD_INDEX_FIRST;
525 }
526 } else {
527 if (amPmTimeOrder_ == "01") {
528 secondNodePosition = CHILD_INDEX_THIRD;
529 } else if (language_ == "ug") {
530 secondNodePosition = CHILD_INDEX_SECOND;
531 }
532 }
533 host->RemoveChildAtIndex(secondNodePosition);
534 }
535
SetAmPmButtonIdeaSize()536 double TimePickerRowPattern::SetAmPmButtonIdeaSize()
537 {
538 auto host = GetHost();
539 CHECK_NULL_RETURN(host, 0);
540 auto children = host->GetChildren();
541 float width = 0.0f;
542 for (const auto& child : children) {
543 auto buttonNode = DynamicCast<FrameNode>(child->GetFirstChild());
544 CHECK_NULL_RETURN(buttonNode, 0);
545 width = buttonNode->GetGeometryNode()->GetFrameSize().Width();
546 }
547 if (width > 0) {
548 return width;
549 }
550 return 0;
551 }
552
SetEventCallback(EventCallback && value)553 void TimePickerRowPattern::SetEventCallback(EventCallback&& value)
554 {
555 auto host = GetHost();
556 CHECK_NULL_VOID(host);
557 auto children = host->GetChildren();
558 for (const auto& child : children) {
559 auto stackNode = DynamicCast<FrameNode>(child);
560 CHECK_NULL_VOID(stackNode);
561 auto columnBlendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
562 CHECK_NULL_VOID(columnBlendNode);
563 auto childNode = DynamicCast<FrameNode>(columnBlendNode->GetLastChild());
564 CHECK_NULL_VOID(childNode);
565 auto timePickerColumnPattern = childNode->GetPattern<TimePickerColumnPattern>();
566 CHECK_NULL_VOID(timePickerColumnPattern);
567 timePickerColumnPattern->SetEventCallback(std::move(value));
568 }
569 }
570
FireChangeEvent(bool refresh)571 void TimePickerRowPattern::FireChangeEvent(bool refresh)
572 {
573 if (refresh) {
574 auto timePickerEventHub = GetEventHub<TimePickerEventHub>();
575 CHECK_NULL_VOID(timePickerEventHub);
576 auto str = GetSelectedObject(true);
577 auto info = std::make_shared<DatePickerChangeEvent>(str);
578 timePickerEventHub->FireChangeEvent(info.get());
579 timePickerEventHub->FireDialogChangeEvent(str);
580 firedTimeStr_ = str;
581 }
582 }
583
SetEnterSelectedAreaEventCallback(EventCallback && value)584 void TimePickerRowPattern::SetEnterSelectedAreaEventCallback(EventCallback&& value)
585 {
586 auto host = GetHost();
587 CHECK_NULL_VOID(host);
588 auto children = host->GetChildren();
589 for (const auto& child : children) {
590 auto stackNode = DynamicCast<FrameNode>(child);
591 CHECK_NULL_VOID(stackNode);
592 auto blendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
593 CHECK_NULL_VOID(blendNode);
594 auto childNode = DynamicCast<FrameNode>(blendNode->GetLastChild());
595 CHECK_NULL_VOID(childNode);
596 auto pickerColumnPattern = childNode->GetPattern<TimePickerColumnPattern>();
597 CHECK_NULL_VOID(pickerColumnPattern);
598 pickerColumnPattern->SetEnterSelectedAreaEventCallback(std::move(value));
599 }
600 }
601
FireEnterSelectedAreaEvent(bool refresh)602 void TimePickerRowPattern::FireEnterSelectedAreaEvent(bool refresh)
603 {
604 if (refresh) {
605 auto timePickerEventHub = GetEventHub<TimePickerEventHub>();
606 CHECK_NULL_VOID(timePickerEventHub);
607 auto str = GetEnterObject(true);
608 auto info = std::make_shared<DatePickerChangeEvent>(str);
609 timePickerEventHub->FireEnterSelectedAreaEvent(info.get());
610 timePickerEventHub->FireDialogEnterSelectedAreaEvent(str);
611 }
612 }
613
GetSelectedObject(bool isColumnChange,int32_t status)614 std::string TimePickerRowPattern::GetSelectedObject(bool isColumnChange, int32_t status)
615 {
616 auto time = selectedTime_;
617 if (isColumnChange) {
618 time = GetCurrentTime();
619 }
620 return time.ToString(true, hasSecond_, status);
621 }
622
GetCurrentTime()623 PickerTime TimePickerRowPattern::GetCurrentTime()
624 {
625 PickerTime time;
626 UpdateAllChildNode();
627 auto amPmColumn = allChildNode_["amPm"].Upgrade();
628 auto hourColumn = allChildNode_["hour"].Upgrade();
629 auto minuteColumn = allChildNode_["minute"].Upgrade();
630 CHECK_NULL_RETURN(hourColumn, time);
631 CHECK_NULL_RETURN(minuteColumn, time);
632 auto hourPickerColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
633 CHECK_NULL_RETURN(hourPickerColumnPattern, time);
634 auto minutePickerColumnPattern = minuteColumn->GetPattern<TimePickerColumnPattern>();
635 CHECK_NULL_RETURN(minutePickerColumnPattern, time);
636 auto hourPickerColumnIndex = hourPickerColumnPattern->GetCurrentIndex();
637 auto hour = GetOptionsValue(hourColumn, hourPickerColumnIndex);
638 auto minutePickerColumnIdex = minutePickerColumnPattern->GetCurrentIndex();
639 auto minute = GetOptionsValue(minuteColumn, minutePickerColumnIdex);
640
641 if (startTime_.ToMinutes() == START_DEFAULT_TIME.ToMinutes() &&
642 endTime_.ToMinutes() == END_DEFAULT_TIME.ToMinutes()) {
643 if (GetHour24()) {
644 time.SetHour(hourPickerColumnPattern->GetCurrentIndex()); // hour from 0 to 23, index from 0 to 23
645 } else if (amPmColumn) {
646 auto amPmPickerColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
647 CHECK_NULL_RETURN(amPmPickerColumnPattern, time);
648 time.SetHour(GetHourFromAmPm(
649 amPmPickerColumnPattern->GetCurrentIndex() == 0, hourPickerColumnPattern->GetCurrentIndex() + 1));
650 }
651 time.SetMinute(minutePickerColumnPattern->GetCurrentIndex()); // minute from 0 to 59, index from 0 to 59
652 } else {
653 if (GetHour24()) {
654 time.SetHour(hourPickerColumnPattern->GetCurrentIndex() + startTime_.GetHour());
655 } else if (amPmColumn) {
656 auto amPmPickerColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
657 CHECK_NULL_RETURN(amPmPickerColumnPattern, time);
658 time.SetHour(
659 GetHourFromAmPm(amPmPickerColumnPattern->GetCurrentIndex() == 0, StringUtils::StringToUint(hour)));
660 }
661 time.SetMinute(StringUtils::StringToUint(minute));
662 }
663
664 if (hasSecond_) {
665 auto secondColumn = allChildNode_["second"].Upgrade();
666 CHECK_NULL_RETURN(secondColumn, time);
667 auto secondPickerColumnPattern = secondColumn->GetPattern<TimePickerColumnPattern>();
668 CHECK_NULL_RETURN(secondPickerColumnPattern, time);
669 time.SetSecond(secondPickerColumnPattern->GetCurrentIndex()); // second from 0 to 59, index from 0 to 59
670 }
671 return time;
672 }
673
GetEnterObject(bool isColumnChange,int32_t status)674 std::string TimePickerRowPattern::GetEnterObject(bool isColumnChange, int32_t status)
675 {
676 auto time = selectedTime_;
677 if (isColumnChange) {
678 time = GetCurrentEnterTime();
679 }
680 return time.ToString(true, hasSecond_, status);
681 }
682
GetCurrentEnterTime()683 PickerTime TimePickerRowPattern::GetCurrentEnterTime()
684 {
685 PickerTime time;
686 UpdateAllChildNode();
687 auto amPmColumn = allChildNode_["amPm"].Upgrade();
688 auto hourColumn = allChildNode_["hour"].Upgrade();
689 auto minuteColumn = allChildNode_["minute"].Upgrade();
690 CHECK_NULL_RETURN(hourColumn, time);
691 CHECK_NULL_RETURN(minuteColumn, time);
692 auto hourPickerColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
693 CHECK_NULL_RETURN(hourPickerColumnPattern, time);
694 auto minutePickerColumnPattern = minuteColumn->GetPattern<TimePickerColumnPattern>();
695 CHECK_NULL_RETURN(minutePickerColumnPattern, time);
696
697 if (GetHour24()) {
698 if (IsStartEndTimeDefined()) {
699 time.SetHour(hourPickerColumnPattern->GetEnterIndex() + startTime_.GetHour());
700 } else {
701 time.SetHour(hourPickerColumnPattern->GetEnterIndex()); // hour from 0 to 23, index from 0 to 23
702 }
703 } else if (amPmColumn) {
704 auto amPmPickerColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
705 CHECK_NULL_RETURN(amPmPickerColumnPattern, time);
706 if (IsStartEndTimeDefined()) {
707 auto hourPickerColumnIndex = hourPickerColumnPattern->GetEnterIndex();
708 auto hour = GetOptionsValue(hourColumn, hourPickerColumnIndex);
709 time.SetHour(
710 GetHourFromAmPm(amPmPickerColumnPattern->GetEnterIndex() == 0, StringUtils::StringToUint(hour)));
711 } else {
712 time.SetHour(GetHourFromAmPm(
713 amPmPickerColumnPattern->GetEnterIndex() == 0, hourPickerColumnPattern->GetEnterIndex() + 1));
714 }
715 }
716
717 time.SetMinute(minutePickerColumnPattern->GetEnterIndex()); // minute from 0 to 59, index from 0 to 59
718 if (hasSecond_) {
719 auto secondColumn = allChildNode_["second"].Upgrade();
720 CHECK_NULL_RETURN(secondColumn, time);
721 auto secondPickerColumnPattern = secondColumn->GetPattern<TimePickerColumnPattern>();
722 CHECK_NULL_RETURN(secondPickerColumnPattern, time);
723 time.SetSecond(secondPickerColumnPattern->GetEnterIndex()); // second from 0 to 59, index from 0 to 59
724 }
725 return time;
726 }
727
GetHourFromAmPm(bool isAm,uint32_t amPmhour) const728 uint32_t TimePickerRowPattern::GetHourFromAmPm(bool isAm, uint32_t amPmhour) const
729 {
730 if (isAm) {
731 if (amPmhour == AM_PM_HOUR_12) { // AM 12:00 means 00:00
732 return 0;
733 }
734 return amPmhour;
735 }
736 if (amPmhour == AM_PM_HOUR_12) { // PM 12 means 12:00
737 return AM_PM_HOUR_12;
738 }
739 return amPmhour + AM_PM_HOUR_12; // need add 12 hour to 24 hours style
740 }
741
HandleColumnChange(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,bool needNotify)742 void TimePickerRowPattern::HandleColumnChange(const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, bool needNotify)
743 {
744 std::vector<RefPtr<FrameNode>> tags;
745 if (wheelModeEnabled_ && isEnableCascade_ && !IsStartEndTimeDefined()) {
746 OnDataLinking(tag, isAdd, index, tags);
747 }
748 for (const auto& tag : tags) {
749 auto iter = std::find_if(timePickerColumns_.begin(), timePickerColumns_.end(), [&tag](const auto& c) {
750 auto column = c.Upgrade();
751 return column && column->GetId() == tag->GetId();
752 });
753 if (iter != timePickerColumns_.end()) {
754 auto timePickerColumn = (*iter).Upgrade();
755 CHECK_NULL_VOID(timePickerColumn);
756 auto timePickerColumnPattern = timePickerColumn->GetPattern<TimePickerColumnPattern>();
757 CHECK_NULL_VOID(timePickerColumnPattern);
758 timePickerColumnPattern->FlushCurrentOptions();
759 }
760 }
761
762 HandleColumnsChangeTimeRange(tag);
763 }
764
IsStartEndTimeDefined()765 bool TimePickerRowPattern::IsStartEndTimeDefined()
766 {
767 auto isStartEndTimeDefined = startTime_.ToMinutes() != START_DEFAULT_TIME.ToMinutes() ||
768 endTime_.ToMinutes() != END_DEFAULT_TIME.ToMinutes();
769 return isStartEndTimeDefined;
770 }
771
HandleColumnsChangeTimeRange(const RefPtr<FrameNode> & tag)772 void TimePickerRowPattern::HandleColumnsChangeTimeRange(const RefPtr<FrameNode>& tag)
773 {
774 if (IsStartEndTimeDefined()) {
775 auto hourColumn = allChildNode_["hour"].Upgrade();
776 CHECK_NULL_VOID(hourColumn);
777 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
778 CHECK_NULL_VOID(hourColumnPattern);
779
780 auto minuteColumn = allChildNode_["minute"].Upgrade();
781 CHECK_NULL_VOID(minuteColumn);
782 auto minuteColumnPattern = minuteColumn->GetPattern<TimePickerColumnPattern>();
783 CHECK_NULL_VOID(minuteColumnPattern);
784 auto amPmColumn = allChildNode_["amPm"].Upgrade();
785 auto secondColumn = allChildNode_["second"].Upgrade();
786 if (!GetHour24() && tag == amPmColumn) {
787 options_[hourColumn].clear();
788 options_[minuteColumn].clear();
789 UpdateHourAndMinuteTimeRange(tag);
790 UpdateSecondTimeRange();
791 hourColumnPattern->FlushCurrentOptions();
792 minuteColumnPattern->FlushCurrentOptions();
793 auto amPmColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
794 CHECK_NULL_VOID(amPmColumnPattern);
795 amPmColumnPattern->FlushCurrentOptions();
796 if (hasSecond_ && secondColumn) {
797 HandleSecondsChangeTimeRange(secondColumn);
798 }
799 } else if (tag == hourColumn || tag == minuteColumn) {
800 options_[hourColumn].clear();
801 options_[minuteColumn].clear();
802 UpdateHourAndMinuteTimeRange(tag);
803 hourColumnPattern->FlushCurrentOptions();
804 minuteColumnPattern->FlushCurrentOptions();
805 if (hasSecond_ && secondColumn) {
806 HandleSecondsChangeTimeRange(secondColumn);
807 }
808 } else if (tag == secondColumn) {
809 HandleSecondsChangeTimeRange(secondColumn);
810 }
811 oldHourValue_ = GetOptionsCurrentValue(hourColumn);
812 oldMinuteValue_ = GetOptionsCurrentValue(minuteColumn);
813 }
814 }
815
HandleSecondsChangeTimeRange(const RefPtr<FrameNode> & secondColumn)816 void TimePickerRowPattern::HandleSecondsChangeTimeRange(const RefPtr<FrameNode>& secondColumn)
817 {
818 if (hasSecond_ && secondColumn) {
819 options_[secondColumn].clear();
820 UpdateSecondTimeRange();
821 auto secondColumnPattern = secondColumn->GetPattern<TimePickerColumnPattern>();
822 CHECK_NULL_VOID(secondColumnPattern);
823 secondColumnPattern->SetOptions(GetOptionsCount());
824 secondColumnPattern->SetShowCount(GetShowCount());
825 secondColumnPattern->FlushCurrentOptions();
826 secondColumn->MarkModifyDone();
827 secondColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
828 }
829 }
830
UpdateHourAndMinuteTimeRange(const RefPtr<FrameNode> & tag)831 void TimePickerRowPattern::UpdateHourAndMinuteTimeRange(const RefPtr<FrameNode>& tag)
832 {
833 auto hourColumn = allChildNode_["hour"].Upgrade();
834 CHECK_NULL_VOID(hourColumn);
835 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
836 CHECK_NULL_VOID(hourColumnPattern);
837 auto minuteColumn = allChildNode_["minute"].Upgrade();
838 CHECK_NULL_VOID(minuteColumn);
839 auto minuteColumnPattern = minuteColumn->GetPattern<TimePickerColumnPattern>();
840 CHECK_NULL_VOID(minuteColumnPattern);
841 auto amPmColumn = allChildNode_["amPm"].Upgrade();
842
843 // update hour column's options
844 HourChangeBuildTimeRange();
845 if (!GetHour24() && tag == amPmColumn) {
846 // update Hour column option after changing ampm column
847 // and set corresponding new index based on old value
848 uint32_t newIndex = INDEX_HOUR_STRAT;
849 if (!GetOptionsIndex(hourColumn, oldHourValue_, newIndex)) {
850 auto uintOldHour = StringUtils::StringToUint(oldHourValue_);
851 if (((IsAmJudgeByAmPmColumn(amPmColumn) && uintOldHour == AM_PM_HOUR_12) ? INDEX_HOUR_STRAT : uintOldHour) <
852 startTime_.GetHour()) {
853 newIndex = INDEX_HOUR_STRAT;
854 } else {
855 newIndex = options_[hourColumn].size() - 1;
856 }
857 }
858 hourColumnPattern->SetCurrentIndex(newIndex);
859 hourColumnPattern->SetEnterIndex(newIndex);
860 }
861 oldHourValue_ = GetOptionsCurrentValue(hourColumn);
862
863 // update minute column's options
864 auto currentHourOf24 = StringUtils::StringToUint(oldHourValue_);
865 if (!GetHour24()) {
866 currentHourOf24 = GetHourFromAmPm(IsAmJudgeByAmPmColumn(amPmColumn), StringUtils::StringToUint(oldHourValue_));
867 }
868 MinuteChangeBuildTimeRange(currentHourOf24);
869 if (tag != minuteColumn) {
870 uint32_t newIndex = INDEX_MINUTE_STRAT;
871 if (!GetOptionsIndex(minuteColumn, oldMinuteValue_, newIndex)) {
872 if (StringUtils::StringToUint(oldMinuteValue_) < startTime_.GetMinute()) {
873 newIndex = INDEX_MINUTE_STRAT;
874 } else {
875 newIndex = options_[minuteColumn].size() - 1;
876 }
877 }
878 minuteColumnPattern->SetCurrentIndex(newIndex);
879 minuteColumnPattern->SetEnterIndex(newIndex);
880 }
881 oldMinuteValue_ = GetOptionsCurrentValue(minuteColumn);
882 }
883
IsAmJudgeByAmPmColumn(const RefPtr<FrameNode> & amPmColumn)884 bool TimePickerRowPattern::IsAmJudgeByAmPmColumn(const RefPtr<FrameNode>& amPmColumn)
885 {
886 auto isAm = false;
887 CHECK_NULL_RETURN(amPmColumn, isAm);
888 auto amPmColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
889 CHECK_NULL_RETURN(amPmColumnPattern, false);
890 isAm = (options_[amPmColumn].size() == SIZE_OF_AMPM_COLUMN_OPTION && amPmColumnPattern->GetCurrentIndex() == 0) ||
891 (options_[amPmColumn].size() < SIZE_OF_AMPM_COLUMN_OPTION && IsAmHour(startTime_.GetHour()));
892 return isAm;
893 }
894
UpdateSecondTimeRange()895 void TimePickerRowPattern::UpdateSecondTimeRange()
896 {
897 auto secondColumn = allChildNode_["second"].Upgrade();
898 CHECK_NULL_VOID(secondColumn);
899 auto secondColumnPattern = secondColumn->GetPattern<TimePickerColumnPattern>();
900 CHECK_NULL_VOID(secondColumnPattern);
901 optionsTotalCount_[secondColumn] = 0;
902
903 for (uint32_t second = INDEX_SECOND_STRAT; second <= INDEX_SECOND_END; second++) { // time's second from 0 to 59
904 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
905 GetPrefixSecond() == ZeroPrefixType::HIDE) {
906 options_[secondColumn][second] = std::to_string(second);
907 } else {
908 if (second < INDEX_SECOND_ADD_ZERO) { // time's second less than 10
909 options_[secondColumn][second] = std::string("0") + std::to_string(second);
910 } else {
911 options_[secondColumn][second] = std::to_string(second);
912 }
913 }
914 optionsTotalCount_[secondColumn]++;
915 }
916 secondColumnPattern->SetOptions(GetOptionsCount());
917 IsStartEndTimeDefined() ? secondColumnPattern->SetWheelModeEnabled(false)
918 : secondColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
919 }
920
HourChangeBuildTimeRange()921 void TimePickerRowPattern::HourChangeBuildTimeRange()
922 {
923 if (GetHour24()) {
924 Hour24ChangeBuildTimeRange();
925 } else {
926 Hour12ChangeBuildTimeRange();
927 }
928 }
929
Hour24ChangeBuildTimeRange()930 void TimePickerRowPattern::Hour24ChangeBuildTimeRange()
931 {
932 auto hourColumn = allChildNode_["hour"].Upgrade();
933 CHECK_NULL_VOID(hourColumn);
934 optionsTotalCount_[hourColumn] = 0;
935 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
936 CHECK_NULL_VOID(hourColumnPattern);
937 for (uint32_t index = 0; index < defined24Hours_.size(); index++) {
938 options_[hourColumn][index] = defined24Hours_[index];
939 optionsTotalCount_[hourColumn]++;
940 }
941 hourColumnPattern->SetOptions(GetOptionsCount());
942 IsStartEndTimeDefined() ? hourColumnPattern->SetWheelModeEnabled(false)
943 : hourColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
944 hourColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
945 }
946
Hour12ChangeBuildTimeRange()947 void TimePickerRowPattern::Hour12ChangeBuildTimeRange()
948 {
949 auto amPmColumn = allChildNode_["amPm"].Upgrade();
950 CHECK_NULL_VOID(amPmColumn);
951 auto hourColumn = allChildNode_["hour"].Upgrade();
952 CHECK_NULL_VOID(hourColumn);
953 optionsTotalCount_[hourColumn] = 0;
954 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
955 CHECK_NULL_VOID(hourColumnPattern);
956
957 if (IsAmJudgeByAmPmColumn(amPmColumn)) {
958 for (uint32_t index = 0; index < definedAMHours_.size(); index++) {
959 options_[hourColumn][index] = definedAMHours_[index];
960 optionsTotalCount_[hourColumn]++;
961 }
962 } else {
963 for (uint32_t index = 0; index < definedPMHours_.size(); index++) {
964 options_[hourColumn][index] = definedPMHours_[index];
965 optionsTotalCount_[hourColumn]++;
966 }
967 }
968
969 hourColumnPattern->SetOptions(GetOptionsCount());
970 IsStartEndTimeDefined() ? hourColumnPattern->SetWheelModeEnabled(false)
971 : hourColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
972 }
973
MinuteChangeBuildTimeRange(uint32_t hourOf24)974 void TimePickerRowPattern::MinuteChangeBuildTimeRange(uint32_t hourOf24)
975 {
976 uint32_t startMinute = (hourOf24 == startTime_.GetHour()) ? startTime_.GetMinute() : INDEX_MINUTE_STRAT;
977 uint32_t endMinute = (hourOf24 == endTime_.GetHour()) ? endTime_.GetMinute() : INDEX_MINUTE_END;
978 auto minuteColumn = allChildNode_["minute"].Upgrade();
979 CHECK_NULL_VOID(minuteColumn);
980 auto minuteColumnPattern = minuteColumn->GetPattern<TimePickerColumnPattern>();
981 CHECK_NULL_VOID(minuteColumnPattern);
982 optionsTotalCount_[minuteColumn] = 0;
983 uint32_t index = 0;
984 for (uint32_t minute = startMinute; minute <= endMinute; minute++) {
985 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
986 GetPrefixMinute() == ZeroPrefixType::HIDE) {
987 options_[minuteColumn][index] = std::to_string(minute);
988 } else {
989 options_[minuteColumn][index] =
990 (minute < MINUTE_10) ? std::string("0") + std::to_string(minute) : std::to_string(minute);
991 }
992 optionsTotalCount_[minuteColumn]++;
993 index++;
994 }
995
996 minuteColumnPattern->SetOptions(GetOptionsCount());
997 IsStartEndTimeDefined() ? minuteColumnPattern->SetWheelModeEnabled(false)
998 : minuteColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
999 }
1000
OnFontConfigurationUpdate()1001 void TimePickerRowPattern::OnFontConfigurationUpdate()
1002 {
1003 CHECK_NULL_VOID(closeDialogEvent_);
1004 closeDialogEvent_();
1005 }
1006
OnFontScaleConfigurationUpdate()1007 void TimePickerRowPattern::OnFontScaleConfigurationUpdate()
1008 {
1009 CHECK_NULL_VOID(closeDialogEvent_);
1010 closeDialogEvent_();
1011 }
1012
UpdateConfirmButtonMargin(const RefPtr<FrameNode> & buttonConfirmNode,const RefPtr<DialogTheme> & dialogTheme)1013 void TimePickerRowPattern::UpdateConfirmButtonMargin(
1014 const RefPtr<FrameNode>& buttonConfirmNode, const RefPtr<DialogTheme>& dialogTheme)
1015 {
1016 MarginProperty margin;
1017 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1018 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1019 DialogTypeMargin::UpdateDialogMargin(isRtl, margin, dialogTheme, true, ModuleDialogType::TIMEPICKER_DIALOG);
1020 } else {
1021 DialogTypeMargin::UpdateDialogMargin(isRtl, margin, dialogTheme, false, ModuleDialogType::TIMEPICKER_DIALOG);
1022 }
1023 buttonConfirmNode->GetLayoutProperty()->UpdateMargin(margin);
1024 }
1025
UpdateCancelButtonMargin(const RefPtr<FrameNode> & buttonCancelNode,const RefPtr<DialogTheme> & dialogTheme)1026 void TimePickerRowPattern::UpdateCancelButtonMargin(
1027 const RefPtr<FrameNode>& buttonCancelNode, const RefPtr<DialogTheme>& dialogTheme)
1028 {
1029 MarginProperty margin;
1030 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1031 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1032 DialogTypeMargin::UpdateDialogMargin(!isRtl, margin, dialogTheme, true, ModuleDialogType::TIMEPICKER_DIALOG);
1033 } else {
1034 DialogTypeMargin::UpdateDialogMargin(!isRtl, margin, dialogTheme, false,
1035 ModuleDialogType::TIMEPICKER_DIALOG);
1036 }
1037 buttonCancelNode->GetLayoutProperty()->UpdateMargin(margin);
1038 }
1039
OnLanguageConfigurationUpdate()1040 void TimePickerRowPattern::OnLanguageConfigurationUpdate()
1041 {
1042 FlushAmPmFormatString();
1043 UpdateLanguageAndAmPmTimeOrder();
1044 if (!GetHour24()) {
1045 auto host = GetHost();
1046 CHECK_NULL_VOID(host);
1047 auto children = host->GetChildren();
1048 auto iter = children.begin();
1049 CHECK_NULL_VOID(*iter);
1050 auto amPmNode = *iter;
1051 CHECK_NULL_VOID(amPmNode);
1052 if (amPmTimeOrder_ == "01" && isAmPmTimeOrderUpdate_) {
1053 // if hasSecond_ is true, then amPmNode should be moved from slot 0 to 3, otherwise from slot 0 to 2
1054 hasSecond_ ? amPmNode->MovePosition(3) : amPmNode->MovePosition(2);
1055 } else if (amPmTimeOrder_ == "10" && isAmPmTimeOrderUpdate_) {
1056 // if hasSecond_ is true, then amPmNode should be moved from slot 3 to 0, otherwise form slot 2 to 0
1057 hasSecond_ ? std::advance(iter, 3) : std::advance(iter, 2);
1058 amPmNode = *iter;
1059 CHECK_NULL_VOID(amPmNode);
1060 amPmNode->MovePosition(0);
1061 }
1062 UpdateNodePositionForUg();
1063 auto layoutProperty = AceType::DynamicCast<FrameNode>(amPmNode)->GetLayoutProperty<LayoutProperty>();
1064 layoutProperty->UpdateAlignment(Alignment::CENTER);
1065 layoutProperty->UpdateLayoutWeight(1);
1066 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1067 }
1068 auto buttonConfirmNode = weakButtonConfirm_.Upgrade();
1069 CHECK_NULL_VOID(buttonConfirmNode);
1070 auto confirmNode = AceType::DynamicCast<FrameNode>(buttonConfirmNode->GetFirstChild());
1071 CHECK_NULL_VOID(confirmNode);
1072 auto confirmNodeLayout = confirmNode->GetLayoutProperty<TextLayoutProperty>();
1073 CHECK_NULL_VOID(confirmNodeLayout);
1074 confirmNodeLayout->UpdateContent(Localization::GetInstance()->GetEntryLetters("common.ok"));
1075 auto pipeline = confirmNode->GetContextRefPtr();
1076 CHECK_NULL_VOID(pipeline);
1077 auto dialogTheme = pipeline->GetTheme<DialogTheme>();
1078 CHECK_NULL_VOID(dialogTheme);
1079 UpdateConfirmButtonMargin(buttonConfirmNode, dialogTheme);
1080 confirmNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1081
1082 auto buttonCancelNode = weakButtonCancel_.Upgrade();
1083 CHECK_NULL_VOID(buttonCancelNode);
1084 auto cancelNode = AceType::DynamicCast<FrameNode>(buttonCancelNode->GetFirstChild());
1085 CHECK_NULL_VOID(cancelNode);
1086 auto cancelNodeLayout = cancelNode->GetLayoutProperty<TextLayoutProperty>();
1087 CHECK_NULL_VOID(cancelNodeLayout);
1088 cancelNodeLayout->UpdateContent(Localization::GetInstance()->GetEntryLetters("common.cancel"));
1089 UpdateCancelButtonMargin(buttonCancelNode, dialogTheme);
1090 cancelNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1091 }
1092
UpdateNodePositionForUg()1093 void TimePickerRowPattern::UpdateNodePositionForUg()
1094 {
1095 if (!isPreLanguageUg_ && language_ != "ug") {
1096 return;
1097 }
1098
1099 auto host = GetHost();
1100 CHECK_NULL_VOID(host);
1101 // ug's node order is S:M:H, need to change it to H:M:S
1102 if (isPreLanguageUg_ && isAmPmTimeOrderUpdate_) {
1103 if (hasSecond_) {
1104 auto secondNode = host->GetChildAtIndex(CHILD_INDEX_FIRST);
1105 CHECK_NULL_VOID(secondNode);
1106 secondNode->MovePosition(CHILD_INDEX_THIRD);
1107
1108 auto minuteNode = host->GetChildAtIndex(CHILD_INDEX_FIRST);
1109 CHECK_NULL_VOID(minuteNode);
1110 minuteNode->MovePosition(CHILD_INDEX_SECOND);
1111 } else {
1112 auto minuteNode = host->GetChildAtIndex(CHILD_INDEX_FIRST);
1113 CHECK_NULL_VOID(minuteNode);
1114 minuteNode->MovePosition(CHILD_INDEX_SECOND);
1115 }
1116 } else if ((isPreLanguageUg_ && !isAmPmTimeOrderUpdate_) || (language_ == "ug")) {
1117 if (hasSecond_) {
1118 auto hourNode = host->GetChildAtIndex(CHILD_INDEX_FOURTH);
1119 CHECK_NULL_VOID(hourNode);
1120 hourNode->MovePosition(CHILD_INDEX_SECOND);
1121 auto minuteNode = host->GetChildAtIndex(CHILD_INDEX_FOURTH);
1122 CHECK_NULL_VOID(minuteNode);
1123 minuteNode->MovePosition(CHILD_INDEX_THIRD);
1124 } else {
1125 auto hourNode = host->GetChildAtIndex(CHILD_INDEX_THIRD);
1126 CHECK_NULL_VOID(hourNode);
1127 hourNode->MovePosition(CHILD_INDEX_SECOND);
1128 }
1129 }
1130 if (isPreLanguageUg_) {
1131 isPreLanguageUg_ = false;
1132 }
1133 }
1134
FlushAmPmFormatString()1135 void TimePickerRowPattern::FlushAmPmFormatString()
1136 {
1137 auto amPmStrings = Localization::GetInstance()->GetAmPmStrings();
1138 if (amPmStrings.size() > 1) {
1139 vecAmPm_.clear();
1140 std::string am = amPmStrings[0];
1141 vecAmPm_.emplace_back(am);
1142 std::string pm = amPmStrings[1];
1143 vecAmPm_.emplace_back(pm);
1144 }
1145 }
1146
SetChangeCallback(ColumnChangeCallback && value)1147 void TimePickerRowPattern::SetChangeCallback(ColumnChangeCallback&& value)
1148 {
1149 auto host = GetHost();
1150 CHECK_NULL_VOID(host);
1151 auto children = host->GetChildren();
1152 for (const auto& child : children) {
1153 auto stackNode = DynamicCast<FrameNode>(child);
1154 CHECK_NULL_VOID(stackNode);
1155 auto columnBlendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
1156 CHECK_NULL_VOID(columnBlendNode);
1157 auto childNode = DynamicCast<FrameNode>(columnBlendNode->GetLastChild());
1158 CHECK_NULL_VOID(childNode);
1159 auto timePickerColumnPattern = childNode->GetPattern<TimePickerColumnPattern>();
1160 CHECK_NULL_VOID(timePickerColumnPattern);
1161 timePickerColumnPattern->SetChangeCallback(std::move(value));
1162 }
1163 }
1164
FlushColumn()1165 void TimePickerRowPattern::FlushColumn()
1166 {
1167 UpdateAllChildNode();
1168 auto amPmColumn = allChildNode_["amPm"].Upgrade();
1169 auto hourColumn = allChildNode_["hour"].Upgrade();
1170 if (GetHour24()) {
1171 CHECK_NULL_VOID(hourColumn);
1172 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
1173 CHECK_NULL_VOID(hourColumnPattern);
1174 hourColumnPattern->SetOptions(GetOptionsCount());
1175 hourColumnPattern->SetShowCount(GetShowCount());
1176 hourColumnPattern->FlushCurrentOptions();
1177 hourColumn->MarkModifyDone();
1178 hourColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1179 } else if (amPmColumn) {
1180 auto amPmColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
1181 CHECK_NULL_VOID(amPmColumnPattern);
1182 amPmColumnPattern->SetShowCount(AM_PM_COUNT);
1183 amPmColumnPattern->FlushCurrentOptions();
1184 amPmColumn->MarkModifyDone();
1185 amPmColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1186
1187 CHECK_NULL_VOID(hourColumn);
1188 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
1189 CHECK_NULL_VOID(hourColumnPattern);
1190 hourColumnPattern->SetOptions(GetOptionsCount());
1191 hourColumnPattern->SetShowCount(GetShowCount());
1192 hourColumnPattern->FlushCurrentOptions();
1193 hourColumn->MarkModifyDone();
1194 hourColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1195 }
1196
1197 auto minuteColumn = allChildNode_["minute"].Upgrade();
1198 CHECK_NULL_VOID(minuteColumn);
1199 auto minuteColumnPattern = minuteColumn->GetPattern<TimePickerColumnPattern>();
1200 CHECK_NULL_VOID(minuteColumnPattern);
1201 minuteColumnPattern->SetShowCount(GetShowCount());
1202 minuteColumnPattern->FlushCurrentOptions();
1203 minuteColumn->MarkModifyDone();
1204 minuteColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1205 if (hasSecond_) {
1206 auto secondColumn = allChildNode_["second"].Upgrade();
1207 CHECK_NULL_VOID(secondColumn);
1208 auto secondColumnPattern = secondColumn->GetPattern<TimePickerColumnPattern>();
1209 CHECK_NULL_VOID(secondColumnPattern);
1210 secondColumnPattern->SetOptions(GetOptionsCount());
1211 secondColumnPattern->SetShowCount(GetShowCount());
1212 secondColumnPattern->FlushCurrentOptions();
1213 }
1214 }
1215
OnDataLinking(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)1216 void TimePickerRowPattern::OnDataLinking(
1217 const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
1218 {
1219 CHECK_NULL_VOID(tag);
1220 auto hourNode = allChildNode_["hour"].Upgrade();
1221 CHECK_NULL_VOID(hourNode);
1222 if (tag->GetId() != hourNode->GetId()) {
1223 return;
1224 }
1225
1226 if (!GetHour24()) {
1227 HandleHour12Change(isAdd, index, resultTags);
1228 }
1229 }
1230
GetOptionsValue(const RefPtr<FrameNode> & frameNode,uint32_t optionIndex)1231 const std::string& TimePickerRowPattern::GetOptionsValue(const RefPtr<FrameNode>& frameNode, uint32_t optionIndex)
1232 {
1233 UpdateAllChildNode();
1234 if (frameNode == allChildNode_["amPm"]) {
1235 return options_[allChildNode_["amPm"]][optionIndex];
1236 }
1237 bool isHour12 = !GetHour24();
1238 auto isHourNode = frameNode == allChildNode_["hour"];
1239 if (options_.find(frameNode) == options_.end()) {
1240 options_[frameNode] = std::unordered_map<uint32_t, std::string>();
1241 }
1242 if (options_[frameNode].find(optionIndex) == options_[frameNode].end()) {
1243 options_[frameNode][optionIndex] =
1244 isHourNode ? GetHourFormatString(optionIndex + isHour12) : GetMinuteFormatString(optionIndex);
1245 }
1246 return options_[frameNode][optionIndex];
1247 }
1248
GetOptionsIndex(const RefPtr<FrameNode> & frameNode,const std::string & value,uint32_t & columnIndex)1249 bool TimePickerRowPattern::GetOptionsIndex(
1250 const RefPtr<FrameNode>& frameNode, const std::string& value, uint32_t& columnIndex)
1251 {
1252 CHECK_NULL_RETURN(frameNode, false);
1253 bool result = false;
1254 auto columnFound = options_.find(frameNode);
1255 if (columnFound != options_.end()) {
1256 for (const auto& option : columnFound->second) {
1257 if (option.second == value) {
1258 columnIndex = option.first;
1259 result = true;
1260 }
1261 }
1262 }
1263 return result;
1264 }
1265
GetOptionsCurrentValue(const RefPtr<FrameNode> & frameNode)1266 std::string TimePickerRowPattern::GetOptionsCurrentValue(const RefPtr<FrameNode>& frameNode)
1267 {
1268 std::string result = "";
1269 CHECK_NULL_RETURN(frameNode, result);
1270 auto columnFound = options_.find(frameNode);
1271 if (columnFound != options_.end()) {
1272 auto columnPattern = frameNode->GetPattern<TimePickerColumnPattern>();
1273 CHECK_NULL_RETURN(columnPattern, result);
1274 auto currentIndex = columnPattern->GetCurrentIndex();
1275 for (const auto& option : columnFound->second) {
1276 if (option.first == currentIndex) {
1277 result = option.second;
1278 }
1279 }
1280 }
1281 return result;
1282 }
1283
GetOptionsValueWithIndex(const RefPtr<FrameNode> & frameNode,uint32_t optionIndex)1284 std::string TimePickerRowPattern::GetOptionsValueWithIndex(const RefPtr<FrameNode>& frameNode, uint32_t optionIndex)
1285 {
1286 std::string result = "";
1287 CHECK_NULL_RETURN(frameNode, result);
1288 auto columnFound = options_.find(frameNode);
1289 if (columnFound != options_.end()) {
1290 auto currentIndex = optionIndex;
1291 for (const auto& option : columnFound->second) {
1292 if (option.first == currentIndex) {
1293 result = option.second;
1294 }
1295 }
1296 }
1297 return result;
1298 }
1299
OnColumnsBuilding()1300 void TimePickerRowPattern::OnColumnsBuilding()
1301 {
1302 if (IsStartEndTimeDefined()) {
1303 HandleHourColumnBuildingRange(GetSelectedTime());
1304 HandleMinAndSecColumnBuildingRange();
1305 RecordHourAndMinuteOptions();
1306 } else {
1307 HandleHourColumnBuilding();
1308 HandleMinAndSecColumnBuilding();
1309 }
1310 }
1311
HandleHourColumnBuilding()1312 void TimePickerRowPattern::HandleHourColumnBuilding()
1313 {
1314 UpdateAllChildNode();
1315 auto hourColumn = allChildNode_["hour"].Upgrade();
1316 CHECK_NULL_VOID(hourColumn);
1317 optionsTotalCount_[hourColumn] = 0;
1318 if (GetHour24()) {
1319 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
1320 CHECK_NULL_VOID(hourColumnPattern);
1321 for (uint32_t hour = 0; hour <= 23; ++hour) { // time's hour from 0 to 23.
1322 if (hour == selectedTime_.GetHour()) {
1323 hourColumnPattern->SetCurrentIndex(hour);
1324 hourColumnPattern->SetEnterIndex(hour);
1325 }
1326 optionsTotalCount_[hourColumn]++;
1327 }
1328 hourColumnPattern->SetOptions(GetOptionsCount());
1329 hourColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1330 hourColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1331 } else {
1332 auto amPmColumn = allChildNode_["amPm"].Upgrade();
1333 CHECK_NULL_VOID(amPmColumn);
1334 auto amPmColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
1335 CHECK_NULL_VOID(amPmColumnPattern);
1336 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
1337 CHECK_NULL_VOID(hourColumnPattern);
1338 options_[amPmColumn][INDEX_AM_0] = GetAmFormatString();
1339 options_[amPmColumn][INDEX_PM_1] = GetPmFormatString();
1340
1341 if (IsAmHour(selectedTime_.GetHour())) {
1342 amPmColumnPattern->SetCurrentIndex(0); // AM's index
1343 amPmColumnPattern->SetEnterIndex(0);
1344 } else {
1345 amPmColumnPattern->SetCurrentIndex(1); // PM's index
1346 amPmColumnPattern->SetEnterIndex(1);
1347 }
1348 optionsTotalCount_[amPmColumn] = CHILD_WITHOUT_AMPM_SIZE;
1349 auto selectedHour = GetAmPmHour(selectedTime_.GetHour());
1350 for (uint32_t hour = 1; hour <= AM_PM_HOUR_12; ++hour) { // AM_PM hour start from 1 to 12
1351 if (hour == selectedHour) {
1352 hourColumnPattern->SetCurrentIndex(hour - 1);
1353 hourColumnPattern->SetEnterIndex(hour - 1);
1354 }
1355 optionsTotalCount_[hourColumn]++;
1356 }
1357 amPmColumnPattern->SetOptions(GetOptionsCount());
1358 hourColumnPattern->SetOptions(GetOptionsCount());
1359 amPmColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1360 hourColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1361 }
1362 }
1363
HandleMinAndSecColumnBuilding()1364 void TimePickerRowPattern::HandleMinAndSecColumnBuilding()
1365 {
1366 UpdateAllChildNode();
1367 auto minuteColumn = allChildNode_["minute"].Upgrade();
1368 CHECK_NULL_VOID(minuteColumn);
1369 MinOrSecColumnBuilding(minuteColumn, GetPrefixMinute() == ZeroPrefixType::HIDE, selectedTime_.GetMinute());
1370 auto secondColumn = allChildNode_["second"].Upgrade();
1371 CHECK_NULL_VOID(secondColumn);
1372 MinOrSecColumnBuilding(secondColumn, GetPrefixSecond() == ZeroPrefixType::HIDE, selectedTime_.GetSecond());
1373 }
1374
MinOrSecColumnBuilding(const RefPtr<FrameNode> & columnFrameNode,bool isZeroPrefixTypeHide,uint32_t selectedTime)1375 void TimePickerRowPattern::MinOrSecColumnBuilding(
1376 const RefPtr<FrameNode>& columnFrameNode, bool isZeroPrefixTypeHide, uint32_t selectedTime)
1377 {
1378 CHECK_NULL_VOID(columnFrameNode);
1379 auto columnPattern = columnFrameNode->GetPattern<TimePickerColumnPattern>();
1380 CHECK_NULL_VOID(columnPattern);
1381 optionsTotalCount_[columnFrameNode] = 0;
1382
1383 for (uint32_t time = 0; time <= 59; ++time) { // time's minute or second from 0 to 59
1384 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) && isZeroPrefixTypeHide) {
1385 options_[columnFrameNode][time] = std::to_string(time);
1386 } else {
1387 if (time < 10) { // time's minute or second less than 10
1388 options_[columnFrameNode][time] = std::string("0") + std::to_string(time);
1389 }
1390 }
1391 if (time == selectedTime) {
1392 columnPattern->SetCurrentIndex(time);
1393 columnPattern->SetEnterIndex(time);
1394 }
1395 optionsTotalCount_[columnFrameNode]++;
1396 }
1397 columnPattern->SetOptions(GetOptionsCount());
1398 columnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1399 }
1400
RecordHourAndMinuteOptions()1401 void TimePickerRowPattern::RecordHourAndMinuteOptions()
1402 {
1403 RecordHourOptions();
1404 RecordHourMinuteValues();
1405 }
1406
RecordHourOptions()1407 void TimePickerRowPattern::RecordHourOptions()
1408 {
1409 uint32_t startHour = startTime_.GetHour();
1410 uint32_t endHour = endTime_.GetHour();
1411 definedAMHours_.clear();
1412 definedAMHours_.shrink_to_fit();
1413 definedPMHours_.clear();
1414 definedPMHours_.shrink_to_fit();
1415 defined24Hours_.clear();
1416 defined24Hours_.shrink_to_fit();
1417 if (GetHour24()) {
1418 for (uint32_t hour = startHour; hour <= endHour; ++hour) {
1419 defined24Hours_.emplace_back(GetHourFormatString(hour));
1420 }
1421 } else {
1422 bool isAmStart = IsAmHour(startHour);
1423 bool isAmEnd = IsAmHour(endHour);
1424 if (isAmStart && !isAmEnd) {
1425 // start time is in the morning and end time is in the afternoon
1426 for (uint32_t hour = startHour; hour <= AM_PM_HOUR_11; hour++) {
1427 definedAMHours_.emplace_back(GetHourFormatString(GetAmPmHour(hour)));
1428 }
1429 for (uint32_t hour = AM_PM_HOUR_12; hour <= endHour; hour++) {
1430 definedPMHours_.emplace_back(GetHourFormatString(GetAmPmHour(hour)));
1431 }
1432 } else if (isAmStart) {
1433 // both start time and end time are in the morning
1434 for (uint32_t hour = startHour; hour <= endHour; hour++) {
1435 definedAMHours_.emplace_back(GetHourFormatString(GetAmPmHour(hour)));
1436 }
1437 } else {
1438 // both start time and end time are in the afternoon
1439 for (uint32_t hour = startHour; hour <= endHour; hour++) {
1440 definedPMHours_.emplace_back(GetHourFormatString(GetAmPmHour(hour)));
1441 }
1442 }
1443 }
1444 }
1445
RecordHourMinuteValues()1446 void TimePickerRowPattern::RecordHourMinuteValues()
1447 {
1448 auto hourColumn = allChildNode_["hour"].Upgrade();
1449 CHECK_NULL_VOID(hourColumn);
1450 oldHourValue_ = GetOptionsCurrentValue(hourColumn);
1451
1452 auto minuteColumn = allChildNode_["minute"].Upgrade();
1453 CHECK_NULL_VOID(minuteColumn);
1454 oldMinuteValue_ = GetOptionsCurrentValue(minuteColumn);
1455 }
1456
HandleHourColumnBuildingRange(const PickerTime & value)1457 void TimePickerRowPattern::HandleHourColumnBuildingRange(const PickerTime& value)
1458 {
1459 UpdateAllChildNode();
1460 uint32_t startHour = startTime_.GetHour();
1461 uint32_t endHour = endTime_.GetHour();
1462 auto amPmColumn = allChildNode_["amPm"].Upgrade();
1463 auto hourColumn = allChildNode_["hour"].Upgrade();
1464 optionsTotalCount_[hourColumn] = 0;
1465 if (GetHour24()) {
1466 CHECK_NULL_VOID(hourColumn);
1467 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
1468 CHECK_NULL_VOID(hourColumnPattern);
1469 for (uint32_t hour = startHour; hour <= endHour; ++hour) {
1470 options_[hourColumn][hour - startHour] = GetHourFormatString(hour);
1471 if (hour == value.GetHour()) {
1472 hourColumnPattern->SetCurrentIndex(hour - startHour);
1473 hourColumnPattern->SetEnterIndex(hour - startHour);
1474 }
1475 optionsTotalCount_[hourColumn]++;
1476 }
1477 hourColumnPattern->SetOptions(GetOptionsCount());
1478 IsStartEndTimeDefined() ? hourColumnPattern->SetWheelModeEnabled(false)
1479 : hourColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1480 hourColumn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1481 } else {
1482 HandleAmPmColumnBuilding(value);
1483 }
1484 }
1485
HandleAmPmColumnBuilding(const PickerTime & value)1486 void TimePickerRowPattern::HandleAmPmColumnBuilding(const PickerTime& value)
1487 {
1488 UpdateAllChildNode();
1489 auto amPmColumn = allChildNode_["amPm"].Upgrade();
1490 auto hourColumn = allChildNode_["hour"].Upgrade();
1491 CHECK_NULL_VOID(amPmColumn);
1492 CHECK_NULL_VOID(hourColumn);
1493 auto amPmColumnPattern = amPmColumn->GetPattern<TimePickerColumnPattern>();
1494 CHECK_NULL_VOID(amPmColumnPattern);
1495 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
1496 CHECK_NULL_VOID(hourColumnPattern);
1497 options_[amPmColumn][INDEX_AM_0] = GetAmFormatString();
1498 options_[amPmColumn][INDEX_PM_1] = GetPmFormatString();
1499
1500 if (IsAmHour(value.GetHour())) {
1501 amPmColumnPattern->SetCurrentIndex(0); // AM's index
1502 amPmColumnPattern->SetEnterIndex(0);
1503 } else {
1504 amPmColumnPattern->SetCurrentIndex(1); // PM's index
1505 amPmColumnPattern->SetEnterIndex(1);
1506 }
1507 optionsTotalCount_[amPmColumn] = CHILD_WITHOUT_AMPM_SIZE;
1508 if (startTime_.ToMinutes() == START_DEFAULT_TIME.ToMinutes() &&
1509 endTime_.ToMinutes() == END_DEFAULT_TIME.ToMinutes()) {
1510 auto selectedHour = GetAmPmHour(selectedTime_.GetHour());
1511 for (uint32_t hour = 1; hour <= AM_PM_HOUR_12; ++hour) {
1512 if (hour == selectedHour) {
1513 hourColumnPattern->SetCurrentIndex(hour - 1);
1514 hourColumnPattern->SetEnterIndex(hour - 1);
1515 }
1516 optionsTotalCount_[hourColumn]++;
1517 }
1518 } else {
1519 HandleAmPmColumnChange(value.GetHour());
1520 }
1521 amPmColumnPattern->SetOptions(GetOptionsCount());
1522 hourColumnPattern->SetOptions(GetOptionsCount());
1523 amPmColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1524 IsStartEndTimeDefined() ? hourColumnPattern->SetWheelModeEnabled(false)
1525 : hourColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1526 }
1527
HandleAmPmColumnChange(uint32_t selectedHour)1528 void TimePickerRowPattern::HandleAmPmColumnChange(uint32_t selectedHour)
1529 {
1530 auto amPmColumn = allChildNode_["amPm"].Upgrade();
1531 auto hourColumn = allChildNode_["hour"].Upgrade();
1532 CHECK_NULL_VOID(amPmColumn);
1533 CHECK_NULL_VOID(hourColumn);
1534 uint32_t startHour = startTime_.GetHour();
1535 uint32_t endHour = endTime_.GetHour();
1536 bool isAmStart = IsAmHour(startHour);
1537 bool isAmEnd = IsAmHour(endHour);
1538 if (isAmStart && !isAmEnd) {
1539 endHour = ParseHourOf24(endHour);
1540 if (IsAmHour(selectedHour)) {
1541 endHour = AM_PM_HOUR_11;
1542 } else {
1543 startHour = 0;
1544 }
1545 } else {
1546 options_[amPmColumn][INDEX_AM_0] = isAmStart ? GetAmFormatString() : GetPmFormatString();
1547 optionsTotalCount_[amPmColumn] = 1;
1548 startHour = ParseHourOf24(startHour);
1549 endHour = ParseHourOf24(endHour);
1550 }
1551 HandleAmToPmHourColumnBuilding(selectedHour, startHour, endHour);
1552 }
1553
HandleAmToPmHourColumnBuilding(uint32_t selectedHour,uint32_t startHour,uint32_t endHour)1554 void TimePickerRowPattern::HandleAmToPmHourColumnBuilding(uint32_t selectedHour, uint32_t startHour, uint32_t endHour)
1555 {
1556 auto hourColumn = allChildNode_["hour"].Upgrade();
1557 CHECK_NULL_VOID(hourColumn);
1558 auto hourColumnPattern = hourColumn->GetPattern<TimePickerColumnPattern>();
1559 CHECK_NULL_VOID(hourColumnPattern);
1560 uint32_t selectedParseHour = ParseHourOf24(selectedHour);
1561 for (uint32_t hour = startHour; hour <= endHour; ++hour) {
1562 if (hour == 0) {
1563 options_[hourColumn][INDEX_HOUR_STRAT] = GetHourFormatString(AM_PM_HOUR_12);
1564 } else {
1565 options_[hourColumn][hour - startHour] = GetHourFormatString(hour);
1566 }
1567 if (hour == selectedParseHour) {
1568 hourColumnPattern->SetCurrentIndex(hour - startHour);
1569 hourColumnPattern->SetEnterIndex(hour - startHour);
1570 }
1571 optionsTotalCount_[hourColumn]++;
1572 }
1573 }
1574
HandleMinAndSecColumnBuildingRange()1575 void TimePickerRowPattern::HandleMinAndSecColumnBuildingRange()
1576 {
1577 UpdateAllChildNode();
1578 HandleMinColumnChange(selectedTime_);
1579 UpdateSecondTimeRange();
1580 auto secondColumn = allChildNode_["second"].Upgrade();
1581 CHECK_NULL_VOID(secondColumn);
1582 auto secondColumnPattern = secondColumn->GetPattern<TimePickerColumnPattern>();
1583 CHECK_NULL_VOID(secondColumnPattern);
1584 secondColumnPattern->SetCurrentIndex(selectedTime_.GetSecond());
1585 secondColumnPattern->SetEnterIndex(selectedTime_.GetSecond());
1586 }
1587
HandleMinColumnChange(const PickerTime & value)1588 void TimePickerRowPattern::HandleMinColumnChange(const PickerTime& value)
1589 {
1590 uint32_t startMinue = (startTime_.GetHour() == value.GetHour()) ? startTime_.GetMinute() : 0;
1591 uint32_t endMinute = (endTime_.GetHour() == value.GetHour()) ? endTime_.GetMinute() : 59;
1592 auto minuteColumn = allChildNode_["minute"].Upgrade();
1593 CHECK_NULL_VOID(minuteColumn);
1594 auto minuteColumnPattern = minuteColumn->GetPattern<TimePickerColumnPattern>();
1595 CHECK_NULL_VOID(minuteColumnPattern);
1596 optionsTotalCount_[minuteColumn] = 0;
1597
1598 for (uint32_t minute = startMinue; minute <= endMinute; ++minute) {
1599 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
1600 GetPrefixMinute() == ZeroPrefixType::HIDE) {
1601 options_[minuteColumn][minute - startMinue] = std::to_string(minute);
1602 } else {
1603 options_[minuteColumn][minute - startMinue] =
1604 (minute < MINUTE_10) ? std::string("0") + std::to_string(minute) : std::to_string(minute);
1605 }
1606 if (minute == value.GetMinute()) {
1607 minuteColumnPattern->SetCurrentIndex(minute - startMinue);
1608 minuteColumnPattern->SetEnterIndex(minute - startMinue);
1609 }
1610 optionsTotalCount_[minuteColumn]++;
1611 }
1612 minuteColumnPattern->SetOptions(GetOptionsCount());
1613 IsStartEndTimeDefined() ? minuteColumnPattern->SetWheelModeEnabled(false)
1614 : minuteColumnPattern->SetWheelModeEnabled(wheelModeEnabled_);
1615 }
1616
SetSelectedTime(const PickerTime & value)1617 void TimePickerRowPattern::SetSelectedTime(const PickerTime& value)
1618 {
1619 selectedTime_ = AdjustTime(value);
1620 isFiredTimeChange_ = firedTimeStr_.has_value() && firedTimeStr_.value() == selectedTime_.ToString(true, hasSecond_);
1621 firedTimeStr_.reset();
1622 }
1623
1624
AdjustTime(const PickerTime & time)1625 PickerTime TimePickerRowPattern::AdjustTime(const PickerTime& time)
1626 {
1627 if (time.ToMinutes() < startTime_.ToMinutes()) {
1628 return startTime_;
1629 }
1630 if (time.ToMinutes() > endTime_.ToMinutes()) {
1631 return endTime_;
1632 }
1633 return time;
1634 }
1635
UpdateAllChildNode()1636 void TimePickerRowPattern::UpdateAllChildNode()
1637 {
1638 if (hasSecond_) {
1639 GetAllChildNodeWithSecond();
1640 return;
1641 }
1642 auto host = GetHost();
1643 CHECK_NULL_VOID(host);
1644 if (GetHour24() && host->GetChildren().size() == CHILD_WITH_AMPM_SIZE) {
1645 // if amPmTimeOrder is "10", amPm node is in slot 0, otherwise in slot 2
1646 host->RemoveChildAtIndex(amPmTimeOrder_ == "10" ? AMPMDEFAULTPOSITION : AMPM_FORWARD_WITHOUTSECOND);
1647 amPmId_.reset();
1648 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1649 host->MarkModifyDone();
1650 } else if (!GetHour24() && host->GetChildren().size() == CHILD_WITHOUT_AMPM_SIZE) {
1651 CreateAmPmNode();
1652 }
1653 if (GetHour24() && host->GetChildren().size() != CHILD_WITHOUT_AMPM_SIZE) {
1654 return;
1655 }
1656
1657 if (!GetHour24() && host->GetChildren().size() != CHILD_WITH_AMPM_SIZE) {
1658 return;
1659 }
1660 if (language_ == "ug") {
1661 UpdateAllChildNodeForUg();
1662 return;
1663 }
1664 auto children = host->GetChildren();
1665 auto iter = children.begin();
1666 CHECK_NULL_VOID(*iter);
1667 auto amPmNode = GetAmPmNode(iter);
1668 auto hourNode = GetHourNode(iter);
1669 auto minuteNode = GetMinuteNode(iter);
1670 allChildNode_["amPm"] = amPmNode;
1671 allChildNode_["hour"] = hourNode;
1672 allChildNode_["minute"] = minuteNode;
1673 }
1674
GetAllChildNodeWithSecond()1675 void TimePickerRowPattern::GetAllChildNodeWithSecond()
1676 {
1677 auto host = GetHost();
1678 CHECK_NULL_VOID(host);
1679 if (GetHour24() && host->GetChildren().size() == CHILD_WITH_AMPM_SIZE + 1) {
1680 host->RemoveChildAtIndex(amPmTimeOrder_ == "10" ? AMPMDEFAULTPOSITION : AMPM_FORWARD_WITHSECOND);
1681 amPmId_.reset();
1682 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1683 host->MarkModifyDone();
1684 } else if (!GetHour24() && host->GetChildren().size() == CHILD_WITHOUT_AMPM_SIZE + 1) {
1685 CreateAmPmNode();
1686 }
1687 if ((GetHour24() && host->GetChildren().size() != CHILD_WITHOUT_AMPM_SIZE + 1) ||
1688 (!GetHour24() && host->GetChildren().size() != CHILD_WITH_AMPM_SIZE + 1)) {
1689 return;
1690 }
1691 if (language_ == "ug") {
1692 UpdateAllChildNodeForUg();
1693 return;
1694 }
1695 auto children = host->GetChildren();
1696 auto iter = children.begin();
1697 CHECK_NULL_VOID(*iter);
1698 auto amPmNode = GetAmPmNode(iter);
1699 auto hourNode = GetHourNode(iter);
1700 auto minuteNode = GetMinuteNode(iter);
1701 auto secondNode = GetSecondNode(iter);
1702 allChildNode_["amPm"] = amPmNode;
1703 allChildNode_["hour"] = hourNode;
1704 allChildNode_["minute"] = minuteNode;
1705 allChildNode_["second"] = secondNode;
1706 }
1707
GetAmPmNode(std::list<RefPtr<UINode>>::iterator & iter)1708 RefPtr<FrameNode> TimePickerRowPattern::GetAmPmNode(std::list<RefPtr<UINode>>::iterator& iter)
1709 {
1710 if (GetHour24()) {
1711 return nullptr;
1712 }
1713 auto amPm = (*iter);
1714 if (amPmTimeOrder_ == "01") {
1715 if (!hasSecond_) {
1716 std::advance(iter, AMPM_FORWARD_WITHOUTSECOND);
1717 amPm = (*iter);
1718 std::advance(iter, AMPM_BACKWARD_WITHOUTSECOND);
1719 } else {
1720 std::advance(iter, AMPM_FORWARD_WITHSECOND);
1721 amPm = (*iter);
1722 std::advance(iter, AMPM_BACKWARD_WITHSECOND);
1723 }
1724 } else {
1725 iter++;
1726 }
1727 CHECK_NULL_RETURN(amPm, nullptr);
1728 auto amPmStackNode = DynamicCast<FrameNode>(amPm);
1729 auto amPmBlendNode = DynamicCast<FrameNode>(amPmStackNode->GetLastChild());
1730 CHECK_NULL_RETURN(amPmBlendNode, nullptr);
1731 auto amPmNode = DynamicCast<FrameNode>(amPmBlendNode->GetLastChild());
1732 CHECK_NULL_RETURN(amPmNode, nullptr);
1733 return amPmNode;
1734 }
1735
GetHourNode(std::list<RefPtr<UINode>>::iterator & iter)1736 RefPtr<FrameNode> TimePickerRowPattern::GetHourNode(std::list<RefPtr<UINode>>::iterator& iter)
1737 {
1738 auto hour = *iter;
1739 CHECK_NULL_RETURN(hour, nullptr);
1740 auto hourStackNode = DynamicCast<FrameNode>(hour);
1741 auto hourBlendNode = DynamicCast<FrameNode>(hourStackNode->GetLastChild());
1742 CHECK_NULL_RETURN(hourBlendNode, nullptr);
1743 auto hourNode = DynamicCast<FrameNode>(hourBlendNode->GetLastChild());
1744 CHECK_NULL_RETURN(hourNode, nullptr);
1745 iter++;
1746 return hourNode;
1747 }
1748
GetMinuteNode(std::list<RefPtr<UINode>>::iterator & iter)1749 RefPtr<FrameNode> TimePickerRowPattern::GetMinuteNode(std::list<RefPtr<UINode>>::iterator& iter)
1750 {
1751 auto minute = *iter;
1752 CHECK_NULL_RETURN(minute, nullptr);
1753 auto minuteStackNode = DynamicCast<FrameNode>(minute);
1754 auto minuteBlendNode = DynamicCast<FrameNode>(minuteStackNode->GetLastChild());
1755 CHECK_NULL_RETURN(minuteBlendNode, nullptr);
1756 auto minuteNode = DynamicCast<FrameNode>(minuteBlendNode->GetLastChild());
1757 CHECK_NULL_RETURN(minuteNode, nullptr);
1758 iter++;
1759 return minuteNode;
1760 }
1761
GetSecondNode(std::list<RefPtr<UINode>>::iterator & iter)1762 RefPtr<FrameNode> TimePickerRowPattern::GetSecondNode(std::list<RefPtr<UINode>>::iterator& iter)
1763 {
1764 if (!hasSecond_) {
1765 return nullptr;
1766 }
1767 auto second = *iter;
1768 CHECK_NULL_RETURN(second, nullptr);
1769 auto secondStackNode = DynamicCast<FrameNode>(second);
1770 auto secondBlendNode = DynamicCast<FrameNode>(secondStackNode->GetLastChild());
1771 CHECK_NULL_RETURN(secondBlendNode, nullptr);
1772 auto secondNode = DynamicCast<FrameNode>(secondBlendNode->GetLastChild());
1773 CHECK_NULL_RETURN(secondNode, nullptr);
1774 if (language_ == "ug") {
1775 iter++;
1776 }
1777 return secondNode;
1778 }
1779
UpdateAllChildNodeForUg()1780 void TimePickerRowPattern::UpdateAllChildNodeForUg()
1781 {
1782 auto host = GetHost();
1783 CHECK_NULL_VOID(host);
1784 auto children = host->GetChildren();
1785 auto iter = children.begin();
1786 CHECK_NULL_VOID(*iter);
1787 RefPtr<FrameNode> amPmNode;
1788 if (!GetHour24()) {
1789 auto amPm = (*iter);
1790 CHECK_NULL_VOID(amPm);
1791 auto amPmStackNode = DynamicCast<FrameNode>(amPm);
1792 amPmNode = DynamicCast<FrameNode>(amPmStackNode->GetLastChild()->GetLastChild());
1793 CHECK_NULL_VOID(amPmNode);
1794 iter++;
1795 }
1796 auto secondNode = GetSecondNode(iter);
1797 auto minuteNode = GetMinuteNode(iter);
1798 auto hourNode = GetHourNode(iter);
1799 allChildNode_["amPm"] = amPmNode;
1800 allChildNode_["hour"] = hourNode;
1801 allChildNode_["minute"] = minuteNode;
1802 allChildNode_["second"] = secondNode;
1803 }
1804
HandleHour12Change(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)1805 void TimePickerRowPattern::HandleHour12Change(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
1806 {
1807 UpdateAllChildNode();
1808 auto amPm = allChildNode_["amPm"].Upgrade();
1809 CHECK_NULL_VOID(amPm);
1810 auto amPmPickerColumnPattern = amPm->GetPattern<TimePickerColumnPattern>();
1811
1812 if (amPmPickerColumnPattern->GetCurrentIndex() == 0 && isAdd && index == 11) { // hour index start from 0 to 11
1813 amPmPickerColumnPattern->SetCurrentIndex(1); // add to PM's index
1814 resultTags.emplace_back(amPm);
1815 return;
1816 }
1817 if (amPmPickerColumnPattern->GetCurrentIndex() == 1 && !isAdd && index == 10) { // reduce to 11 hour (index is 10)
1818 amPmPickerColumnPattern->SetCurrentIndex(0); // change to AM whose index is 0
1819 resultTags.emplace_back(amPm);
1820 return;
1821 }
1822 if (amPmPickerColumnPattern->GetCurrentIndex() == 1 && isAdd && index == 11) {
1823 amPmPickerColumnPattern->SetCurrentIndex(0); // is PM (index is 1) and last hour (index is 11)
1824 resultTags.emplace_back(amPm); // change to PM (index is 0)
1825 return;
1826 }
1827 if (amPmPickerColumnPattern->GetCurrentIndex() == 0 && !isAdd && index == 10) { // reduce to 11 hour(index is 10)
1828 amPmPickerColumnPattern->SetCurrentIndex(1); // change to PM
1829 resultTags.emplace_back(amPm);
1830 return;
1831 }
1832 }
1833
GetAmPmHour(uint32_t hourOf24) const1834 uint32_t TimePickerRowPattern::GetAmPmHour(uint32_t hourOf24) const
1835 {
1836 if (hourOf24 == 0) {
1837 return AM_PM_HOUR_12; // AM 12:00 means 00:00 in 24 hour style
1838 }
1839 if (1 <= hourOf24 && hourOf24 <= AM_PM_HOUR_11) { // 00:00 to 11:00 is the same for any hour style
1840 return hourOf24;
1841 }
1842 if (hourOf24 == AM_PM_HOUR_12) { // 12:00 means PM start hour
1843 return AM_PM_HOUR_12; // 12 PM
1844 } // hour from 13 to 23
1845 return hourOf24 - AM_PM_HOUR_12; // need reduce 12 to 12 hours style
1846 }
1847
ParseHourOf24(uint32_t hourOf24) const1848 uint32_t TimePickerRowPattern::ParseHourOf24(uint32_t hourOf24) const
1849 {
1850 return (hourOf24 <= AM_PM_HOUR_11)? hourOf24 : (hourOf24 - AM_PM_HOUR_12);
1851 }
1852
IsAmHour(uint32_t hourOf24) const1853 bool TimePickerRowPattern::IsAmHour(uint32_t hourOf24) const
1854 {
1855 return (0 <= hourOf24 && hourOf24 <= AM_PM_HOUR_11); // 00:00 to 11:00 is AM hour
1856 }
1857
GetAmFormatString() const1858 std::string TimePickerRowPattern::GetAmFormatString() const
1859 {
1860 if (vecAmPm_.empty()) {
1861 return "AM";
1862 }
1863 return vecAmPm_[0]; // first index is AM
1864 }
1865
GetPmFormatString() const1866 std::string TimePickerRowPattern::GetPmFormatString() const
1867 {
1868 if (vecAmPm_.size() < 2) { // size need to be 2 for AM and PM
1869 return "PM";
1870 }
1871 return vecAmPm_[1]; // second index is PM
1872 }
1873
GetHourFormatString(uint32_t hour) const1874 std::string TimePickerRowPattern::GetHourFormatString(uint32_t hour) const
1875 {
1876 DateTime time;
1877 time.minute = hour; // minute range [0, 59], hour range [0, 23]; hour range is in minute range.
1878 if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1879 if (Localization::GetInstance()->HasZeroHour()) {
1880 return AddZeroPrefix(Localization::GetInstance()->FormatDateTime(time, "m"));
1881 }
1882 } else {
1883 if (((GetPrefixHour() == ZeroPrefixType::AUTO) && GetHour24()) ||
1884 GetPrefixHour() == ZeroPrefixType::SHOW) {
1885 return AddZeroPrefix(Localization::GetInstance()->FormatDateTime(time, "m"));
1886 }
1887 }
1888 return Localization::GetInstance()->FormatDateTime(time, "m");
1889 }
1890
GetMinuteFormatString(uint32_t minute) const1891 std::string TimePickerRowPattern::GetMinuteFormatString(uint32_t minute) const
1892 {
1893 DateTime time;
1894 time.minute = minute;
1895 if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1896 return AddZeroPrefix(Localization::GetInstance()->FormatDateTime(time, "m"));
1897 } else {
1898 return Localization::GetInstance()->FormatDateTime(time, "m");
1899 }
1900 }
1901
GetSecondFormatString(uint32_t second) const1902 std::string TimePickerRowPattern::GetSecondFormatString(uint32_t second) const
1903 {
1904 DateTime time;
1905 time.second = second;
1906 if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1907 return AddZeroPrefix(Localization::GetInstance()->FormatDateTime(time, "s"));
1908 } else {
1909 return Localization::GetInstance()->FormatDateTime(time, "s");
1910 }
1911 }
1912
AddZeroPrefix(const std::string & value) const1913 std::string TimePickerRowPattern::AddZeroPrefix(const std::string& value) const
1914 {
1915 if (value.size() == 1 && '0' <= value[0] && value[0] <= '9') { // value is number in range [0, 9]
1916 return std::string("0") + value; // add prefix '0'
1917 }
1918 return value;
1919 }
1920
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)1921 void TimePickerRowPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
1922 {
1923 auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
1924 auto pattern = wp.Upgrade();
1925 if (pattern) {
1926 return pattern->OnKeyEvent(event);
1927 }
1928 return false;
1929 };
1930 focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
1931
1932 auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
1933 auto pattern = wp.Upgrade();
1934 if (pattern) {
1935 pattern->GetInnerFocusPaintRect(paintRect);
1936 }
1937 };
1938 focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
1939 }
1940
SetDigitalCrownSensitivity(int32_t crownSensitivity)1941 void TimePickerRowPattern::SetDigitalCrownSensitivity(int32_t crownSensitivity)
1942 {
1943 #ifdef SUPPORT_DIGITAL_CROWN
1944 auto host = GetHost();
1945 CHECK_NULL_VOID(host);
1946 auto&& children = host->GetChildren();
1947 for (const auto& child : children) {
1948 auto stackNode = DynamicCast<FrameNode>(child);
1949 CHECK_NULL_VOID(stackNode);
1950 auto blendNode = DynamicCast<FrameNode>(stackNode->GetLastChild());
1951 CHECK_NULL_VOID(blendNode);
1952 auto childNode = DynamicCast<FrameNode>(blendNode->GetLastChild());
1953 CHECK_NULL_VOID(childNode);
1954 auto pickerColumnPattern = childNode->GetPattern<TimePickerColumnPattern>();
1955 CHECK_NULL_VOID(pickerColumnPattern);
1956 pickerColumnPattern->SetDigitalCrownSensitivity(crownSensitivity);
1957 }
1958 #endif
1959 }
1960
PaintFocusState()1961 void TimePickerRowPattern::PaintFocusState()
1962 {
1963 auto host = GetHost();
1964 CHECK_NULL_VOID(host);
1965
1966 RoundRect focusRect;
1967 GetInnerFocusPaintRect(focusRect);
1968
1969 auto focusHub = host->GetFocusHub();
1970 CHECK_NULL_VOID(focusHub);
1971 focusHub->PaintInnerFocusState(focusRect);
1972
1973 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1974 }
1975
CalcLeftTotalColumnWidth(const RefPtr<FrameNode> & host,float & leftTotalColumnWidth,float childSize)1976 void TimePickerRowPattern::CalcLeftTotalColumnWidth(
1977 const RefPtr<FrameNode>& host, float& leftTotalColumnWidth, float childSize)
1978 {
1979 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
1980 if (isRtl) {
1981 for (int32_t index = childSize - 1; index > focusKeyID_; --index) {
1982 auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(index));
1983 CHECK_NULL_VOID(stackChild);
1984 auto geometryNode = stackChild->GetGeometryNode();
1985 CHECK_NULL_VOID(geometryNode);
1986 leftTotalColumnWidth += geometryNode->GetFrameSize().Width();
1987 }
1988 } else {
1989 for (int32_t index = 0; index < focusKeyID_; ++index) {
1990 auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(index));
1991 CHECK_NULL_VOID(stackChild);
1992 auto geometryNode = stackChild->GetGeometryNode();
1993 CHECK_NULL_VOID(geometryNode);
1994 leftTotalColumnWidth += geometryNode->GetFrameSize().Width();
1995 }
1996 }
1997 }
1998
GetInnerFocusPaintRect(RoundRect & paintRect)1999 void TimePickerRowPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
2000 {
2001 auto host = GetHost();
2002 CHECK_NULL_VOID(host);
2003 auto childSize = static_cast<float>(host->GetChildren().size());
2004 CHECK_EQUAL_VOID(childSize, 0);
2005 auto leftTotalColumnWidth = 0.0f;
2006 CalcLeftTotalColumnWidth(host, leftTotalColumnWidth, childSize);
2007 auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
2008 CHECK_NULL_VOID(stackChild);
2009 auto columnBlendChild = DynamicCast<FrameNode>(stackChild->GetLastChild());
2010 CHECK_NULL_VOID(columnBlendChild);
2011 auto pickerChild = DynamicCast<FrameNode>(columnBlendChild->GetLastChild());
2012 CHECK_NULL_VOID(pickerChild);
2013 auto columnWidth = pickerChild->GetGeometryNode()->GetFrameSize().Width();
2014 auto pipeline = PipelineBase::GetCurrentContext();
2015 CHECK_NULL_VOID(pipeline);
2016 auto pickerTheme = pipeline->GetTheme<PickerTheme>();
2017 CHECK_NULL_VOID(pickerTheme);
2018 auto dividerSpacing = pipeline->NormalizeToPx(pickerTheme->GetDividerSpacing());
2019
2020 float paintRectWidth = columnWidth - FOCUS_INTERVAL.ConvertToPx() * RATE - LINE_WIDTH.ConvertToPx() * RATE;
2021 float paintRectHeight = dividerSpacing - FOCUS_INTERVAL.ConvertToPx() * RATE - LINE_WIDTH.ConvertToPx() * RATE;
2022 auto centerX = leftTotalColumnWidth + FOCUS_INTERVAL.ConvertToPx() + LINE_WIDTH.ConvertToPx();
2023 auto centerY = (host->GetGeometryNode()->GetFrameSize().Height() - dividerSpacing) / RATE +
2024 FOCUS_INTERVAL.ConvertToPx() + LINE_WIDTH.ConvertToPx();
2025
2026 paintRect.SetRect(RectF(centerX, centerY, paintRectWidth, paintRectHeight));
2027 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
2028 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
2029 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
2030 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
2031 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
2032 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
2033 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
2034 static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
2035 }
2036
OnKeyEvent(const KeyEvent & event)2037 bool TimePickerRowPattern::OnKeyEvent(const KeyEvent& event)
2038 {
2039 if (event.action != KeyAction::DOWN) {
2040 return false;
2041 }
2042 if (event.code == KeyCode::KEY_DPAD_UP || event.code == KeyCode::KEY_DPAD_DOWN ||
2043 event.code == KeyCode::KEY_DPAD_LEFT || event.code == KeyCode::KEY_DPAD_RIGHT ||
2044 event.code == KeyCode::KEY_MOVE_HOME || event.code == KeyCode::KEY_MOVE_END) {
2045 return HandleDirectionKey(event.code);
2046 }
2047 return false;
2048 }
2049
SetFocusDisable()2050 void TimePickerRowPattern::SetFocusDisable()
2051 {
2052 auto host = GetHost();
2053 CHECK_NULL_VOID(host);
2054
2055 auto focusHub = host->GetFocusHub();
2056 CHECK_NULL_VOID(focusHub);
2057
2058 focusHub->SetFocusable(false);
2059 }
2060
SetFocusEnable()2061 void TimePickerRowPattern::SetFocusEnable()
2062 {
2063 auto host = GetHost();
2064 CHECK_NULL_VOID(host);
2065
2066 auto focusHub = host->GetFocusHub();
2067 CHECK_NULL_VOID(focusHub);
2068
2069 focusHub->SetFocusable(true);
2070 }
2071
CheckFocusID(int32_t childSize)2072 bool TimePickerRowPattern::CheckFocusID(int32_t childSize)
2073 {
2074 if (focusKeyID_ > childSize - 1) {
2075 focusKeyID_ = childSize - 1;
2076 return false;
2077 }
2078 if (NeedAdaptForAging() && !GetIsShowInDatePickerDialog()) {
2079 if (GetCurrentPage() == 1) {
2080 if (focusKeyID_ < 1) {
2081 focusKeyID_ = 1;
2082 return false;
2083 }
2084 } else {
2085 if (focusKeyID_ != 0) {
2086 focusKeyID_ = 0;
2087 return false;
2088 }
2089 }
2090 } else {
2091 if (focusKeyID_ < 0) {
2092 focusKeyID_ = 0;
2093 return false;
2094 }
2095 }
2096 return true;
2097 }
2098
ParseDirectionKey(RefPtr<FrameNode> & host,RefPtr<TimePickerColumnPattern> & pattern,KeyCode & code,int32_t currentIndex,uint32_t totalOptionCount,int32_t childSize)2099 bool TimePickerRowPattern::ParseDirectionKey(RefPtr<FrameNode>& host, RefPtr<TimePickerColumnPattern>& pattern,
2100 KeyCode& code, int32_t currentIndex, uint32_t totalOptionCount, int32_t childSize)
2101 {
2102 bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
2103 if (code == KeyCode::KEY_DPAD_UP || code == KeyCode::KEY_DPAD_DOWN) {
2104 auto index = (code == KeyCode::KEY_DPAD_UP) ? -1 : 1;
2105 pattern->SetCurrentIndex((totalOptionCount + currentIndex + index) % totalOptionCount);
2106 pattern->FlushCurrentOptions();
2107 pattern->HandleChangeCallback((code == KeyCode::KEY_DPAD_UP) ? false : true, true);
2108 pattern->HandleEventCallback(true);
2109 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2110 return true;
2111 }
2112 if (code == KeyCode::KEY_MOVE_HOME) {
2113 pattern->SetCurrentIndex(1);
2114 pattern->InnerHandleScroll(false, false);
2115 return true;
2116 }
2117 if (code == KeyCode::KEY_MOVE_END) {
2118 pattern->SetCurrentIndex(totalOptionCount - UNOPTION_COUNT);
2119 pattern->InnerHandleScroll(true, false);
2120 return true;
2121 }
2122 if (code == KeyCode::KEY_DPAD_LEFT) {
2123 focusKeyID_ = isRtl ? (focusKeyID_ + 1) : (focusKeyID_ - 1);
2124 if (!CheckFocusID(childSize)) {
2125 return false;
2126 }
2127 PaintFocusState();
2128 return true;
2129 }
2130 if (code == KeyCode::KEY_DPAD_RIGHT) {
2131 focusKeyID_ = isRtl ? (focusKeyID_ - 1) : (focusKeyID_ + 1);
2132 if (!CheckFocusID(childSize)) {
2133 return false;
2134 }
2135 PaintFocusState();
2136 return true;
2137 }
2138 return false;
2139 }
2140
HandleDirectionKey(KeyCode code)2141 bool TimePickerRowPattern::HandleDirectionKey(KeyCode code)
2142 {
2143 auto host = GetHost();
2144 CHECK_NULL_RETURN(host, false);
2145 auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
2146 CHECK_NULL_RETURN(stackChild, false);
2147 auto childSize = host->GetChildren().size();
2148 auto pickerChild = DynamicCast<FrameNode>(stackChild->GetLastChild()->GetLastChild());
2149 CHECK_NULL_RETURN(pickerChild, false);
2150 auto pattern = pickerChild->GetPattern<TimePickerColumnPattern>();
2151 CHECK_NULL_RETURN(pattern, false);
2152 auto currentIndex = pattern->GetCurrentIndex();
2153 auto totalOptionCount = GetOptionCount(pickerChild);
2154 if (totalOptionCount == 0) {
2155 return false;
2156 }
2157 return ParseDirectionKey(host, pattern, code, currentIndex, totalOptionCount, static_cast<int32_t>(childSize));
2158 }
2159
OnColorConfigurationUpdate()2160 void TimePickerRowPattern::OnColorConfigurationUpdate()
2161 {
2162 auto host = GetHost();
2163 CHECK_NULL_VOID(host);
2164 host->SetNeedCallChildrenUpdate(false);
2165 auto context = host->GetContext();
2166 CHECK_NULL_VOID(context);
2167 auto pickerTheme = context->GetTheme<PickerTheme>(host->GetThemeScopeId());
2168 CHECK_NULL_VOID(pickerTheme);
2169 auto dialogTheme = context->GetTheme<DialogTheme>();
2170 CHECK_NULL_VOID(dialogTheme);
2171 auto disappearStyle = pickerTheme->GetDisappearOptionStyle();
2172 auto normalStyle = pickerTheme->GetOptionStyle(false, false);
2173 auto pickerProperty = host->GetLayoutProperty<TimePickerLayoutProperty>();
2174 CHECK_NULL_VOID(pickerProperty);
2175 pickerProperty->UpdateColor(GetTextProperties().normalTextStyle_.textColor.value_or(normalStyle.GetTextColor()));
2176 pickerProperty->UpdateDisappearColor(
2177 GetTextProperties().disappearTextStyle_.textColor.value_or(disappearStyle.GetTextColor()));
2178 if (isPicker_) {
2179 return;
2180 }
2181 SetBackgroundColor(dialogTheme->GetBackgroundColor());
2182 auto buttonTitleNode = buttonTitleNode_.Upgrade();
2183 CHECK_NULL_VOID(buttonTitleNode);
2184 auto buttonTitleRenderContext = buttonTitleNode->GetRenderContext();
2185 CHECK_NULL_VOID(buttonTitleRenderContext);
2186 buttonTitleRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
2187 auto childText = buttonTitleNode->GetFirstChild();
2188 CHECK_NULL_VOID(childText);
2189 auto textTitleNode = DynamicCast<FrameNode>(childText);
2190 CHECK_NULL_VOID(textTitleNode);
2191 auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
2192 CHECK_NULL_VOID(textLayoutProperty);
2193 textLayoutProperty->UpdateTextColor(pickerTheme->GetTitleStyle().GetTextColor());
2194 auto contentRowNode = contentRowNode_.Upgrade();
2195 CHECK_NULL_VOID(contentRowNode);
2196 auto layoutRenderContext = contentRowNode->GetRenderContext();
2197 CHECK_NULL_VOID(layoutRenderContext);
2198 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) || !layoutRenderContext->IsUniRenderEnabled()) {
2199 layoutRenderContext->UpdateBackgroundColor(dialogTheme->GetButtonBackgroundColor());
2200 }
2201 host->MarkModifyDone();
2202 }
2203
OnThemeScopeUpdate(int32_t themeScopeId)2204 bool TimePickerRowPattern::OnThemeScopeUpdate(int32_t themeScopeId)
2205 {
2206 bool result = false;
2207 auto host = GetHost();
2208 CHECK_NULL_RETURN(host, result);
2209 host->SetNeedCallChildrenUpdate(false);
2210 auto pickerProperty = host->GetLayoutProperty<TimePickerLayoutProperty>();
2211 CHECK_NULL_RETURN(pickerProperty, result);
2212 // The following three attributes will be affected by withTheme.
2213 // If they are setted by user, then use the value by user set; Otherwise use the value from withTheme
2214 // When the "result" is true, mean to notify the framework to Re-render
2215 if ((!pickerProperty->HasColor()) || (!pickerProperty->HasDisappearColor()) ||
2216 (!pickerProperty->HasSelectedColor())) {
2217 result = true;
2218 }
2219 OnModifyDone();
2220 return result;
2221 }
2222
NeedAdaptForAging()2223 bool TimePickerRowPattern::NeedAdaptForAging()
2224 {
2225 auto host = GetHost();
2226 CHECK_NULL_RETURN(host, false);
2227 auto pipeline = host->GetContext();
2228 CHECK_NULL_RETURN(pipeline, false);
2229 auto pickerTheme = pipeline->GetTheme<PickerTheme>();
2230 CHECK_NULL_RETURN(pickerTheme, false);
2231
2232 if (GreatOrEqual(pipeline->GetFontScale(), pickerTheme->GetMaxOneFontScale()) &&
2233 Dimension(pipeline->GetRootHeight()).ConvertToVp() > pickerTheme->GetDeviceHeightLimit()) {
2234 return true;
2235 }
2236 return false;
2237 }
2238
UpdateUserSetSelectColor()2239 void TimePickerRowPattern::UpdateUserSetSelectColor()
2240 {
2241 CHECK_EQUAL_VOID(IsCircle(), false);
2242 isUserSetSelectColor_ = true;
2243 for (auto iter = allChildNode_.begin(); iter != allChildNode_.end(); iter++) {
2244 auto columnNode = iter->second.Upgrade();
2245 if (columnNode) {
2246 auto pattern = columnNode->GetPattern<TimePickerColumnPattern>();
2247 if (pattern) {
2248 pattern->UpdateUserSetSelectColor();
2249 }
2250 }
2251 }
2252 }
2253
2254 } // namespace OHOS::Ace::NG
2255