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