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