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_utils.h"
26 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
27 #include "bridge/declarative_frontend/jsview/models/picker_model_impl.h"
28 #include "bridge/declarative_frontend/jsview/models/timepicker_model_impl.h"
29 #include "bridge/declarative_frontend/view_stack_processor.h"
30 #include "core/components/picker/picker_data.h"
31 #include "core/components/picker/picker_date_component.h"
32 #include "core/components/picker/picker_theme.h"
33 #include "core/components/picker/picker_time_component.h"
34 #include "core/components_ng/base/view_stack_processor.h"
35 #include "core/components_ng/pattern/picker/datepicker_model_ng.h"
36 #include "core/components_ng/pattern/time_picker/timepicker_model.h"
37 #include "core/components_ng/pattern/time_picker/timepicker_model_ng.h"
38 #include "core/components_v2/inspector/inspector_constants.h"
39 #include "core/event/ace_event_helper.h"
40 #include "core/pipeline_ng/pipeline_context.h"
41 #include "frameworks/bridge/declarative_frontend/ark_theme/theme_apply/js_date_picker_theme.h"
42 #include "frameworks/bridge/declarative_frontend/ark_theme/theme_apply/js_time_picker_theme.h"
43 
44 namespace OHOS::Ace {
45 namespace {
46 const DimensionOffset DATEPICKER_OFFSET_DEFAULT_TOP = DimensionOffset(0.0_vp, 40.0_vp);
47 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
48     DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
49     DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
50     DialogAlignment::BOTTOM_END };
51 const std::vector<HoverModeAreaType> HOVER_MODE_AREA_TYPE = { HoverModeAreaType::TOP_SCREEN,
52     HoverModeAreaType::BOTTOM_SCREEN };
53 const char TIMEPICKER_OPTIONS_HOUR[] = "hour";
54 const char TIMEPICKER_OPTIONS_MINUTE[] = "minute";
55 const char TIMEPICKER_OPTIONS_SECOND[] = "second";
56 const std::string TIMEPICKER_OPTIONS_NUMERIC_VAL = "numeric";
57 const std::string TIMEPICKER_OPTIONS_TWO_DIGIT_VAL = "2-digit";
58 } // namespace
59 
60 std::unique_ptr<DatePickerModel> DatePickerModel::datePickerInstance_ = nullptr;
61 std::unique_ptr<DatePickerDialogModel> DatePickerDialogModel::datePickerDialogInstance_ = nullptr;
62 std::unique_ptr<TimePickerModel> TimePickerModel::timePickerInstance_ = nullptr;
63 std::unique_ptr<TimePickerDialogModel> TimePickerDialogModel::timePickerDialogInstance_ = nullptr;
64 std::mutex DatePickerModel::mutex_;
65 std::mutex DatePickerDialogModel::mutex_;
66 std::mutex TimePickerModel::mutex_;
67 std::mutex TimePickerDialogModel::mutex_;
68 
GetInstance()69 DatePickerModel* DatePickerModel::GetInstance()
70 {
71     if (!datePickerInstance_) {
72         std::lock_guard<std::mutex> lock(mutex_);
73         if (!datePickerInstance_) {
74 #ifdef NG_BUILD
75             datePickerInstance_.reset(new NG::DatePickerModelNG());
76 #else
77             if (Container::IsCurrentUseNewPipeline()) {
78                 datePickerInstance_.reset(new NG::DatePickerModelNG());
79             } else {
80                 datePickerInstance_.reset(new Framework::DatePickerModelImpl());
81             }
82 #endif
83         }
84     }
85     return datePickerInstance_.get();
86 }
87 
GetInstance()88 DatePickerDialogModel* DatePickerDialogModel::GetInstance()
89 {
90     if (!datePickerDialogInstance_) {
91         std::lock_guard<std::mutex> lock(mutex_);
92         if (!datePickerDialogInstance_) {
93 #ifdef NG_BUILD
94             datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
95 #else
96             if (Container::IsCurrentUseNewPipeline()) {
97                 datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG());
98             } else {
99                 datePickerDialogInstance_.reset(new Framework::DatePickerDialogModelImpl());
100             }
101 #endif
102         }
103     }
104     return datePickerDialogInstance_.get();
105 }
106 
GetInstance()107 TimePickerModel* TimePickerModel::GetInstance()
108 {
109     if (!timePickerInstance_) {
110         std::lock_guard<std::mutex> lock(mutex_);
111         if (!timePickerInstance_) {
112 #ifdef NG_BUILD
113             timePickerInstance_.reset(new NG::TimePickerModelNG());
114 #else
115             if (Container::IsCurrentUseNewPipeline()) {
116                 timePickerInstance_.reset(new NG::TimePickerModelNG());
117             } else {
118                 timePickerInstance_.reset(new Framework::TimePickerModelImpl());
119             }
120 #endif
121         }
122     }
123     return timePickerInstance_.get();
124 }
125 
GetInstance()126 TimePickerDialogModel* TimePickerDialogModel::GetInstance()
127 {
128     if (!timePickerDialogInstance_) {
129         std::lock_guard<std::mutex> lock(mutex_);
130         if (!timePickerDialogInstance_) {
131 #ifdef NG_BUILD
132             timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
133 #else
134             if (Container::IsCurrentUseNewPipeline()) {
135                 timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG());
136             } else {
137                 timePickerDialogInstance_.reset(new Framework::TimePickerDialogModelImpl());
138             }
139 #endif
140         }
141     }
142     return timePickerDialogInstance_.get();
143 }
144 } // namespace OHOS::Ace
145 
146 namespace OHOS::Ace::Framework {
147 namespace {
DatePickerChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)148 JSRef<JSVal> DatePickerChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
149 {
150     JSRef<JSObject> obj = JSRef<JSObject>::New();
151     std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
152     if (!argsPtr) {
153         return JSRef<JSVal>::Cast(obj);
154     }
155     std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
156     for (auto iter = keys.begin(); iter != keys.end(); iter++) {
157         const std::string key = *iter;
158         const auto value = argsPtr->GetValue(key);
159         if (!value || value->ToString().empty()) {
160             continue;
161         }
162         obj->SetProperty<int32_t>(key.c_str(), value->GetInt());
163     }
164     return JSRef<JSVal>::Cast(obj);
165 }
166 
DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)167 JSRef<JSVal> DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent& eventInfo)
168 {
169     JSRef<JSObject> obj = JSRef<JSObject>::New();
170     std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr());
171     if (!argsPtr) {
172         return JSRef<JSVal>::Cast(obj);
173     }
174     auto dateObj = JSDatePickerDialog::GetDateObj(argsPtr);
175     return JSRef<JSVal>::Cast(dateObj);
176 }
177 
ParseFontOfButtonStyle(const JSRef<JSObject>& pickerButtonParamObject, ButtonInfo& buttonInfo)178 void ParseFontOfButtonStyle(const JSRef<JSObject>& pickerButtonParamObject, ButtonInfo& buttonInfo)
179 {
180     CalcDimension fontSize;
181     JSRef<JSVal> sizeProperty = pickerButtonParamObject->GetProperty("fontSize");
182     if (JSViewAbstract::ParseJsDimensionVpNG(sizeProperty, fontSize) && fontSize.Unit() != DimensionUnit::PERCENT &&
183         GreatOrEqual(fontSize.Value(), 0.0)) {
184         if (JSViewAbstract::ParseJsDimensionFp(sizeProperty, fontSize)) {
185             buttonInfo.fontSize = fontSize;
186         }
187     }
188     Color fontColor;
189     if (JSViewAbstract::ParseJsColor(pickerButtonParamObject->GetProperty("fontColor"), fontColor)) {
190         buttonInfo.fontColor = fontColor;
191     }
192     auto fontWeight = pickerButtonParamObject->GetProperty("fontWeight");
193     if (fontWeight->IsString() || fontWeight->IsNumber()) {
194         buttonInfo.fontWeight = ConvertStrToFontWeight(fontWeight->ToString(), FontWeight::MEDIUM);
195     }
196     JSRef<JSVal> style = pickerButtonParamObject->GetProperty("fontStyle");
197     if (style->IsNumber()) {
198         auto value = style->ToNumber<int32_t>();
199         if (value >= 0 && value < static_cast<int32_t>(FontStyle::NONE)) {
200             buttonInfo.fontStyle = static_cast<FontStyle>(value);
201         }
202     }
203     JSRef<JSVal> family = pickerButtonParamObject->GetProperty("fontFamily");
204     std::vector<std::string> fontFamilies;
205     if (JSViewAbstract::ParseJsFontFamilies(family, fontFamilies)) {
206         buttonInfo.fontFamily = fontFamilies;
207     }
208 }
209 
ParseButtonStyle(const JSRef<JSObject>& pickerButtonParamObject)210 ButtonInfo ParseButtonStyle(const JSRef<JSObject>& pickerButtonParamObject)
211 {
212     ButtonInfo buttonInfo;
213     if (pickerButtonParamObject->GetProperty("type")->IsNumber()) {
214         auto buttonTypeIntValue = pickerButtonParamObject->GetProperty("type")->ToNumber<int32_t>();
215         if (buttonTypeIntValue == static_cast<int32_t>(ButtonType::CAPSULE) ||
216             buttonTypeIntValue == static_cast<int32_t>(ButtonType::CIRCLE) ||
217             buttonTypeIntValue == static_cast<int32_t>(ButtonType::ARC) ||
218             buttonTypeIntValue == static_cast<int32_t>(ButtonType::NORMAL) ||
219             buttonTypeIntValue == static_cast<int32_t>(ButtonType::ROUNDED_RECTANGLE)) {
220             buttonInfo.type = static_cast<ButtonType>(buttonTypeIntValue);
221         }
222     }
223     if (pickerButtonParamObject->GetProperty("style")->IsNumber()) {
224         auto styleModeIntValue = pickerButtonParamObject->GetProperty("style")->ToNumber<int32_t>();
225         if (styleModeIntValue >= static_cast<int32_t>(ButtonStyleMode::NORMAL) &&
226             styleModeIntValue <= static_cast<int32_t>(ButtonStyleMode::TEXT)) {
227             buttonInfo.buttonStyle = static_cast<ButtonStyleMode>(styleModeIntValue);
228         }
229     }
230     if (pickerButtonParamObject->GetProperty("role")->IsNumber()) {
231         auto buttonRoleIntValue = pickerButtonParamObject->GetProperty("role")->ToNumber<int32_t>();
232         if (buttonRoleIntValue >= static_cast<int32_t>(ButtonRole::NORMAL) &&
233             buttonRoleIntValue <= static_cast<int32_t>(ButtonRole::ERROR)) {
234             buttonInfo.role = static_cast<ButtonRole>(buttonRoleIntValue);
235         }
236     }
237     ParseFontOfButtonStyle(pickerButtonParamObject, buttonInfo);
238     Color backgroundColor;
239     if (JSViewAbstract::ParseJsColor(pickerButtonParamObject->GetProperty("backgroundColor"), backgroundColor)) {
240         buttonInfo.backgroundColor = backgroundColor;
241     }
242     auto radius = ParseBorderRadiusAttr(pickerButtonParamObject->GetProperty("borderRadius"));
243     if (radius.has_value()) {
244         buttonInfo.borderRadius = radius.value();
245     }
246 
247     auto primaryValue = pickerButtonParamObject->GetProperty("primary");
248     if (primaryValue->IsBoolean()) {
249         buttonInfo.isPrimary = primaryValue->ToBoolean();
250     }
251 
252     return buttonInfo;
253 }
254 
ParseButtonStyles(const JSRef<JSObject>& paramObject)255 std::vector<ButtonInfo> ParseButtonStyles(const JSRef<JSObject>& paramObject)
256 {
257     std::vector<ButtonInfo> buttonInfos;
258     auto acceptButtonStyle = paramObject->GetProperty("acceptButtonStyle");
259     if (acceptButtonStyle->IsObject()) {
260         auto acceptButtonStyleParamObject = JSRef<JSObject>::Cast(acceptButtonStyle);
261         buttonInfos.emplace_back(ParseButtonStyle(acceptButtonStyleParamObject));
262         buttonInfos[0].isAcceptButton = true;
263     } else {
264         ButtonInfo buttonInfo;
265         buttonInfos.emplace_back(buttonInfo);
266     }
267     auto cancelButtonStyle = paramObject->GetProperty("cancelButtonStyle");
268     if (cancelButtonStyle->IsObject()) {
269         auto cancelButtonStyleParamObject = JSRef<JSObject>::Cast(cancelButtonStyle);
270         buttonInfos.emplace_back(ParseButtonStyle(cancelButtonStyleParamObject));
271     }
272 
273     return buttonInfos;
274 }
275 
ParseDatePickerHoverMode(PickerDialogInfo& pickerDialog, const JSRef<JSObject>& paramObject)276 void ParseDatePickerHoverMode(PickerDialogInfo& pickerDialog, const JSRef<JSObject>& paramObject)
277 {
278     auto enableHoverModeValue = paramObject->GetProperty("enableHoverMode");
279     if (enableHoverModeValue->IsBoolean()) {
280         pickerDialog.enableHoverMode = enableHoverModeValue->ToBoolean();
281     }
282 
283     auto hoverModeAreaValue = paramObject->GetProperty("hoverModeArea");
284     if (hoverModeAreaValue->IsNumber()) {
285         auto hoverModeArea = hoverModeAreaValue->ToNumber<int32_t>();
286         if (hoverModeArea >= 0 && hoverModeArea < static_cast<int32_t>(HOVER_MODE_AREA_TYPE.size())) {
287             pickerDialog.hoverModeArea = HOVER_MODE_AREA_TYPE[hoverModeArea];
288         }
289     }
290 }
291 } // namespace
292 
JSBind(BindingTarget globalObj)293 void JSDatePicker::JSBind(BindingTarget globalObj)
294 {
295     JSClass<JSDatePicker>::Declare("DatePicker");
296     MethodOptions opt = MethodOptions::NONE;
297     JSClass<JSDatePicker>::StaticMethod("create", &JSDatePicker::Create, opt);
298     JSClass<JSDatePicker>::StaticMethod("lunar", &JSDatePicker::SetLunar);
299     JSClass<JSDatePicker>::StaticMethod("onChange", &JSDatePicker::OnChange);
300     JSClass<JSDatePicker>::StaticMethod("onDateChange", &JSDatePicker::OnDateChange);
301     JSClass<JSDatePicker>::StaticMethod("backgroundColor", &JSDatePicker::PickerBackgroundColor);
302     JSClass<JSDatePicker>::StaticMethod("opacity", &JSDatePicker::JsOpacity);
303     // keep compatible, need remove after
304     JSClass<JSDatePicker>::StaticMethod("useMilitaryTime", &JSDatePicker::UseMilitaryTime);
305     JSClass<JSDatePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
306     JSClass<JSDatePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
307     JSClass<JSDatePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
308     JSClass<JSDatePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
309     JSClass<JSDatePicker>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
310     JSClass<JSDatePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
311     JSClass<JSDatePicker>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
312     JSClass<JSDatePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
313     JSClass<JSDatePicker>::StaticMethod("disappearTextStyle", &JSDatePicker::SetDisappearTextStyle);
314     JSClass<JSDatePicker>::StaticMethod("textStyle", &JSDatePicker::SetTextStyle);
315     JSClass<JSDatePicker>::StaticMethod("selectedTextStyle", &JSDatePicker::SetSelectedTextStyle);
316     JSClass<JSDatePicker>::InheritAndBind<JSViewAbstract>(globalObj);
317 }
318 
Create(const JSCallbackInfo& info)319 void JSDatePicker::Create(const JSCallbackInfo& info)
320 {
321     DatePickerType pickerType = DatePickerType::DATE;
322     JSRef<JSObject> paramObject;
323     if (info.Length() >= 1 && info[0]->IsObject()) {
324         paramObject = JSRef<JSObject>::Cast(info[0]);
325         auto type = paramObject->GetProperty("type");
326         if (type->IsNumber()) {
327             pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
328         }
329     }
330     switch (pickerType) {
331         case DatePickerType::TIME: {
332             CreateTimePicker(info, paramObject);
333             break;
334         }
335         case DatePickerType::DATE: {
336             CreateDatePicker(info, paramObject);
337             break;
338         }
339         default: {
340             break;
341         }
342     }
343 }
344 
SetLunar(bool isLunar)345 void JSDatePicker::SetLunar(bool isLunar)
346 {
347     DatePickerModel::GetInstance()->SetShowLunar(isLunar);
348 }
349 
UseMilitaryTime(bool isUseMilitaryTime)350 void JSDatePicker::UseMilitaryTime(bool isUseMilitaryTime)
351 {
352     DatePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
353 }
354 
ParseTextProperties(const JSRef<JSObject>& paramObj, NG::PickerTextProperties& result)355 void JSDatePicker::ParseTextProperties(const JSRef<JSObject>& paramObj, NG::PickerTextProperties& result)
356 {
357     auto disappearProperty = paramObj->GetProperty("disappearTextStyle");
358     auto normalProperty = paramObj->GetProperty("textStyle");
359     auto selectedProperty = paramObj->GetProperty("selectedTextStyle");
360 
361     if (!disappearProperty->IsNull() && disappearProperty->IsObject()) {
362         JSRef<JSObject> disappearObj = JSRef<JSObject>::Cast(disappearProperty);
363         JSDatePicker::ParseTextStyle(disappearObj, result.disappearTextStyle_, "disappearTextStyle");
364     }
365 
366     if (!normalProperty->IsNull() && normalProperty->IsObject()) {
367         JSRef<JSObject> noramlObj = JSRef<JSObject>::Cast(normalProperty);
368         JSDatePicker::ParseTextStyle(noramlObj, result.normalTextStyle_, "textStyle");
369     }
370 
371     if (!selectedProperty->IsNull() && selectedProperty->IsObject()) {
372         JSRef<JSObject> selectedObj = JSRef<JSObject>::Cast(selectedProperty);
373         JSDatePicker::ParseTextStyle(selectedObj, result.selectedTextStyle_, "selectedTextStyle");
374     }
375 }
376 
IsUserDefinedFontFamily(const std::string& pos)377 void JSDatePicker::IsUserDefinedFontFamily(const std::string& pos)
378 {
379     if (pos == "disappearTextStyle") {
380         DatePickerModel::GetInstance()->HasUserDefinedDisappearFontFamily(true);
381     } else if (pos == "textStyle") {
382         DatePickerModel::GetInstance()->HasUserDefinedNormalFontFamily(true);
383     } else if (pos == "selectedTextStyle") {
384         DatePickerModel::GetInstance()->HasUserDefinedSelectedFontFamily(true);
385     } else if (pos == "disappearTextStyleTime") {
386         TimePickerModel::GetInstance()->HasUserDefinedDisappearFontFamily(true);
387     } else if (pos == "textStyleTime") {
388         TimePickerModel::GetInstance()->HasUserDefinedNormalFontFamily(true);
389     } else if (pos == "selectedTextStyleTime") {
390         TimePickerModel::GetInstance()->HasUserDefinedSelectedFontFamily(true);
391     }
392 }
393 
ParseTextStyle( const JSRef<JSObject>& paramObj, NG::PickerTextStyle& textStyle, const std::string& pos)394 void JSDatePicker::ParseTextStyle(
395     const JSRef<JSObject>& paramObj, NG::PickerTextStyle& textStyle, const std::string& pos)
396 {
397     auto fontColor = paramObj->GetProperty("color");
398     auto fontOptions = paramObj->GetProperty("font");
399 
400     Color textColor;
401     if (JSViewAbstract::ParseJsColor(fontColor, textColor)) {
402         textStyle.textColor = textColor;
403     }
404 
405     if (!fontOptions->IsObject()) {
406         return;
407     }
408     JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(fontOptions);
409     auto fontSize = fontObj->GetProperty("size");
410     auto fontWeight = fontObj->GetProperty("weight");
411     auto fontFamily = fontObj->GetProperty("family");
412     auto fontStyle = fontObj->GetProperty("style");
413     if (fontSize->IsNull() || fontSize->IsUndefined()) {
414         textStyle.fontSize = Dimension(-1);
415     } else {
416         CalcDimension size;
417         if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) {
418             textStyle.fontSize = Dimension(-1);
419         } else {
420             textStyle.fontSize = size;
421         }
422     }
423 
424     if (!fontWeight->IsNull() && !fontWeight->IsUndefined()) {
425         std::string weight;
426         if (fontWeight->IsNumber()) {
427             weight = std::to_string(fontWeight->ToNumber<int32_t>());
428         } else {
429             ParseJsString(fontWeight, weight);
430         }
431         textStyle.fontWeight = ConvertStrToFontWeight(weight);
432     }
433 
434     if (!fontFamily->IsNull() && !fontFamily->IsUndefined()) {
435         std::vector<std::string> families;
436         if (ParseJsFontFamilies(fontFamily, families)) {
437             textStyle.fontFamily = families;
438             IsUserDefinedFontFamily(pos);
439         }
440     }
441 
442     if (fontStyle->IsNumber()) {
443         auto style = fontStyle->ToNumber<int32_t>();
444         if (style < 0 || style > 1) {
445             return;
446         }
447         textStyle.fontStyle = static_cast<FontStyle>(style);
448     }
449 }
450 
SetDisappearTextStyle(const JSCallbackInfo& info)451 void JSDatePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
452 {
453     auto theme = GetTheme<PickerTheme>();
454     CHECK_NULL_VOID(theme);
455     NG::PickerTextStyle textStyle;
456     JSDatePickerTheme::ObtainTextStyle(textStyle);
457     if (info[0]->IsObject()) {
458         JSDatePicker::ParseTextStyle(info[0], textStyle, "disappearTextStyle");
459     }
460     DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
461 }
462 
SetTextStyle(const JSCallbackInfo& info)463 void JSDatePicker::SetTextStyle(const JSCallbackInfo& info)
464 {
465     auto theme = GetTheme<PickerTheme>();
466     CHECK_NULL_VOID(theme);
467     NG::PickerTextStyle textStyle;
468     JSDatePickerTheme::ObtainTextStyle(textStyle);
469     if (info[0]->IsObject()) {
470         JSDatePicker::ParseTextStyle(info[0], textStyle, "textStyle");
471     }
472     DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
473 }
474 
SetSelectedTextStyle(const JSCallbackInfo& info)475 void JSDatePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
476 {
477     auto theme = GetTheme<PickerTheme>();
478     CHECK_NULL_VOID(theme);
479     NG::PickerTextStyle textStyle;
480     JSDatePickerTheme::ObtainSelectedTextStyle(textStyle);
481     if (info[0]->IsObject()) {
482         JSDatePicker::ParseTextStyle(info[0], textStyle, "selectedTextStyle");
483     }
484     DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
485 }
486 
JsOpacity(const JSCallbackInfo& info)487 void JSDatePicker::JsOpacity(const JSCallbackInfo& info)
488 {
489     JSViewAbstract::JsOpacity(info);
490     DatePickerModel::GetInstance()->HasUserDefinedOpacity();
491 }
492 
OnChange(const JSCallbackInfo& info)493 void JSDatePicker::OnChange(const JSCallbackInfo& info)
494 {
495     if (!info[0]->IsFunction()) {
496         return;
497     }
498 
499     auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
500         JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
501     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
502     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
503                         const BaseEventInfo* info) {
504         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
505         ACE_SCORING_EVENT("datePicker.onChange");
506         PipelineContext::SetCallBackNode(node);
507         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
508         func->Execute(*eventInfo);
509     };
510     DatePickerModel::GetInstance()->SetOnChange(std::move(onChange));
511 }
512 
OnDateChange(const JSCallbackInfo& info)513 void JSDatePicker::OnDateChange(const JSCallbackInfo& info)
514 {
515     if (!info[0]->IsFunction()) {
516         return;
517     }
518     auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
519         JSRef<JSFunc>::Cast(info[0]), DatePickerDateChangeEventToJSValue);
520     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
521     auto onDateChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
522                             const BaseEventInfo* info) {
523         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
524         ACE_SCORING_EVENT("datePicker.onDateChange");
525         PipelineContext::SetCallBackNode(node);
526         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
527         func->Execute(*eventInfo);
528     };
529     DatePickerModel::GetInstance()->SetOnDateChange(std::move(onDateChange));
530 }
531 
OnChange(const JSCallbackInfo& info)532 void JSTimePicker::OnChange(const JSCallbackInfo& info)
533 {
534     if (!info[0]->IsFunction()) {
535         return;
536     }
537 
538     auto jsFunc = AceType::MakeRefPtr<JsEventFunction<DatePickerChangeEvent, 1>>(
539         JSRef<JSFunc>::Cast(info[0]), DatePickerChangeEventToJSValue);
540     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
541     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
542                         const BaseEventInfo* index) {
543         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
544         ACE_SCORING_EVENT("datePicker.onChange");
545         PipelineContext::SetCallBackNode(node);
546         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(index);
547         func->Execute(*eventInfo);
548     };
549     TimePickerModel::GetInstance()->SetOnChange(std::move(onChange));
550 }
551 
PickerBackgroundColor(const JSCallbackInfo& info)552 void JSDatePicker::PickerBackgroundColor(const JSCallbackInfo& info)
553 {
554     JSViewAbstract::JsBackgroundColor(info);
555 
556     if (info.Length() < 1) {
557         return;
558     }
559     Color backgroundColor;
560     if (!ParseJsColor(info[0], backgroundColor)) {
561         return;
562     }
563     DatePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
564 }
565 
ParseDate(const JSRef<JSVal>& dateVal)566 PickerDate JSDatePicker::ParseDate(const JSRef<JSVal>& dateVal)
567 {
568     auto pickerDate = PickerDate();
569     if (!dateVal->IsObject()) {
570         return pickerDate;
571     }
572     auto dateObj = JSRef<JSObject>::Cast(dateVal);
573     auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
574     auto monthFuncJsVal = dateObj->GetProperty("getMonth");
575     auto dateFuncJsVal = dateObj->GetProperty("getDate");
576     if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
577         return pickerDate;
578     }
579     auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
580     auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
581     auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
582     JSRef<JSVal> year = yearFunc->Call(dateObj);
583     JSRef<JSVal> month = monthFunc->Call(dateObj);
584     JSRef<JSVal> date = dateFunc->Call(dateObj);
585 
586     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
587         pickerDate.SetYear(year->ToNumber<int32_t>());
588         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
589         pickerDate.SetDay(date->ToNumber<int32_t>());
590     }
591     return pickerDate;
592 }
593 
ParseTime(const JSRef<JSVal>& timeVal)594 PickerTime JSDatePicker::ParseTime(const JSRef<JSVal>& timeVal)
595 {
596     auto pickerTime = PickerTime();
597     if (!timeVal->IsObject()) {
598         return pickerTime;
599     }
600     auto timeObj = JSRef<JSObject>::Cast(timeVal);
601     auto hourFuncJsVal = timeObj->GetProperty("getHours");
602     auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
603     auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
604     if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
605         return pickerTime;
606     }
607     auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
608     auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
609     auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
610     JSRef<JSVal> hour = hourFunc->Call(timeObj);
611     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
612     JSRef<JSVal> second = secondFunc->Call(timeObj);
613 
614     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
615         pickerTime.SetHour(hour->ToNumber<int32_t>());
616         pickerTime.SetMinute(minute->ToNumber<int32_t>());
617         pickerTime.SetSecond(second->ToNumber<int32_t>());
618     }
619     return pickerTime;
620 }
621 
ParseSelectedDateTimeObject(const JSCallbackInfo& info, const JSRef<JSObject>& selectedObject, bool isDatePicker)622 void ParseSelectedDateTimeObject(const JSCallbackInfo& info, const JSRef<JSObject>& selectedObject, bool isDatePicker)
623 {
624     JSRef<JSVal> changeEventVal = selectedObject->GetProperty("changeEvent");
625     if (changeEventVal->IsUndefined() || !changeEventVal->IsFunction()) {
626         return;
627     }
628     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
629     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
630     auto changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc),
631                            node = targetNode, isDatePicker](const BaseEventInfo* info) {
632         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
633         ACE_SCORING_EVENT("DatePicker.SelectedDateTimeChangeEvent");
634         const auto* eventInfo = TypeInfoHelper::DynamicCast<DatePickerChangeEvent>(info);
635         CHECK_NULL_VOID(eventInfo);
636         auto selectedStr = eventInfo->GetSelectedStr();
637         auto sourceJson = JsonUtil::ParseJsonString(selectedStr);
638         if (!sourceJson || sourceJson->IsNull()) {
639             return;
640         }
641 
642         auto dateObj = JSDatePickerDialog::GetDateObj(sourceJson, isDatePicker);
643         PipelineContext::SetCallBackNode(node);
644         func->ExecuteJS(1, &dateObj);
645     };
646     if (isDatePicker) {
647         DatePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
648     } else {
649         TimePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
650     }
651 }
652 
CreateDatePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)653 void JSDatePicker::CreateDatePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
654 {
655     auto theme = GetTheme<PickerTheme>();
656     CHECK_NULL_VOID(theme);
657     JSRef<JSVal> startDate;
658     JSRef<JSVal> endDate;
659     JSRef<JSVal> selectedDate;
660     if (!paramObj->IsUndefined()) {
661         startDate = paramObj->GetProperty("start");
662         endDate = paramObj->GetProperty("end");
663         selectedDate = paramObj->GetProperty("selected");
664     }
665     auto parseStartDate = ParseDate(startDate);
666     auto parseEndDate = ParseDate(endDate);
667     if (parseStartDate.GetYear() <= 0) {
668         parseStartDate = theme->GetDefaultStartDate();
669     }
670     if (parseEndDate.GetYear() <= 0) {
671         parseEndDate = theme->GetDefaultEndDate();
672     }
673     auto startDays = parseStartDate.ToDays();
674     auto endDays = parseEndDate.ToDays();
675     if (startDays > endDays) {
676         parseStartDate = theme->GetDefaultStartDate();
677         parseEndDate = theme->GetDefaultEndDate();
678     }
679     DatePickerModel::GetInstance()->CreateDatePicker(theme);
680     if (startDate->IsObject()) {
681         DatePickerModel::GetInstance()->SetStartDate(parseStartDate);
682     }
683     if (endDate->IsObject()) {
684         DatePickerModel::GetInstance()->SetEndDate(parseEndDate);
685     }
686     if (selectedDate->IsObject()) {
687         JSRef<JSObject> selectedDateObj = JSRef<JSObject>::Cast(selectedDate);
688         JSRef<JSVal> changeEventVal = selectedDateObj->GetProperty("changeEvent");
689         PickerDate parseSelectedDate;
690         if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
691             ParseSelectedDateTimeObject(info, selectedDateObj, true);
692             parseSelectedDate = ParseDate(selectedDateObj->GetProperty("value"));
693         } else {
694             parseSelectedDate = ParseDate(selectedDate);
695         }
696         DatePickerModel::GetInstance()->SetSelectedDate(parseSelectedDate);
697     }
698     if (!JSDatePickerTheme::ApplyTheme()) {
699         SetDefaultAttributes();
700     }
701 }
702 
SetDefaultAttributes()703 void JSDatePicker::SetDefaultAttributes()
704 {
705     auto theme = GetTheme<PickerTheme>();
706     CHECK_NULL_VOID(theme);
707     NG::PickerTextStyle textStyle;
708     auto selectedStyle = theme->GetOptionStyle(true, false);
709     textStyle.textColor = selectedStyle.GetTextColor();
710     textStyle.fontSize = selectedStyle.GetFontSize();
711     textStyle.fontWeight = selectedStyle.GetFontWeight();
712     DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
713 
714     auto disappearStyle = theme->GetDisappearOptionStyle();
715     textStyle.textColor = disappearStyle.GetTextColor();
716     textStyle.fontSize = disappearStyle.GetFontSize();
717     textStyle.fontWeight = disappearStyle.GetFontWeight();
718     DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
719 
720     auto normalStyle = theme->GetOptionStyle(false, false);
721     textStyle.textColor = normalStyle.GetTextColor();
722     textStyle.fontSize = normalStyle.GetFontSize();
723     textStyle.fontWeight = normalStyle.GetFontWeight();
724     DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
725 }
726 
CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)727 void JSDatePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
728 {
729     auto theme = GetTheme<PickerTheme>();
730     CHECK_NULL_VOID(theme);
731     DatePickerModel::GetInstance()->CreateTimePicker(theme);
732     auto selectedTime = paramObj->GetProperty("selected");
733     if (selectedTime->IsObject()) {
734         JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
735         JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
736         if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
737             ParseSelectedDateTimeObject(info, selectedTimeObj, true);
738             auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
739             DatePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
740         } else {
741             DatePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
742         }
743     }
744 }
745 
JSBind(BindingTarget globalObj)746 void JSDatePickerDialog::JSBind(BindingTarget globalObj)
747 {
748     JSClass<JSDatePickerDialog>::Declare("DatePickerDialog");
749     JSClass<JSDatePickerDialog>::StaticMethod("show", &JSDatePickerDialog::Show);
750 
751     JSClass<JSDatePickerDialog>::Bind<>(globalObj);
752 }
753 
DatePickerDialogAppearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent)754 void DatePickerDialogAppearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent)
755 {
756     std::function<void()> didAppearEvent;
757     std::function<void()> willAppearEvent;
758     if (info.Length() == 0 || !info[0]->IsObject()) {
759         return;
760     }
761     auto paramObject = JSRef<JSObject>::Cast(info[0]);
762     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
763     auto onDidAppear = paramObject->GetProperty("onDidAppear");
764     if (!onDidAppear->IsUndefined() && onDidAppear->IsFunction()) {
765         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidAppear));
766         didAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
767             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
768             ACE_SCORING_EVENT("DatePickerDialog.onDidAppear");
769             PipelineContext::SetCallBackNode(node);
770             func->Execute();
771         };
772     }
773     auto onWillAppear = paramObject->GetProperty("onWillAppear");
774     if (!onWillAppear->IsUndefined() && onWillAppear->IsFunction()) {
775         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillAppear));
776         willAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
777             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
778             ACE_SCORING_EVENT("DatePickerDialog.onWillAppear");
779             PipelineContext::SetCallBackNode(node);
780             func->Execute();
781         };
782     }
783     pickerDialogEvent.onDidAppear = std::move(didAppearEvent);
784     pickerDialogEvent.onWillAppear = std::move(willAppearEvent);
785 }
786 
DatePickerDialogDisappearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent)787 void DatePickerDialogDisappearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent)
788 {
789     std::function<void()> didDisappearEvent;
790     std::function<void()> willDisappearEvent;
791     if (info.Length() == 0 || !info[0]->IsObject()) {
792         return;
793     }
794     auto paramObject = JSRef<JSObject>::Cast(info[0]);
795     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
796     auto onDidDisappear = paramObject->GetProperty("onDidDisappear");
797     if (!onDidDisappear->IsUndefined() && onDidDisappear->IsFunction()) {
798         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidDisappear));
799         didDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
800             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
801             ACE_SCORING_EVENT("DatePickerDialog.onDidDisappear");
802             PipelineContext::SetCallBackNode(node);
803             func->Execute();
804         };
805     }
806     auto onWillDisappear = paramObject->GetProperty("onWillDisappear");
807     if (!onWillDisappear->IsUndefined() && onWillDisappear->IsFunction()) {
808         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDisappear));
809         willDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
810             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
811             ACE_SCORING_EVENT("DatePickerDialog.onWillDisappear");
812             PipelineContext::SetCallBackNode(node);
813             func->Execute();
814         };
815     }
816     pickerDialogEvent.onDidDisappear = std::move(didDisappearEvent);
817     pickerDialogEvent.onWillDisappear = std::move(willDisappearEvent);
818 }
819 
GetDateChangeEvent(const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)820 std::function<void(const std::string&)> JSDatePickerDialog::GetDateChangeEvent(const JSRef<JSObject>& paramObject,
821     const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)
822 {
823     std::function<void(const std::string&)> dateChangeEvent;
824     auto onDateChange = paramObject->GetProperty("onDateChange");
825     if (!onDateChange->IsUndefined() && onDateChange->IsFunction()) {
826         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateChange));
827         dateChangeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
828                               node = frameNode](const std::string& info) {
829             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
830             ACE_SCORING_EVENT("DatePickerDialog.onDateChange");
831             auto selectedJson = JsonUtil::ParseJsonString(info);
832             if (!selectedJson || selectedJson->IsNull()) {
833                 return;
834             }
835             auto dateObj = GetDateObj(selectedJson);
836             PipelineContext::SetCallBackNode(node);
837             func->ExecuteJS(1, &dateObj);
838         };
839     }
840     return dateChangeEvent;
841 }
842 
GetDateAcceptEvent(const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)843 std::function<void(const std::string&)> JSDatePickerDialog::GetDateAcceptEvent(const JSRef<JSObject>& paramObject,
844     const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)
845 {
846     std::function<void(const std::string&)> dateAcceptEvent;
847     auto onDateAccept = paramObject->GetProperty("onDateAccept");
848     if (!onDateAccept->IsUndefined() && onDateAccept->IsFunction()) {
849         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDateAccept));
850         dateAcceptEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
851                               node = frameNode](const std::string& info) {
852             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
853             ACE_SCORING_EVENT("DatePickerDialog.onDateAccept");
854             auto selectedJson = JsonUtil::ParseJsonString(info);
855             if (!selectedJson || selectedJson->IsNull()) {
856                 return;
857             }
858             auto dateObj = GetDateObj(selectedJson);
859             PipelineContext::SetCallBackNode(node);
860             func->ExecuteJS(1, &dateObj);
861         };
862     }
863     return dateAcceptEvent;
864 }
865 
GetDateObj(const std::unique_ptr<JsonValue>& selectedJson, bool isDatePicker)866 JsiRef<JsiValue> JSDatePickerDialog::GetDateObj(const std::unique_ptr<JsonValue>& selectedJson, bool isDatePicker)
867 {
868     std::tm dateTime = { 0 };
869     auto year = selectedJson->GetValue("year");
870     if (year && year->IsNumber()) {
871         dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
872     }
873     auto month = selectedJson->GetValue("month");
874     if (month && month->IsNumber()) {
875         dateTime.tm_mon = month->GetInt();
876     }
877     auto day = selectedJson->GetValue("day");
878     if (day && day->IsNumber()) {
879         dateTime.tm_mday = day->GetInt();
880     }
881     auto hour = selectedJson->GetValue("hour");
882     if (hour && hour->IsNumber()) {
883         dateTime.tm_hour = hour->GetInt();
884     }
885     auto minute = selectedJson->GetValue("minute");
886     if (minute && minute->IsNumber()) {
887         dateTime.tm_min = minute->GetInt();
888     }
889     auto second = selectedJson->GetValue("second");
890     if (second && second->IsNumber()) {
891         dateTime.tm_sec = second->GetInt();
892     }
893     if (!isDatePicker) {
894         auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime);
895         auto dateObj = JSDate::New(milliseconds);
896         return dateObj;
897     }
898     auto timestamp = std::chrono::system_clock::from_time_t(std::mktime(&dateTime));
899     auto duration = timestamp.time_since_epoch();
900     auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
901     auto dateObj = JSDate::New(milliseconds);
902     return dateObj;
903 }
904 
GetChangeEvent(const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)905 std::function<void(const std::string&)> JSDatePickerDialog::GetChangeEvent(const JSRef<JSObject>& paramObject,
906     const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr<NG::FrameNode>& frameNode)
907 {
908     std::function<void(const std::string&)> changeEvent;
909     auto onChange = paramObject->GetProperty("onChange");
910     if (!onChange->IsUndefined() && onChange->IsFunction()) {
911         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
912         changeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc),
913                           node = frameNode](const std::string& info) {
914             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
915             std::vector<std::string> keys;
916             keys = { "year", "month", "day" };
917             ACE_SCORING_EVENT("DatePickerDialog.onChange");
918             PipelineContext::SetCallBackNode(node);
919             func->Execute(keys, info);
920         };
921     }
922     return changeEvent;
923 }
924 
GetAcceptEvent( const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const WeakPtr<NG::FrameNode>& frameNode)925 std::function<void(const std::string&)> JSDatePickerDialog::GetAcceptEvent(
926     const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const WeakPtr<NG::FrameNode>& frameNode)
927 {
928     std::function<void(const std::string&)> acceptEvent;
929     auto onAccept = paramObject->GetProperty("onAccept");
930     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
931         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
932         acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode](
933                           const std::string& info) {
934             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
935             std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
936             ACE_SCORING_EVENT("DatePickerDialog.onAccept");
937             PipelineContext::SetCallBackNode(node);
938             func->Execute(keys, info);
939         };
940     }
941     return acceptEvent;
942 }
943 
GetCancelEvent( const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const WeakPtr<NG::FrameNode>& frameNode)944 std::function<void()> JSDatePickerDialog::GetCancelEvent(
945     const JSRef<JSObject>& paramObject, const JSCallbackInfo& info, const WeakPtr<NG::FrameNode>& frameNode)
946 {
947     std::function<void()> cancelEvent;
948     auto onCancel = paramObject->GetProperty("onCancel");
949     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
950         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
951         cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() {
952             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
953             ACE_SCORING_EVENT("DatePickerDialog.onCancel");
954             PipelineContext::SetCallBackNode(node);
955             func->Execute();
956         };
957     }
958     return cancelEvent;
959 }
960 
UpdateLunarSwitchSettingData( const JSRef<JSObject>& paramObject, NG::DatePickerSettingData& settingData)961 void JSDatePickerDialog::UpdateLunarSwitchSettingData(
962     const JSRef<JSObject>& paramObject, NG::DatePickerSettingData& settingData)
963 {
964     auto selectedColorValue = paramObject->GetProperty("selectedColor");
965     auto unselectedColorValue = paramObject->GetProperty("unselectedColor");
966     auto strokeColorValue = paramObject->GetProperty("strokeColor");
967     Color selectedColor;
968     if (JSViewAbstract::ParseJsColor(selectedColorValue, selectedColor)) {
969         settingData.checkboxSettingData.selectedColor = selectedColor;
970     }
971     Color unselectedColor;
972     if (JSViewAbstract::ParseJsColor(unselectedColorValue, unselectedColor)) {
973         settingData.checkboxSettingData.unselectedColor = unselectedColor;
974     }
975     Color strokeColor;
976     if (JSViewAbstract::ParseJsColor(strokeColorValue, strokeColor)) {
977         settingData.checkboxSettingData.strokeColor = strokeColor;
978     }
979 }
980 
UpdateDatePickerSettingData( const JSRef<JSObject>& paramObject, NG::DatePickerSettingData& settingData)981 void JSDatePickerDialog::UpdateDatePickerSettingData(
982     const JSRef<JSObject>& paramObject, NG::DatePickerSettingData& settingData)
983 {
984     auto lunar = paramObject->GetProperty("lunar");
985     auto lunarSwitch = paramObject->GetProperty("lunarSwitch");
986     auto sTime = paramObject->GetProperty("showTime");
987     auto useMilitary = paramObject->GetProperty("useMilitaryTime");
988     settingData.isLunar = lunar->ToBoolean();
989     settingData.lunarswitch = lunarSwitch->ToBoolean();
990     if (settingData.lunarswitch) {
991         auto lunarSwitchStyle = paramObject->GetProperty("lunarSwitchStyle");
992         if ((!lunarSwitchStyle->IsUndefined()) && lunarSwitchStyle->IsObject()) {
993             auto style = JSRef<JSObject>::Cast(lunarSwitchStyle);
994             UpdateLunarSwitchSettingData(style, settingData);
995         }
996     }
997     settingData.showTime = sTime->ToBoolean();
998     settingData.useMilitary = useMilitary->ToBoolean();
999     auto dateTimeOptionsValue = paramObject->GetProperty("dateTimeOptions");
1000     if (dateTimeOptionsValue->IsObject()) {
1001         auto dateTimeOptionsObj = JSRef<JSObject>::Cast(dateTimeOptionsValue);
1002         JSDatePickerDialog::ParseDateTimeOptions(dateTimeOptionsObj, settingData.dateTimeOptions);
1003     }
1004     JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
1005 }
1006 
UpdatePickerDialogTimeInfo(const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)1007 void JSDatePickerDialog::UpdatePickerDialogTimeInfo(const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)
1008 {
1009     auto theme = GetTheme<PickerTheme>();
1010     CHECK_NULL_VOID(theme);
1011 
1012     auto startDate = paramObject->GetProperty("start");
1013     if (startDate->IsObject()) {
1014         pickerDialog.isStartDate = true;
1015     }
1016     auto endDate = paramObject->GetProperty("end");
1017     if (endDate->IsObject()) {
1018         pickerDialog.isEndDate = true;
1019     }
1020     auto selectedDate = paramObject->GetProperty("selected");
1021     if (selectedDate->IsObject()) {
1022         pickerDialog.isSelectedDate = true;
1023     }
1024     auto parseStartDate = ParseDate(startDate);
1025     auto parseEndDate = ParseDate(endDate);
1026     if (parseStartDate.GetYear() <= 0) {
1027         parseStartDate = theme->GetDefaultStartDate();
1028     }
1029     if (parseEndDate.GetYear() <= 0) {
1030         parseEndDate = theme->GetDefaultEndDate();
1031     }
1032     auto startDays = parseStartDate.ToDays();
1033     auto endDays = parseEndDate.ToDays();
1034     if (startDays > endDays) {
1035         parseStartDate = theme->GetDefaultStartDate();
1036         parseEndDate = theme->GetDefaultEndDate();
1037     }
1038     pickerDialog.parseStartDate = parseStartDate;
1039     pickerDialog.parseEndDate = parseEndDate;
1040     pickerDialog.parseSelectedDate = ParseDate(selectedDate);
1041     pickerDialog.pickerTime = ParseTime(selectedDate);
1042 }
1043 
UpdatePickerDialogPositionInfo( const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)1044 void JSDatePickerDialog::UpdatePickerDialogPositionInfo(
1045     const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)
1046 {
1047     // Parse alignment
1048     auto alignmentValue = paramObject->GetProperty("alignment");
1049     if (alignmentValue->IsNumber()) {
1050         auto alignment = alignmentValue->ToNumber<int32_t>();
1051         if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
1052             pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
1053         }
1054         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1055             if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
1056                 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
1057                 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
1058                 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
1059             }
1060         }
1061     }
1062 
1063     // Parse offset
1064     auto offsetValue = paramObject->GetProperty("offset");
1065     if (offsetValue->IsObject()) {
1066         auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
1067         CalcDimension dx;
1068         auto dxValue = offsetObj->GetProperty("dx");
1069         ParseJsDimensionVp(dxValue, dx);
1070         CalcDimension dy;
1071         auto dyValue = offsetObj->GetProperty("dy");
1072         ParseJsDimensionVp(dyValue, dy);
1073         pickerDialog.offset = DimensionOffset(dx, dy);
1074     }
1075 }
1076 
UpdatePickerDialogInfo(const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)1077 void JSDatePickerDialog::UpdatePickerDialogInfo(const JSRef<JSObject>& paramObject, PickerDialogInfo& pickerDialog)
1078 {
1079     UpdatePickerDialogTimeInfo(paramObject, pickerDialog);
1080     UpdatePickerDialogPositionInfo(paramObject, pickerDialog);
1081     // Parse maskRect.
1082     auto maskRectValue = paramObject->GetProperty("maskRect");
1083     DimensionRect maskRect;
1084     if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
1085         pickerDialog.maskRect = maskRect;
1086     }
1087 
1088     auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
1089     Color backgroundColor;
1090     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
1091         pickerDialog.backgroundColor = backgroundColor;
1092     }
1093 
1094     auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
1095     if (backgroundBlurStyle->IsNumber()) {
1096         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
1097         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
1098             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
1099             pickerDialog.backgroundBlurStyle = blurStyle;
1100         }
1101     }
1102 
1103     auto shadowValue = paramObject->GetProperty("shadow");
1104     Shadow shadow;
1105     if ((shadowValue->IsObject() || shadowValue->IsNumber()) && JSViewAbstract::ParseShadowProps(shadowValue, shadow)) {
1106         pickerDialog.shadow = shadow;
1107     }
1108 
1109     ParseDatePickerHoverMode(pickerDialog, paramObject);
1110 }
1111 
Show(const JSCallbackInfo& info)1112 void JSDatePickerDialog::Show(const JSCallbackInfo& info)
1113 {
1114     auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
1115     CHECK_NULL_VOID(scopedDelegate);
1116     if (!info[0]->IsObject()) {
1117         return;
1118     }
1119 
1120     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1121     DatePickerType pickerType = DatePickerType::DATE;
1122     auto type = paramObject->GetProperty("type");
1123     if (type->IsNumber()) {
1124         pickerType = static_cast<DatePickerType>(type->ToNumber<int32_t>());
1125     }
1126     std::function<void()> cancelEvent;
1127     std::function<void(const std::string&)> acceptEvent;
1128     std::function<void(const std::string&)> changeEvent;
1129     std::function<void(const std::string&)> dateChangeEvent;
1130     std::function<void(const std::string&)> dateAcceptEvent;
1131     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1132     changeEvent = GetChangeEvent(paramObject, info, pickerType, frameNode);
1133     acceptEvent = GetAcceptEvent(paramObject, info, frameNode);
1134     cancelEvent = GetCancelEvent(paramObject, info, frameNode);
1135     dateChangeEvent = GetDateChangeEvent(paramObject, info, pickerType, frameNode);
1136     dateAcceptEvent = GetDateAcceptEvent(paramObject, info, pickerType, frameNode);
1137     NG::DatePickerSettingData settingData;
1138     UpdateDatePickerSettingData(paramObject, settingData);
1139     PickerDialogInfo pickerDialog;
1140     UpdatePickerDialogInfo(paramObject, pickerDialog);
1141 
1142     auto buttonInfos = ParseButtonStyles(paramObject);
1143     PickerDialogEvent pickerDialogEvent { nullptr, nullptr, nullptr, nullptr };
1144     DatePickerDialogAppearEvent(info, pickerDialogEvent);
1145     DatePickerDialogDisappearEvent(info, pickerDialogEvent);
1146     DatePickerDialogModel::GetInstance()->SetDatePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent),
1147         std::move(acceptEvent), std::move(changeEvent), std::move(dateAcceptEvent), std::move(dateChangeEvent),
1148         pickerType, pickerDialogEvent, buttonInfos);
1149 }
1150 
DatePickerDialogShow(const JSRef<JSObject>& paramObj, const std::map<std::string, NG::DialogEvent>& dialogEvent, const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)1151 void JSDatePickerDialog::DatePickerDialogShow(const JSRef<JSObject>& paramObj,
1152     const std::map<std::string, NG::DialogEvent>& dialogEvent,
1153     const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
1154 {
1155     auto container = Container::CurrentSafely();
1156     if (!container) {
1157         return;
1158     }
1159     auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1160     if (!pipelineContext) {
1161         return;
1162     }
1163 
1164     auto executor = pipelineContext->GetTaskExecutor();
1165     if (!executor) {
1166         return;
1167     }
1168 
1169     NG::DatePickerSettingData settingData;
1170     auto startDate = paramObj->GetProperty("start");
1171     auto endDate = paramObj->GetProperty("end");
1172     auto selectedDate = paramObj->GetProperty("selected");
1173     auto lunar = paramObj->GetProperty("lunar");
1174     auto sTime = paramObj->GetProperty("showTime");
1175     auto useMilitary = paramObj->GetProperty("useMilitaryTime");
1176     settingData.isLunar = lunar->ToBoolean();
1177     settingData.showTime = sTime->ToBoolean();
1178     settingData.useMilitary = useMilitary->ToBoolean();
1179     auto parseStartDate = ParseDate(startDate);
1180     auto parseEndDate = ParseDate(endDate);
1181     auto parseSelectedDate = ParseDate(selectedDate);
1182 
1183     auto theme = GetTheme<DialogTheme>();
1184     CHECK_NULL_VOID(theme);
1185 
1186     DialogProperties properties;
1187     properties.alignment = theme->GetAlignment();
1188     if (properties.alignment == DialogAlignment::BOTTOM &&
1189         Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) {
1190         properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1191     }
1192     properties.customStyle = false;
1193     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1194         properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1195     }
1196 
1197     std::map<std::string, PickerDate> datePickerProperty;
1198     std::map<std::string, PickerTime> timePickerProperty;
1199     if (startDate->IsObject()) {
1200         settingData.datePickerProperty["start"] = parseStartDate;
1201     }
1202     if (endDate->IsObject()) {
1203         settingData.datePickerProperty["end"] = parseEndDate;
1204     }
1205     if (selectedDate->IsObject()) {
1206         settingData.datePickerProperty["selected"] = parseSelectedDate;
1207         settingData.timePickerProperty["selected"] = ParseTime(selectedDate);
1208     }
1209 
1210     JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
1211     auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
1212     auto overlayManager = context ? context->GetOverlayManager() : nullptr;
1213     executor->PostTask(
1214         [properties, settingData, dialogEvent, dialogCancelEvent, weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
1215             auto overlayManager = weak.Upgrade();
1216             CHECK_NULL_VOID(overlayManager);
1217             overlayManager->ShowDateDialog(properties, settingData, dialogEvent, dialogCancelEvent);
1218         },
1219         TaskExecutor::TaskType::UI, "ArkUIDialogShowDatePicker");
1220 }
1221 
CreateDatePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)1222 void JSDatePickerDialog::CreateDatePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
1223 {
1224     auto datePicker = AceType::MakeRefPtr<PickerDateComponent>();
1225     auto startDate = paramObj->GetProperty("start");
1226     auto endDate = paramObj->GetProperty("end");
1227     auto selectedDate = paramObj->GetProperty("selected");
1228     auto lunar = paramObj->GetProperty("lunar");
1229     bool isLunar = lunar->ToBoolean();
1230     auto parseStartDate = ParseDate(startDate);
1231     auto parseEndDate = ParseDate(endDate);
1232     auto parseSelectedDate = ParseDate(selectedDate);
1233     auto startDays = parseStartDate.ToDays();
1234     auto endDays = parseEndDate.ToDays();
1235     if (startDays > endDays) {
1236         parseStartDate.SetYear(0);
1237         parseEndDate.SetYear(0);
1238     }
1239     if (startDate->IsObject()) {
1240         datePicker->SetStartDate(parseStartDate);
1241     }
1242     if (endDate->IsObject()) {
1243         datePicker->SetEndDate(parseEndDate);
1244     }
1245     if (selectedDate->IsObject()) {
1246         datePicker->SetSelectedDate(parseSelectedDate);
1247     }
1248     datePicker->SetIsDialog(true);
1249     datePicker->SetIsCreateDialogComponent(true);
1250     datePicker->SetShowLunar(isLunar);
1251 
1252     component = datePicker;
1253 }
1254 
CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)1255 void JSDatePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
1256 {
1257     auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
1258     auto selectedTime = paramObj->GetProperty("selected");
1259     auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1260     bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
1261     if (selectedTime->IsObject()) {
1262         timePicker->SetSelectedTime(ParseTime(selectedTime));
1263     }
1264     timePicker->SetIsDialog(true);
1265     timePicker->SetIsCreateDialogComponent(true);
1266     timePicker->SetHour24(isUseMilitaryTime);
1267     component = timePicker;
1268 }
1269 
ParseDate(const JSRef<JSVal>& dateVal)1270 PickerDate JSDatePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
1271 {
1272     auto pickerDate = PickerDate();
1273     if (!dateVal->IsObject()) {
1274         return pickerDate;
1275     }
1276     auto dateObj = JSRef<JSObject>::Cast(dateVal);
1277     auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
1278     auto monthFuncJsVal = dateObj->GetProperty("getMonth");
1279     auto dateFuncJsVal = dateObj->GetProperty("getDate");
1280     if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
1281         return pickerDate;
1282     }
1283     auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1284     auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
1285     auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
1286     JSRef<JSVal> year = yearFunc->Call(dateObj);
1287     JSRef<JSVal> month = monthFunc->Call(dateObj);
1288     JSRef<JSVal> date = dateFunc->Call(dateObj);
1289 
1290     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
1291         pickerDate.SetYear(year->ToNumber<int32_t>());
1292         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
1293         pickerDate.SetDay(date->ToNumber<int32_t>());
1294     }
1295     return pickerDate;
1296 }
1297 
ParseTime(const JSRef<JSVal>& timeVal)1298 PickerTime JSDatePickerDialog::ParseTime(const JSRef<JSVal>& timeVal)
1299 {
1300     auto pickerTime = PickerTime();
1301     if (!timeVal->IsObject()) {
1302         return pickerTime;
1303     }
1304     auto timeObj = JSRef<JSObject>::Cast(timeVal);
1305     auto hourFuncJsVal = timeObj->GetProperty("getHours");
1306     auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1307     auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1308     if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1309         return pickerTime;
1310     }
1311     auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1312     auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1313     auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1314     JSRef<JSVal> hour = hourFunc->Call(timeObj);
1315     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1316     JSRef<JSVal> second = secondFunc->Call(timeObj);
1317 
1318     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1319         pickerTime.SetHour(hour->ToNumber<int32_t>());
1320         pickerTime.SetMinute(minute->ToNumber<int32_t>());
1321         pickerTime.SetSecond(second->ToNumber<int32_t>());
1322     }
1323     return pickerTime;
1324 }
1325 
ParseDateTimeOptions(const JSRef<JSObject>& paramObj, DateTimeType& dateTimeOptions)1326 void JSDatePickerDialog::ParseDateTimeOptions(const JSRef<JSObject>& paramObj, DateTimeType& dateTimeOptions)
1327 {
1328     dateTimeOptions.hourType = ZeroPrefixType::AUTO;
1329     dateTimeOptions.minuteType = ZeroPrefixType::AUTO;
1330     dateTimeOptions.secondType = ZeroPrefixType::AUTO;
1331 
1332     auto hourValue = paramObj->GetProperty(TIMEPICKER_OPTIONS_HOUR);
1333     if (hourValue->IsString()) {
1334         std::string hour = hourValue->ToString();
1335         if (hour == TIMEPICKER_OPTIONS_TWO_DIGIT_VAL) {
1336             dateTimeOptions.hourType = ZeroPrefixType::SHOW;
1337         } else if (hour == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1338             dateTimeOptions.hourType = ZeroPrefixType::HIDE;
1339         }
1340     }
1341     auto minuteValue = paramObj->GetProperty(TIMEPICKER_OPTIONS_MINUTE);
1342     if (minuteValue->IsString()) {
1343         dateTimeOptions.minuteType = ZeroPrefixType::SHOW;
1344         std::string minute = minuteValue->ToString();
1345         if (minute == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1346             dateTimeOptions.minuteType = ZeroPrefixType::HIDE;
1347         }
1348     }
1349 }
1350 
JSBind(BindingTarget globalObj)1351 void JSTimePicker::JSBind(BindingTarget globalObj)
1352 {
1353     JSClass<JSTimePicker>::Declare("TimePicker");
1354     MethodOptions opt = MethodOptions::NONE;
1355     JSClass<JSTimePicker>::StaticMethod("create", &JSTimePicker::Create, opt);
1356     JSClass<JSTimePicker>::StaticMethod("onChange", &JSTimePicker::OnChange);
1357     JSClass<JSTimePicker>::StaticMethod("backgroundColor", &JSTimePicker::PickerBackgroundColor);
1358     JSClass<JSTimePicker>::StaticMethod("loop", &JSTimePicker::Loop);
1359     JSClass<JSTimePicker>::StaticMethod("useMilitaryTime", &JSTimePicker::UseMilitaryTime);
1360     JSClass<JSTimePicker>::StaticMethod("enableHapticFeedback", &JSTimePicker::EnableHapticFeedback);
1361     JSClass<JSTimePicker>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
1362     JSClass<JSTimePicker>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
1363     JSClass<JSTimePicker>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
1364     JSClass<JSTimePicker>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
1365     JSClass<JSTimePicker>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
1366     JSClass<JSTimePicker>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
1367     JSClass<JSTimePicker>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
1368     JSClass<JSTimePicker>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
1369     JSClass<JSTimePicker>::StaticMethod("disappearTextStyle", &JSTimePicker::SetDisappearTextStyle);
1370     JSClass<JSTimePicker>::StaticMethod("textStyle", &JSTimePicker::SetTextStyle);
1371     JSClass<JSTimePicker>::StaticMethod("selectedTextStyle", &JSTimePicker::SetSelectedTextStyle);
1372     JSClass<JSTimePicker>::StaticMethod("dateTimeOptions", &JSTimePicker::DateTimeOptions);
1373     JSClass<JSTimePicker>::StaticMethod("opacity", &JSTimePicker::JsOpacity);
1374     JSClass<JSTimePicker>::InheritAndBind<JSViewAbstract>(globalObj);
1375 }
1376 
Create(const JSCallbackInfo& info)1377 void JSTimePicker::Create(const JSCallbackInfo& info)
1378 {
1379     JSRef<JSObject> paramObject = JSRef<JSObject>::New();
1380     if (info.Length() >= 1 && info[0]->IsObject()) {
1381         paramObject = JSRef<JSObject>::Cast(info[0]);
1382     }
1383     CreateTimePicker(info, paramObject);
1384 }
1385 
JsOpacity(const JSCallbackInfo& info)1386 void JSTimePicker::JsOpacity(const JSCallbackInfo& info)
1387 {
1388     JSViewAbstract::JsOpacity(info);
1389     TimePickerModel::GetInstance()->HasUserDefinedOpacity();
1390 }
1391 
Loop(const JSCallbackInfo& info)1392 void JSTimePicker::Loop(const JSCallbackInfo& info)
1393 {
1394     bool isLoop = true;
1395     if (info[0]->IsBoolean()) {
1396         isLoop = info[0]->ToBoolean();
1397     }
1398     TimePickerModel::GetInstance()->SetWheelModeEnabled(isLoop);
1399 }
1400 
EnableHapticFeedback(const JSCallbackInfo& info)1401 void JSTimePicker::EnableHapticFeedback(const JSCallbackInfo& info)
1402 {
1403     bool isEnableHapticFeedback = true;
1404     if (info[0]->IsBoolean()) {
1405         isEnableHapticFeedback = info[0]->ToBoolean();
1406     }
1407     TimePickerModel::GetInstance()->SetIsEnableHapticFeedback(isEnableHapticFeedback);
1408 }
1409 
UseMilitaryTime(bool isUseMilitaryTime)1410 void JSTimePicker::UseMilitaryTime(bool isUseMilitaryTime)
1411 {
1412     TimePickerModel::GetInstance()->SetHour24(isUseMilitaryTime);
1413 }
1414 
DateTimeOptions(const JSCallbackInfo& info)1415 void JSTimePicker::DateTimeOptions(const JSCallbackInfo& info)
1416 {
1417     JSRef<JSObject> paramObject;
1418     ZeroPrefixType hourType = ZeroPrefixType::AUTO;
1419     ZeroPrefixType minuteType = ZeroPrefixType::AUTO;
1420     ZeroPrefixType secondType = ZeroPrefixType::AUTO;
1421     if (info.Length() >= 1 && info[0]->IsObject()) {
1422         paramObject = JSRef<JSObject>::Cast(info[0]);
1423         auto hourValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_HOUR);
1424         if (hourValue->IsString()) {
1425             std::string hour = hourValue->ToString();
1426             if (hour == TIMEPICKER_OPTIONS_TWO_DIGIT_VAL) {
1427                 hourType = ZeroPrefixType::SHOW;
1428             } else if (hour == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1429                 hourType = ZeroPrefixType::HIDE;
1430             }
1431         }
1432         auto minuteValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_MINUTE);
1433         if (minuteValue->IsString()) {
1434             minuteType = ZeroPrefixType::SHOW;
1435             std::string minute = minuteValue->ToString();
1436             if (minute == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1437                 minuteType = ZeroPrefixType::HIDE;
1438             }
1439         }
1440         auto secondValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_SECOND);
1441         if (secondValue->IsString()) {
1442             secondType = ZeroPrefixType::SHOW;
1443             std::string second = secondValue->ToString();
1444             if (second == TIMEPICKER_OPTIONS_NUMERIC_VAL) {
1445                 secondType = ZeroPrefixType::HIDE;
1446             }
1447         }
1448     }
1449     TimePickerModel::GetInstance()->SetDateTimeOptions(hourType, minuteType, secondType);
1450 }
1451 
PickerBackgroundColor(const JSCallbackInfo& info)1452 void JSTimePicker::PickerBackgroundColor(const JSCallbackInfo& info)
1453 {
1454     JSViewAbstract::JsBackgroundColor(info);
1455 
1456     if (info.Length() < 1) {
1457         return;
1458     }
1459     Color backgroundColor;
1460     if (!ParseJsColor(info[0], backgroundColor)) {
1461         return;
1462     }
1463     TimePickerModel::GetInstance()->SetBackgroundColor(backgroundColor);
1464 }
1465 
SetDisappearTextStyle(const JSCallbackInfo& info)1466 void JSTimePicker::SetDisappearTextStyle(const JSCallbackInfo& info)
1467 {
1468     auto theme = GetTheme<PickerTheme>();
1469     CHECK_NULL_VOID(theme);
1470     NG::PickerTextStyle textStyle;
1471     JSTimePickerTheme::ObtainTextStyle(textStyle);
1472     if (info[0]->IsObject()) {
1473         JSDatePicker::ParseTextStyle(info[0], textStyle, "disappearTextStyleTime");
1474     }
1475     TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1476 }
1477 
SetTextStyle(const JSCallbackInfo& info)1478 void JSTimePicker::SetTextStyle(const JSCallbackInfo& info)
1479 {
1480     auto theme = GetTheme<PickerTheme>();
1481     CHECK_NULL_VOID(theme);
1482     NG::PickerTextStyle textStyle;
1483     JSTimePickerTheme::ObtainTextStyle(textStyle);
1484     if (info[0]->IsObject()) {
1485         JSDatePicker::ParseTextStyle(info[0], textStyle, "textStyleTime");
1486     }
1487     TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1488 }
1489 
SetSelectedTextStyle(const JSCallbackInfo& info)1490 void JSTimePicker::SetSelectedTextStyle(const JSCallbackInfo& info)
1491 {
1492     auto theme = GetTheme<PickerTheme>();
1493     CHECK_NULL_VOID(theme);
1494     NG::PickerTextStyle textStyle;
1495     JSTimePickerTheme::ObtainSelectedTextStyle(textStyle);
1496     if (info[0]->IsObject()) {
1497         JSDatePicker::ParseTextStyle(info[0], textStyle, "selectedTextStyleTime");
1498     }
1499     TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1500 }
1501 
CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)1502 void JSTimePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef<JSObject>& paramObj)
1503 {
1504     auto selectedTime = paramObj->GetProperty("selected");
1505     auto theme = GetTheme<PickerTheme>();
1506     CHECK_NULL_VOID(theme);
1507     auto formatValue = paramObj->GetProperty("format");
1508     bool showSecond = false;
1509     if (formatValue->IsNumber()) {
1510         auto displayedFormat = static_cast<TimePickerFormat>(formatValue->ToNumber<int32_t>());
1511         if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) {
1512             showSecond = true;
1513         }
1514     }
1515     TimePickerModel::GetInstance()->CreateTimePicker(theme, showSecond);
1516     if (selectedTime->IsObject()) {
1517         JSRef<JSObject> selectedTimeObj = JSRef<JSObject>::Cast(selectedTime);
1518         JSRef<JSVal> changeEventVal = selectedTimeObj->GetProperty("changeEvent");
1519         if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
1520             ParseSelectedDateTimeObject(info, selectedTimeObj, false);
1521             auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value"));
1522             TimePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime);
1523         } else {
1524             TimePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime));
1525         }
1526     }
1527     if (!JSTimePickerTheme::ApplyTheme()) {
1528         SetDefaultAttributes();
1529     }
1530 }
1531 
SetDefaultAttributes()1532 void JSTimePicker::SetDefaultAttributes()
1533 {
1534     auto theme = GetTheme<PickerTheme>();
1535     CHECK_NULL_VOID(theme);
1536     NG::PickerTextStyle textStyle;
1537     auto selectedStyle = theme->GetOptionStyle(true, false);
1538     textStyle.textColor = selectedStyle.GetTextColor();
1539     textStyle.fontSize = selectedStyle.GetFontSize();
1540     textStyle.fontWeight = selectedStyle.GetFontWeight();
1541     TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle);
1542 
1543     auto disappearStyle = theme->GetDisappearOptionStyle();
1544     textStyle.textColor = disappearStyle.GetTextColor();
1545     textStyle.fontSize = disappearStyle.GetFontSize();
1546     textStyle.fontWeight = disappearStyle.GetFontWeight();
1547     TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle);
1548 
1549     auto normalStyle = theme->GetOptionStyle(false, false);
1550     textStyle.textColor = normalStyle.GetTextColor();
1551     textStyle.fontSize = normalStyle.GetFontSize();
1552     textStyle.fontWeight = normalStyle.GetFontWeight();
1553     TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle);
1554 }
1555 
ParseTime(const JSRef<JSVal>& timeVal)1556 PickerTime JSTimePicker::ParseTime(const JSRef<JSVal>& timeVal)
1557 {
1558     auto pickerTime = PickerTime::Current();
1559     if (!timeVal->IsObject()) {
1560         return pickerTime;
1561     }
1562     auto timeObj = JSRef<JSObject>::Cast(timeVal);
1563     auto yearFuncJsVal = timeObj->GetProperty("getFullYear");
1564     if (yearFuncJsVal->IsFunction()) {
1565         auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1566         JSRef<JSVal> year = yearFunc->Call(timeObj);
1567         if (year->IsNumber() && LessOrEqual(year->ToNumber<int32_t>(), 0)) {
1568             return pickerTime;
1569         }
1570     }
1571 
1572     auto hourFuncJsVal = timeObj->GetProperty("getHours");
1573     auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1574     auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1575     if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1576         return pickerTime;
1577     }
1578     auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1579     auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1580     auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1581     JSRef<JSVal> hour = hourFunc->Call(timeObj);
1582     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1583     JSRef<JSVal> second = secondFunc->Call(timeObj);
1584 
1585     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1586         pickerTime.SetHour(hour->ToNumber<int32_t>());
1587         pickerTime.SetMinute(minute->ToNumber<int32_t>());
1588         pickerTime.SetSecond(second->ToNumber<int32_t>());
1589     }
1590     return pickerTime;
1591 }
1592 
JSBind(BindingTarget globalObj)1593 void JSTimePickerDialog::JSBind(BindingTarget globalObj)
1594 {
1595     JSClass<JSTimePickerDialog>::Declare("TimePickerDialog");
1596     JSClass<JSTimePickerDialog>::StaticMethod("show", &JSTimePickerDialog::Show);
1597 
1598     JSClass<JSTimePickerDialog>::Bind<>(globalObj);
1599 }
1600 
TimePickerDialogAppearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent)1601 void TimePickerDialogAppearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent)
1602 {
1603     std::function<void()> didAppearEvent;
1604     std::function<void()> willAppearEvent;
1605     if (info.Length() == 0 || !info[0]->IsObject()) {
1606         return;
1607     }
1608     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1609     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1610     auto onDidAppear = paramObject->GetProperty("onDidAppear");
1611     if (!onDidAppear->IsUndefined() && onDidAppear->IsFunction()) {
1612         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidAppear));
1613         didAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1614             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1615             ACE_SCORING_EVENT("DatePickerDialog.onDidAppear");
1616             PipelineContext::SetCallBackNode(node);
1617             func->Execute();
1618         };
1619     }
1620     auto onWillAppear = paramObject->GetProperty("onWillAppear");
1621     if (!onWillAppear->IsUndefined() && onWillAppear->IsFunction()) {
1622         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillAppear));
1623         willAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1624             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1625             ACE_SCORING_EVENT("DatePickerDialog.onWillAppear");
1626             PipelineContext::SetCallBackNode(node);
1627             func->Execute();
1628         };
1629     }
1630     timePickerDialogEvent.onDidAppear = std::move(didAppearEvent);
1631     timePickerDialogEvent.onWillAppear = std::move(willAppearEvent);
1632 }
1633 
TimePickerDialogDisappearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent)1634 void TimePickerDialogDisappearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent)
1635 {
1636     std::function<void()> didDisappearEvent;
1637     std::function<void()> willDisappearEvent;
1638     if (info.Length() == 0 || !info[0]->IsObject()) {
1639         return;
1640     }
1641     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1642     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1643     auto onDidDisappear = paramObject->GetProperty("onDidDisappear");
1644     if (!onDidDisappear->IsUndefined() && onDidDisappear->IsFunction()) {
1645         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onDidDisappear));
1646         didDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1647             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1648             ACE_SCORING_EVENT("DatePickerDialog.onDidDisappear");
1649             PipelineContext::SetCallBackNode(node);
1650             func->Execute();
1651         };
1652     }
1653     auto onWillDisappear = paramObject->GetProperty("onWillDisappear");
1654     if (!onWillDisappear->IsUndefined() && onWillDisappear->IsFunction()) {
1655         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onWillDisappear));
1656         willDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1657             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1658             ACE_SCORING_EVENT("DatePickerDialog.onWillDisappear");
1659             PipelineContext::SetCallBackNode(node);
1660             func->Execute();
1661         };
1662     }
1663     timePickerDialogEvent.onDidDisappear = std::move(didDisappearEvent);
1664     timePickerDialogEvent.onWillDisappear = std::move(willDisappearEvent);
1665 }
1666 
Show(const JSCallbackInfo& info)1667 void JSTimePickerDialog::Show(const JSCallbackInfo& info)
1668 {
1669     auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
1670     CHECK_NULL_VOID(scopedDelegate);
1671     if (!info[0]->IsObject()) {
1672         return;
1673     }
1674     auto paramObject = JSRef<JSObject>::Cast(info[0]);
1675     std::function<void()> cancelEvent;
1676     std::function<void(const std::string&)> acceptEvent;
1677     std::function<void(const std::string&)> changeEvent;
1678     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1679     auto onChange = paramObject->GetProperty("onChange");
1680     if (!onChange->IsUndefined() && onChange->IsFunction()) {
1681         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
1682         changeEvent = [execCtx = info.GetExecutionContext(), type = DatePickerType::TIME, func = std::move(jsFunc),
1683                           node = targetNode](const std::string& info) {
1684             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1685             std::vector<std::string> keys;
1686             keys = { "year", "month", "day", "hour", "minute", "second" };
1687             ACE_SCORING_EVENT("DatePickerDialog.onChange");
1688             PipelineContext::SetCallBackNode(node);
1689             func->Execute(keys, info);
1690         };
1691     }
1692     auto onAccept = paramObject->GetProperty("onAccept");
1693     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
1694         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
1695         acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
1696                           const std::string& info) {
1697             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1698             std::vector<std::string> keys = { "year", "month", "day", "hour", "minute", "second" };
1699             ACE_SCORING_EVENT("DatePickerDialog.onAccept");
1700             PipelineContext::SetCallBackNode(node);
1701             func->Execute(keys, info);
1702         };
1703     }
1704     auto onCancel = paramObject->GetProperty("onCancel");
1705     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
1706         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
1707         cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() {
1708             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1709             ACE_SCORING_EVENT("DatePickerDialog.onCancel");
1710             PipelineContext::SetCallBackNode(node);
1711             func->Execute();
1712         };
1713     }
1714     auto selectedTime = paramObject->GetProperty("selected");
1715     auto useMilitaryTime = paramObject->GetProperty("useMilitaryTime");
1716     NG::TimePickerSettingData settingData;
1717     PickerDialogInfo pickerDialog;
1718     settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1719     pickerDialog.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1720     if (selectedTime->IsObject()) {
1721         PickerDate dialogTitleDate = ParseDate(selectedTime);
1722         if (dialogTitleDate.GetYear() != 0) {
1723             settingData.dialogTitleDate = dialogTitleDate;
1724             pickerDialog.isSelectedTime = true;
1725             pickerDialog.pickerTime = ParseTime(selectedTime);
1726         }
1727     }
1728     JSDatePicker::ParseTextProperties(paramObject, settingData.properties);
1729     auto dateTimeOptionsValue = paramObject->GetProperty("dateTimeOptions");
1730     if (dateTimeOptionsValue->IsObject()) {
1731         auto dateTimeOptionsObj = JSRef<JSObject>::Cast(dateTimeOptionsValue);
1732         JSDatePickerDialog::ParseDateTimeOptions(dateTimeOptionsObj, settingData.dateTimeOptions);
1733     }
1734 
1735     // Parse alignment
1736     auto alignmentValue = paramObject->GetProperty("alignment");
1737     if (alignmentValue->IsNumber()) {
1738         auto alignment = alignmentValue->ToNumber<int32_t>();
1739         if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
1740             pickerDialog.alignment = DIALOG_ALIGNMENT[alignment];
1741         }
1742         if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1743             if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
1744                 alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
1745                 alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
1746                 pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP;
1747             }
1748         }
1749     }
1750 
1751     // Parse offset
1752     auto offsetValue = paramObject->GetProperty("offset");
1753     if (offsetValue->IsObject()) {
1754         auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
1755         CalcDimension dx;
1756         auto dxValue = offsetObj->GetProperty("dx");
1757         JSAlertDialog::ParseJsDimensionVp(dxValue, dx);
1758         CalcDimension dy;
1759         auto dyValue = offsetObj->GetProperty("dy");
1760         JSAlertDialog::ParseJsDimensionVp(dyValue, dy);
1761         pickerDialog.offset = DimensionOffset(dx, dy);
1762     }
1763 
1764     // Parse maskRect.
1765     auto maskRectValue = paramObject->GetProperty("maskRect");
1766     DimensionRect maskRect;
1767     if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
1768         pickerDialog.maskRect = maskRect;
1769     }
1770 
1771     auto backgroundColorValue = paramObject->GetProperty("backgroundColor");
1772     Color backgroundColor;
1773     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
1774         pickerDialog.backgroundColor = backgroundColor;
1775     }
1776 
1777     auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle");
1778     if (backgroundBlurStyle->IsNumber()) {
1779         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
1780         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
1781             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
1782             pickerDialog.backgroundBlurStyle = blurStyle;
1783         }
1784     }
1785 
1786     ParseDatePickerHoverMode(pickerDialog, paramObject);
1787 
1788     auto buttonInfos = ParseButtonStyles(paramObject);
1789 
1790     auto shadowValue = paramObject->GetProperty("shadow");
1791     Shadow shadow;
1792     if ((shadowValue->IsObject() || shadowValue->IsNumber()) && JSViewAbstract::ParseShadowProps(shadowValue, shadow)) {
1793         pickerDialog.shadow = shadow;
1794     }
1795     auto formatValue = paramObject->GetProperty("format");
1796     bool showSecond = false;
1797     if (formatValue->IsNumber()) {
1798         auto displayedFormat = static_cast<TimePickerFormat>(formatValue->ToNumber<int32_t>());
1799         if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) {
1800             showSecond = true;
1801         }
1802     }
1803     settingData.showSecond = showSecond;
1804     TimePickerDialogEvent timePickerDialogEvent { nullptr, nullptr, nullptr, nullptr };
1805     TimePickerDialogAppearEvent(info, timePickerDialogEvent);
1806     TimePickerDialogDisappearEvent(info, timePickerDialogEvent);
1807     TimePickerDialogModel::GetInstance()->SetTimePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent),
1808         std::move(acceptEvent), std::move(changeEvent), timePickerDialogEvent, buttonInfos);
1809 }
1810 
TimePickerDialogShow(const JSRef<JSObject>& paramObj, const std::map<std::string, NG::DialogEvent>& dialogEvent, const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)1811 void JSTimePickerDialog::TimePickerDialogShow(const JSRef<JSObject>& paramObj,
1812     const std::map<std::string, NG::DialogEvent>& dialogEvent,
1813     const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
1814 {
1815     auto container = Container::CurrentSafely();
1816     CHECK_NULL_VOID(container);
1817 
1818     auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
1819     CHECK_NULL_VOID(pipelineContext);
1820 
1821     auto executor = pipelineContext->GetTaskExecutor();
1822     CHECK_NULL_VOID(executor);
1823 
1824     auto theme = JSAlertDialog::GetTheme<DialogTheme>();
1825     CHECK_NULL_VOID(theme);
1826 
1827     auto selectedTime = paramObj->GetProperty("selected");
1828     auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1829     NG::TimePickerSettingData settingData;
1830     settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean();
1831 
1832     DialogProperties properties;
1833     properties.alignment = theme->GetAlignment();
1834     if (properties.alignment == DialogAlignment::BOTTOM &&
1835         Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1836         properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1837     }
1838 
1839     properties.customStyle = false;
1840     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1841         properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
1842     }
1843 
1844     std::map<std::string, PickerTime> timePickerProperty;
1845     if (selectedTime->IsObject()) {
1846         settingData.dialogTitleDate = ParseDate(selectedTime);
1847         timePickerProperty["selected"] = ParseTime(selectedTime);
1848     }
1849     JSDatePicker::ParseTextProperties(paramObj, settingData.properties);
1850 
1851     auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
1852     auto overlayManager = context ? context->GetOverlayManager() : nullptr;
1853     executor->PostTask(
1854         [properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent,
1855             weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
1856             auto overlayManager = weak.Upgrade();
1857             CHECK_NULL_VOID(overlayManager);
1858             overlayManager->ShowTimeDialog(properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent);
1859         },
1860         TaskExecutor::TaskType::UI, "ArkUIDialogShowTimePicker");
1861 }
1862 
CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)1863 void JSTimePickerDialog::CreateTimePicker(RefPtr<Component>& component, const JSRef<JSObject>& paramObj)
1864 {
1865     auto timePicker = AceType::MakeRefPtr<PickerTimeComponent>();
1866     auto selectedTime = paramObj->GetProperty("selected");
1867     auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime");
1868     bool isUseMilitaryTime = useMilitaryTime->ToBoolean();
1869     if (selectedTime->IsObject()) {
1870         timePicker->SetSelectedTime(ParseTime(selectedTime));
1871     }
1872     timePicker->SetIsDialog(true);
1873     timePicker->SetIsCreateDialogComponent(true);
1874     timePicker->SetHour24(isUseMilitaryTime);
1875     component = timePicker;
1876 }
1877 
ParseTime(const JSRef<JSVal>& timeVal)1878 PickerTime JSTimePickerDialog::ParseTime(const JSRef<JSVal>& timeVal)
1879 {
1880     auto pickerTime = PickerTime();
1881     if (!timeVal->IsObject()) {
1882         return pickerTime;
1883     }
1884     auto timeObj = JSRef<JSObject>::Cast(timeVal);
1885     auto hourFuncJsVal = timeObj->GetProperty("getHours");
1886     auto minuteFuncJsVal = timeObj->GetProperty("getMinutes");
1887     auto secondFuncJsVal = timeObj->GetProperty("getSeconds");
1888     if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) {
1889         return pickerTime;
1890     }
1891     auto hourFunc = JSRef<JSFunc>::Cast(hourFuncJsVal);
1892     auto minuteFunc = JSRef<JSFunc>::Cast(minuteFuncJsVal);
1893     auto secondFunc = JSRef<JSFunc>::Cast(secondFuncJsVal);
1894     JSRef<JSVal> hour = hourFunc->Call(timeObj);
1895     JSRef<JSVal> minute = minuteFunc->Call(timeObj);
1896     JSRef<JSVal> second = secondFunc->Call(timeObj);
1897 
1898     if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) {
1899         pickerTime.SetHour(hour->ToNumber<int32_t>());
1900         pickerTime.SetMinute(minute->ToNumber<int32_t>());
1901         pickerTime.SetSecond(second->ToNumber<int32_t>());
1902     }
1903     return pickerTime;
1904 }
1905 
ParseDate(const JSRef<JSVal>& dateVal)1906 PickerDate JSTimePickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
1907 {
1908     auto pickerDate = PickerDate();
1909     if (!dateVal->IsObject()) {
1910         return pickerDate;
1911     }
1912     auto dateObj = JSRef<JSObject>::Cast(dateVal);
1913     auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
1914     auto monthFuncJsVal = dateObj->GetProperty("getMonth");
1915     auto dateFuncJsVal = dateObj->GetProperty("getDate");
1916     if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
1917         return pickerDate;
1918     }
1919     auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
1920     auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
1921     auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
1922     JSRef<JSVal> year = yearFunc->Call(dateObj);
1923     JSRef<JSVal> month = monthFunc->Call(dateObj);
1924     JSRef<JSVal> date = dateFunc->Call(dateObj);
1925 
1926     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
1927         pickerDate.SetYear(year->ToNumber<int32_t>());
1928         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
1929         pickerDate.SetDay(date->ToNumber<int32_t>());
1930     }
1931     return pickerDate;
1932 }
1933 } // namespace OHOS::Ace::Framework
1934