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