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