/* * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "bridge/declarative_frontend/jsview/js_datepicker.h" #include #include "base/log/ace_scoring_log.h" #include "base/utils/utils.h" #include "bridge/common/utils/engine_helper.h" #include "bridge/declarative_frontend/engine/functions/js_function.h" #include "bridge/declarative_frontend/jsview/js_interactable_view.h" #include "bridge/declarative_frontend/jsview/js_utils.h" #include "bridge/declarative_frontend/jsview/js_view_common_def.h" #include "bridge/declarative_frontend/jsview/models/picker_model_impl.h" #include "bridge/declarative_frontend/jsview/models/timepicker_model_impl.h" #include "bridge/declarative_frontend/view_stack_processor.h" #include "core/components/picker/picker_data.h" #include "core/components/picker/picker_date_component.h" #include "core/components/picker/picker_theme.h" #include "core/components/picker/picker_time_component.h" #include "core/components_ng/base/view_stack_processor.h" #include "core/components_ng/pattern/picker/datepicker_model_ng.h" #include "core/components_ng/pattern/time_picker/timepicker_model.h" #include "core/components_ng/pattern/time_picker/timepicker_model_ng.h" #include "core/components_v2/inspector/inspector_constants.h" #include "core/event/ace_event_helper.h" #include "core/pipeline_ng/pipeline_context.h" #include "frameworks/bridge/declarative_frontend/ark_theme/theme_apply/js_date_picker_theme.h" #include "frameworks/bridge/declarative_frontend/ark_theme/theme_apply/js_time_picker_theme.h" namespace OHOS::Ace { namespace { const DimensionOffset DATEPICKER_OFFSET_DEFAULT_TOP = DimensionOffset(0.0_vp, 40.0_vp); const std::vector DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER, DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END, DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START, DialogAlignment::BOTTOM_END }; const std::vector HOVER_MODE_AREA_TYPE = { HoverModeAreaType::TOP_SCREEN, HoverModeAreaType::BOTTOM_SCREEN }; const char TIMEPICKER_OPTIONS_HOUR[] = "hour"; const char TIMEPICKER_OPTIONS_MINUTE[] = "minute"; const char TIMEPICKER_OPTIONS_SECOND[] = "second"; const std::string TIMEPICKER_OPTIONS_NUMERIC_VAL = "numeric"; const std::string TIMEPICKER_OPTIONS_TWO_DIGIT_VAL = "2-digit"; } // namespace std::unique_ptr DatePickerModel::datePickerInstance_ = nullptr; std::unique_ptr DatePickerDialogModel::datePickerDialogInstance_ = nullptr; std::unique_ptr TimePickerModel::timePickerInstance_ = nullptr; std::unique_ptr TimePickerDialogModel::timePickerDialogInstance_ = nullptr; std::mutex DatePickerModel::mutex_; std::mutex DatePickerDialogModel::mutex_; std::mutex TimePickerModel::mutex_; std::mutex TimePickerDialogModel::mutex_; DatePickerModel* DatePickerModel::GetInstance() { if (!datePickerInstance_) { std::lock_guard lock(mutex_); if (!datePickerInstance_) { #ifdef NG_BUILD datePickerInstance_.reset(new NG::DatePickerModelNG()); #else if (Container::IsCurrentUseNewPipeline()) { datePickerInstance_.reset(new NG::DatePickerModelNG()); } else { datePickerInstance_.reset(new Framework::DatePickerModelImpl()); } #endif } } return datePickerInstance_.get(); } DatePickerDialogModel* DatePickerDialogModel::GetInstance() { if (!datePickerDialogInstance_) { std::lock_guard lock(mutex_); if (!datePickerDialogInstance_) { #ifdef NG_BUILD datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG()); #else if (Container::IsCurrentUseNewPipeline()) { datePickerDialogInstance_.reset(new NG::DatePickerDialogModelNG()); } else { datePickerDialogInstance_.reset(new Framework::DatePickerDialogModelImpl()); } #endif } } return datePickerDialogInstance_.get(); } TimePickerModel* TimePickerModel::GetInstance() { if (!timePickerInstance_) { std::lock_guard lock(mutex_); if (!timePickerInstance_) { #ifdef NG_BUILD timePickerInstance_.reset(new NG::TimePickerModelNG()); #else if (Container::IsCurrentUseNewPipeline()) { timePickerInstance_.reset(new NG::TimePickerModelNG()); } else { timePickerInstance_.reset(new Framework::TimePickerModelImpl()); } #endif } } return timePickerInstance_.get(); } TimePickerDialogModel* TimePickerDialogModel::GetInstance() { if (!timePickerDialogInstance_) { std::lock_guard lock(mutex_); if (!timePickerDialogInstance_) { #ifdef NG_BUILD timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG()); #else if (Container::IsCurrentUseNewPipeline()) { timePickerDialogInstance_.reset(new NG::TimePickerDialogModelNG()); } else { timePickerDialogInstance_.reset(new Framework::TimePickerDialogModelImpl()); } #endif } } return timePickerDialogInstance_.get(); } } // namespace OHOS::Ace namespace OHOS::Ace::Framework { namespace { JSRef DatePickerChangeEventToJSValue(const DatePickerChangeEvent& eventInfo) { JSRef obj = JSRef::New(); std::unique_ptr argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr()); if (!argsPtr) { return JSRef::Cast(obj); } std::vector keys = { "year", "month", "day", "hour", "minute", "second" }; for (auto iter = keys.begin(); iter != keys.end(); iter++) { const std::string key = *iter; const auto value = argsPtr->GetValue(key); if (!value || value->ToString().empty()) { continue; } obj->SetProperty(key.c_str(), value->GetInt()); } return JSRef::Cast(obj); } JSRef DatePickerDateChangeEventToJSValue(const DatePickerChangeEvent& eventInfo) { JSRef obj = JSRef::New(); std::unique_ptr argsPtr = JsonUtil::ParseJsonString(eventInfo.GetSelectedStr()); if (!argsPtr) { return JSRef::Cast(obj); } auto dateObj = JSDatePickerDialog::GetDateObj(argsPtr); return JSRef::Cast(dateObj); } void ParseFontOfButtonStyle(const JSRef& pickerButtonParamObject, ButtonInfo& buttonInfo) { CalcDimension fontSize; JSRef sizeProperty = pickerButtonParamObject->GetProperty("fontSize"); if (JSViewAbstract::ParseJsDimensionVpNG(sizeProperty, fontSize) && fontSize.Unit() != DimensionUnit::PERCENT && GreatOrEqual(fontSize.Value(), 0.0)) { if (JSViewAbstract::ParseJsDimensionFp(sizeProperty, fontSize)) { buttonInfo.fontSize = fontSize; } } Color fontColor; if (JSViewAbstract::ParseJsColor(pickerButtonParamObject->GetProperty("fontColor"), fontColor)) { buttonInfo.fontColor = fontColor; } auto fontWeight = pickerButtonParamObject->GetProperty("fontWeight"); if (fontWeight->IsString() || fontWeight->IsNumber()) { buttonInfo.fontWeight = ConvertStrToFontWeight(fontWeight->ToString(), FontWeight::MEDIUM); } JSRef style = pickerButtonParamObject->GetProperty("fontStyle"); if (style->IsNumber()) { auto value = style->ToNumber(); if (value >= 0 && value < static_cast(FontStyle::NONE)) { buttonInfo.fontStyle = static_cast(value); } } JSRef family = pickerButtonParamObject->GetProperty("fontFamily"); std::vector fontFamilies; if (JSViewAbstract::ParseJsFontFamilies(family, fontFamilies)) { buttonInfo.fontFamily = fontFamilies; } } ButtonInfo ParseButtonStyle(const JSRef& pickerButtonParamObject) { ButtonInfo buttonInfo; if (pickerButtonParamObject->GetProperty("type")->IsNumber()) { buttonInfo.type = static_cast(pickerButtonParamObject->GetProperty("type")->ToNumber()); } if (pickerButtonParamObject->GetProperty("style")->IsNumber()) { auto styleModeIntValue = pickerButtonParamObject->GetProperty("style")->ToNumber(); if (styleModeIntValue >= static_cast(ButtonStyleMode::NORMAL) && styleModeIntValue <= static_cast(ButtonStyleMode::TEXT)) { buttonInfo.buttonStyle = static_cast(styleModeIntValue); } } if (pickerButtonParamObject->GetProperty("role")->IsNumber()) { auto buttonRoleIntValue = pickerButtonParamObject->GetProperty("role")->ToNumber(); if (buttonRoleIntValue >= static_cast(ButtonRole::NORMAL) && buttonRoleIntValue <= static_cast(ButtonRole::ERROR)) { buttonInfo.role = static_cast(buttonRoleIntValue); } } ParseFontOfButtonStyle(pickerButtonParamObject, buttonInfo); Color backgroundColor; if (JSViewAbstract::ParseJsColor(pickerButtonParamObject->GetProperty("backgroundColor"), backgroundColor)) { buttonInfo.backgroundColor = backgroundColor; } auto radius = ParseBorderRadiusAttr(pickerButtonParamObject->GetProperty("borderRadius")); if (radius.has_value()) { buttonInfo.borderRadius = radius.value(); } auto primaryValue = pickerButtonParamObject->GetProperty("primary"); if (primaryValue->IsBoolean()) { buttonInfo.isPrimary = primaryValue->ToBoolean(); } return buttonInfo; } std::vector ParseButtonStyles(const JSRef& paramObject) { std::vector buttonInfos; auto acceptButtonStyle = paramObject->GetProperty("acceptButtonStyle"); if (acceptButtonStyle->IsObject()) { auto acceptButtonStyleParamObject = JSRef::Cast(acceptButtonStyle); buttonInfos.emplace_back(ParseButtonStyle(acceptButtonStyleParamObject)); buttonInfos[0].isAcceptButton = true; } else { ButtonInfo buttonInfo; buttonInfos.emplace_back(buttonInfo); } auto cancelButtonStyle = paramObject->GetProperty("cancelButtonStyle"); if (cancelButtonStyle->IsObject()) { auto cancelButtonStyleParamObject = JSRef::Cast(cancelButtonStyle); buttonInfos.emplace_back(ParseButtonStyle(cancelButtonStyleParamObject)); } return buttonInfos; } void ParseDatePickerHoverMode(PickerDialogInfo& pickerDialog, const JSRef& paramObject) { auto enableHoverModeValue = paramObject->GetProperty("enableHoverMode"); if (enableHoverModeValue->IsBoolean()) { pickerDialog.enableHoverMode = enableHoverModeValue->ToBoolean(); } auto hoverModeAreaValue = paramObject->GetProperty("hoverModeArea"); if (hoverModeAreaValue->IsNumber()) { auto hoverModeArea = hoverModeAreaValue->ToNumber(); if (hoverModeArea >= 0 && hoverModeArea < static_cast(HOVER_MODE_AREA_TYPE.size())) { pickerDialog.hoverModeArea = HOVER_MODE_AREA_TYPE[hoverModeArea]; } } } } // namespace void JSDatePicker::JSBind(BindingTarget globalObj) { JSClass::Declare("DatePicker"); MethodOptions opt = MethodOptions::NONE; JSClass::StaticMethod("create", &JSDatePicker::Create, opt); JSClass::StaticMethod("lunar", &JSDatePicker::SetLunar); JSClass::StaticMethod("onChange", &JSDatePicker::OnChange); JSClass::StaticMethod("onDateChange", &JSDatePicker::OnDateChange); JSClass::StaticMethod("backgroundColor", &JSDatePicker::PickerBackgroundColor); JSClass::StaticMethod("opacity", &JSDatePicker::JsOpacity); // keep compatible, need remove after JSClass::StaticMethod("useMilitaryTime", &JSDatePicker::UseMilitaryTime); JSClass::StaticMethod("onClick", &JSInteractableView::JsOnClick); JSClass::StaticMethod("onTouch", &JSInteractableView::JsOnTouch); JSClass::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey); JSClass::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete); JSClass::StaticMethod("onAttach", &JSInteractableView::JsOnAttach); JSClass::StaticMethod("onAppear", &JSInteractableView::JsOnAppear); JSClass::StaticMethod("onDetach", &JSInteractableView::JsOnDetach); JSClass::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear); JSClass::StaticMethod("disappearTextStyle", &JSDatePicker::SetDisappearTextStyle); JSClass::StaticMethod("textStyle", &JSDatePicker::SetTextStyle); JSClass::StaticMethod("selectedTextStyle", &JSDatePicker::SetSelectedTextStyle); JSClass::InheritAndBind(globalObj); } void JSDatePicker::Create(const JSCallbackInfo& info) { DatePickerType pickerType = DatePickerType::DATE; JSRef paramObject; if (info.Length() >= 1 && info[0]->IsObject()) { paramObject = JSRef::Cast(info[0]); auto type = paramObject->GetProperty("type"); if (type->IsNumber()) { pickerType = static_cast(type->ToNumber()); } } switch (pickerType) { case DatePickerType::TIME: { CreateTimePicker(info, paramObject); break; } case DatePickerType::DATE: { CreateDatePicker(info, paramObject); break; } default: { break; } } } void JSDatePicker::SetLunar(bool isLunar) { DatePickerModel::GetInstance()->SetShowLunar(isLunar); } void JSDatePicker::UseMilitaryTime(bool isUseMilitaryTime) { DatePickerModel::GetInstance()->SetHour24(isUseMilitaryTime); } void JSDatePicker::ParseTextProperties(const JSRef& paramObj, NG::PickerTextProperties& result) { auto disappearProperty = paramObj->GetProperty("disappearTextStyle"); auto normalProperty = paramObj->GetProperty("textStyle"); auto selectedProperty = paramObj->GetProperty("selectedTextStyle"); if (!disappearProperty->IsNull() && disappearProperty->IsObject()) { JSRef disappearObj = JSRef::Cast(disappearProperty); JSDatePicker::ParseTextStyle(disappearObj, result.disappearTextStyle_, "disappearTextStyle"); } if (!normalProperty->IsNull() && normalProperty->IsObject()) { JSRef noramlObj = JSRef::Cast(normalProperty); JSDatePicker::ParseTextStyle(noramlObj, result.normalTextStyle_, "textStyle"); } if (!selectedProperty->IsNull() && selectedProperty->IsObject()) { JSRef selectedObj = JSRef::Cast(selectedProperty); JSDatePicker::ParseTextStyle(selectedObj, result.selectedTextStyle_, "selectedTextStyle"); } } void JSDatePicker::IsUserDefinedFontFamily(const std::string& pos) { if (pos == "disappearTextStyle") { DatePickerModel::GetInstance()->HasUserDefinedDisappearFontFamily(true); } else if (pos == "textStyle") { DatePickerModel::GetInstance()->HasUserDefinedNormalFontFamily(true); } else if (pos == "selectedTextStyle") { DatePickerModel::GetInstance()->HasUserDefinedSelectedFontFamily(true); } else if (pos == "disappearTextStyleTime") { TimePickerModel::GetInstance()->HasUserDefinedDisappearFontFamily(true); } else if (pos == "textStyleTime") { TimePickerModel::GetInstance()->HasUserDefinedNormalFontFamily(true); } else if (pos == "selectedTextStyleTime") { TimePickerModel::GetInstance()->HasUserDefinedSelectedFontFamily(true); } } void JSDatePicker::ParseTextStyle( const JSRef& paramObj, NG::PickerTextStyle& textStyle, const std::string& pos) { auto fontColor = paramObj->GetProperty("color"); auto fontOptions = paramObj->GetProperty("font"); Color textColor; if (JSViewAbstract::ParseJsColor(fontColor, textColor)) { textStyle.textColor = textColor; } if (!fontOptions->IsObject()) { return; } JSRef fontObj = JSRef::Cast(fontOptions); auto fontSize = fontObj->GetProperty("size"); auto fontWeight = fontObj->GetProperty("weight"); auto fontFamily = fontObj->GetProperty("family"); auto fontStyle = fontObj->GetProperty("style"); if (fontSize->IsNull() || fontSize->IsUndefined()) { textStyle.fontSize = Dimension(-1); } else { CalcDimension size; if (!ParseJsDimensionFp(fontSize, size) || size.Unit() == DimensionUnit::PERCENT) { textStyle.fontSize = Dimension(-1); } else { textStyle.fontSize = size; } } if (!fontWeight->IsNull() && !fontWeight->IsUndefined()) { std::string weight; if (fontWeight->IsNumber()) { weight = std::to_string(fontWeight->ToNumber()); } else { ParseJsString(fontWeight, weight); } textStyle.fontWeight = ConvertStrToFontWeight(weight); } if (!fontFamily->IsNull() && !fontFamily->IsUndefined()) { std::vector families; if (ParseJsFontFamilies(fontFamily, families)) { textStyle.fontFamily = families; IsUserDefinedFontFamily(pos); } } if (fontStyle->IsNumber()) { auto style = fontStyle->ToNumber(); if (style < 0 || style > 1) { return; } textStyle.fontStyle = static_cast(style); } } void JSDatePicker::SetDisappearTextStyle(const JSCallbackInfo& info) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; JSDatePickerTheme::ObtainTextStyle(textStyle); if (info[0]->IsObject()) { JSDatePicker::ParseTextStyle(info[0], textStyle, "disappearTextStyle"); } DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle); } void JSDatePicker::SetTextStyle(const JSCallbackInfo& info) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; JSDatePickerTheme::ObtainTextStyle(textStyle); if (info[0]->IsObject()) { JSDatePicker::ParseTextStyle(info[0], textStyle, "textStyle"); } DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle); } void JSDatePicker::SetSelectedTextStyle(const JSCallbackInfo& info) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; JSDatePickerTheme::ObtainSelectedTextStyle(textStyle); if (info[0]->IsObject()) { JSDatePicker::ParseTextStyle(info[0], textStyle, "selectedTextStyle"); } DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle); } void JSDatePicker::JsOpacity(const JSCallbackInfo& info) { JSViewAbstract::JsOpacity(info); DatePickerModel::GetInstance()->HasUserDefinedOpacity(); } void JSDatePicker::OnChange(const JSCallbackInfo& info) { if (!info[0]->IsFunction()) { return; } auto jsFunc = AceType::MakeRefPtr>( JSRef::Cast(info[0]), DatePickerChangeEventToJSValue); WeakPtr targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]( const BaseEventInfo* info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("datePicker.onChange"); PipelineContext::SetCallBackNode(node); const auto* eventInfo = TypeInfoHelper::DynamicCast(info); func->Execute(*eventInfo); }; DatePickerModel::GetInstance()->SetOnChange(std::move(onChange)); } void JSDatePicker::OnDateChange(const JSCallbackInfo& info) { if (!info[0]->IsFunction()) { return; } auto jsFunc = AceType::MakeRefPtr>( JSRef::Cast(info[0]), DatePickerDateChangeEventToJSValue); WeakPtr targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onDateChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]( const BaseEventInfo* info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("datePicker.onDateChange"); PipelineContext::SetCallBackNode(node); const auto* eventInfo = TypeInfoHelper::DynamicCast(info); func->Execute(*eventInfo); }; DatePickerModel::GetInstance()->SetOnDateChange(std::move(onDateChange)); } void JSTimePicker::OnChange(const JSCallbackInfo& info) { if (!info[0]->IsFunction()) { return; } auto jsFunc = AceType::MakeRefPtr>( JSRef::Cast(info[0]), DatePickerChangeEventToJSValue); WeakPtr targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]( const BaseEventInfo* index) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("datePicker.onChange"); PipelineContext::SetCallBackNode(node); const auto* eventInfo = TypeInfoHelper::DynamicCast(index); func->Execute(*eventInfo); }; TimePickerModel::GetInstance()->SetOnChange(std::move(onChange)); } void JSDatePicker::PickerBackgroundColor(const JSCallbackInfo& info) { JSViewAbstract::JsBackgroundColor(info); if (info.Length() < 1) { return; } Color backgroundColor; if (!ParseJsColor(info[0], backgroundColor)) { return; } DatePickerModel::GetInstance()->SetBackgroundColor(backgroundColor); } PickerDate JSDatePicker::ParseDate(const JSRef& dateVal) { auto pickerDate = PickerDate(); if (!dateVal->IsObject()) { return pickerDate; } auto dateObj = JSRef::Cast(dateVal); auto yearFuncJsVal = dateObj->GetProperty("getFullYear"); auto monthFuncJsVal = dateObj->GetProperty("getMonth"); auto dateFuncJsVal = dateObj->GetProperty("getDate"); if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) { return pickerDate; } auto yearFunc = JSRef::Cast(yearFuncJsVal); auto monthFunc = JSRef::Cast(monthFuncJsVal); auto dateFunc = JSRef::Cast(dateFuncJsVal); JSRef year = yearFunc->Call(dateObj); JSRef month = monthFunc->Call(dateObj); JSRef date = dateFunc->Call(dateObj); if (year->IsNumber() && month->IsNumber() && date->IsNumber()) { pickerDate.SetYear(year->ToNumber()); pickerDate.SetMonth(month->ToNumber() + 1); // 0-11 means 1 to 12 months pickerDate.SetDay(date->ToNumber()); } return pickerDate; } PickerTime JSDatePicker::ParseTime(const JSRef& timeVal) { auto pickerTime = PickerTime(); if (!timeVal->IsObject()) { return pickerTime; } auto timeObj = JSRef::Cast(timeVal); auto hourFuncJsVal = timeObj->GetProperty("getHours"); auto minuteFuncJsVal = timeObj->GetProperty("getMinutes"); auto secondFuncJsVal = timeObj->GetProperty("getSeconds"); if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) { return pickerTime; } auto hourFunc = JSRef::Cast(hourFuncJsVal); auto minuteFunc = JSRef::Cast(minuteFuncJsVal); auto secondFunc = JSRef::Cast(secondFuncJsVal); JSRef hour = hourFunc->Call(timeObj); JSRef minute = minuteFunc->Call(timeObj); JSRef second = secondFunc->Call(timeObj); if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) { pickerTime.SetHour(hour->ToNumber()); pickerTime.SetMinute(minute->ToNumber()); pickerTime.SetSecond(second->ToNumber()); } return pickerTime; } void ParseSelectedDateTimeObject(const JSCallbackInfo& info, const JSRef& selectedObject, bool isDatePicker) { JSRef changeEventVal = selectedObject->GetProperty("changeEvent"); if (changeEventVal->IsUndefined() || !changeEventVal->IsFunction()) { return; } auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(changeEventVal)); WeakPtr targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto changeEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode, isDatePicker](const BaseEventInfo* info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePicker.SelectedDateTimeChangeEvent"); const auto* eventInfo = TypeInfoHelper::DynamicCast(info); CHECK_NULL_VOID(eventInfo); auto selectedStr = eventInfo->GetSelectedStr(); auto sourceJson = JsonUtil::ParseJsonString(selectedStr); if (!sourceJson || sourceJson->IsNull()) { return; } auto dateObj = JSDatePickerDialog::GetDateObj(sourceJson, isDatePicker); PipelineContext::SetCallBackNode(node); func->ExecuteJS(1, &dateObj); }; if (isDatePicker) { DatePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent)); } else { TimePickerModel::GetInstance()->SetChangeEvent(std::move(changeEvent)); } } void JSDatePicker::CreateDatePicker(const JSCallbackInfo& info, const JSRef& paramObj) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); JSRef startDate; JSRef endDate; JSRef selectedDate; if (!paramObj->IsUndefined()) { startDate = paramObj->GetProperty("start"); endDate = paramObj->GetProperty("end"); selectedDate = paramObj->GetProperty("selected"); } auto parseStartDate = ParseDate(startDate); auto parseEndDate = ParseDate(endDate); if (parseStartDate.GetYear() <= 0) { parseStartDate = theme->GetDefaultStartDate(); } if (parseEndDate.GetYear() <= 0) { parseEndDate = theme->GetDefaultEndDate(); } auto startDays = parseStartDate.ToDays(); auto endDays = parseEndDate.ToDays(); if (startDays > endDays) { parseStartDate = theme->GetDefaultStartDate(); parseEndDate = theme->GetDefaultEndDate(); } DatePickerModel::GetInstance()->CreateDatePicker(theme); if (startDate->IsObject()) { DatePickerModel::GetInstance()->SetStartDate(parseStartDate); } if (endDate->IsObject()) { DatePickerModel::GetInstance()->SetEndDate(parseEndDate); } if (selectedDate->IsObject()) { JSRef selectedDateObj = JSRef::Cast(selectedDate); JSRef changeEventVal = selectedDateObj->GetProperty("changeEvent"); PickerDate parseSelectedDate; if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) { ParseSelectedDateTimeObject(info, selectedDateObj, true); parseSelectedDate = ParseDate(selectedDateObj->GetProperty("value")); } else { parseSelectedDate = ParseDate(selectedDate); } DatePickerModel::GetInstance()->SetSelectedDate(parseSelectedDate); } if (!JSDatePickerTheme::ApplyTheme()) { SetDefaultAttributes(); } } void JSDatePicker::SetDefaultAttributes() { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; auto selectedStyle = theme->GetOptionStyle(true, false); textStyle.textColor = selectedStyle.GetTextColor(); textStyle.fontSize = selectedStyle.GetFontSize(); textStyle.fontWeight = selectedStyle.GetFontWeight(); DatePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle); auto disappearStyle = theme->GetDisappearOptionStyle(); textStyle.textColor = disappearStyle.GetTextColor(); textStyle.fontSize = disappearStyle.GetFontSize(); textStyle.fontWeight = disappearStyle.GetFontWeight(); DatePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle); auto normalStyle = theme->GetOptionStyle(false, false); textStyle.textColor = normalStyle.GetTextColor(); textStyle.fontSize = normalStyle.GetFontSize(); textStyle.fontWeight = normalStyle.GetFontWeight(); DatePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle); } void JSDatePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef& paramObj) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); DatePickerModel::GetInstance()->CreateTimePicker(theme); auto selectedTime = paramObj->GetProperty("selected"); if (selectedTime->IsObject()) { JSRef selectedTimeObj = JSRef::Cast(selectedTime); JSRef changeEventVal = selectedTimeObj->GetProperty("changeEvent"); if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) { ParseSelectedDateTimeObject(info, selectedTimeObj, true); auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value")); DatePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime); } else { DatePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime)); } } } void JSDatePickerDialog::JSBind(BindingTarget globalObj) { JSClass::Declare("DatePickerDialog"); JSClass::StaticMethod("show", &JSDatePickerDialog::Show); JSClass::Bind<>(globalObj); } void DatePickerDialogAppearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent) { std::function didAppearEvent; std::function willAppearEvent; if (info.Length() == 0 || !info[0]->IsObject()) { return; } auto paramObject = JSRef::Cast(info[0]); WeakPtr frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onDidAppear = paramObject->GetProperty("onDidAppear"); if (!onDidAppear->IsUndefined() && onDidAppear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onDidAppear)); didAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onDidAppear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } auto onWillAppear = paramObject->GetProperty("onWillAppear"); if (!onWillAppear->IsUndefined() && onWillAppear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onWillAppear)); willAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onWillAppear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } pickerDialogEvent.onDidAppear = std::move(didAppearEvent); pickerDialogEvent.onWillAppear = std::move(willAppearEvent); } void DatePickerDialogDisappearEvent(const JSCallbackInfo& info, PickerDialogEvent& pickerDialogEvent) { std::function didDisappearEvent; std::function willDisappearEvent; if (info.Length() == 0 || !info[0]->IsObject()) { return; } auto paramObject = JSRef::Cast(info[0]); WeakPtr frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onDidDisappear = paramObject->GetProperty("onDidDisappear"); if (!onDidDisappear->IsUndefined() && onDidDisappear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onDidDisappear)); didDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onDidDisappear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } auto onWillDisappear = paramObject->GetProperty("onWillDisappear"); if (!onWillDisappear->IsUndefined() && onWillDisappear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onWillDisappear)); willDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onWillDisappear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } pickerDialogEvent.onDidDisappear = std::move(didDisappearEvent); pickerDialogEvent.onWillDisappear = std::move(willDisappearEvent); } std::function JSDatePickerDialog::GetDateChangeEvent(const JSRef& paramObject, const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr& frameNode) { std::function dateChangeEvent; auto onDateChange = paramObject->GetProperty("onDateChange"); if (!onDateChange->IsUndefined() && onDateChange->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onDateChange)); dateChangeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc), node = frameNode](const std::string& info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onDateChange"); auto selectedJson = JsonUtil::ParseJsonString(info); if (!selectedJson || selectedJson->IsNull()) { return; } auto dateObj = GetDateObj(selectedJson); PipelineContext::SetCallBackNode(node); func->ExecuteJS(1, &dateObj); }; } return dateChangeEvent; } std::function JSDatePickerDialog::GetDateAcceptEvent(const JSRef& paramObject, const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr& frameNode) { std::function dateAcceptEvent; auto onDateAccept = paramObject->GetProperty("onDateAccept"); if (!onDateAccept->IsUndefined() && onDateAccept->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onDateAccept)); dateAcceptEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc), node = frameNode](const std::string& info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onDateAccept"); auto selectedJson = JsonUtil::ParseJsonString(info); if (!selectedJson || selectedJson->IsNull()) { return; } auto dateObj = GetDateObj(selectedJson); PipelineContext::SetCallBackNode(node); func->ExecuteJS(1, &dateObj); }; } return dateAcceptEvent; } JsiRef JSDatePickerDialog::GetDateObj(const std::unique_ptr& selectedJson, bool isDatePicker) { std::tm dateTime = { 0 }; auto year = selectedJson->GetValue("year"); if (year && year->IsNumber()) { dateTime.tm_year = year->GetInt() - 1900; // local date start from 1900 } auto month = selectedJson->GetValue("month"); if (month && month->IsNumber()) { dateTime.tm_mon = month->GetInt(); } auto day = selectedJson->GetValue("day"); if (day && day->IsNumber()) { dateTime.tm_mday = day->GetInt(); } auto hour = selectedJson->GetValue("hour"); if (hour && hour->IsNumber()) { dateTime.tm_hour = hour->GetInt(); } auto minute = selectedJson->GetValue("minute"); if (minute && minute->IsNumber()) { dateTime.tm_min = minute->GetInt(); } auto second = selectedJson->GetValue("second"); if (second && second->IsNumber()) { dateTime.tm_sec = second->GetInt(); } if (!isDatePicker) { auto milliseconds = Date::GetMilliSecondsByDateTime(dateTime); auto dateObj = JSDate::New(milliseconds); return dateObj; } auto timestamp = std::chrono::system_clock::from_time_t(std::mktime(&dateTime)); auto duration = timestamp.time_since_epoch(); auto milliseconds = std::chrono::duration_cast(duration).count(); auto dateObj = JSDate::New(milliseconds); return dateObj; } std::function JSDatePickerDialog::GetChangeEvent(const JSRef& paramObject, const JSCallbackInfo& info, const DatePickerType& pickerType, const WeakPtr& frameNode) { std::function changeEvent; auto onChange = paramObject->GetProperty("onChange"); if (!onChange->IsUndefined() && onChange->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onChange)); changeEvent = [execCtx = info.GetExecutionContext(), type = pickerType, func = std::move(jsFunc), node = frameNode](const std::string& info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); std::vector keys; keys = { "year", "month", "day" }; ACE_SCORING_EVENT("DatePickerDialog.onChange"); PipelineContext::SetCallBackNode(node); func->Execute(keys, info); }; } return changeEvent; } std::function JSDatePickerDialog::GetAcceptEvent( const JSRef& paramObject, const JSCallbackInfo& info, const WeakPtr& frameNode) { std::function acceptEvent; auto onAccept = paramObject->GetProperty("onAccept"); if (!onAccept->IsUndefined() && onAccept->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onAccept)); acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]( const std::string& info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); std::vector keys = { "year", "month", "day", "hour", "minute", "second" }; ACE_SCORING_EVENT("DatePickerDialog.onAccept"); PipelineContext::SetCallBackNode(node); func->Execute(keys, info); }; } return acceptEvent; } std::function JSDatePickerDialog::GetCancelEvent( const JSRef& paramObject, const JSCallbackInfo& info, const WeakPtr& frameNode) { std::function cancelEvent; auto onCancel = paramObject->GetProperty("onCancel"); if (!onCancel->IsUndefined() && onCancel->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onCancel)); cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = frameNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onCancel"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } return cancelEvent; } void JSDatePickerDialog::UpdateLunarSwitchSettingData( const JSRef& paramObject, NG::DatePickerSettingData& settingData) { auto selectedColorValue = paramObject->GetProperty("selectedColor"); auto unselectedColorValue = paramObject->GetProperty("unselectedColor"); auto strokeColorValue = paramObject->GetProperty("strokeColor"); Color selectedColor; if (JSViewAbstract::ParseJsColor(selectedColorValue, selectedColor)) { settingData.checkboxSettingData.selectedColor = selectedColor; } Color unselectedColor; if (JSViewAbstract::ParseJsColor(unselectedColorValue, unselectedColor)) { settingData.checkboxSettingData.unselectedColor = unselectedColor; } Color strokeColor; if (JSViewAbstract::ParseJsColor(strokeColorValue, strokeColor)) { settingData.checkboxSettingData.strokeColor = strokeColor; } } void JSDatePickerDialog::UpdateDatePickerSettingData( const JSRef& paramObject, NG::DatePickerSettingData& settingData) { auto lunar = paramObject->GetProperty("lunar"); auto lunarSwitch = paramObject->GetProperty("lunarSwitch"); auto sTime = paramObject->GetProperty("showTime"); auto useMilitary = paramObject->GetProperty("useMilitaryTime"); settingData.isLunar = lunar->ToBoolean(); settingData.lunarswitch = lunarSwitch->ToBoolean(); if (settingData.lunarswitch) { auto lunarSwitchStyle = paramObject->GetProperty("lunarSwitchStyle"); if ((!lunarSwitchStyle->IsUndefined()) && lunarSwitchStyle->IsObject()) { auto style = JSRef::Cast(lunarSwitchStyle); UpdateLunarSwitchSettingData(style, settingData); } } settingData.showTime = sTime->ToBoolean(); settingData.useMilitary = useMilitary->ToBoolean(); auto dateTimeOptionsValue = paramObject->GetProperty("dateTimeOptions"); if (dateTimeOptionsValue->IsObject()) { auto dateTimeOptionsObj = JSRef::Cast(dateTimeOptionsValue); JSDatePickerDialog::ParseDateTimeOptions(dateTimeOptionsObj, settingData.dateTimeOptions); } JSDatePicker::ParseTextProperties(paramObject, settingData.properties); } void JSDatePickerDialog::UpdatePickerDialogTimeInfo(const JSRef& paramObject, PickerDialogInfo& pickerDialog) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); auto startDate = paramObject->GetProperty("start"); if (startDate->IsObject()) { pickerDialog.isStartDate = true; } auto endDate = paramObject->GetProperty("end"); if (endDate->IsObject()) { pickerDialog.isEndDate = true; } auto selectedDate = paramObject->GetProperty("selected"); if (selectedDate->IsObject()) { pickerDialog.isSelectedDate = true; } auto parseStartDate = ParseDate(startDate); auto parseEndDate = ParseDate(endDate); if (parseStartDate.GetYear() <= 0) { parseStartDate = theme->GetDefaultStartDate(); } if (parseEndDate.GetYear() <= 0) { parseEndDate = theme->GetDefaultEndDate(); } auto startDays = parseStartDate.ToDays(); auto endDays = parseEndDate.ToDays(); if (startDays > endDays) { parseStartDate = theme->GetDefaultStartDate(); parseEndDate = theme->GetDefaultEndDate(); } pickerDialog.parseStartDate = parseStartDate; pickerDialog.parseEndDate = parseEndDate; pickerDialog.parseSelectedDate = ParseDate(selectedDate); pickerDialog.pickerTime = ParseTime(selectedDate); } void JSDatePickerDialog::UpdatePickerDialogPositionInfo( const JSRef& paramObject, PickerDialogInfo& pickerDialog) { // Parse alignment auto alignmentValue = paramObject->GetProperty("alignment"); if (alignmentValue->IsNumber()) { auto alignment = alignmentValue->ToNumber(); if (alignment >= 0 && alignment < static_cast(DIALOG_ALIGNMENT.size())) { pickerDialog.alignment = DIALOG_ALIGNMENT[alignment]; } if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) { if (alignment == static_cast(DialogAlignment::TOP) || alignment == static_cast(DialogAlignment::TOP_START) || alignment == static_cast(DialogAlignment::TOP_END)) { pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP; } } } // Parse offset auto offsetValue = paramObject->GetProperty("offset"); if (offsetValue->IsObject()) { auto offsetObj = JSRef::Cast(offsetValue); CalcDimension dx; auto dxValue = offsetObj->GetProperty("dx"); ParseJsDimensionVp(dxValue, dx); CalcDimension dy; auto dyValue = offsetObj->GetProperty("dy"); ParseJsDimensionVp(dyValue, dy); pickerDialog.offset = DimensionOffset(dx, dy); } } void JSDatePickerDialog::UpdatePickerDialogInfo(const JSRef& paramObject, PickerDialogInfo& pickerDialog) { UpdatePickerDialogTimeInfo(paramObject, pickerDialog); UpdatePickerDialogPositionInfo(paramObject, pickerDialog); // Parse maskRect. auto maskRectValue = paramObject->GetProperty("maskRect"); DimensionRect maskRect; if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) { pickerDialog.maskRect = maskRect; } auto backgroundColorValue = paramObject->GetProperty("backgroundColor"); Color backgroundColor; if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) { pickerDialog.backgroundColor = backgroundColor; } auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle"); if (backgroundBlurStyle->IsNumber()) { auto blurStyle = backgroundBlurStyle->ToNumber(); if (blurStyle >= static_cast(BlurStyle::NO_MATERIAL) && blurStyle <= static_cast(BlurStyle::COMPONENT_ULTRA_THICK)) { pickerDialog.backgroundBlurStyle = blurStyle; } } auto shadowValue = paramObject->GetProperty("shadow"); Shadow shadow; if ((shadowValue->IsObject() || shadowValue->IsNumber()) && JSViewAbstract::ParseShadowProps(shadowValue, shadow)) { pickerDialog.shadow = shadow; } ParseDatePickerHoverMode(pickerDialog, paramObject); } void JSDatePickerDialog::Show(const JSCallbackInfo& info) { auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely(); CHECK_NULL_VOID(scopedDelegate); if (!info[0]->IsObject()) { return; } auto paramObject = JSRef::Cast(info[0]); DatePickerType pickerType = DatePickerType::DATE; auto type = paramObject->GetProperty("type"); if (type->IsNumber()) { pickerType = static_cast(type->ToNumber()); } std::function cancelEvent; std::function acceptEvent; std::function changeEvent; std::function dateChangeEvent; std::function dateAcceptEvent; WeakPtr frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); changeEvent = GetChangeEvent(paramObject, info, pickerType, frameNode); acceptEvent = GetAcceptEvent(paramObject, info, frameNode); cancelEvent = GetCancelEvent(paramObject, info, frameNode); dateChangeEvent = GetDateChangeEvent(paramObject, info, pickerType, frameNode); dateAcceptEvent = GetDateAcceptEvent(paramObject, info, pickerType, frameNode); NG::DatePickerSettingData settingData; UpdateDatePickerSettingData(paramObject, settingData); PickerDialogInfo pickerDialog; UpdatePickerDialogInfo(paramObject, pickerDialog); auto buttonInfos = ParseButtonStyles(paramObject); PickerDialogEvent pickerDialogEvent { nullptr, nullptr, nullptr, nullptr }; DatePickerDialogAppearEvent(info, pickerDialogEvent); DatePickerDialogDisappearEvent(info, pickerDialogEvent); DatePickerDialogModel::GetInstance()->SetDatePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent), std::move(acceptEvent), std::move(changeEvent), std::move(dateAcceptEvent), std::move(dateChangeEvent), pickerType, pickerDialogEvent, buttonInfos); } void JSDatePickerDialog::DatePickerDialogShow(const JSRef& paramObj, const std::map& dialogEvent, const std::map& dialogCancelEvent) { auto container = Container::CurrentSafely(); if (!container) { return; } auto pipelineContext = AccessibilityManager::DynamicCast(container->GetPipelineContext()); if (!pipelineContext) { return; } auto executor = pipelineContext->GetTaskExecutor(); if (!executor) { return; } NG::DatePickerSettingData settingData; auto startDate = paramObj->GetProperty("start"); auto endDate = paramObj->GetProperty("end"); auto selectedDate = paramObj->GetProperty("selected"); auto lunar = paramObj->GetProperty("lunar"); auto sTime = paramObj->GetProperty("showTime"); auto useMilitary = paramObj->GetProperty("useMilitaryTime"); settingData.isLunar = lunar->ToBoolean(); settingData.showTime = sTime->ToBoolean(); settingData.useMilitary = useMilitary->ToBoolean(); auto parseStartDate = ParseDate(startDate); auto parseEndDate = ParseDate(endDate); auto parseSelectedDate = ParseDate(selectedDate); auto theme = GetTheme(); CHECK_NULL_VOID(theme); DialogProperties properties; properties.alignment = theme->GetAlignment(); if (properties.alignment == DialogAlignment::BOTTOM && Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) { properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx())); } properties.customStyle = false; if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) { properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx())); } std::map datePickerProperty; std::map timePickerProperty; if (startDate->IsObject()) { settingData.datePickerProperty["start"] = parseStartDate; } if (endDate->IsObject()) { settingData.datePickerProperty["end"] = parseEndDate; } if (selectedDate->IsObject()) { settingData.datePickerProperty["selected"] = parseSelectedDate; settingData.timePickerProperty["selected"] = ParseTime(selectedDate); } JSDatePicker::ParseTextProperties(paramObj, settingData.properties); auto context = AccessibilityManager::DynamicCast(pipelineContext); auto overlayManager = context ? context->GetOverlayManager() : nullptr; executor->PostTask( [properties, settingData, dialogEvent, dialogCancelEvent, weak = WeakPtr(overlayManager)] { auto overlayManager = weak.Upgrade(); CHECK_NULL_VOID(overlayManager); overlayManager->ShowDateDialog(properties, settingData, dialogEvent, dialogCancelEvent); }, TaskExecutor::TaskType::UI, "ArkUIDialogShowDatePicker"); } void JSDatePickerDialog::CreateDatePicker(RefPtr& component, const JSRef& paramObj) { auto datePicker = AceType::MakeRefPtr(); auto startDate = paramObj->GetProperty("start"); auto endDate = paramObj->GetProperty("end"); auto selectedDate = paramObj->GetProperty("selected"); auto lunar = paramObj->GetProperty("lunar"); bool isLunar = lunar->ToBoolean(); auto parseStartDate = ParseDate(startDate); auto parseEndDate = ParseDate(endDate); auto parseSelectedDate = ParseDate(selectedDate); auto startDays = parseStartDate.ToDays(); auto endDays = parseEndDate.ToDays(); if (startDays > endDays) { parseStartDate.SetYear(0); parseEndDate.SetYear(0); } if (startDate->IsObject()) { datePicker->SetStartDate(parseStartDate); } if (endDate->IsObject()) { datePicker->SetEndDate(parseEndDate); } if (selectedDate->IsObject()) { datePicker->SetSelectedDate(parseSelectedDate); } datePicker->SetIsDialog(true); datePicker->SetIsCreateDialogComponent(true); datePicker->SetShowLunar(isLunar); component = datePicker; } void JSDatePickerDialog::CreateTimePicker(RefPtr& component, const JSRef& paramObj) { auto timePicker = AceType::MakeRefPtr(); auto selectedTime = paramObj->GetProperty("selected"); auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime"); bool isUseMilitaryTime = useMilitaryTime->ToBoolean(); if (selectedTime->IsObject()) { timePicker->SetSelectedTime(ParseTime(selectedTime)); } timePicker->SetIsDialog(true); timePicker->SetIsCreateDialogComponent(true); timePicker->SetHour24(isUseMilitaryTime); component = timePicker; } PickerDate JSDatePickerDialog::ParseDate(const JSRef& dateVal) { auto pickerDate = PickerDate(); if (!dateVal->IsObject()) { return pickerDate; } auto dateObj = JSRef::Cast(dateVal); auto yearFuncJsVal = dateObj->GetProperty("getFullYear"); auto monthFuncJsVal = dateObj->GetProperty("getMonth"); auto dateFuncJsVal = dateObj->GetProperty("getDate"); if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) { return pickerDate; } auto yearFunc = JSRef::Cast(yearFuncJsVal); auto monthFunc = JSRef::Cast(monthFuncJsVal); auto dateFunc = JSRef::Cast(dateFuncJsVal); JSRef year = yearFunc->Call(dateObj); JSRef month = monthFunc->Call(dateObj); JSRef date = dateFunc->Call(dateObj); if (year->IsNumber() && month->IsNumber() && date->IsNumber()) { pickerDate.SetYear(year->ToNumber()); pickerDate.SetMonth(month->ToNumber() + 1); // 0-11 means 1 to 12 months pickerDate.SetDay(date->ToNumber()); } return pickerDate; } PickerTime JSDatePickerDialog::ParseTime(const JSRef& timeVal) { auto pickerTime = PickerTime(); if (!timeVal->IsObject()) { return pickerTime; } auto timeObj = JSRef::Cast(timeVal); auto hourFuncJsVal = timeObj->GetProperty("getHours"); auto minuteFuncJsVal = timeObj->GetProperty("getMinutes"); auto secondFuncJsVal = timeObj->GetProperty("getSeconds"); if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) { return pickerTime; } auto hourFunc = JSRef::Cast(hourFuncJsVal); auto minuteFunc = JSRef::Cast(minuteFuncJsVal); auto secondFunc = JSRef::Cast(secondFuncJsVal); JSRef hour = hourFunc->Call(timeObj); JSRef minute = minuteFunc->Call(timeObj); JSRef second = secondFunc->Call(timeObj); if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) { pickerTime.SetHour(hour->ToNumber()); pickerTime.SetMinute(minute->ToNumber()); pickerTime.SetSecond(second->ToNumber()); } return pickerTime; } void JSDatePickerDialog::ParseDateTimeOptions(const JSRef& paramObj, DateTimeType& dateTimeOptions) { dateTimeOptions.hourType = ZeroPrefixType::AUTO; dateTimeOptions.minuteType = ZeroPrefixType::AUTO; dateTimeOptions.secondType = ZeroPrefixType::AUTO; auto hourValue = paramObj->GetProperty(TIMEPICKER_OPTIONS_HOUR); if (hourValue->IsString()) { std::string hour = hourValue->ToString(); if (hour == TIMEPICKER_OPTIONS_TWO_DIGIT_VAL) { dateTimeOptions.hourType = ZeroPrefixType::SHOW; } else if (hour == TIMEPICKER_OPTIONS_NUMERIC_VAL) { dateTimeOptions.hourType = ZeroPrefixType::HIDE; } } auto minuteValue = paramObj->GetProperty(TIMEPICKER_OPTIONS_MINUTE); if (minuteValue->IsString()) { dateTimeOptions.minuteType = ZeroPrefixType::SHOW; std::string minute = minuteValue->ToString(); if (minute == TIMEPICKER_OPTIONS_NUMERIC_VAL) { dateTimeOptions.minuteType = ZeroPrefixType::HIDE; } } } void JSTimePicker::JSBind(BindingTarget globalObj) { JSClass::Declare("TimePicker"); MethodOptions opt = MethodOptions::NONE; JSClass::StaticMethod("create", &JSTimePicker::Create, opt); JSClass::StaticMethod("onChange", &JSTimePicker::OnChange); JSClass::StaticMethod("backgroundColor", &JSTimePicker::PickerBackgroundColor); JSClass::StaticMethod("loop", &JSTimePicker::Loop); JSClass::StaticMethod("useMilitaryTime", &JSTimePicker::UseMilitaryTime); JSClass::StaticMethod("enableHapticFeedback", &JSTimePicker::EnableHapticFeedback); JSClass::StaticMethod("onClick", &JSInteractableView::JsOnClick); JSClass::StaticMethod("onTouch", &JSInteractableView::JsOnTouch); JSClass::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey); JSClass::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete); JSClass::StaticMethod("onAttach", &JSInteractableView::JsOnAttach); JSClass::StaticMethod("onAppear", &JSInteractableView::JsOnAppear); JSClass::StaticMethod("onDetach", &JSInteractableView::JsOnDetach); JSClass::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear); JSClass::StaticMethod("disappearTextStyle", &JSTimePicker::SetDisappearTextStyle); JSClass::StaticMethod("textStyle", &JSTimePicker::SetTextStyle); JSClass::StaticMethod("selectedTextStyle", &JSTimePicker::SetSelectedTextStyle); JSClass::StaticMethod("dateTimeOptions", &JSTimePicker::DateTimeOptions); JSClass::StaticMethod("opacity", &JSTimePicker::JsOpacity); JSClass::InheritAndBind(globalObj); } void JSTimePicker::Create(const JSCallbackInfo& info) { JSRef paramObject = JSRef::New(); if (info.Length() >= 1 && info[0]->IsObject()) { paramObject = JSRef::Cast(info[0]); } CreateTimePicker(info, paramObject); } void JSTimePicker::JsOpacity(const JSCallbackInfo& info) { JSViewAbstract::JsOpacity(info); TimePickerModel::GetInstance()->HasUserDefinedOpacity(); } void JSTimePicker::Loop(const JSCallbackInfo& info) { bool isLoop = true; if (info[0]->IsBoolean()) { isLoop = info[0]->ToBoolean(); } TimePickerModel::GetInstance()->SetWheelModeEnabled(isLoop); } void JSTimePicker::EnableHapticFeedback(const JSCallbackInfo& info) { bool isEnableHapticFeedback = true; if (info[0]->IsBoolean()) { isEnableHapticFeedback = info[0]->ToBoolean(); } TimePickerModel::GetInstance()->SetIsEnableHapticFeedback(isEnableHapticFeedback); } void JSTimePicker::UseMilitaryTime(bool isUseMilitaryTime) { TimePickerModel::GetInstance()->SetHour24(isUseMilitaryTime); } void JSTimePicker::DateTimeOptions(const JSCallbackInfo& info) { JSRef paramObject; ZeroPrefixType hourType = ZeroPrefixType::AUTO; ZeroPrefixType minuteType = ZeroPrefixType::AUTO; ZeroPrefixType secondType = ZeroPrefixType::AUTO; if (info.Length() >= 1 && info[0]->IsObject()) { paramObject = JSRef::Cast(info[0]); auto hourValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_HOUR); if (hourValue->IsString()) { std::string hour = hourValue->ToString(); if (hour == TIMEPICKER_OPTIONS_TWO_DIGIT_VAL) { hourType = ZeroPrefixType::SHOW; } else if (hour == TIMEPICKER_OPTIONS_NUMERIC_VAL) { hourType = ZeroPrefixType::HIDE; } } auto minuteValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_MINUTE); if (minuteValue->IsString()) { minuteType = ZeroPrefixType::SHOW; std::string minute = minuteValue->ToString(); if (minute == TIMEPICKER_OPTIONS_NUMERIC_VAL) { minuteType = ZeroPrefixType::HIDE; } } auto secondValue = paramObject->GetProperty(TIMEPICKER_OPTIONS_SECOND); if (secondValue->IsString()) { secondType = ZeroPrefixType::SHOW; std::string second = secondValue->ToString(); if (second == TIMEPICKER_OPTIONS_NUMERIC_VAL) { secondType = ZeroPrefixType::HIDE; } } } TimePickerModel::GetInstance()->SetDateTimeOptions(hourType, minuteType, secondType); } void JSTimePicker::PickerBackgroundColor(const JSCallbackInfo& info) { JSViewAbstract::JsBackgroundColor(info); if (info.Length() < 1) { return; } Color backgroundColor; if (!ParseJsColor(info[0], backgroundColor)) { return; } TimePickerModel::GetInstance()->SetBackgroundColor(backgroundColor); } void JSTimePicker::SetDisappearTextStyle(const JSCallbackInfo& info) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; JSTimePickerTheme::ObtainTextStyle(textStyle); if (info[0]->IsObject()) { JSDatePicker::ParseTextStyle(info[0], textStyle, "disappearTextStyleTime"); } TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle); } void JSTimePicker::SetTextStyle(const JSCallbackInfo& info) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; JSTimePickerTheme::ObtainTextStyle(textStyle); if (info[0]->IsObject()) { JSDatePicker::ParseTextStyle(info[0], textStyle, "textStyleTime"); } TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle); } void JSTimePicker::SetSelectedTextStyle(const JSCallbackInfo& info) { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; JSTimePickerTheme::ObtainSelectedTextStyle(textStyle); if (info[0]->IsObject()) { JSDatePicker::ParseTextStyle(info[0], textStyle, "selectedTextStyleTime"); } TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle); } void JSTimePicker::CreateTimePicker(const JSCallbackInfo& info, const JSRef& paramObj) { auto selectedTime = paramObj->GetProperty("selected"); auto theme = GetTheme(); CHECK_NULL_VOID(theme); auto formatValue = paramObj->GetProperty("format"); bool showSecond = false; if (formatValue->IsNumber()) { auto displayedFormat = static_cast(formatValue->ToNumber()); if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) { showSecond = true; } } TimePickerModel::GetInstance()->CreateTimePicker(theme, showSecond); if (selectedTime->IsObject()) { JSRef selectedTimeObj = JSRef::Cast(selectedTime); JSRef changeEventVal = selectedTimeObj->GetProperty("changeEvent"); if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) { ParseSelectedDateTimeObject(info, selectedTimeObj, false); auto parseSelectedTime = ParseTime(selectedTimeObj->GetProperty("value")); TimePickerModel::GetInstance()->SetSelectedTime(parseSelectedTime); } else { TimePickerModel::GetInstance()->SetSelectedTime(ParseTime(selectedTime)); } } if (!JSTimePickerTheme::ApplyTheme()) { SetDefaultAttributes(); } } void JSTimePicker::SetDefaultAttributes() { auto theme = GetTheme(); CHECK_NULL_VOID(theme); NG::PickerTextStyle textStyle; auto selectedStyle = theme->GetOptionStyle(true, false); textStyle.textColor = selectedStyle.GetTextColor(); textStyle.fontSize = selectedStyle.GetFontSize(); textStyle.fontWeight = selectedStyle.GetFontWeight(); TimePickerModel::GetInstance()->SetSelectedTextStyle(theme, textStyle); auto disappearStyle = theme->GetDisappearOptionStyle(); textStyle.textColor = disappearStyle.GetTextColor(); textStyle.fontSize = disappearStyle.GetFontSize(); textStyle.fontWeight = disappearStyle.GetFontWeight(); TimePickerModel::GetInstance()->SetDisappearTextStyle(theme, textStyle); auto normalStyle = theme->GetOptionStyle(false, false); textStyle.textColor = normalStyle.GetTextColor(); textStyle.fontSize = normalStyle.GetFontSize(); textStyle.fontWeight = normalStyle.GetFontWeight(); TimePickerModel::GetInstance()->SetNormalTextStyle(theme, textStyle); } PickerTime JSTimePicker::ParseTime(const JSRef& timeVal) { auto pickerTime = PickerTime::Current(); if (!timeVal->IsObject()) { return pickerTime; } auto timeObj = JSRef::Cast(timeVal); auto yearFuncJsVal = timeObj->GetProperty("getFullYear"); if (yearFuncJsVal->IsFunction()) { auto yearFunc = JSRef::Cast(yearFuncJsVal); JSRef year = yearFunc->Call(timeObj); if (year->IsNumber() && LessOrEqual(year->ToNumber(), 0)) { return pickerTime; } } auto hourFuncJsVal = timeObj->GetProperty("getHours"); auto minuteFuncJsVal = timeObj->GetProperty("getMinutes"); auto secondFuncJsVal = timeObj->GetProperty("getSeconds"); if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) { return pickerTime; } auto hourFunc = JSRef::Cast(hourFuncJsVal); auto minuteFunc = JSRef::Cast(minuteFuncJsVal); auto secondFunc = JSRef::Cast(secondFuncJsVal); JSRef hour = hourFunc->Call(timeObj); JSRef minute = minuteFunc->Call(timeObj); JSRef second = secondFunc->Call(timeObj); if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) { pickerTime.SetHour(hour->ToNumber()); pickerTime.SetMinute(minute->ToNumber()); pickerTime.SetSecond(second->ToNumber()); } return pickerTime; } void JSTimePickerDialog::JSBind(BindingTarget globalObj) { JSClass::Declare("TimePickerDialog"); JSClass::StaticMethod("show", &JSTimePickerDialog::Show); JSClass::Bind<>(globalObj); } void TimePickerDialogAppearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent) { std::function didAppearEvent; std::function willAppearEvent; if (info.Length() == 0 || !info[0]->IsObject()) { return; } auto paramObject = JSRef::Cast(info[0]); WeakPtr targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onDidAppear = paramObject->GetProperty("onDidAppear"); if (!onDidAppear->IsUndefined() && onDidAppear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onDidAppear)); didAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onDidAppear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } auto onWillAppear = paramObject->GetProperty("onWillAppear"); if (!onWillAppear->IsUndefined() && onWillAppear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onWillAppear)); willAppearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onWillAppear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } timePickerDialogEvent.onDidAppear = std::move(didAppearEvent); timePickerDialogEvent.onWillAppear = std::move(willAppearEvent); } void TimePickerDialogDisappearEvent(const JSCallbackInfo& info, TimePickerDialogEvent& timePickerDialogEvent) { std::function didDisappearEvent; std::function willDisappearEvent; if (info.Length() == 0 || !info[0]->IsObject()) { return; } auto paramObject = JSRef::Cast(info[0]); WeakPtr targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onDidDisappear = paramObject->GetProperty("onDidDisappear"); if (!onDidDisappear->IsUndefined() && onDidDisappear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onDidDisappear)); didDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onDidDisappear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } auto onWillDisappear = paramObject->GetProperty("onWillDisappear"); if (!onWillDisappear->IsUndefined() && onWillDisappear->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onWillDisappear)); willDisappearEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onWillDisappear"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } timePickerDialogEvent.onDidDisappear = std::move(didDisappearEvent); timePickerDialogEvent.onWillDisappear = std::move(willDisappearEvent); } void JSTimePickerDialog::Show(const JSCallbackInfo& info) { auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely(); CHECK_NULL_VOID(scopedDelegate); if (!info[0]->IsObject()) { return; } auto paramObject = JSRef::Cast(info[0]); std::function cancelEvent; std::function acceptEvent; std::function changeEvent; WeakPtr targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode()); auto onChange = paramObject->GetProperty("onChange"); if (!onChange->IsUndefined() && onChange->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onChange)); changeEvent = [execCtx = info.GetExecutionContext(), type = DatePickerType::TIME, func = std::move(jsFunc), node = targetNode](const std::string& info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); std::vector keys; keys = { "year", "month", "day", "hour", "minute", "second" }; ACE_SCORING_EVENT("DatePickerDialog.onChange"); PipelineContext::SetCallBackNode(node); func->Execute(keys, info); }; } auto onAccept = paramObject->GetProperty("onAccept"); if (!onAccept->IsUndefined() && onAccept->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onAccept)); acceptEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]( const std::string& info) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); std::vector keys = { "year", "month", "day", "hour", "minute", "second" }; ACE_SCORING_EVENT("DatePickerDialog.onAccept"); PipelineContext::SetCallBackNode(node); func->Execute(keys, info); }; } auto onCancel = paramObject->GetProperty("onCancel"); if (!onCancel->IsUndefined() && onCancel->IsFunction()) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(onCancel)); cancelEvent = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode]() { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("DatePickerDialog.onCancel"); PipelineContext::SetCallBackNode(node); func->Execute(); }; } auto selectedTime = paramObject->GetProperty("selected"); auto useMilitaryTime = paramObject->GetProperty("useMilitaryTime"); NG::TimePickerSettingData settingData; PickerDialogInfo pickerDialog; settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean(); pickerDialog.isUseMilitaryTime = useMilitaryTime->ToBoolean(); if (selectedTime->IsObject()) { PickerDate dialogTitleDate = ParseDate(selectedTime); if (dialogTitleDate.GetYear() != 0) { settingData.dialogTitleDate = dialogTitleDate; pickerDialog.isSelectedTime = true; pickerDialog.pickerTime = ParseTime(selectedTime); } } JSDatePicker::ParseTextProperties(paramObject, settingData.properties); auto dateTimeOptionsValue = paramObject->GetProperty("dateTimeOptions"); if (dateTimeOptionsValue->IsObject()) { auto dateTimeOptionsObj = JSRef::Cast(dateTimeOptionsValue); JSDatePickerDialog::ParseDateTimeOptions(dateTimeOptionsObj, settingData.dateTimeOptions); } // Parse alignment auto alignmentValue = paramObject->GetProperty("alignment"); if (alignmentValue->IsNumber()) { auto alignment = alignmentValue->ToNumber(); if (alignment >= 0 && alignment < static_cast(DIALOG_ALIGNMENT.size())) { pickerDialog.alignment = DIALOG_ALIGNMENT[alignment]; } if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) { if (alignment == static_cast(DialogAlignment::TOP) || alignment == static_cast(DialogAlignment::TOP_START) || alignment == static_cast(DialogAlignment::TOP_END)) { pickerDialog.offset = DATEPICKER_OFFSET_DEFAULT_TOP; } } } // Parse offset auto offsetValue = paramObject->GetProperty("offset"); if (offsetValue->IsObject()) { auto offsetObj = JSRef::Cast(offsetValue); CalcDimension dx; auto dxValue = offsetObj->GetProperty("dx"); JSAlertDialog::ParseJsDimensionVp(dxValue, dx); CalcDimension dy; auto dyValue = offsetObj->GetProperty("dy"); JSAlertDialog::ParseJsDimensionVp(dyValue, dy); pickerDialog.offset = DimensionOffset(dx, dy); } // Parse maskRect. auto maskRectValue = paramObject->GetProperty("maskRect"); DimensionRect maskRect; if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) { pickerDialog.maskRect = maskRect; } auto backgroundColorValue = paramObject->GetProperty("backgroundColor"); Color backgroundColor; if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) { pickerDialog.backgroundColor = backgroundColor; } auto backgroundBlurStyle = paramObject->GetProperty("backgroundBlurStyle"); if (backgroundBlurStyle->IsNumber()) { auto blurStyle = backgroundBlurStyle->ToNumber(); if (blurStyle >= static_cast(BlurStyle::NO_MATERIAL) && blurStyle <= static_cast(BlurStyle::COMPONENT_ULTRA_THICK)) { pickerDialog.backgroundBlurStyle = blurStyle; } } ParseDatePickerHoverMode(pickerDialog, paramObject); auto buttonInfos = ParseButtonStyles(paramObject); auto shadowValue = paramObject->GetProperty("shadow"); Shadow shadow; if ((shadowValue->IsObject() || shadowValue->IsNumber()) && JSViewAbstract::ParseShadowProps(shadowValue, shadow)) { pickerDialog.shadow = shadow; } auto formatValue = paramObject->GetProperty("format"); bool showSecond = false; if (formatValue->IsNumber()) { auto displayedFormat = static_cast(formatValue->ToNumber()); if (displayedFormat == TimePickerFormat::HOUR_MINUTE_SECOND) { showSecond = true; } } settingData.showSecond = showSecond; TimePickerDialogEvent timePickerDialogEvent { nullptr, nullptr, nullptr, nullptr }; TimePickerDialogAppearEvent(info, timePickerDialogEvent); TimePickerDialogDisappearEvent(info, timePickerDialogEvent); TimePickerDialogModel::GetInstance()->SetTimePickerDialogShow(pickerDialog, settingData, std::move(cancelEvent), std::move(acceptEvent), std::move(changeEvent), timePickerDialogEvent, buttonInfos); } void JSTimePickerDialog::TimePickerDialogShow(const JSRef& paramObj, const std::map& dialogEvent, const std::map& dialogCancelEvent) { auto container = Container::CurrentSafely(); CHECK_NULL_VOID(container); auto pipelineContext = AccessibilityManager::DynamicCast(container->GetPipelineContext()); CHECK_NULL_VOID(pipelineContext); auto executor = pipelineContext->GetTaskExecutor(); CHECK_NULL_VOID(executor); auto theme = JSAlertDialog::GetTheme(); CHECK_NULL_VOID(theme); auto selectedTime = paramObj->GetProperty("selected"); auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime"); NG::TimePickerSettingData settingData; settingData.isUseMilitaryTime = useMilitaryTime->ToBoolean(); DialogProperties properties; properties.alignment = theme->GetAlignment(); if (properties.alignment == DialogAlignment::BOTTOM && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) { properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx())); } properties.customStyle = false; if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) { properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx())); } std::map timePickerProperty; if (selectedTime->IsObject()) { settingData.dialogTitleDate = ParseDate(selectedTime); timePickerProperty["selected"] = ParseTime(selectedTime); } JSDatePicker::ParseTextProperties(paramObj, settingData.properties); auto context = AccessibilityManager::DynamicCast(pipelineContext); auto overlayManager = context ? context->GetOverlayManager() : nullptr; executor->PostTask( [properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent, weak = WeakPtr(overlayManager)] { auto overlayManager = weak.Upgrade(); CHECK_NULL_VOID(overlayManager); overlayManager->ShowTimeDialog(properties, settingData, timePickerProperty, dialogEvent, dialogCancelEvent); }, TaskExecutor::TaskType::UI, "ArkUIDialogShowTimePicker"); } void JSTimePickerDialog::CreateTimePicker(RefPtr& component, const JSRef& paramObj) { auto timePicker = AceType::MakeRefPtr(); auto selectedTime = paramObj->GetProperty("selected"); auto useMilitaryTime = paramObj->GetProperty("useMilitaryTime"); bool isUseMilitaryTime = useMilitaryTime->ToBoolean(); if (selectedTime->IsObject()) { timePicker->SetSelectedTime(ParseTime(selectedTime)); } timePicker->SetIsDialog(true); timePicker->SetIsCreateDialogComponent(true); timePicker->SetHour24(isUseMilitaryTime); component = timePicker; } PickerTime JSTimePickerDialog::ParseTime(const JSRef& timeVal) { auto pickerTime = PickerTime(); if (!timeVal->IsObject()) { return pickerTime; } auto timeObj = JSRef::Cast(timeVal); auto hourFuncJsVal = timeObj->GetProperty("getHours"); auto minuteFuncJsVal = timeObj->GetProperty("getMinutes"); auto secondFuncJsVal = timeObj->GetProperty("getSeconds"); if (!(hourFuncJsVal->IsFunction() && minuteFuncJsVal->IsFunction() && secondFuncJsVal->IsFunction())) { return pickerTime; } auto hourFunc = JSRef::Cast(hourFuncJsVal); auto minuteFunc = JSRef::Cast(minuteFuncJsVal); auto secondFunc = JSRef::Cast(secondFuncJsVal); JSRef hour = hourFunc->Call(timeObj); JSRef minute = minuteFunc->Call(timeObj); JSRef second = secondFunc->Call(timeObj); if (hour->IsNumber() && minute->IsNumber() && second->IsNumber()) { pickerTime.SetHour(hour->ToNumber()); pickerTime.SetMinute(minute->ToNumber()); pickerTime.SetSecond(second->ToNumber()); } return pickerTime; } PickerDate JSTimePickerDialog::ParseDate(const JSRef& dateVal) { auto pickerDate = PickerDate(); if (!dateVal->IsObject()) { return pickerDate; } auto dateObj = JSRef::Cast(dateVal); auto yearFuncJsVal = dateObj->GetProperty("getFullYear"); auto monthFuncJsVal = dateObj->GetProperty("getMonth"); auto dateFuncJsVal = dateObj->GetProperty("getDate"); if (!(yearFuncJsVal->IsFunction() && monthFuncJsVal->IsFunction() && dateFuncJsVal->IsFunction())) { return pickerDate; } auto yearFunc = JSRef::Cast(yearFuncJsVal); auto monthFunc = JSRef::Cast(monthFuncJsVal); auto dateFunc = JSRef::Cast(dateFuncJsVal); JSRef year = yearFunc->Call(dateObj); JSRef month = monthFunc->Call(dateObj); JSRef date = dateFunc->Call(dateObj); if (year->IsNumber() && month->IsNumber() && date->IsNumber()) { pickerDate.SetYear(year->ToNumber()); pickerDate.SetMonth(month->ToNumber() + 1); // 0-11 means 1 to 12 months pickerDate.SetDay(date->ToNumber()); } return pickerDate; } } // namespace OHOS::Ace::Framework