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