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