1 /*
2 * Copyright (c) 2021-2023 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 "bridge/declarative_frontend/jsview/js_datepicker.h"
17
18 #include <utility>
19
20 #include "base/log/ace_scoring_log.h"
21 #include "base/utils/utils.h"
22 #include "bridge/common/utils/engine_helper.h"
23 #include "bridge/declarative_frontend/engine/functions/js_function.h"
24 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
25 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
26 #include "bridge/declarative_frontend/jsview/models/picker_model_impl.h"
27 #include "bridge/declarative_frontend/jsview/models/timepicker_model_impl.h"
28 #include "bridge/declarative_frontend/view_stack_processor.h"
29 #include "core/components/picker/picker_data.h"
30 #include "core/components/picker/picker_date_component.h"
31 #include "core/components/picker/picker_theme.h"
32 #include "core/components/picker/picker_time_component.h"
33 #include "core/components_ng/base/view_stack_processor.h"
34 #include "core/components_ng/pattern/picker/datepicker_model_ng.h"
35 #include "core/components_ng/pattern/time_picker/timepicker_model.h"
36 #include "core/components_ng/pattern/time_picker/timepicker_model_ng.h"
37 #include "core/components_v2/inspector/inspector_constants.h"
38 #include "core/event/ace_event_helper.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40
41 namespace OHOS::Ace {
42 namespace {
43 const DimensionOffset DATEPICKER_OFFSET_DEFAULT_TOP = DimensionOffset(0.0_vp, 40.0_vp);
44 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
45 DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
46 DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
47 DialogAlignment::BOTTOM_END };
48 } // namespace
49
50 std::unique_ptr<DatePickerModel> DatePickerModel::datePickerInstance_ = nullptr;
51 std::unique_ptr<DatePickerDialogModel> DatePickerDialogModel::datePickerDialogInstance_ = nullptr;
52 std::unique_ptr<TimePickerModel> TimePickerModel::timePickerInstance_ = nullptr;
53 std::unique_ptr<TimePickerDialogModel> TimePickerDialogModel::timePickerDialogInstance_ = nullptr;
54 std::mutex DatePickerModel::mutex_;
55 std::mutex DatePickerDialogModel::mutex_;
56 std::mutex TimePickerModel::mutex_;
57 std::mutex TimePickerDialogModel::mutex_;
58
GetInstance()59 DatePickerModel* DatePickerModel::GetInstance()
60 {
61 if (!datePickerInstance_) {
62 std::lock_guard<std::mutex> lock(mutex_);
63 if (!datePickerInstance_) {
64 #ifdef NG_BUILD
65 datePickerInstance_.reset(new NG::DatePickerModelNG());
66 #else
67 if (Container::IsCurrentUseNewPipeline()) {
68 datePickerInstance_.reset(new NG::DatePickerModelNG());
69 } else {
70 datePickerInstance_.reset(new Framework::DatePickerModelImpl());
71 }
72 #endif
73 }
74 }
75 return datePickerInstance_.get();
76 }
77
GetInstance()78 DatePickerDialogModel* DatePickerDialogModel::GetInstance()
79 {
80 if (!datePickerDialogInstance_) {
81 std::lock_guard<std::mutex> lock(mutex_);
82 if (!datePickerDialogInstance_) {
83 #ifdef NG_BUILD
84 datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
85 #else
86 if (Container::IsCurrentUseNewPipeline()) {
87 datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
88 } else {
89 datePickerDialogInstance_.reset(new Framework::DatePickerDialogModelImpl());
90 }
91 #endif
92 }
93 }
94 return datePickerDialogInstance_.get();
95 }
96
GetInstance()97 TimePickerModel* TimePickerModel::GetInstance()
98 {
99 if (!timePickerInstance_) {
100 std::lock_guard<std::mutex> lock(mutex_);
101 if (!timePickerInstance_) {
102 #ifdef NG_BUILD
103 timePickerInstance_.reset(new NG::TimePickerModelNG());
104 #else
105 if (Container::IsCurrentUseNewPipeline()) {
106 timePickerInstance_.reset(new NG::TimePickerModelNG());
107 } else {
108 timePickerInstance_.reset(new Framework::TimePickerModelImpl());
109 }
110 #endif
111 }
112 }
113 return timePickerInstance_.get();
114 }
115
GetInstance()116 TimePickerDialogModel* TimePickerDialogModel::GetInstance()
117 {
118 if (!timePickerDialogInstance_) {
119 std::lock_guard<std::mutex> lock(mutex_);
120 if (!timePickerDialogInstance_) {
121 #ifdef NG_BUILD
122 timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
123 #else
124 if (Container::IsCurrentUseNewPipeline()) {
125 timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
126 } else {
127 timePickerDialogInstance_.reset(new Framework::TimePickerDialogModelImpl());
128 }
129 #endif
130 }
131 }
132 return timePickerDialogInstance_.get();
133 }
134 } // namespace OHOS::Ace
135
136 namespace OHOS::Ace::Framework {
137 namespace {
DatePickerChangeEventToJSValue(const DatePickerChangeEvent & eventInfo)138 JSRef<JSVal> DatePickerChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
139 {
140 JSRef<JSObject> obj = JSRef<JSObject>::New();
141 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
142 if (!argsPtr) {
143 return JSRef<JSVal>::Cast(obj);
144 }
145 std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
146 for (auto iter = keys.begin(); iter != keys.end(); iter++) {
147 const std::string key = *iter;
148 const auto value = argsPtr->GetValue(key);
149 if (!value || value->ToString().empty()) {
150 continue;
151 }
152 obj->SetProperty<int32_t>(key.c_str(), value->GetInt());
153 }
154 return JSRef<JSVal>::Cast(obj);
155 }
156
DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent & eventInfo)157 JSRef<JSVal> DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
158 {
159 JSRef<JSObject> obj = JSRef<JSObject>::New();
160 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
161 if (!argsPtr) {
162 return JSRef<JSVal>::Cast(obj);
163 }
164 std::tm dateTime = { 0 };
165 auto year = argsPtr->GetValue("year");
166 if (year && year->IsNumber()) {
167 dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
168 }
169 auto month = argsPtr->GetValue("month");
170 if (month && month->IsNumber()) {
171 dateTime.tm_mon = month->GetInt();
172 }
173 auto day = argsPtr->GetValue("day");
174 if (day && day->IsNumber()) {
175 dateTime.tm_mday = day->GetInt();
176 }
177 auto hour = argsPtr->GetValue("hour");
178 if (hour && hour->IsNumber()) {
179 dateTime.tm_hour = hour->GetInt();
180 }
181 auto minute = argsPtr->GetValue("minute");
182 if (minute && minute->IsNumber()) {
183 dateTime.tm_min = minute->GetInt();
184 }
185
186 auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
187 auto dateObj = JSDate::New(milliseconds);
188 return JSRef<JSVal>::Cast(dateObj);
189 }
190 } // namespace
191
JSBind(BindingTarget globalObj)192 void JSDatePicker::JSBind(BindingTarget globalObj)
193 {
194 JSClass<JSDatePicker>::Declare("DatePicker");
195 MethodOptions opt = MethodOptions::NONE;
196 JSClass<JSDatePicker>::StaticMethod("create", &JSDatePicker::Create, opt);
197 JSClass<JSDatePicker>::StaticMethod("lunar", &JSDatePicker::SetLunar);
198 JSClass<JSDatePicker>::StaticMethod("onChange", &JSDatePicker::OnChange);
199 JSClass<JSDatePicker>::StaticMethod("onDateChange", &JSDatePicker::OnDateChange);
200 JSClass<JSDatePicker>::StaticMethod("backgroundColor", &JSDatePicker::PickerBackgroundColor);
201 // keep compatible, need remove after
202 JSClass<JSDatePicker>::StaticMethod("useMilitaryTime", &JSDatePicker::UseMilitaryTime);
203 JSClass<JSDatePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
204 JSClass<JSDatePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
205 JSClass<JSDatePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
206 JSClass<JSDatePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
207 JSClass<JSDatePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
208 JSClass<JSDatePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
209 JSClass<JSDatePicker>::StaticMethod("disappearTextStyle", &JSDatePicker::SetDisappearTextStyle);
210 JSClass<JSDatePicker>::StaticMethod("textStyle", &JSDatePicker::SetTextStyle);
211 JSClass<JSDatePicker>::StaticMethod("selectedTextStyle", &JSDatePicker::SetSelectedTextStyle);
212 JSClass<JSDatePicker>::InheritAndBind<JSViewAbstract>(globalObj);
213 }
214
Create(const JSCallbackInfo & info)215 void JSDatePicker::Create(const JSCallbackInfo& info)
216 {
217 DatePickerType pickerType = DatePickerType::DATE;
218 JSRef<JSObject> paramObject;
219 if (info.Length() >= 1 && info[0]->IsObject()) {
220 paramObject = JSRef<JSObject>::Cast(info[0]);
221 auto type = paramObject->GetProperty("type");
222 if (type->IsNumber()) {
223 pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
224 }
225 }
226 switch (pickerType) {
227 case DatePickerType::TIME: {
228 CreateTimePicker(info, paramObject);
229 break;
230 }
231 case DatePickerType::DATE: {
232 CreateDatePicker(info, paramObject);
233 break;
234 }
235 default: {
236 break;
237 }
238 }
239 }
240
SetLunar(bool isLunar)241 void JSDatePicker::SetLunar(bool isLunar)
242 {
243 DatePickerModel::GetInstance()->SetShowLunar(isLunar);
244 }
245
UseMilitaryTime(bool isUseMilitaryTime)246 void JSDatePicker::UseMilitaryTime(bool isUseMilitaryTime)
247 {
248 DatePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
249 }
250
ParseTextProperties(const JSRef<JSObject> & paramObj,NG::PickerTextProperties & result)251 void JSDatePicker::ParseTextProperties(const JSRef<JSObject>& paramObj, NG::PickerTextProperties& result)
252 {
253 auto disappearProperty = paramObj->GetProperty("disappearTextStyle");
254 auto normalProperty = paramObj->GetProperty("textStyle");
255 auto selectedProperty = paramObj->GetProperty("selectedTextStyle");
256
257 if (!disappearProperty->IsNull() && disappearProperty->IsObject()) {
258 JSRef<JSObject> disappearObj = JSRef<JSObject>::Cast(disappearProperty);
259 JSDatePicker::ParseTextStyle(disappearObj, result.disappearTextStyle_);
260 }
261
262 if (!normalProperty->IsNull() && normalProperty->IsObject()) {
263 JSRef<JSObject> noramlObj = JSRef<JSObject>::Cast(normalProperty);
264 JSDatePicker::ParseTextStyle(noramlObj, result.normalTextStyle_);
265 }
266
267 if (!selectedProperty->IsNull() && selectedProperty->IsObject()) {
268 JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(selectedProperty);
269 JSDatePicker::ParseTextStyle(selectedObj, result.selectedTextStyle_);
270 }
271 }
272
ParseTextStyle(const JSRef<JSObject> & paramObj,NG::PickerTextStyle & textStyle)273 void JSDatePicker::ParseTextStyle(const JSRef<JSObject>& paramObj, NG::PickerTextStyle& textStyle)
274 {
275 auto fontColor = paramObj->GetProperty("color");
276 auto fontOptions = paramObj->GetProperty("font");
277
278 Color textColor;
279 if (JSViewAbstract::ParseJsColor(fontColor, textColor)) {
280 textStyle.textColor = textColor;
281 }
282
283 if (!fontOptions->IsObject()) {
284 return;
285 }
286 JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(fontOptions);
287 auto fontSize = fontObj->GetProperty("size");
288 auto fontWeight = fontObj->GetProperty("weight");
289 auto fontFamily = fontObj->GetProperty("family");
290 auto fontStyle = fontObj->GetProperty("style");
291 if (fontSize->IsNull() || fontSize->IsUndefined()) {
292 textStyle.fontSize = Dimension(-1);
293 } else {
294 CalcDimension size;
295 if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) {
296 textStyle.fontSize = Dimension(-1);
297 } else {
298 textStyle.fontSize = size;
299 }
300 }
301
302 if (!fontWeight->IsNull() && !fontWeight->IsUndefined()) {
303 std::string weight;
304 if (fontWeight->IsNumber()) {
305 weight = std::to_string(fontWeight->ToNumber<int32_t>());
306 } else {
307 ParseJsString(fontWeight, weight);
308 }
309 textStyle.fontWeight = ConvertStrToFontWeight(weight);
310 }
311
312 if (!fontFamily->IsNull() && !fontFamily->IsUndefined()) {
313 std::vector<std::string> families;
314 if (ParseJsFontFamilies(fontFamily, families)) {
315 textStyle.fontFamily = families;
316 }
317 }
318
319 if (fontStyle->IsNumber()) {
320 auto style = fontStyle->ToNumber<int32_t>();
321 if (style < 0 || style > 1) {
322 return;
323 }
324 textStyle.fontStyle = static_cast<FontStyle>(style);
325 }
326 }
327
SetDisappearTextStyle(const JSCallbackInfo & info)328 void JSDatePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
329 {
330 auto theme = GetTheme<PickerTheme>();
331 CHECK_NULL_VOID(theme);
332 NG::PickerTextStyle textStyle;
333 if (info[0]->IsObject()) {
334 JSDatePicker::ParseTextStyle(info[0], textStyle);
335 }
336 DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
337 }
338
SetTextStyle(const JSCallbackInfo & info)339 void JSDatePicker::SetTextStyle(const JSCallbackInfo& info)
340 {
341 auto theme = GetTheme<PickerTheme>();
342 CHECK_NULL_VOID(theme);
343 NG::PickerTextStyle textStyle;
344 if (info[0]->IsObject()) {
345 JSDatePicker::ParseTextStyle(info[0], textStyle);
346 }
347 DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
348 }
349
SetSelectedTextStyle(const JSCallbackInfo & info)350 void JSDatePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
351 {
352 auto theme = GetTheme<PickerTheme>();
353 CHECK_NULL_VOID(theme);
354 NG::PickerTextStyle textStyle;
355 if (info[0]->IsObject()) {
356 JSDatePicker::ParseTextStyle(info[0], textStyle);
357 }
358 DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
359 }
360
OnChange(const JSCallbackInfo & info)361 void JSDatePicker::OnChange(const JSCallbackInfo& info)
362 {
363 if (!info[0]->IsFunction()) {
364 return;
365 }
366
367 auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
368 JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
369 WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
370 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
371 const BaseEventInfo* info) {
372 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
373 ACE_SCORING_EVENT("datePicker.onChange");
374 PipelineContext::SetCallBackNode(node);
375 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
376 func->Execute(*eventInfo);
377 };
378 DatePickerModel::GetInstance()->SetOnChange(std::move(onChange));
379 }
380
OnDateChange(const JSCallbackInfo & info)381 void JSDatePicker::OnDateChange(const JSCallbackInfo& info)
382 {
383 if (!info[0]->IsFunction()) {
384 return;
385 }
386 auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
387 JSRef<JSFunc>::Cast(info[0]), DatePickerDateChangeEventToJSValue);
388 WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
389 auto onDateChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
390 const BaseEventInfo* info) {
391 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
392 ACE_SCORING_EVENT("datePicker.onDateChange");
393 PipelineContext::SetCallBackNode(node);
394 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
395 func->Execute(*eventInfo);
396 };
397 DatePickerModel::GetInstance()->SetOnDateChange(std::move(onDateChange));
398 }
399
OnChange(const JSCallbackInfo & info)400 void JSTimePicker::OnChange(const JSCallbackInfo& info)
401 {
402 if (!info[0]->IsFunction()) {
403 return;
404 }
405
406 auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
407 JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
408 WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
409 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
410 const BaseEventInfo* index) {
411 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
412 ACE_SCORING_EVENT("datePicker.onChange");
413 PipelineContext::SetCallBackNode(node);
414 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(index);
415 func->Execute(*eventInfo);
416 };
417 TimePickerModel::GetInstance()->SetOnChange(std::move(onChange));
418 }
419
PickerBackgroundColor(const JSCallbackInfo & info)420 void JSDatePicker::PickerBackgroundColor(const JSCallbackInfo& info)
421 {
422 JSViewAbstract::JsBackgroundColor(info);
423
424 if (info.Length() < 1) {
425 return;
426 }
427 Color backgroundColor;
428 if (!ParseJsColor(info[0], backgroundColor)) {
429 return;
430 }
431 DatePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
432 }
433
ParseDate(const JSRef<JSVal> & dateVal)434 PickerDate JSDatePicker::ParseDate(const JSRef<JSVal>& dateVal)
435 {
436 auto pickerDate = PickerDate();
437 if (!dateVal->IsObject()) {
438 return pickerDate;
439 }
440 auto dateObj = JSRef<JSObject>::Cast(dateVal);
441 auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
442 auto monthFuncJsVal = dateObj->GetProperty("getMonth");
443 auto dateFuncJsVal = dateObj->GetProperty("getDate");
444 if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
445 return pickerDate;
446 }
447 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
448 auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
449 auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
450 JSRef<JSVal> year = yearFunc->Call(dateObj);
451 JSRef<JSVal> month = monthFunc->Call(dateObj);
452 JSRef<JSVal> date = dateFunc->Call(dateObj);
453
454 if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
455 pickerDate.SetYear(year->ToNumber<int32_t>());
456 pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
457 pickerDate.SetDay(date->ToNumber<int32_t>());
458 }
459 return pickerDate;
460 }
461
ParseTime(const JSRef<JSVal> & timeVal)462 PickerTime JSDatePicker::ParseTime(const JSRef<JSVal>& timeVal)
463 {
464 auto pickerTime = PickerTime();
465 if (!timeVal->IsObject()) {
466 return pickerTime;
467 }
468 auto timeObj = JSRef<JSObject>::Cast(timeVal);
469 auto hourFuncJsVal = timeObj->GetProperty("getHours");
470 auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
471 auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
472 if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
473 return pickerTime;
474 }
475 auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
476 auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
477 auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
478 JSRef<JSVal> hour = hourFunc->Call(timeObj);
479 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
480 JSRef<JSVal> second = secondFunc->Call(timeObj);
481
482 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
483 pickerTime.SetHour(hour->ToNumber<int32_t>());
484 pickerTime.SetMinute(minute->ToNumber<int32_t>());
485 pickerTime.SetSecond(second->ToNumber<int32_t>());
486 }
487 return pickerTime;
488 }
489
ParseSelectedDateTimeObject(const JSCallbackInfo & info,const JSRef<JSObject> & selectedObject,bool isDatePicker)490 void ParseSelectedDateTimeObject(const JSCallbackInfo& info, const JSRef<JSObject>& selectedObject, bool isDatePicker)
491 {
492 JSRef<JSVal> changeEventVal = selectedObject->GetProperty("changeEvent");
493 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
494 WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
495 auto changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
496 const BaseEventInfo* info) {
497 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
498 ACE_SCORING_EVENT("DatePicker.SelectedDateTimeChangeEvent");
499 const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
500 CHECK_NULL_VOID(eventInfo);
501 auto selectedStr = eventInfo->GetSelectedStr();
502 auto sourceJson = JsonUtil::ParseJsonString(selectedStr);
503 if (!sourceJson || sourceJson->IsNull()) {
504 return;
505 }
506
507 std::tm dateTime = { 0 };
508 auto year = sourceJson->GetValue("year");
509 if (year && year->IsNumber()) {
510 dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
511 }
512 auto month = sourceJson->GetValue("month");
513 if (month && month->IsNumber()) {
514 dateTime.tm_mon = month->GetInt();
515 }
516 auto day = sourceJson->GetValue("day");
517 if (day && day->IsNumber()) {
518 dateTime.tm_mday = day->GetInt();
519 }
520 auto hour = sourceJson->GetValue("hour");
521 if (hour && hour->IsNumber()) {
522 dateTime.tm_hour = hour->GetInt();
523 }
524 auto minute = sourceJson->GetValue("minute");
525 if (minute && minute->IsNumber()) {
526 dateTime.tm_min = minute->GetInt();
527 }
528 PipelineContext::SetCallBackNode(node);
529 auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
530 auto dateObj = JSDate::New(milliseconds);
531 func->ExecuteJS(1, &dateObj);
532 };
533 if (isDatePicker) {
534 DatePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
535 } else {
536 TimePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
537 }
538 }
539
CreateDatePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)540 void JSDatePicker::CreateDatePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
541 {
542 auto theme = GetTheme<PickerTheme>();
543 CHECK_NULL_VOID(theme);
544 JSRef<JSVal> startDate;
545 JSRef<JSVal> endDate;
546 JSRef<JSVal> selectedDate;
547 if (!paramObj->IsUndefined()) {
548 startDate = paramObj->GetProperty("start");
549 endDate = paramObj->GetProperty("end");
550 selectedDate = paramObj->GetProperty("selected");
551 }
552 auto parseStartDate = ParseDate(startDate);
553 auto parseEndDate = ParseDate(endDate);
554 if (parseStartDate.GetYear() <= 0) {
555 parseStartDate = theme->GetDefaultStartDate();
556 }
557 if (parseEndDate.GetYear() <= 0) {
558 parseEndDate = theme->GetDefaultEndDate();
559 }
560 auto startDays = parseStartDate.ToDays();
561 auto endDays = parseEndDate.ToDays();
562 if (startDays > endDays) {
563 parseStartDate = theme->GetDefaultStartDate();
564 parseEndDate = theme->GetDefaultEndDate();
565 }
566 DatePickerModel::GetInstance()->CreateDatePicker(theme);
567 if (startDate->IsObject()) {
568 DatePickerModel::GetInstance()->SetStartDate(parseStartDate);
569 }
570 if (endDate->IsObject()) {
571 DatePickerModel::GetInstance()->SetEndDate(parseEndDate);
572 }
573 if (selectedDate->IsObject()) {
574 JSRef<JSObject> selectedDateObj = JSRef<JSObject>::Cast(selectedDate);
575 JSRef<JSVal> changeEventVal = selectedDateObj->GetProperty("changeEvent");
576 PickerDate parseSelectedDate;
577 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
578 ParseSelectedDateTimeObject(info, selectedDateObj, true);
579 parseSelectedDate = ParseDate(selectedDateObj->GetProperty("value"));
580 } else {
581 parseSelectedDate = ParseDate(selectedDate);
582 }
583 DatePickerModel::GetInstance()->SetSelectedDate(parseSelectedDate);
584 }
585 SetDefaultAttributes();
586 }
587
SetDefaultAttributes()588 void JSDatePicker::SetDefaultAttributes()
589 {
590 auto theme = GetTheme<PickerTheme>();
591 CHECK_NULL_VOID(theme);
592 NG::PickerTextStyle textStyle;
593 auto selectedStyle = theme->GetOptionStyle(true, false);
594 textStyle.textColor = selectedStyle.GetTextColor();
595 textStyle.fontSize = selectedStyle.GetFontSize();
596 textStyle.fontWeight = selectedStyle.GetFontWeight();
597 DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
598
599 auto disappearStyle = theme->GetDisappearOptionStyle();
600 textStyle.textColor = disappearStyle.GetTextColor();
601 textStyle.fontSize = disappearStyle.GetFontSize();
602 textStyle.fontWeight = disappearStyle.GetFontWeight();
603 DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
604
605 auto normalStyle = theme->GetOptionStyle(false, false);
606 textStyle.textColor = normalStyle.GetTextColor();
607 textStyle.fontSize = normalStyle.GetFontSize();
608 textStyle.fontWeight = normalStyle.GetFontWeight();
609 DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
610 }
611
CreateTimePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)612 void JSDatePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
613 {
614 auto theme = GetTheme<PickerTheme>();
615 CHECK_NULL_VOID(theme);
616 DatePickerModel::GetInstance()->CreateTimePicker(theme);
617 auto selectedTime = paramObj->GetProperty("selected");
618 if (selectedTime->IsObject()) {
619 JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
620 JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
621 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
622 ParseSelectedDateTimeObject(info, selectedTimeObj, true);
623 auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
624 DatePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
625 } else {
626 DatePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
627 }
628 }
629 }
630
JSBind(BindingTarget globalObj)631 void JSDatePickerDialog::JSBind(BindingTarget globalObj)
632 {
633 JSClass<JSDatePickerDialog>::Declare("DatePickerDialog");
634 JSClass<JSDatePickerDialog>::StaticMethod("show", &JSDatePickerDialog::Show);
635
636 JSClass<JSDatePickerDialog>::Bind<>(globalObj);
637 }
638
Show(const JSCallbackInfo & info)639 void JSDatePickerDialog::Show(const JSCallbackInfo& info)
640 {
641 auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
642 CHECK_NULL_VOID(scopedDelegate);
643 if (!info[0]->IsObject()) {
644 return;
645 }
646 auto theme = GetTheme<PickerTheme>();
647 CHECK_NULL_VOID(theme);
648
649 auto paramObject = JSRef<JSObject>::Cast(info[0]);
650 DatePickerType pickerType = DatePickerType::DATE;
651 auto type = paramObject->GetProperty("type");
652 if (type->IsNumber()) {
653 pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
654 }
655 std::function<void()> cancelEvent;
656 std::function<void(const std::string&)> acceptEvent;
657 std::function<void(const std::string&)> changeEvent;
658 std::function<void(const std::string&)> dateChangeEvent;
659 std::function<void(const std::string&)> dateAcceptEvent;
660 WeakPtr<NG::FrameNode> frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
661 auto onChange = paramObject->GetProperty("onChange");
662 if (!onChange->IsUndefined() && onChange->IsFunction()) {
663 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
664 changeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
665 node = frameNode](const std::string& info) {
666 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
667 std::vector<std::string> keys;
668 keys = { "year", "month", "day" };
669 ACE_SCORING_EVENT("DatePickerDialog.onChange");
670 PipelineContext::SetCallBackNode(node);
671 func->Execute(keys, info);
672 };
673 }
674 auto onAccept = paramObject->GetProperty("onAccept");
675 if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
676 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
677 acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
678 const std::string& info) {
679 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
680 std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
681 ACE_SCORING_EVENT("DatePickerDialog.onAccept");
682 PipelineContext::SetCallBackNode(node);
683 func->Execute(keys, info);
684 };
685 }
686 auto onCancel = paramObject->GetProperty("onCancel");
687 if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
688 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
689 cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
690 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
691 ACE_SCORING_EVENT("DatePickerDialog.onCancel");
692 PipelineContext::SetCallBackNode(node);
693 func->Execute();
694 };
695 }
696 auto onDateChange = paramObject->GetProperty("onDateChange");
697 if (!onDateChange->IsUndefined() && onDateChange->IsFunction()) {
698 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateChange));
699 dateChangeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
700 node = frameNode](const std::string& info) {
701 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
702 ACE_SCORING_EVENT("DatePickerDialog.onDateChange");
703 auto selectedJson = JsonUtil::ParseJsonString(info);
704 if (!selectedJson || selectedJson->IsNull()) {
705 return;
706 }
707 std::tm dateTime = { 0 };
708 auto year = selectedJson->GetValue("year");
709 if (year && year->IsNumber()) {
710 dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
711 }
712 auto month = selectedJson->GetValue("month");
713 if (month && month->IsNumber()) {
714 dateTime.tm_mon = month->GetInt();
715 }
716 auto day = selectedJson->GetValue("day");
717 if (day && day->IsNumber()) {
718 dateTime.tm_mday = day->GetInt();
719 }
720 auto hour = selectedJson->GetValue("hour");
721 if (hour && hour->IsNumber()) {
722 dateTime.tm_hour = hour->GetInt();
723 }
724 auto minute = selectedJson->GetValue("minute");
725 if (minute && minute->IsNumber()) {
726 dateTime.tm_min = minute->GetInt();
727 }
728 auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
729 auto dateObj = JSDate::New(milliseconds);
730 PipelineContext::SetCallBackNode(node);
731 func->ExecuteJS(1, &dateObj);
732 };
733 }
734 auto onDateAccept = paramObject->GetProperty("onDateAccept");
735 if (!onDateAccept->IsUndefined() && onDateAccept->IsFunction()) {
736 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateAccept));
737 dateAcceptEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
738 node = frameNode](const std::string& info) {
739 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
740 ACE_SCORING_EVENT("DatePickerDialog.onDateAccept");
741 auto selectedJson = JsonUtil::ParseJsonString(info);
742 if (!selectedJson || selectedJson->IsNull()) {
743 return;
744 }
745 std::tm dateTime = { 0 };
746 auto year = selectedJson->GetValue("year");
747 if (year && year->IsNumber()) {
748 dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
749 }
750 auto month = selectedJson->GetValue("month");
751 if (month && month->IsNumber()) {
752 dateTime.tm_mon = month->GetInt();
753 }
754 auto day = selectedJson->GetValue("day");
755 if (day && day->IsNumber()) {
756 dateTime.tm_mday = day->GetInt();
757 }
758 auto hour = selectedJson->GetValue("hour");
759 if (hour && hour->IsNumber()) {
760 dateTime.tm_hour = hour->GetInt();
761 }
762 auto minute = selectedJson->GetValue("minute");
763 if (minute && minute->IsNumber()) {
764 dateTime.tm_min = minute->GetInt();
765 }
766 auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
767 auto dateObj = JSDate::New(milliseconds);
768 PipelineContext::SetCallBackNode(node);
769 func->ExecuteJS(1, &dateObj);
770 };
771 }
772 NG::DatePickerSettingData settingData;
773 PickerDialogInfo pickerDialog;
774 auto startDate = paramObject->GetProperty("start");
775 if (startDate->IsObject()) {
776 pickerDialog.isStartDate = true;
777 }
778 auto endDate = paramObject->GetProperty("end");
779 if (endDate->IsObject()) {
780 pickerDialog.isEndDate = true;
781 }
782 auto selectedDate = paramObject->GetProperty("selected");
783 if (selectedDate->IsObject()) {
784 pickerDialog.isSelectedDate = true;
785 }
786 auto lunar = paramObject->GetProperty("lunar");
787 auto lunarSwitch = paramObject->GetProperty("lunarSwitch");
788 auto sTime = paramObject->GetProperty("showTime");
789 auto useMilitary = paramObject->GetProperty("useMilitaryTime");
790 settingData.isLunar = lunar->ToBoolean();
791 settingData.lunarswitch = lunarSwitch->ToBoolean();
792 settingData.showTime = sTime->ToBoolean();
793 settingData.useMilitary = useMilitary->ToBoolean();
794 auto parseStartDate = ParseDate(startDate);
795 auto parseEndDate = ParseDate(endDate);
796 if (parseStartDate.GetYear() <= 0) {
797 parseStartDate = theme->GetDefaultStartDate();
798 }
799 if (parseEndDate.GetYear() <= 0) {
800 parseEndDate = theme->GetDefaultEndDate();
801 }
802 auto startDays = parseStartDate.ToDays();
803 auto endDays = parseEndDate.ToDays();
804 if (startDays > endDays) {
805 parseStartDate = theme->GetDefaultStartDate();
806 parseEndDate = theme->GetDefaultEndDate();
807 }
808 pickerDialog.parseStartDate = parseStartDate;
809 pickerDialog.parseEndDate = parseEndDate;
810 pickerDialog.parseSelectedDate = ParseDate(selectedDate);
811 pickerDialog.pickerTime = ParseTime(selectedDate);
812 JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
813
814 // Parse alignment
815 auto alignmentValue = paramObject->GetProperty("alignment");
816 if (alignmentValue->IsNumber()) {
817 auto alignment = alignmentValue->ToNumber<int32_t>();
818 if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
819 pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
820 }
821 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
822 if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
823 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
824 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
825 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
826 }
827 }
828 }
829
830 // Parse offset
831 auto offsetValue = paramObject->GetProperty("offset");
832 if (offsetValue->IsObject()) {
833 auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
834 CalcDimension dx;
835 auto dxValue = offsetObj->GetProperty("dx");
836 ParseJsDimensionVp(dxValue, dx);
837 CalcDimension dy;
838 auto dyValue = offsetObj->GetProperty("dy");
839 ParseJsDimensionVp(dyValue, dy);
840 pickerDialog.offset = DimensionOffset(dx, dy);
841 }
842
843 // Parse maskRect.
844 auto maskRectValue = paramObject->GetProperty("maskRect");
845 DimensionRect maskRect;
846 if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
847 pickerDialog.maskRect = maskRect;
848 }
849
850 auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
851 Color backgroundColor;
852 if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
853 pickerDialog.backgroundColor = backgroundColor;
854 }
855
856 auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
857 BlurStyleOption styleOption;
858 if (backgroundBlurStyle->IsNumber()) {
859 auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
860 if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
861 blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
862 pickerDialog.backgroundBlurStyle = blurStyle;
863 }
864 }
865
866 DatePickerDialogModel::GetInstance()->SetDatePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent),
867 std::move(acceptEvent), std::move(changeEvent), std::move(dateAcceptEvent), std::move(dateChangeEvent),
868 pickerType);
869 }
870
DatePickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)871 void JSDatePickerDialog::DatePickerDialogShow(const JSRef<JSObject>& paramObj,
872 const std::map<std::string, NG::DialogEvent>& dialogEvent,
873 const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
874 {
875 auto container = Container::CurrentSafely();
876 if (!container) {
877 return;
878 }
879 auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
880 if (!pipelineContext) {
881 return;
882 }
883
884 auto executor = pipelineContext->GetTaskExecutor();
885 if (!executor) {
886 return;
887 }
888
889 NG::DatePickerSettingData settingData;
890 auto startDate = paramObj->GetProperty("start");
891 auto endDate = paramObj->GetProperty("end");
892 auto selectedDate = paramObj->GetProperty("selected");
893 auto lunar = paramObj->GetProperty("lunar");
894 auto sTime = paramObj->GetProperty("showTime");
895 auto useMilitary = paramObj->GetProperty("useMilitaryTime");
896 settingData.isLunar = lunar->ToBoolean();
897 settingData.showTime = sTime->ToBoolean();
898 settingData.useMilitary = useMilitary->ToBoolean();
899 auto parseStartDate = ParseDate(startDate);
900 auto parseEndDate = ParseDate(endDate);
901 auto parseSelectedDate = ParseDate(selectedDate);
902
903 auto theme = GetTheme<DialogTheme>();
904 CHECK_NULL_VOID(theme);
905
906 ButtonInfo buttonInfo;
907 DialogProperties properties;
908 if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
909 properties.alignment = DialogAlignment::BOTTOM;
910 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
911 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
912 }
913 } else {
914 properties.alignment = DialogAlignment::CENTER;
915 }
916 properties.customStyle = false;
917 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
918 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
919 }
920
921 std::map<std::string, PickerDate> datePickerProperty;
922 std::map<std::string, PickerTime> timePickerProperty;
923 if (startDate->IsObject()) {
924 settingData.datePickerProperty["start"] = parseStartDate;
925 }
926 if (endDate->IsObject()) {
927 settingData.datePickerProperty["end"] = parseEndDate;
928 }
929 if (selectedDate->IsObject()) {
930 settingData.datePickerProperty["selected"] = parseSelectedDate;
931 settingData.timePickerProperty["selected"] = ParseTime(selectedDate);
932 }
933
934 JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
935 auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
936 auto overlayManager = context ? context->GetOverlayManager() : nullptr;
937 executor->PostTask(
938 [properties, settingData, dialogEvent, dialogCancelEvent, weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
939 auto overlayManager = weak.Upgrade();
940 CHECK_NULL_VOID(overlayManager);
941 overlayManager->ShowDateDialog(properties, settingData, dialogEvent, dialogCancelEvent);
942 },
943 TaskExecutor::TaskType::UI);
944 }
945
CreateDatePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)946 void JSDatePickerDialog::CreateDatePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
947 {
948 auto datePicker = AceType::MakeRefPtr<PickerDateComponent>();
949 auto startDate = paramObj->GetProperty("start");
950 auto endDate = paramObj->GetProperty("end");
951 auto selectedDate = paramObj->GetProperty("selected");
952 auto lunar = paramObj->GetProperty("lunar");
953 bool isLunar = lunar->ToBoolean();
954 auto parseStartDate = ParseDate(startDate);
955 auto parseEndDate = ParseDate(endDate);
956 auto parseSelectedDate = ParseDate(selectedDate);
957 auto startDays = parseStartDate.ToDays();
958 auto endDays = parseEndDate.ToDays();
959 if (startDays > endDays) {
960 parseStartDate.SetYear(0);
961 parseEndDate.SetYear(0);
962 }
963 if (startDate->IsObject()) {
964 datePicker->SetStartDate(parseStartDate);
965 }
966 if (endDate->IsObject()) {
967 datePicker->SetEndDate(parseEndDate);
968 }
969 if (selectedDate->IsObject()) {
970 datePicker->SetSelectedDate(parseSelectedDate);
971 }
972 datePicker->SetIsDialog(true);
973 datePicker->SetIsCreateDialogComponent(true);
974 datePicker->SetShowLunar(isLunar);
975
976 component = datePicker;
977 }
978
CreateTimePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)979 void JSDatePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
980 {
981 auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
982 auto selectedTime = paramObj->GetProperty("selected");
983 auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
984 bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
985 if (selectedTime->IsObject()) {
986 timePicker->SetSelectedTime(ParseTime(selectedTime));
987 }
988 timePicker->SetIsDialog(true);
989 timePicker->SetIsCreateDialogComponent(true);
990 timePicker->SetHour24(isUseMilitaryTime);
991 component = timePicker;
992 }
993
ParseDate(const JSRef<JSVal> & dateVal)994 PickerDate JSDatePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
995 {
996 auto pickerDate = PickerDate();
997 if (!dateVal->IsObject()) {
998 return pickerDate;
999 }
1000 auto dateObj = JSRef<JSObject>::Cast(dateVal);
1001 auto yearFunc = JSRef<JSFunc>::Cast(dateObj->GetProperty("getFullYear"));
1002 auto monthFunc = JSRef<JSFunc>::Cast(dateObj->GetProperty("getMonth"));
1003 auto dateFunc = JSRef<JSFunc>::Cast(dateObj->GetProperty("getDate"));
1004 JSRef<JSVal> year = yearFunc->Call(dateObj);
1005 JSRef<JSVal> month = monthFunc->Call(dateObj);
1006 JSRef<JSVal> date = dateFunc->Call(dateObj);
1007
1008 if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
1009 pickerDate.SetYear(year->ToNumber<int32_t>());
1010 pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
1011 pickerDate.SetDay(date->ToNumber<int32_t>());
1012 }
1013 return pickerDate;
1014 }
1015
ParseTime(const JSRef<JSVal> & timeVal)1016 PickerTime JSDatePickerDialog::ParseTime(const JSRef<JSVal>& timeVal)
1017 {
1018 auto pickerTime = PickerTime();
1019 if (!timeVal->IsObject()) {
1020 return pickerTime;
1021 }
1022 auto timeObj = JSRef<JSObject>::Cast(timeVal);
1023 auto hourFunc = JSRef<JSFunc>::Cast(timeObj->GetProperty("getHours"));
1024 auto minuteFunc = JSRef<JSFunc>::Cast(timeObj->GetProperty("getMinutes"));
1025 auto secondFunc = JSRef<JSFunc>::Cast(timeObj->GetProperty("getSeconds"));
1026 JSRef<JSVal> hour = hourFunc->Call(timeObj);
1027 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1028 JSRef<JSVal> second = secondFunc->Call(timeObj);
1029
1030 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1031 pickerTime.SetHour(hour->ToNumber<int32_t>());
1032 pickerTime.SetMinute(minute->ToNumber<int32_t>());
1033 pickerTime.SetSecond(second->ToNumber<int32_t>());
1034 }
1035 return pickerTime;
1036 }
1037
JSBind(BindingTarget globalObj)1038 void JSTimePicker::JSBind(BindingTarget globalObj)
1039 {
1040 JSClass<JSTimePicker>::Declare("TimePicker");
1041 MethodOptions opt = MethodOptions::NONE;
1042 JSClass<JSTimePicker>::StaticMethod("create", &JSTimePicker::Create, opt);
1043 JSClass<JSTimePicker>::StaticMethod("onChange", &JSTimePicker::OnChange);
1044 JSClass<JSTimePicker>::StaticMethod("backgroundColor", &JSTimePicker::PickerBackgroundColor);
1045 JSClass<JSTimePicker>::StaticMethod("loop", &JSTimePicker::Loop);
1046 JSClass<JSTimePicker>::StaticMethod("useMilitaryTime", &JSTimePicker::UseMilitaryTime);
1047 JSClass<JSTimePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
1048 JSClass<JSTimePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
1049 JSClass<JSTimePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
1050 JSClass<JSTimePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
1051 JSClass<JSTimePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
1052 JSClass<JSTimePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
1053 JSClass<JSTimePicker>::StaticMethod("disappearTextStyle", &JSTimePicker::SetDisappearTextStyle);
1054 JSClass<JSTimePicker>::StaticMethod("textStyle", &JSTimePicker::SetTextStyle);
1055 JSClass<JSTimePicker>::StaticMethod("selectedTextStyle", &JSTimePicker::SetSelectedTextStyle);
1056 JSClass<JSTimePicker>::InheritAndBind<JSViewAbstract>(globalObj);
1057 }
1058
Create(const JSCallbackInfo & info)1059 void JSTimePicker::Create(const JSCallbackInfo& info)
1060 {
1061 JSRef<JSObject> paramObject = JSRef<JSObject>::New();
1062 if (info.Length() >= 1 && info[0]->IsObject()) {
1063 paramObject = JSRef<JSObject>::Cast(info[0]);
1064 }
1065 CreateTimePicker(info, paramObject);
1066 }
1067
Loop(bool isLoop)1068 void JSTimePicker::Loop(bool isLoop)
1069 {
1070 TimePickerModel::GetInstance()->SetWheelModeEnabled(isLoop);
1071 }
1072
UseMilitaryTime(bool isUseMilitaryTime)1073 void JSTimePicker::UseMilitaryTime(bool isUseMilitaryTime)
1074 {
1075 TimePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
1076 }
1077
PickerBackgroundColor(const JSCallbackInfo & info)1078 void JSTimePicker::PickerBackgroundColor(const JSCallbackInfo& info)
1079 {
1080 JSViewAbstract::JsBackgroundColor(info);
1081
1082 if (info.Length() < 1) {
1083 return;
1084 }
1085 Color backgroundColor;
1086 if (!ParseJsColor(info[0], backgroundColor)) {
1087 return;
1088 }
1089 TimePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
1090 }
1091
SetDisappearTextStyle(const JSCallbackInfo & info)1092 void JSTimePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
1093 {
1094 auto theme = GetTheme<PickerTheme>();
1095 CHECK_NULL_VOID(theme);
1096 NG::PickerTextStyle textStyle;
1097 if (info[0]->IsObject()) {
1098 JSDatePicker::ParseTextStyle(info[0], textStyle);
1099 }
1100 TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1101 }
1102
SetTextStyle(const JSCallbackInfo & info)1103 void JSTimePicker::SetTextStyle(const JSCallbackInfo& info)
1104 {
1105 auto theme = GetTheme<PickerTheme>();
1106 CHECK_NULL_VOID(theme);
1107 NG::PickerTextStyle textStyle;
1108 if (info[0]->IsObject()) {
1109 JSDatePicker::ParseTextStyle(info[0], textStyle);
1110 }
1111 TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1112 }
1113
SetSelectedTextStyle(const JSCallbackInfo & info)1114 void JSTimePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
1115 {
1116 auto theme = GetTheme<PickerTheme>();
1117 CHECK_NULL_VOID(theme);
1118 NG::PickerTextStyle textStyle;
1119 if (info[0]->IsObject()) {
1120 JSDatePicker::ParseTextStyle(info[0], textStyle);
1121 }
1122 TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1123 }
1124
CreateTimePicker(const JSCallbackInfo & info,const JSRef<JSObject> & paramObj)1125 void JSTimePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
1126 {
1127 auto selectedTime = paramObj->GetProperty("selected");
1128 auto theme = GetTheme<PickerTheme>();
1129 CHECK_NULL_VOID(theme);
1130 auto formatValue = paramObj->GetProperty("format");
1131 bool showSecond = false;
1132 if (formatValue->IsNumber()) {
1133 auto displayedFormat = static_cast<TimePickerFormat>(formatValue->ToNumber<int32_t>());
1134 if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) {
1135 showSecond = true;
1136 }
1137 }
1138 TimePickerModel::GetInstance()->CreateTimePicker(theme, showSecond);
1139 if (selectedTime->IsObject()) {
1140 JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
1141 JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
1142 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
1143 ParseSelectedDateTimeObject(info, selectedTimeObj, false);
1144 auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
1145 TimePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
1146 } else {
1147 TimePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
1148 }
1149 }
1150 SetDefaultAttributes();
1151 }
1152
SetDefaultAttributes()1153 void JSTimePicker::SetDefaultAttributes()
1154 {
1155 auto theme = GetTheme<PickerTheme>();
1156 CHECK_NULL_VOID(theme);
1157 NG::PickerTextStyle textStyle;
1158 auto selectedStyle = theme->GetOptionStyle(true, false);
1159 textStyle.textColor = selectedStyle.GetTextColor();
1160 textStyle.fontSize = selectedStyle.GetFontSize();
1161 textStyle.fontWeight = selectedStyle.GetFontWeight();
1162 TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1163
1164 auto disappearStyle = theme->GetDisappearOptionStyle();
1165 textStyle.textColor = disappearStyle.GetTextColor();
1166 textStyle.fontSize = disappearStyle.GetFontSize();
1167 textStyle.fontWeight = disappearStyle.GetFontWeight();
1168 TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1169
1170 auto normalStyle = theme->GetOptionStyle(false, false);
1171 textStyle.textColor = normalStyle.GetTextColor();
1172 textStyle.fontSize = normalStyle.GetFontSize();
1173 textStyle.fontWeight = normalStyle.GetFontWeight();
1174 TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1175 }
1176
ParseTime(const JSRef<JSVal> & timeVal)1177 PickerTime JSTimePicker::ParseTime(const JSRef<JSVal>& timeVal)
1178 {
1179 auto pickerTime = PickerTime::Current();
1180 if (!timeVal->IsObject()) {
1181 return pickerTime;
1182 }
1183 auto timeObj = JSRef<JSObject>::Cast(timeVal);
1184 auto yearFuncJsVal = timeObj->GetProperty("getFullYear");
1185 if (yearFuncJsVal->IsFunction()) {
1186 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1187 JSRef<JSVal> year = yearFunc->Call(timeObj);
1188 if (year->IsNumber() && LessOrEqual(year->ToNumber<int32_t>(), 0)) {
1189 return pickerTime;
1190 }
1191 }
1192
1193 auto hourFuncJsVal = timeObj->GetProperty("getHours");
1194 auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1195 auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1196 if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1197 return pickerTime;
1198 }
1199 auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1200 auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1201 auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1202 JSRef<JSVal> hour = hourFunc->Call(timeObj);
1203 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1204 JSRef<JSVal> second = secondFunc->Call(timeObj);
1205
1206 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1207 pickerTime.SetHour(hour->ToNumber<int32_t>());
1208 pickerTime.SetMinute(minute->ToNumber<int32_t>());
1209 pickerTime.SetSecond(second->ToNumber<int32_t>());
1210 }
1211 return pickerTime;
1212 }
1213
JSBind(BindingTarget globalObj)1214 void JSTimePickerDialog::JSBind(BindingTarget globalObj)
1215 {
1216 JSClass<JSTimePickerDialog>::Declare("TimePickerDialog");
1217 JSClass<JSTimePickerDialog>::StaticMethod("show", &JSTimePickerDialog::Show);
1218
1219 JSClass<JSTimePickerDialog>::Bind<>(globalObj);
1220 }
1221
Show(const JSCallbackInfo & info)1222 void JSTimePickerDialog::Show(const JSCallbackInfo& info)
1223 {
1224 auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
1225 CHECK_NULL_VOID(scopedDelegate);
1226 if (!info[0]->IsObject()) {
1227 return;
1228 }
1229 auto paramObject = JSRef<JSObject>::Cast(info[0]);
1230 std::function<void()> cancelEvent;
1231 std::function<void(const std::string&)> acceptEvent;
1232 std::function<void(const std::string&)> changeEvent;
1233 WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
1234 auto onChange = paramObject->GetProperty("onChange");
1235 if (!onChange->IsUndefined() && onChange->IsFunction()) {
1236 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
1237 changeEvent = [execCtx = info.GetExecutionContext(), type = DatePickerType::TIME, func = std::move(jsFunc),
1238 node = targetNode](const std::string& info) {
1239 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1240 std::vector<std::string> keys;
1241 keys = { "hour", "minute" };
1242 ACE_SCORING_EVENT("DatePickerDialog.onChange");
1243 PipelineContext::SetCallBackNode(node);
1244 func->Execute(keys, info);
1245 };
1246 }
1247 auto onAccept = paramObject->GetProperty("onAccept");
1248 if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1249 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1250 acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
1251 const std::string& info) {
1252 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1253 std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
1254 ACE_SCORING_EVENT("DatePickerDialog.onAccept");
1255 PipelineContext::SetCallBackNode(node);
1256 func->Execute(keys, info);
1257 };
1258 }
1259 auto onCancel = paramObject->GetProperty("onCancel");
1260 if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1261 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1262 cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1263 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1264 ACE_SCORING_EVENT("DatePickerDialog.onCancel");
1265 PipelineContext::SetCallBackNode(node);
1266 func->Execute();
1267 };
1268 }
1269 auto selectedTime = paramObject->GetProperty("selected");
1270 auto useMilitaryTime = paramObject->GetProperty("useMilitaryTime");
1271 NG::TimePickerSettingData settingData;
1272 PickerDialogInfo pickerDialog;
1273 settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1274 pickerDialog.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1275 if (selectedTime->IsObject()) {
1276 PickerDate dialogTitleDate = ParseDate(selectedTime);
1277 if (dialogTitleDate.GetYear() != 0) {
1278 settingData.dialogTitleDate = dialogTitleDate;
1279 pickerDialog.isSelectedTime = true;
1280 pickerDialog.pickerTime = ParseTime(selectedTime);
1281 }
1282 }
1283 JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
1284
1285 // Parse alignment
1286 auto alignmentValue = paramObject->GetProperty("alignment");
1287 if (alignmentValue->IsNumber()) {
1288 auto alignment = alignmentValue->ToNumber<int32_t>();
1289 if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
1290 pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
1291 }
1292 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1293 if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
1294 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
1295 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
1296 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
1297 }
1298 }
1299 }
1300
1301 // Parse offset
1302 auto offsetValue = paramObject->GetProperty("offset");
1303 if (offsetValue->IsObject()) {
1304 auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
1305 CalcDimension dx;
1306 auto dxValue = offsetObj->GetProperty("dx");
1307 JSAlertDialog::ParseJsDimensionVp(dxValue, dx);
1308 CalcDimension dy;
1309 auto dyValue = offsetObj->GetProperty("dy");
1310 JSAlertDialog::ParseJsDimensionVp(dyValue, dy);
1311 pickerDialog.offset = DimensionOffset(dx, dy);
1312 }
1313
1314 // Parse maskRect.
1315 auto maskRectValue = paramObject->GetProperty("maskRect");
1316 DimensionRect maskRect;
1317 if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
1318 pickerDialog.maskRect = maskRect;
1319 }
1320
1321 auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
1322 Color backgroundColor;
1323 if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
1324 pickerDialog.backgroundColor = backgroundColor;
1325 }
1326
1327 auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
1328 BlurStyleOption styleOption;
1329 if (backgroundBlurStyle->IsNumber()) {
1330 auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
1331 if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
1332 blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
1333 pickerDialog.backgroundBlurStyle = blurStyle;
1334 }
1335 }
1336
1337 TimePickerDialogModel::GetInstance()->SetTimePickerDialogShow(
1338 pickerDialog, settingData, std::move(cancelEvent), std::move(acceptEvent), std::move(changeEvent));
1339 }
1340
TimePickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)1341 void JSTimePickerDialog::TimePickerDialogShow(const JSRef<JSObject>& paramObj,
1342 const std::map<std::string, NG::DialogEvent>& dialogEvent,
1343 const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
1344 {
1345 auto container = Container::CurrentSafely();
1346 if (!container) {
1347 return;
1348 }
1349 auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1350 if (!pipelineContext) {
1351 return;
1352 }
1353
1354 auto executor = pipelineContext->GetTaskExecutor();
1355 if (!executor) {
1356 return;
1357 }
1358
1359 auto theme = JSAlertDialog::GetTheme<DialogTheme>();
1360 CHECK_NULL_VOID(theme);
1361
1362 auto selectedTime = paramObj->GetProperty("selected");
1363 auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1364 NG::TimePickerSettingData settingData;
1365 settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1366
1367 ButtonInfo buttonInfo;
1368 DialogProperties properties;
1369 if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
1370 properties.alignment = DialogAlignment::BOTTOM;
1371 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1372 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1373 }
1374 } else {
1375 properties.alignment = DialogAlignment::CENTER;
1376 }
1377 properties.customStyle = false;
1378 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1379 properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1380 }
1381
1382 std::map<std::string, PickerTime> timePickerProperty;
1383 if (selectedTime->IsObject()) {
1384 settingData.dialogTitleDate = ParseDate(selectedTime);
1385 timePickerProperty["selected"] = ParseTime(selectedTime);
1386 }
1387 JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
1388
1389 auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
1390 auto overlayManager = context ? context->GetOverlayManager() : nullptr;
1391 executor->PostTask(
1392 [properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent,
1393 weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
1394 auto overlayManager = weak.Upgrade();
1395 CHECK_NULL_VOID(overlayManager);
1396 overlayManager->ShowTimeDialog(properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent);
1397 },
1398 TaskExecutor::TaskType::UI);
1399 }
1400
CreateTimePicker(RefPtr<Component> & component,const JSRef<JSObject> & paramObj)1401 void JSTimePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
1402 {
1403 auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
1404 auto selectedTime = paramObj->GetProperty("selected");
1405 auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1406 bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
1407 if (selectedTime->IsObject()) {
1408 timePicker->SetSelectedTime(ParseTime(selectedTime));
1409 }
1410 timePicker->SetIsDialog(true);
1411 timePicker->SetIsCreateDialogComponent(true);
1412 timePicker->SetHour24(isUseMilitaryTime);
1413 component = timePicker;
1414 }
1415
ParseTime(const JSRef<JSVal> & timeVal)1416 PickerTime JSTimePickerDialog::ParseTime(const JSRef<JSVal>& timeVal)
1417 {
1418 auto pickerTime = PickerTime();
1419 if (!timeVal->IsObject()) {
1420 return pickerTime;
1421 }
1422 auto timeObj = JSRef<JSObject>::Cast(timeVal);
1423 auto hourFuncJsVal = timeObj->GetProperty("getHours");
1424 auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1425 auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1426 if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1427 return pickerTime;
1428 }
1429 auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1430 auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1431 auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1432 JSRef<JSVal> hour = hourFunc->Call(timeObj);
1433 JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1434 JSRef<JSVal> second = secondFunc->Call(timeObj);
1435
1436 if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1437 pickerTime.SetHour(hour->ToNumber<int32_t>());
1438 pickerTime.SetMinute(minute->ToNumber<int32_t>());
1439 pickerTime.SetSecond(second->ToNumber<int32_t>());
1440 }
1441 return pickerTime;
1442 }
1443
ParseDate(const JSRef<JSVal> & dateVal)1444 PickerDate JSTimePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
1445 {
1446 auto pickerDate = PickerDate();
1447 if (!dateVal->IsObject()) {
1448 return pickerDate;
1449 }
1450 auto dateObj = JSRef<JSObject>::Cast(dateVal);
1451 auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
1452 auto monthFuncJsVal = dateObj->GetProperty("getMonth");
1453 auto dateFuncJsVal = dateObj->GetProperty("getDate");
1454 if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
1455 return pickerDate;
1456 }
1457 auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1458 auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
1459 auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
1460 JSRef<JSVal> year = yearFunc->Call(dateObj);
1461 JSRef<JSVal> month = monthFunc->Call(dateObj);
1462 JSRef<JSVal> date = dateFunc->Call(dateObj);
1463
1464 if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
1465 pickerDate.SetYear(year->ToNumber<int32_t>());
1466 pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
1467 pickerDate.SetDay(date->ToNumber<int32_t>());
1468 }
1469 return pickerDate;
1470 }
1471 } // namespace OHOS::Ace::Framework
1472