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