• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/common/dom/dom_picker_base.h"
17 
18 #include "base/utils/linear_map.h"
19 #include "base/utils/string_utils.h"
20 #include "base/utils/utils.h"
21 #include "frameworks/bridge/common/dom/dom_reflect_map.h"
22 #include "frameworks/bridge/common/utils/utils.h"
23 
24 namespace OHOS::Ace::Framework {
25 namespace {
26 
27 const PickerDate DEFAULT_PICKER_DATE(1970, 1, 1);
28 const PickerDate DEFAULT_END_PICKER_DATE(2100, 12, 31);
29 constexpr char PICKER_DATE_SPLITTER = '-';
30 const PickerTime DEFAULT_PICKER_TIME(0, 0, 0);
31 constexpr char PICKER_TIME_SPLITTER = ':';
32 
33 } // namespace
34 
DOMPickerBase(NodeId nodeId,const std::string & nodeName,bool hasValue)35 DOMPickerBase::DOMPickerBase(NodeId nodeId, const std::string& nodeName, bool hasValue)
36     : DOMNode(nodeId, nodeName), hasValue_(hasValue)
37 {
38     if (!hasValue_) {
39         return;
40     }
41     valuePickerChild_ = AceType::MakeRefPtr<PickerValueComponent>([weak = WeakClaim(this)]() {
42         auto refPtr = weak.Upgrade();
43         if (refPtr) {
44             refPtr->HandleClickCallback();
45         }
46     });
47     pickerId_ = nodeId;
48 }
49 
InitializeStyle()50 void DOMPickerBase::InitializeStyle()
51 {
52     ResetInitializedStyle();
53 }
54 
ResetInitializedStyle()55 void DOMPickerBase::ResetInitializedStyle()
56 {
57     auto theme = GetTheme<PickerTheme>();
58     if (!theme) {
59         return;
60     }
61     theme_ = theme->clone();
62     if (!theme_ || !valuePickerChild_) {
63         return;
64     }
65     valuePickerChild_->SetTheme(theme_);
66 }
67 
GetSpecializedComponent()68 RefPtr<Component> DOMPickerBase::GetSpecializedComponent()
69 {
70     if (!hasValue_) {
71         return basePickerChild_;
72     }
73     return valuePickerChild_;
74 }
75 
HandleClickCallback() const76 void DOMPickerBase::HandleClickCallback() const
77 {
78     if (!hasValue_) {
79         return;
80     }
81     ShowDialog();
82 }
83 
ShowDialog() const84 void DOMPickerBase::ShowDialog() const
85 {
86     if (!basePickerChild_) {
87         LOGW("not implementation now.");
88         return;
89     }
90     auto context = GetPipelineContext().Upgrade();
91     if (!context) {
92         LOGE("Pipeline context not found error!");
93         return;
94     }
95     auto pageStack = context->GetLastStack();
96     if (!pageStack) {
97         LOGE("Page stack not found error!");
98         return;
99     }
100     basePickerChild_->ShowDialog(pageStack);
101 }
102 
GetPickerDate(const std::string & strDate,PickerDate & outDate) const103 bool DOMPickerBase::GetPickerDate(const std::string& strDate, PickerDate& outDate) const
104 {
105     std::string strValue;
106     std::stringstream streamDate(strDate);
107     if (!std::getline(streamDate, strValue, PICKER_DATE_SPLITTER)) {
108         return false;
109     }
110     outDate.SetYear(StringUtils::StringToInt(strValue));
111     if (!std::getline(streamDate, strValue, PICKER_DATE_SPLITTER)) {
112         return false;
113     }
114     outDate.SetMonth(StringUtils::StringToInt(strValue));
115     if (!std::getline(streamDate, strValue, PICKER_DATE_SPLITTER)) {
116         return false;
117     }
118     outDate.SetDay(StringUtils::StringToInt(strValue));
119     return true;
120 }
121 
GetPickerTime(const std::string & strDate,PickerTime & outTime) const122 bool DOMPickerBase::GetPickerTime(const std::string& strDate, PickerTime& outTime) const
123 {
124     std::string strValue;
125     std::stringstream streamDate(strDate);
126     if (!std::getline(streamDate, strValue, PICKER_TIME_SPLITTER)) {
127         return false;
128     }
129     outTime.SetHour(StringUtils::StringToInt(strValue));
130     if (!std::getline(streamDate, strValue, PICKER_TIME_SPLITTER)) {
131         return false;
132     }
133     outTime.SetMinute(StringUtils::StringToInt(strValue));
134     // the format time hh:mm is supported, so the time should be set
135     if (std::getline(streamDate, strValue)) {
136         outTime.SetSecond(StringUtils::StringToInt(strValue));
137     }
138     return true;
139 }
140 
GetPickerDateTime(const std::string & strDate,PickerDateTime & outDateTime) const141 bool DOMPickerBase::GetPickerDateTime(const std::string& strDate, PickerDateTime& outDateTime) const
142 {
143     std::vector<std::string> strValues;
144     StringUtils::StringSplitter(strDate, PICKER_DATE_SPLITTER, strValues);
145     PickerDate outDate = outDateTime.GetDate();
146     PickerTime outTime = outDateTime.GetTime();
147     if (strValues.size() == 4) { // MM-dd-hh-mm
148         outDate.SetMonth(StringUtils::StringToInt(strValues[0]));
149         outDate.SetDay(StringUtils::StringToInt(strValues[1]));
150         outTime.SetHour(StringUtils::StringToInt(strValues[2]));
151         outTime.SetMinute(StringUtils::StringToInt(strValues[3]));
152     } else if (strValues.size() == 5) { // yyyy-MM-dd-hh-mm
153         outDate.SetYear(StringUtils::StringToInt(strValues[0]));
154         outDate.SetMonth(StringUtils::StringToInt(strValues[1]));
155         outDate.SetDay(StringUtils::StringToInt(strValues[2]));
156         outTime.SetHour(StringUtils::StringToInt(strValues[3]));
157         outTime.SetMinute(StringUtils::StringToInt(strValues[4]));
158     } else {
159         LOGE("input date time is invalidate.");
160         return false;
161     }
162     outDateTime.SetDate(outDate);
163     outDateTime.SetTime(outTime);
164     return true;
165 }
166 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)167 bool DOMPickerBase::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
168 {
169     if (attr.first == DOM_VALUE) {
170         if (!hasValue_) {
171             LOGE("picker view has no attribute of value.");
172             return false;
173         }
174         std::string strValue = attr.second;
175         strValue.erase(
176             std::remove_if(strValue.begin(), strValue.end(), [](char c) { return c == DOM_PICKER_SPLIT_ARRAY; }),
177             strValue.end());
178         valuePickerChild_->SetText(strValue);
179         return true;
180     }
181 
182     if (attr.first == DOM_TYPE) {
183         type_ = attr.second;
184         return true;
185     }
186 
187     static const LinearMapNode<void (*)(DOMPickerBase&, const std::string&)> pickerAttrOperators[] = {
188         { DOM_PICKER_COLUMN_COUNT, [](DOMPickerBase& picker, const std::string& val) { picker.SetColumnCount(val); } },
189         { DOM_PICKER_CONTAIN_SECOND, [](DOMPickerBase& picker, const std::string& val) { picker.SetHasSecond(val); } },
190         { DOM_END, [](DOMPickerBase& picker, const std::string& val) { picker.SetEnd(val); } },
191         { DOM_PICKER_HOUR24, [](DOMPickerBase& picker, const std::string& val) { picker.SetHour24(val); } },
192         { DOM_PICKER_PREFIX, [](DOMPickerBase& picker, const std::string& val) { picker.SetPrefix(val); } },
193         { DOM_PICKER_SUFFIX, [](DOMPickerBase& picker, const std::string& val) { picker.SetSuffix(val); } },
194         { DOM_PICKER_SHOW_LUNAR, [](DOMPickerBase& picker, const std::string& val) { picker.SetShowLunar(val); } },
195         { DOM_PICKER_LUNAR, [](DOMPickerBase& picker, const std::string& val) { picker.SetLunar(val); } },
196         { DOM_PICKER_RANGE, [](DOMPickerBase& picker, const std::string& val) { picker.SetRange(val); } },
197         { DOM_SELECTED, [](DOMPickerBase& picker, const std::string& val) { picker.SetSelected(val); } },
198         { DOM_START, [](DOMPickerBase& picker, const std::string& val) { picker.SetStart(val); } },
199         { DOM_PICKER_VIBRATE, [](DOMPickerBase& picker, const std::string& val) { picker.SetVibrate(val); } },
200     };
201     auto it = BinarySearchFindIndex(pickerAttrOperators, ArraySize(pickerAttrOperators), attr.first.c_str());
202     if (it != -1) {
203         if (!basePickerChild_) {
204             storeAttributes_.emplace_back(attr);
205             return true;
206         }
207         pickerAttrOperators[it].value(*this, attr.second);
208         return true;
209     }
210     return false;
211 }
212 
AddSpecializedEvent(int32_t pageId,const std::string & event)213 bool DOMPickerBase::AddSpecializedEvent(int32_t pageId, const std::string& event)
214 {
215     static const LinearMapNode<void (*)(RefPtr<PickerBaseComponent>&, const EventMarker&)> pickerEventOperators[] = {
216         { DOM_CANCEL,
217             [](RefPtr<PickerBaseComponent>& picker, const EventMarker& event) { picker->SetOnCancel(event); } },
218         { DOM_CHANGE,
219             [](RefPtr<PickerBaseComponent>& picker, const EventMarker& event) { picker->SetOnChange(event); } },
220         { DOM_PICKER_COLUMN_CHANGE,
221             [](RefPtr<PickerBaseComponent>& picker, const EventMarker& event) { picker->SetOnColumnChange(event); } },
222     };
223     auto it = BinarySearchFindIndex(pickerEventOperators, ArraySize(pickerEventOperators), event.c_str());
224     if (it != -1) {
225         if (!basePickerChild_) {
226             storeEvents_.emplace_back(std::make_pair(pageId, event));
227             return true;
228         }
229         pickerEventOperators[it].value(basePickerChild_, EventMarker(GetNodeIdForEvent(), event, pageId));
230         return true;
231     }
232     return false;
233 }
234 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)235 bool DOMPickerBase::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
236 {
237     if (!hasValue_) {
238         return SetOptionStyleOperators(style);
239     }
240     return SetTextStyleOperators(style);
241 }
242 
SetOptionStyleOperators(const std::pair<std::string,std::string> & style)243 bool DOMPickerBase::SetOptionStyleOperators(const std::pair<std::string, std::string>& style)
244 {
245     static const LinearMapNode<void (*)(const DOMPickerBase&,
246         const std::string&, TextStyle&, TextStyle&, TextStyle&, TextStyle&)>
247         optionStyleOperators[] = {
248             { DOM_TEXT_COLOR, [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle&,
249                               TextStyle&, TextStyle&) { normal.SetTextColor(node.ParseColor(val)); } },
250             { DOM_PICKER_DISAPPEAR_COLOR, [](const DOMPickerBase& node, const std::string& val,
251                 TextStyle&, TextStyle&, TextStyle&, TextStyle& style) { style.SetTextColor(node.ParseColor(val)); } },
252             { DOM_PICKER_DISAPPEAR_FONT_SIZE, [](const DOMPickerBase& node, const std::string& val,
253                 TextStyle&, TextStyle&, TextStyle&, TextStyle& style) {
254                 style.SetFontSize(node.ParseDimension(val));
255                 style.SetAdaptMaxFontSize(node.ParseDimension(val)); } },
256             { DOM_PICKER_FOCUS_COLOR, [](const DOMPickerBase& node, const std::string& val, TextStyle&, TextStyle&,
257                                       TextStyle& focus, TextStyle&) { focus.SetTextColor(node.ParseColor(val)); } },
258             { DOM_PICKER_FOCUS_SIZE,
259                 [](const DOMPickerBase& node, const std::string& val,
260                     TextStyle&, TextStyle&, TextStyle& focus, TextStyle&) {
261                     focus.SetFontSize(node.ParseDimension(val));
262                     focus.SetAdaptMaxFontSize(node.ParseDimension(val));
263                 } },
264             { DOM_TEXT_FONT_FAMILY,
265                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& select,
266                     TextStyle& focus, TextStyle& disappear) {
267                     normal.SetFontFamilies(node.ParseFontFamilies(val));
268                     select.SetFontFamilies(node.ParseFontFamilies(val));
269                     focus.SetFontFamilies(node.ParseFontFamilies(val));
270                     disappear.SetFontFamilies(node.ParseFontFamilies(val));
271                 } },
272             { DOM_TEXT_FONT_SIZE,
273                 [](const DOMPickerBase& node, const std::string& val,
274                     TextStyle& normal, TextStyle&, TextStyle&, TextStyle&) {
275                     normal.SetFontSize(node.ParseDimension(val));
276                     normal.SetAdaptMaxFontSize(node.ParseDimension(val));
277                 } },
278             { DOM_PICKER_SELECT_COLOR, [](const DOMPickerBase& node, const std::string& val,
279                                        TextStyle&, TextStyle& select,
280                                        TextStyle&, TextStyle&) { select.SetTextColor(node.ParseColor(val)); } },
281             { DOM_PICKER_SELECT_SIZE,
282                 [](const DOMPickerBase& node, const std::string& val,
283                     TextStyle&, TextStyle& select, TextStyle&, TextStyle&) {
284                     select.SetFontSize(node.ParseDimension(val));
285                     select.SetAdaptMaxFontSize(node.ParseDimension(val));
286                 } },
287         };
288     auto styleIter = BinarySearchFindIndex(optionStyleOperators, ArraySize(optionStyleOperators), style.first.c_str());
289     if (styleIter != -1) {
290         if (!basePickerChild_) {
291             storeStyles_.emplace_back(style);
292             return true;
293         }
294         auto theme = basePickerChild_->GetTheme();
295         auto normalStyle = theme->GetOptionStyle(false, false);
296         auto selectStyle = theme->GetOptionStyle(true, false);
297         auto focusStyle = theme->GetOptionStyle(true, true);
298         auto disappearStyle = theme->GetDisappearOptionStyle();
299         optionStyleOperators[styleIter].value(*this, style.second,
300             normalStyle, selectStyle, focusStyle, disappearStyle);
301         theme->SetOptionStyle(false, false, normalStyle);
302         theme->SetOptionStyle(true, false, selectStyle);
303         theme->SetOptionStyle(true, true, focusStyle);
304         theme->SetDisappearOptionStyle(disappearStyle);
305         return true;
306     }
307     return false;
308 }
309 
SetTextBackgroundColor(const std::pair<std::string,std::string> & style)310 bool DOMPickerBase::SetTextBackgroundColor(const std::pair<std::string, std::string>& style)
311 {
312     if (style.first != DOM_BACKGROUND_COLOR) {
313         return false;
314     }
315     auto decoration = theme_->GetOptionDecoration(false);
316     if (!decoration) {
317         return false;
318     }
319     decoration->SetBackgroundColor(ParseColor(style.second));
320     return true;
321 }
322 
SetTextStyleOperators(const std::pair<std::string,std::string> & style)323 bool DOMPickerBase::SetTextStyleOperators(const std::pair<std::string, std::string>& style)
324 {
325     static const LinearMapNode<void (*)(
326         const DOMPickerBase&, const std::string&, TextStyle&, TextStyle&, TextStyle&, TextStyle&)>
327         textStyleOperators[] = {
328             { DOM_TEXT_ALLOW_SCALE,
329                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
330                     TextStyle&) {
331                     normal.SetAllowScale(StringToBool(val));
332                     focus.SetAllowScale(StringToBool(val));
333                 } },
334             { DOM_PICKER_DISAPPEAR_FONT_SIZE,
335                 [](const DOMPickerBase& node, const std::string& val, TextStyle&, TextStyle&, TextStyle&,
336                     TextStyle& disappear) {
337                     Dimension fontSize = node.ParseDimension(val);
338                     if (fontSize.IsValid()) {
339                         disappear.SetFontSize(fontSize);
340                         disappear.SetAdaptMaxFontSize(fontSize);
341                     }
342                 } },
343             { DOM_PICKER_FOCUS_SIZE,
344                 [](const DOMPickerBase& node, const std::string& val, TextStyle&, TextStyle& focus, TextStyle&,
345                     TextStyle&) {
346                     Dimension fontSize = node.ParseDimension(val);
347                     if (fontSize.IsValid()) {
348                         focus.SetFontSize(fontSize);
349                         focus.SetAdaptMaxFontSize(fontSize);
350                     }
351                 } },
352             { DOM_TEXT_FONT_FAMILY,
353                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
354                     TextStyle&) {
355                     normal.SetFontFamilies(node.ParseFontFamilies(val));
356                     focus.SetFontFamilies(node.ParseFontFamilies(val));
357                 } },
358             { DOM_TEXT_FONT_SIZE,
359                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle&, TextStyle&,
360                     TextStyle&) {
361                     Dimension fontSize = node.ParseDimension(val);
362                     if (fontSize.IsValid()) {
363                         normal.SetFontSize(fontSize);
364                         normal.SetAdaptMaxFontSize(fontSize);
365                     }
366                 } },
367             { DOM_TEXT_FONT_STYLE,
368                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
369                     TextStyle&) {
370                     normal.SetFontStyle(ConvertStrToFontStyle(val));
371                     focus.SetFontStyle(ConvertStrToFontStyle(val));
372                 } },
373             { DOM_TEXT_FONT_WEIGHT,
374                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
375                     TextStyle&) {
376                     normal.SetFontWeight(ConvertStrToFontWeight(val));
377                     focus.SetFontWeight(ConvertStrToFontWeight(val));
378                 } },
379             { DOM_TEXT_LETTER_SPACING,
380                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
381                     TextStyle&) {
382                     normal.SetLetterSpacing(node.ParseDimension(val));
383                     focus.SetLetterSpacing(node.ParseDimension(val));
384                 } },
385             { DOM_TEXT_LINE_HEIGHT,
386                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
387                     TextStyle&) {
388                     normal.SetLineHeight(node.ParseLineHeight(val));
389                     focus.SetLineHeight(node.ParseLineHeight(val));
390                 } },
391             { DOM_PICKER_SELECT_SIZE,
392                 [](const DOMPickerBase& node, const std::string& val, TextStyle&, TextStyle&, TextStyle& selected,
393                     TextStyle&) {
394                     Dimension fontSize = node.ParseDimension(val);
395                     if (fontSize.IsValid()) {
396                         selected.SetFontSize(fontSize);
397                         selected.SetAdaptMaxFontSize(fontSize);
398                     }
399                 } },
400             { DOM_PICKER_TEXT_COLOR,
401                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
402                     TextStyle&) {
403                     normal.SetTextColor(node.ParseColor(val));
404                     focus.SetTextColor(node.ParseColor(val));
405                 } },
406             { DOM_TEXT_DECORATION,
407                 [](const DOMPickerBase& node, const std::string& val, TextStyle& normal, TextStyle& focus, TextStyle&,
408                     TextStyle&) {
409                     normal.SetTextDecoration(ConvertStrToTextDecoration(val));
410                     focus.SetTextDecoration(ConvertStrToTextDecoration(val));
411                 } },
412         };
413     auto operatorIter = BinarySearchFindIndex(textStyleOperators, ArraySize(textStyleOperators), style.first.c_str());
414     if (operatorIter != -1) {
415         if (!basePickerChild_) {
416             storeStyles_.emplace_back(style);
417             return true;
418         }
419         auto theme = basePickerChild_->GetTheme();
420         if (theme) {
421             auto normalStyle = theme->GetOptionStyle(false, false);
422             auto focusStyle = theme->GetOptionStyle(true, true);
423             auto selectedStyle = theme->GetOptionStyle(true, false);
424             auto disappearStyle = theme->GetDisappearOptionStyle();
425 
426             textStyleOperators[operatorIter].value(
427                 *this, style.second, normalStyle, focusStyle, selectedStyle, disappearStyle);
428             theme->SetOptionStyle(false, false, normalStyle);
429             theme->SetOptionStyle(true, false, selectedStyle); // selected
430             theme->SetOptionStyle(true, true, focusStyle);
431             theme->SetDisappearOptionStyle(disappearStyle);
432         }
433 
434         // theme is used only by valuePickerChild_
435         auto normalStyle = theme_->GetOptionStyle(false, false);
436         auto focusStyle = theme_->GetOptionStyle(true, true);
437         auto selectedStyle = theme_->GetOptionStyle(true, false);
438         auto disappearStyle = theme_->GetDisappearOptionStyle();
439         textStyleOperators[operatorIter].value(
440             *this, style.second, normalStyle, focusStyle, selectedStyle, disappearStyle);
441         theme_->SetOptionStyle(false, false, normalStyle);
442         theme_->SetOptionStyle(true, false, normalStyle);
443         theme_->SetOptionStyle(true, true, focusStyle);
444         return true;
445     }
446     if (SetColumnHeight(style)) {
447         return true;
448     }
449     if (SetTextBackgroundColor(style)) {
450         return true;
451     }
452     return false;
453 }
454 
CallSpecializedMethod(const std::string & method,const std::string & args)455 void DOMPickerBase::CallSpecializedMethod(const std::string& method, const std::string& args)
456 {
457     if (!basePickerChild_) {
458         LOGW("not implementation now.");
459         return;
460     }
461     if (method == DOM_ROTATION) {
462         auto controller = basePickerChild_->GetRotationController();
463         if (controller) {
464             LOGD("Rotation focus picker view");
465             controller->RequestRotation(true);
466         }
467     }
468     if (!hasValue_) {
469         return;
470     }
471     if (method == DOM_SHOW) {
472         ShowDialog();
473     }
474 }
475 
PrepareSpecializedComponent()476 void DOMPickerBase::PrepareSpecializedComponent()
477 {
478     if (valuePickerChild_) {
479         valuePickerChild_->SetTextDirection((IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR));
480     }
481     if (CreatePicker()) {
482         for (const auto& attribute : storeAttributes_) {
483             SetSpecializedAttr(attribute);
484         }
485         for (const auto& oneEvent : storeEvents_) {
486             AddSpecializedEvent(oneEvent.first, oneEvent.second);
487         }
488         for (const auto& oneStyle : storeStyles_) {
489             SetSpecializedStyle(oneStyle);
490         }
491     }
492     storeAttributes_.clear();
493     storeEvents_.clear();
494     storeStyles_.clear();
495 }
496 
CompositeComponents()497 void DOMPickerBase::CompositeComponents()
498 {
499     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATE &&
500         AceType::InstanceOf<PickerDateComponent>(basePickerChild_)) {
501         auto picker = AceType::DynamicCast<PickerDateComponent>(basePickerChild_);
502         // check invalidate of start and end.
503         const auto& start = picker->GetStartDate();
504         const auto& end = picker->GetEndDate();
505         if (start.GetYear() > end.GetYear() ||
506             (start.GetYear() == end.GetYear() && start.GetMonth() > end.GetMonth()) ||
507             (start.GetYear() == end.GetYear() && start.GetMonth() == end.GetMonth() && start.GetDay() > end.GetDay())) {
508             // invalidate => use default start date and end date.
509             picker->SetStartDate(DEFAULT_PICKER_DATE); // default start date is 1970-1-1 from FA document.
510             picker->SetEndDate(DEFAULT_END_PICKER_DATE); // default end date is 2100-12-31 from FA document.
511         }
512     }
513     if (IsRightToLeft()) {
514         SetAlignment(Alignment::CENTER_RIGHT);
515     }
516     DOMNode::CompositeComponents();
517 }
518 
CreatePicker()519 bool DOMPickerBase::CreatePicker()
520 {
521     // The type cannot be dynamically changed.
522     if (basePickerChild_) {
523         return true;
524     }
525 
526     // Operator map for type.
527     static const std::unordered_map<std::string, void (*)(RefPtr<PickerBaseComponent>&)> pickerOperators = {
528         { DOM_PICKER_TYPE_TIME,
529             [](RefPtr<PickerBaseComponent>& pickerBase) {
530                 pickerBase = AceType::MakeRefPtr<PickerTimeComponent>(); } },
531         { DOM_PICKER_TYPE_DATE,
532             [](RefPtr<PickerBaseComponent>& pickerBase) {
533                 pickerBase = AceType::MakeRefPtr<PickerDateComponent>(); } },
534         { DOM_PICKER_TYPE_TEXT,
535             [](RefPtr<PickerBaseComponent>& pickerBase) {
536                 pickerBase = AceType::MakeRefPtr<PickerTextComponent>(); } },
537         { DOM_PICKER_TYPE_MULTITEXT,
538             [](RefPtr<PickerBaseComponent>& pickerBase) {
539                 pickerBase = AceType::MakeRefPtr<PickerMultiTextComponent>();
540             } },
541         { DOM_PICKER_TYPE_DATETIME,
542             [](RefPtr<PickerBaseComponent>& pickerBase) {
543                 pickerBase = AceType::MakeRefPtr<PickerDateTimeComponent>();
544             } },
545     };
546 
547     auto operatorIter = pickerOperators.find(type_);
548     if (operatorIter != pickerOperators.end()) {
549         operatorIter->second(basePickerChild_);
550     } else {
551         basePickerChild_ = AceType::MakeRefPtr<PickerTextComponent>();
552         type_ = DOM_PICKER_TYPE_TEXT;
553     }
554 
555     if (basePickerChild_) {
556         auto theme = GetTheme<PickerTheme>();
557         basePickerChild_->SetTheme(theme->clone());
558         basePickerChild_->SetTextDirection((IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR));
559         basePickerChild_->SetIsDialog(hasValue_);
560         basePickerChild_->SetNodeId(GetNodeId());
561 #if defined(PREVIEW)
562         basePickerChild_->SetPickerBaseId(pickerId_);
563 #endif
564         return true;
565     }
566 
567     LOGE("unsupported type: %{private}s.", type_.c_str());
568     return false;
569 }
570 
SetColumnHeight(const std::pair<std::string,std::string> & style)571 bool DOMPickerBase::SetColumnHeight(const std::pair<std::string, std::string>& style)
572 {
573     if (style.first != DOM_PICKER_COLUMN_HEIGHT) {
574         return false;
575     }
576 
577     if (!hasValue_) {
578         return false;
579     }
580 
581     if (!basePickerChild_) {
582         storeStyles_.emplace_back(style);
583         return false;
584     }
585 
586     basePickerChild_->SetColumnHeight(StringToDimension(style.second));
587     return true;
588 }
589 
SetStart(const std::string & value)590 bool DOMPickerBase::SetStart(const std::string& value)
591 {
592     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATE &&
593         AceType::InstanceOf<PickerDateComponent>(basePickerChild_)) {
594         auto picker = AceType::DynamicCast<PickerDateComponent>(basePickerChild_);
595         auto date = DEFAULT_PICKER_DATE;
596         if (GetPickerDate(value, date)) {
597             picker->SetStartDate(date);
598         } else {
599             LOGE("the value of picker date is invalid.");
600         }
601 
602         return true;
603     }
604 
605     return false;
606 }
607 
SetEnd(const std::string & value)608 bool DOMPickerBase::SetEnd(const std::string& value)
609 {
610     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATE &&
611         AceType::InstanceOf<PickerDateComponent>(basePickerChild_)) {
612         auto picker = AceType::DynamicCast<PickerDateComponent>(basePickerChild_);
613         auto date = DEFAULT_PICKER_DATE;
614         if (GetPickerDate(value, date)) {
615             picker->SetEndDate(date);
616         } else {
617             LOGE("input value of picker date is invalid.");
618         }
619 
620         return true;
621     }
622 
623     return false;
624 }
625 
SetSelected(const std::string & value)626 bool DOMPickerBase::SetSelected(const std::string& value)
627 {
628     return (SetTextSelected(value) || SetDateTimeSelected(value));
629 }
630 
SetTextSelected(const std::string & value)631 bool DOMPickerBase::SetTextSelected(const std::string& value)
632 {
633     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_TEXT &&
634         AceType::InstanceOf<PickerTextComponent>(basePickerChild_)) {
635         auto picker = AceType::DynamicCast<PickerTextComponent>(basePickerChild_);
636         picker->SetSelected(StringUtils::StringToInt(value));
637         return true;
638     }
639 
640     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_MULTITEXT &&
641         AceType::InstanceOf<PickerMultiTextComponent>(basePickerChild_)) {
642         auto picker = AceType::DynamicCast<PickerMultiTextComponent>(basePickerChild_);
643         std::vector<std::string> out;
644         StringUtils::StringSplitter(value, DOM_PICKER_SPLIT_ARRAY, out);
645         std::vector<uint32_t> selectedIndexes;
646         for (uint32_t index = 0; index < out.size(); ++index) {
647             selectedIndexes.emplace_back(StringUtils::StringToInt(out[index]));
648         }
649         picker->SetSelected(selectedIndexes);
650         return true;
651     }
652 
653     return false;
654 }
655 
SetDateTimeSelected(const std::string & value)656 bool DOMPickerBase::SetDateTimeSelected(const std::string& value)
657 {
658     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATE &&
659         AceType::InstanceOf<PickerDateComponent>(basePickerChild_)) {
660         auto picker = AceType::DynamicCast<PickerDateComponent>(basePickerChild_);
661         auto date = DEFAULT_PICKER_DATE;
662         if (GetPickerDate(value, date)) {
663             picker->SetSelectedDate(date);
664         } else {
665             LOGE("input value of picker date is invalid.");
666         }
667 
668         return true;
669     }
670 
671     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_TIME &&
672         AceType::InstanceOf<PickerTimeComponent>(basePickerChild_)) {
673         auto picker = AceType::DynamicCast<PickerTimeComponent>(basePickerChild_);
674         auto time = DEFAULT_PICKER_TIME;
675         if (GetPickerTime(value, time)) {
676             picker->SetSelectedTime(time);
677         } else {
678             LOGE("input value of picker time is invalid.");
679         }
680         return true;
681     }
682 
683     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATETIME &&
684         AceType::InstanceOf<PickerDateTimeComponent>(basePickerChild_)) {
685         auto picker = AceType::DynamicCast<PickerDateTimeComponent>(basePickerChild_);
686         auto dateTime = PickerDateTime::Current();
687         if (GetPickerDateTime(value, dateTime)) {
688             picker->SetSelectedDateTime(dateTime);
689         } else {
690             LOGE("input value of picker date time is invalid.");
691         }
692 
693         return true;
694     }
695 
696     return false;
697 }
698 
SetHasSecond(const std::string & value)699 bool DOMPickerBase::SetHasSecond(const std::string& value)
700 {
701     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_TIME &&
702         AceType::InstanceOf<PickerTimeComponent>(basePickerChild_)) {
703         auto picker = AceType::DynamicCast<PickerTimeComponent>(basePickerChild_);
704         picker->SetHasSecond((value == "true")); // bool attribute's value is "true" and "false".
705         return true;
706     }
707 
708     return false;
709 }
710 
SetRange(const std::string & value)711 bool DOMPickerBase::SetRange(const std::string& value)
712 {
713     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_TEXT &&
714         AceType::InstanceOf<PickerTextComponent>(basePickerChild_)) {
715         auto picker = AceType::DynamicCast<PickerTextComponent>(basePickerChild_);
716         std::vector<std::string> out;
717         StringUtils::StringSplitter(value, DOM_PICKER_SPLIT_ARRAY, out);
718         picker->SetRange(out);
719         return true;
720     }
721 
722     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_MULTITEXT &&
723         AceType::InstanceOf<PickerMultiTextComponent>(basePickerChild_)) {
724         auto picker = AceType::DynamicCast<PickerMultiTextComponent>(basePickerChild_);
725         std::vector<std::string> out;
726         StringUtils::StringSplitter(value, DOM_PICKER_SPLIT_ARRAY, out);
727         std::vector<std::vector<std::string>> arrayRange;
728         for (uint32_t index = 0; index < out.size(); ++index) {
729             std::vector<std::string> textRange;
730             StringUtils::StringSplitter(out[index], DOM_PICKER_SPLIT_ITEM, textRange);
731             arrayRange.emplace_back(textRange);
732         }
733         picker->SetRange(arrayRange);
734         return true;
735     }
736 
737     return false;
738 }
739 
SetColumnCount(const std::string & value)740 bool DOMPickerBase::SetColumnCount(const std::string& value)
741 {
742     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_MULTITEXT &&
743         AceType::InstanceOf<PickerMultiTextComponent>(basePickerChild_)) {
744         auto picker = AceType::DynamicCast<PickerMultiTextComponent>(basePickerChild_);
745         picker->SetColumnCount(StringUtils::StringToInt(value));
746         return true;
747     }
748 
749     return false;
750 }
751 
SetHour24(const std::string & value)752 bool DOMPickerBase::SetHour24(const std::string& value)
753 {
754     if (basePickerChild_ && (type_ == DOM_PICKER_TYPE_DATETIME || type_ == DOM_PICKER_TYPE_TIME) &&
755         AceType::InstanceOf<PickerTimeComponent>(basePickerChild_)) {
756         auto picker = AceType::DynamicCast<PickerTimeComponent>(basePickerChild_);
757         if (value == "24") {
758             picker->SetHour24(true);
759         } else if (value == "12") {
760             picker->SetHour24(false);
761         } else {
762             LOGE("value of hour24 is invalid.");
763         }
764         return true;
765     }
766 
767     return false;
768 }
769 
SetShowLunar(const std::string & value)770 bool DOMPickerBase::SetShowLunar(const std::string& value)
771 {
772     static const char* FALSE = "false";
773     static const char* TRUE = "true";
774 
775     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATETIME &&
776         AceType::InstanceOf<PickerDateTimeComponent>(basePickerChild_)) {
777         auto picker = AceType::DynamicCast<PickerDateTimeComponent>(basePickerChild_);
778         if (value == TRUE) {
779             picker->SetShowLunar(true);
780         } else if (value == FALSE) {
781             picker->SetShowLunar(false);
782         } else {
783             LOGE("value of show lunar is invalid.");
784         }
785         return true;
786     }
787 
788     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATE &&
789         AceType::InstanceOf<PickerDateComponent>(basePickerChild_)) {
790         auto picker = AceType::DynamicCast<PickerDateComponent>(basePickerChild_);
791         if (value == TRUE) {
792             picker->SetShowLunar(true);
793         } else if (value == FALSE) {
794             picker->SetShowLunar(false);
795         } else {
796             LOGE("value of show lunar is invalid.");
797         }
798         return true;
799     }
800 
801     return false;
802 }
803 
SetLunar(const std::string & value)804 bool DOMPickerBase::SetLunar(const std::string& value)
805 {
806     static const char* FALSE = "false";
807     static const char* TRUE = "true";
808 
809     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATETIME &&
810         AceType::InstanceOf<PickerDateTimeComponent>(basePickerChild_)) {
811         auto picker = AceType::DynamicCast<PickerDateTimeComponent>(basePickerChild_);
812         if (value == TRUE) {
813             picker->SetHasLunar(true);
814         } else if (value == FALSE) {
815             picker->SetHasLunar(false);
816         } else {
817             LOGE("value of lunar is invalid.");
818         }
819         return true;
820     }
821 
822     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_DATE &&
823         AceType::InstanceOf<PickerDateComponent>(basePickerChild_)) {
824         auto picker = AceType::DynamicCast<PickerDateComponent>(basePickerChild_);
825         if (value == TRUE) {
826             picker->SetHasLunar(true);
827         } else if (value == FALSE) {
828             picker->SetHasLunar(false);
829         } else {
830             LOGE("value of lunar is invalid.");
831         }
832         return true;
833     }
834 
835     return false;
836 }
837 
SetPrefix(const std::string & value)838 bool DOMPickerBase::SetPrefix(const std::string& value)
839 {
840     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_TEXT &&
841         AceType::InstanceOf<PickerTextComponent>(basePickerChild_)) {
842         auto picker = AceType::DynamicCast<PickerTextComponent>(basePickerChild_);
843         picker->SetPrefix(value);
844         return true;
845     }
846     return false;
847 }
848 
SetSuffix(const std::string & value)849 bool DOMPickerBase::SetSuffix(const std::string& value)
850 {
851     if (basePickerChild_ && type_ == DOM_PICKER_TYPE_TEXT &&
852         AceType::InstanceOf<PickerTextComponent>(basePickerChild_)) {
853         auto picker = AceType::DynamicCast<PickerTextComponent>(basePickerChild_);
854         picker->SetSuffix(value);
855         return true;
856     }
857     return false;
858 }
859 
SetVibrate(const std::string & value)860 bool DOMPickerBase::SetVibrate(const std::string& value)
861 {
862     static const char* FALSE = "false";
863     static const char* TRUE = "true";
864 
865     if (basePickerChild_) {
866         if (value == TRUE) {
867             basePickerChild_->SetNeedVibrate(true);
868         } else if (value == FALSE) {
869             basePickerChild_->SetNeedVibrate(false);
870         } else {
871             LOGE("value of lunar is invalid.");
872         }
873         return true;
874     }
875     return false;
876 }
877 
878 } // namespace OHOS::Ace::Framework
879