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