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