• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "frameworks/bridge/declarative_frontend/jsview/js_calendar_picker.h"
17 
18 #include "base/log/ace_scoring_log.h"
19 #include "base/utils/date_util.h"
20 #include "bridge/common/utils/engine_helper.h"
21 #include "bridge/declarative_frontend/engine/functions/js_function.h"
22 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
23 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
24 #include "bridge/declarative_frontend/jsview/models/calendar_picker_model_impl.h"
25 #include "core/components/calendar/calendar_theme.h"
26 #include "core/components/dialog/dialog_theme.h"
27 #include "core/components_ng/base/view_abstract_model.h"
28 #include "core/components_ng/base/view_stack_processor.h"
29 #include "core/components_ng/pattern/calendar_picker/calendar_picker_model_ng.h"
30 #include "core/pipeline_ng/pipeline_context.h"
31 
32 namespace OHOS::Ace {
33 std::unique_ptr<CalendarPickerModel> CalendarPickerModel::instance_ = nullptr;
34 std::mutex CalendarPickerModel::mutex_;
GetInstance()35 CalendarPickerModel* CalendarPickerModel::GetInstance()
36 {
37     if (!instance_) {
38         std::lock_guard<std::mutex> lock(mutex_);
39         if (!instance_) {
40 #ifdef NG_BUILD
41             instance_.reset(new NG::CalendarPickerModelNG());
42 #else
43             if (Container::IsCurrentUseNewPipeline()) {
44                 instance_.reset(new NG::CalendarPickerModelNG());
45             } else {
46                 instance_.reset(new Framework::CalendarPickerModelImpl());
47             }
48 #endif
49         }
50     }
51     return instance_.get();
52 }
53 } // namespace OHOS::Ace
54 
55 namespace OHOS::Ace::Framework {
GetMSByDate(const std::string & date)56 double GetMSByDate(const std::string& date)
57 {
58     auto json = JsonUtil::ParseJsonString(date);
59     if (!json || json->IsNull()) {
60         return 0.0f;
61     }
62 
63     std::tm dateTime = { 0 };
64     auto year = json->GetValue("year");
65     if (year && year->IsNumber()) {
66         dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900
67     }
68     auto month = json->GetValue("month");
69     if (month && month->IsNumber()) {
70         dateTime.tm_mon = month->GetInt() - 1;
71     }
72     auto day = json->GetValue("day");
73     if (day && day->IsNumber()) {
74         dateTime.tm_mday = day->GetInt();
75     }
76     auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
77     auto local = std::localtime(&now);
78     CHECK_NULL_RETURN(local, 0.0f);
79     dateTime.tm_hour = local->tm_hour;
80     dateTime.tm_min = local->tm_min;
81     dateTime.tm_sec = local->tm_sec;
82     return Date::GetMilliSecondsByDateTime(dateTime);
83 }
84 
JSBind(BindingTarget globalObj)85 void JSCalendarPicker::JSBind(BindingTarget globalObj)
86 {
87     JSClass<JSCalendarPicker>::Declare("CalendarPicker");
88     JSClass<JSCalendarPicker>::StaticMethod("create", &JSCalendarPicker::Create, MethodOptions::NONE);
89     JSClass<JSCalendarPicker>::StaticMethod("edgeAlign", &JSCalendarPicker::SetEdgeAlign);
90     JSClass<JSCalendarPicker>::StaticMethod("textStyle", &JSCalendarPicker::SetTextStyle);
91     JSClass<JSCalendarPicker>::StaticMethod("onChange", &JSCalendarPicker::SetOnChange);
92     JSClass<JSCalendarPicker>::StaticMethod("border", &JSCalendarPicker::SetBorder);
93     JSClass<JSCalendarPicker>::StaticMethod("padding", &JSCalendarPicker::JsPadding);
94     JSClass<JSCalendarPicker>::InheritAndBind<JSViewAbstract>(globalObj);
95 }
96 
SetBorder(const JSCallbackInfo & info)97 void JSCalendarPicker::SetBorder(const JSCallbackInfo& info)
98 {
99     if (!info[0]->IsObject()) {
100         return;
101     }
102     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
103     auto valueWidth = object->GetProperty("width");
104     if (!valueWidth->IsUndefined()) {
105         ParseBorderWidth(valueWidth);
106     }
107 
108     // use default value when undefined.
109     ParseCalendarPickerBorderColor(object->GetProperty("color"));
110 
111     auto valueRadius = object->GetProperty("radius");
112     if (!valueRadius->IsUndefined()) {
113         ParseBorderRadius(valueRadius);
114     }
115     // use default value when undefined.
116     ParseBorderStyle(object->GetProperty("style"));
117 
118     info.ReturnSelf();
119 }
120 
ParseCalendarPickerBorderColor(const JSRef<JSVal> & args)121 void JSCalendarPicker::ParseCalendarPickerBorderColor(const JSRef<JSVal>& args)
122 {
123     auto pipelineContext = PipelineContext::GetCurrentContext();
124     CHECK_NULL_VOID(pipelineContext);
125     RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
126     CHECK_NULL_VOID(theme);
127     if (!args->IsObject() && !args->IsNumber() && !args->IsString()) {
128         ViewAbstractModel::GetInstance()->SetBorderColor(theme->GetEntryBorderColor());
129     } else {
130         JSViewAbstract::ParseBorderColor(args);
131     }
132 }
133 
SetEdgeAlign(const JSCallbackInfo & info)134 void JSCalendarPicker::SetEdgeAlign(const JSCallbackInfo& info)
135 {
136     NG::CalendarEdgeAlign alignType = NG::CalendarEdgeAlign::EDGE_ALIGN_END;
137     DimensionOffset offset;
138     if (!info[0]->IsNumber()) {
139         CalendarPickerModel::GetInstance()->SetEdgeAlign(alignType, offset);
140         return;
141     }
142     alignType = static_cast<NG::CalendarEdgeAlign>(info[0]->ToNumber<int32_t>());
143 
144     if (!info[1]->IsObject()) {
145         CalendarPickerModel::GetInstance()->SetEdgeAlign(alignType, offset);
146         return;
147     }
148     auto offsetObj = JSRef<JSObject>::Cast(info[1]);
149     CalcDimension dx;
150     auto dxValue = offsetObj->GetProperty("dx");
151     ParseJsDimensionVp(dxValue, dx);
152     CalcDimension dy;
153     auto dyValue = offsetObj->GetProperty("dy");
154     ParseJsDimensionVp(dyValue, dy);
155     offset = DimensionOffset(dx, dy);
156 
157     CalendarPickerModel::GetInstance()->SetEdgeAlign(alignType, offset);
158 }
159 
SetTextStyle(const JSCallbackInfo & info)160 void JSCalendarPicker::SetTextStyle(const JSCallbackInfo& info)
161 {
162     auto pipeline = PipelineBase::GetCurrentContext();
163     CHECK_NULL_VOID(pipeline);
164     RefPtr<CalendarTheme> calendarTheme = pipeline->GetTheme<CalendarTheme>();
165     CHECK_NULL_VOID(calendarTheme);
166     NG::PickerTextStyle textStyle;
167     textStyle.fontSize = calendarTheme->GetEntryFontSize();
168     textStyle.textColor = calendarTheme->GetEntryFontColor();
169     textStyle.fontWeight = FontWeight::NORMAL;
170     if (!info[0]->IsObject()) {
171         CalendarPickerModel::GetInstance()->SetTextStyle(textStyle);
172         return;
173     }
174     JSCalendarPicker::ParseTextStyle(info[0], textStyle);
175     CalendarPickerModel::GetInstance()->SetTextStyle(textStyle);
176 }
177 
SetOnChange(const JSCallbackInfo & info)178 void JSCalendarPicker::SetOnChange(const JSCallbackInfo& info)
179 {
180     if (!info[0]->IsFunction()) {
181         return;
182     }
183 
184     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
185     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
186     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
187                         const std::string& info) {
188         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
189         ACE_SCORING_EVENT("CalendarPicker.onChange");
190         PipelineContext::SetCallBackNode(node);
191         auto dateObj = JSDate::New(GetMSByDate(info));
192         func->ExecuteJS(1, &dateObj);
193     };
194     CalendarPickerModel::GetInstance()->SetOnChange(std::move(onChange));
195 }
196 
JsPadding(const JSCallbackInfo & info)197 void JSCalendarPicker::JsPadding(const JSCallbackInfo& info)
198 {
199     NG::PaddingProperty padding;
200     if (info[0]->IsObject()) {
201         std::optional<CalcDimension> left;
202         std::optional<CalcDimension> right;
203         std::optional<CalcDimension> top;
204         std::optional<CalcDimension> bottom;
205         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info[0]);
206 
207         CalcDimension leftDimen;
208         if (ParseJsDimensionVp(paddingObj->GetProperty("left"), leftDimen)) {
209             left = leftDimen;
210         }
211         CalcDimension rightDimen;
212         if (ParseJsDimensionVp(paddingObj->GetProperty("right"), rightDimen)) {
213             right = rightDimen;
214         }
215         CalcDimension topDimen;
216         if (ParseJsDimensionVp(paddingObj->GetProperty("top"), topDimen)) {
217             top = topDimen;
218         }
219         CalcDimension bottomDimen;
220         if (ParseJsDimensionVp(paddingObj->GetProperty("bottom"), bottomDimen)) {
221             bottom = bottomDimen;
222         }
223         if (left.has_value() || right.has_value() || top.has_value() || bottom.has_value()) {
224             padding = SetPaddings(top, bottom, left, right);
225             CalendarPickerModel::GetInstance()->SetPadding(padding);
226             return;
227         }
228     }
229 
230     CalcDimension length(-1);
231     ParseJsDimensionVp(info[0], length);
232     if (length.IsNonNegative()) {
233         padding.SetEdges(NG::CalcLength(length));
234     }
235     CalendarPickerModel::GetInstance()->SetPadding(padding);
236 }
237 
SetPaddings(const std::optional<CalcDimension> & top,const std::optional<CalcDimension> & bottom,const std::optional<CalcDimension> & left,const std::optional<CalcDimension> & right)238 NG::PaddingProperty JSCalendarPicker::SetPaddings(const std::optional<CalcDimension>& top,
239     const std::optional<CalcDimension>& bottom, const std::optional<CalcDimension>& left,
240     const std::optional<CalcDimension>& right)
241 {
242     NG::PaddingProperty paddings;
243     if (top.has_value()) {
244         if (top.value().Unit() == DimensionUnit::CALC) {
245             paddings.top =
246                 NG::CalcLength(top.value().IsNonNegative() ? top.value().CalcValue() : CalcDimension().CalcValue());
247         } else {
248             paddings.top = NG::CalcLength(top.value().IsNonNegative() ? top.value() : CalcDimension());
249         }
250     }
251     if (bottom.has_value()) {
252         if (bottom.value().Unit() == DimensionUnit::CALC) {
253             paddings.bottom = NG::CalcLength(
254                 bottom.value().IsNonNegative() ? bottom.value().CalcValue() : CalcDimension().CalcValue());
255         } else {
256             paddings.bottom = NG::CalcLength(bottom.value().IsNonNegative() ? bottom.value() : CalcDimension());
257         }
258     }
259     if (left.has_value()) {
260         if (left.value().Unit() == DimensionUnit::CALC) {
261             paddings.left =
262                 NG::CalcLength(left.value().IsNonNegative() ? left.value().CalcValue() : CalcDimension().CalcValue());
263         } else {
264             paddings.left = NG::CalcLength(left.value().IsNonNegative() ? left.value() : CalcDimension());
265         }
266     }
267     if (right.has_value()) {
268         if (right.value().Unit() == DimensionUnit::CALC) {
269             paddings.right =
270                 NG::CalcLength(right.value().IsNonNegative() ? right.value().CalcValue() : CalcDimension().CalcValue());
271         } else {
272             paddings.right = NG::CalcLength(right.value().IsNonNegative() ? right.value() : CalcDimension());
273         }
274     }
275 
276     return paddings;
277 }
278 
ParseSelectedDateObject(const JSCallbackInfo & info,const JSRef<JSObject> & selectedObject)279 void JSCalendarPicker::ParseSelectedDateObject(const JSCallbackInfo& info, const JSRef<JSObject>& selectedObject)
280 {
281     JSRef<JSVal> changeEventVal = selectedObject->GetProperty("changeEvent");
282     if (!changeEventVal->IsFunction()) {
283         return;
284     }
285     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(changeEventVal));
286     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
287     auto changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
288                            const std::string& info) {
289         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
290         ACE_SCORING_EVENT("DatePicker.SelectedDateTimeChangeEvent");
291         PipelineContext::SetCallBackNode(node);
292         auto dateObj = JSDate::New(GetMSByDate(info));
293         func->ExecuteJS(1, &dateObj);
294     };
295     CalendarPickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent));
296 }
297 
Create(const JSCallbackInfo & info)298 void JSCalendarPicker::Create(const JSCallbackInfo& info)
299 {
300     NG::CalendarSettingData settingData;
301     RefPtr<CalendarTheme> calendarTheme = GetTheme<CalendarTheme>();
302     CHECK_NULL_VOID(calendarTheme);
303     CalcDimension dayRadius;
304     if (info[0]->IsObject()) {
305         auto obj = JSRef<JSObject>::Cast(info[0]);
306         if (!ParseJsDimensionVpNG(obj->GetProperty("hintRadius"), dayRadius)) {
307             dayRadius = calendarTheme->GetCalendarDayRadius();
308         }
309         auto selected = obj->GetProperty("selected");
310         auto parseSelectedDate = ParseDate(selected);
311         if (selected->IsObject() && parseSelectedDate.GetYear() != 0) {
312             JSRef<JSObject> selectedDateObj = JSRef<JSObject>::Cast(selected);
313             JSRef<JSVal> changeEventVal = selectedDateObj->GetProperty("changeEvent");
314             if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
315                 ParseSelectedDateObject(info, selectedDateObj);
316                 settingData.selectedDate = ParseDate(selectedDateObj->GetProperty("value"));
317             } else {
318                 settingData.selectedDate = parseSelectedDate;
319             }
320         }
321     } else {
322         dayRadius = calendarTheme->GetCalendarDayRadius();
323     }
324     settingData.dayRadius = dayRadius;
325     CalendarPickerModel::GetInstance()->Create(settingData);
326 }
327 
ParseTextStyle(const JSRef<JSObject> & paramObj,NG::PickerTextStyle & textStyle)328 void JSCalendarPicker::ParseTextStyle(const JSRef<JSObject>& paramObj, NG::PickerTextStyle& textStyle)
329 {
330     auto fontColor = paramObj->GetProperty("color");
331     auto fontStyle = paramObj->GetProperty("font");
332 
333     Color color;
334     if (ParseJsColor(fontColor, color)) {
335         textStyle.textColor = color;
336     }
337 
338     if (!fontStyle->IsObject()) {
339         return;
340     }
341     JSRef<JSObject> fontObj = JSRef<JSObject>::Cast(fontStyle);
342     auto fontSize = fontObj->GetProperty("size");
343     auto fontWeight = fontObj->GetProperty("weight");
344     if (fontSize->IsNull() || fontSize->IsUndefined()) {
345         textStyle.fontSize = Dimension(-1);
346     } else {
347         CalcDimension size;
348         if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) {
349             textStyle.fontSize = Dimension(-1);
350         } else {
351             textStyle.fontSize = size;
352         }
353     }
354 
355     if (!fontWeight->IsNull() && !fontWeight->IsUndefined()) {
356         std::string weight;
357         if (fontWeight->IsNumber()) {
358             weight = std::to_string(fontWeight->ToNumber<int32_t>());
359         } else {
360             ParseJsString(fontWeight, weight);
361         }
362         textStyle.fontWeight = ConvertStrToFontWeight(weight);
363     }
364 }
365 
ParseDate(const JSRef<JSVal> & dateVal)366 PickerDate JSCalendarPicker::ParseDate(const JSRef<JSVal>& dateVal)
367 {
368     auto pickerDate = PickerDate::Current();
369     if (!dateVal->IsObject()) {
370         return pickerDate;
371     }
372     auto dateObj = JSRef<JSObject>::Cast(dateVal);
373     auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
374     auto monthFuncJsVal = dateObj->GetProperty("getMonth");
375     auto dateFuncJsVal = dateObj->GetProperty("getDate");
376     if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
377         return pickerDate;
378     }
379     auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
380     auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
381     auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
382     JSRef<JSVal> year = yearFunc->Call(dateObj);
383     JSRef<JSVal> month = monthFunc->Call(dateObj);
384     JSRef<JSVal> date = dateFunc->Call(dateObj);
385 
386     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
387         pickerDate.SetYear(year->ToNumber<int32_t>());
388         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
389         pickerDate.SetDay(date->ToNumber<int32_t>());
390     }
391     return pickerDate;
392 }
393 
JSBind(BindingTarget globalObj)394 void JSCalendarPickerDialog::JSBind(BindingTarget globalObj)
395 {
396     JSClass<JSCalendarPickerDialog>::Declare("CalendarPickerDialog");
397     JSClass<JSCalendarPickerDialog>::StaticMethod("show", &JSCalendarPickerDialog::Show);
398     JSClass<JSCalendarPickerDialog>::Bind<>(globalObj);
399 }
400 
Show(const JSCallbackInfo & info)401 void JSCalendarPickerDialog::Show(const JSCallbackInfo& info)
402 {
403     auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
404     CHECK_NULL_VOID(scopedDelegate);
405     if (!info[0]->IsObject()) {
406         return;
407     }
408 
409     if (Container::IsCurrentUseNewPipeline()) {
410         auto paramObject = JSRef<JSObject>::Cast(info[0]);
411         auto dialogEvent = ChangeDialogEvent(info);
412         auto dialogCancelEvent = DialogCancelEvent(info);
413         CalendarPickerDialogShow(paramObject, dialogEvent, dialogCancelEvent);
414     }
415 }
416 
ChangeDialogEvent(const JSCallbackInfo & info)417 std::map<std::string, NG::DialogEvent> JSCalendarPickerDialog::ChangeDialogEvent(const JSCallbackInfo& info)
418 {
419     std::map<std::string, NG::DialogEvent> dialogEvent;
420     if (!info[0]->IsObject()) {
421         return dialogEvent;
422     }
423     auto paramObject = JSRef<JSObject>::Cast(info[0]);
424     auto onChange = paramObject->GetProperty("onChange");
425     if (!onChange->IsUndefined() && onChange->IsFunction()) {
426         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onChange));
427         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
428         auto changeId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
429                             const std::string& info) {
430             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
431             ACE_SCORING_EVENT("CalendarDialog.onChange");
432             PipelineContext::SetCallBackNode(node);
433             auto dateObj = JSDate::New(GetMSByDate(info));
434             func->ExecuteJS(1, &dateObj);
435         };
436         dialogEvent["changeId"] = changeId;
437     }
438     auto onAccept = paramObject->GetProperty("onAccept");
439     if (!onAccept->IsUndefined() && onAccept->IsFunction()) {
440         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onAccept));
441         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
442         auto acceptId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
443                             const std::string& info) {
444             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
445             ACE_SCORING_EVENT("CalendarDialog.onAccept");
446             PipelineContext::SetCallBackNode(node);
447             auto dateObj = JSDate::New(GetMSByDate(info));
448             func->ExecuteJS(1, &dateObj);
449         };
450         dialogEvent["acceptId"] = acceptId;
451     }
452     return dialogEvent;
453 }
454 
DialogCancelEvent(const JSCallbackInfo & info)455 std::map<std::string, NG::DialogGestureEvent> JSCalendarPickerDialog::DialogCancelEvent(const JSCallbackInfo& info)
456 {
457     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent;
458     if (!info[0]->IsObject()) {
459         return dialogCancelEvent;
460     }
461     auto paramObject = JSRef<JSObject>::Cast(info[0]);
462     auto onCancel = paramObject->GetProperty("onCancel");
463     if (!onCancel->IsUndefined() && onCancel->IsFunction()) {
464         auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(onCancel));
465         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
466         auto cancelId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
467                             const GestureEvent& /* info */) {
468             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
469             ACE_SCORING_EVENT("CalendarDialog.onCancel");
470             PipelineContext::SetCallBackNode(node);
471             func->Execute();
472         };
473         dialogCancelEvent["cancelId"] = cancelId;
474     }
475     return dialogCancelEvent;
476 }
477 
ParseDate(const JSRef<JSVal> & dateVal)478 PickerDate JSCalendarPickerDialog::ParseDate(const JSRef<JSVal>& dateVal)
479 {
480     auto pickerDate = PickerDate();
481     if (!dateVal->IsObject()) {
482         return pickerDate;
483     }
484     auto dateObj = JSRef<JSObject>::Cast(dateVal);
485 
486     auto yearFuncJsVal = dateObj->GetProperty("getFullYear");
487     auto monthFuncJsVal = dateObj->GetProperty("getMonth");
488     auto dateFuncJsVal = dateObj->GetProperty("getDate");
489     if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) {
490         return pickerDate;
491     }
492     auto yearFunc = JSRef<JSFunc>::Cast(yearFuncJsVal);
493     auto monthFunc = JSRef<JSFunc>::Cast(monthFuncJsVal);
494     auto dateFunc = JSRef<JSFunc>::Cast(dateFuncJsVal);
495     JSRef<JSVal> year = yearFunc->Call(dateObj);
496     JSRef<JSVal> month = monthFunc->Call(dateObj);
497     JSRef<JSVal> date = dateFunc->Call(dateObj);
498 
499     if (year->IsNumber() && month->IsNumber() && date->IsNumber()) {
500         pickerDate.SetYear(year->ToNumber<int32_t>());
501         pickerDate.SetMonth(month->ToNumber<int32_t>() + 1); // 0-11 means 1 to 12 months
502         pickerDate.SetDay(date->ToNumber<int32_t>());
503     }
504     return pickerDate;
505 }
506 
CalendarPickerDialogShow(const JSRef<JSObject> & paramObj,const std::map<std::string,NG::DialogEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & dialogCancelEvent)507 void JSCalendarPickerDialog::CalendarPickerDialogShow(const JSRef<JSObject>& paramObj,
508     const std::map<std::string, NG::DialogEvent>& dialogEvent,
509     const std::map<std::string, NG::DialogGestureEvent>& dialogCancelEvent)
510 {
511     auto container = Container::CurrentSafely();
512     CHECK_NULL_VOID(container);
513     auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
514     CHECK_NULL_VOID(pipelineContext);
515     auto executor = pipelineContext->GetTaskExecutor();
516     CHECK_NULL_VOID(executor);
517 
518     auto theme = GetTheme<DialogTheme>();
519     CHECK_NULL_VOID(theme);
520     auto calendarTheme = pipelineContext->GetTheme<CalendarTheme>();
521     NG::CalendarSettingData settingData;
522     auto selectedDate = paramObj->GetProperty("selected");
523     auto parseSelectedDate = ParseDate(selectedDate);
524     if (selectedDate->IsObject() && parseSelectedDate.GetYear() != 0) {
525         settingData.selectedDate = parseSelectedDate;
526     }
527 
528     CalcDimension radius;
529     if (ParseJsDimensionVpNG(paramObj->GetProperty("hintRadius"), radius)) {
530         settingData.dayRadius = radius;
531     }
532 
533     DialogProperties properties;
534     if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
535         properties.alignment = DialogAlignment::BOTTOM;
536     } else {
537         properties.alignment = DialogAlignment::CENTER;
538     }
539 
540     auto backgroundColorValue = paramObj->GetProperty("backgroundColor");
541     Color backgroundColor;
542     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
543         properties.backgroundColor = backgroundColor;
544     }
545 
546     auto backgroundBlurStyle = paramObj->GetProperty("backgroundBlurStyle");
547     BlurStyleOption styleOption;
548     if (backgroundBlurStyle->IsNumber()) {
549         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
550         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
551             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
552             properties.backgroundBlurStyle = blurStyle;
553         }
554     }
555     properties.customStyle = false;
556     properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
557     NG::BorderRadiusProperty dialogRadius;
558     dialogRadius.SetRadius(calendarTheme->GetDialogBorderRadius());
559     properties.borderRadius = dialogRadius;
560 
561     auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
562     auto overlayManager = context ? context->GetOverlayManager() : nullptr;
563     executor->PostTask(
564         [properties, settingData, dialogEvent, dialogCancelEvent, weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
565             auto overlayManager = weak.Upgrade();
566             CHECK_NULL_VOID(overlayManager);
567             overlayManager->ShowCalendarDialog(properties, settingData, dialogEvent, dialogCancelEvent);
568         },
569         TaskExecutor::TaskType::UI);
570 }
571 } // namespace OHOS::Ace::Framework
572