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