| /* |
| * Copyright (C) 2012 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "third_party/blink/renderer/core/html/forms/date_time_chooser_impl.h" |
| |
| #include "build/build_config.h" |
| #include "third_party/blink/public/mojom/choosers/date_time_chooser.mojom-blink.h" |
| #include "third_party/blink/public/platform/platform.h" |
| #include "third_party/blink/public/strings/grit/blink_strings.h" |
| #include "third_party/blink/renderer/core/dom/element.h" |
| #include "third_party/blink/renderer/core/dom/node_computed_style.h" |
| #include "third_party/blink/renderer/core/frame/local_frame.h" |
| #include "third_party/blink/renderer/core/frame/local_frame_view.h" |
| #include "third_party/blink/renderer/core/html/forms/chooser_resource_loader.h" |
| #include "third_party/blink/renderer/core/html/forms/date_time_chooser_client.h" |
| #include "third_party/blink/renderer/core/input_type_names.h" |
| #include "third_party/blink/renderer/core/layout/layout_theme.h" |
| #include "third_party/blink/renderer/core/page/chrome_client.h" |
| #include "third_party/blink/renderer/core/page/page_popup.h" |
| #include "third_party/blink/renderer/platform/language.h" |
| #include "third_party/blink/renderer/platform/text/date_components.h" |
| #include "third_party/blink/renderer/platform/text/platform_locale.h" |
| #include "ui/base/ui_base_features.h" |
| |
| namespace blink { |
| |
| DateTimeChooserImpl::DateTimeChooserImpl( |
| LocalFrame* frame, |
| DateTimeChooserClient* client, |
| const DateTimeChooserParameters& parameters) |
| : frame_(frame), |
| client_(client), |
| popup_(nullptr), |
| parameters_(¶meters), |
| locale_(Locale::Create(parameters.locale)) { |
| DCHECK(RuntimeEnabledFeatures::InputMultipleFieldsUIEnabled()); |
| DCHECK(frame_); |
| DCHECK(client_); |
| popup_ = frame_->View()->GetChromeClient()->OpenPagePopup(this); |
| parameters_ = nullptr; |
| } |
| |
| DateTimeChooserImpl::~DateTimeChooserImpl() = default; |
| |
| void DateTimeChooserImpl::Trace(Visitor* visitor) const { |
| visitor->Trace(frame_); |
| visitor->Trace(client_); |
| DateTimeChooser::Trace(visitor); |
| } |
| |
| void DateTimeChooserImpl::EndChooser() { |
| if (!popup_) |
| return; |
| frame_->View()->GetChromeClient()->ClosePagePopup(popup_); |
| } |
| |
| AXObject* DateTimeChooserImpl::RootAXObject() { |
| return popup_ ? popup_->RootAXObject() : nullptr; |
| } |
| |
| static String ValueToDateTimeString(double value, AtomicString type) { |
| DateComponents components; |
| if (type == input_type_names::kDate) |
| components.SetMillisecondsSinceEpochForDate(value); |
| else if (type == input_type_names::kDatetimeLocal) |
| components.SetMillisecondsSinceEpochForDateTimeLocal(value); |
| else if (type == input_type_names::kMonth) |
| components.SetMonthsSinceEpoch(value); |
| else if (type == input_type_names::kTime) |
| components.SetMillisecondsSinceMidnight(value); |
| else if (type == input_type_names::kWeek) |
| components.SetMillisecondsSinceEpochForWeek(value); |
| else |
| NOTREACHED(); |
| return components.GetType() == DateComponents::kInvalid |
| ? String() |
| : components.ToString(); |
| } |
| |
| void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) { |
| String step_string = String::Number(parameters_->step); |
| String step_base_string = String::Number(parameters_->step_base, 11); |
| String today_label_string; |
| String other_date_label_string; |
| if (parameters_->type == input_type_names::kMonth) { |
| today_label_string = GetLocale().QueryString(IDS_FORM_THIS_MONTH_LABEL); |
| other_date_label_string = |
| GetLocale().QueryString(IDS_FORM_OTHER_MONTH_LABEL); |
| } else if (parameters_->type == input_type_names::kWeek) { |
| today_label_string = GetLocale().QueryString(IDS_FORM_THIS_WEEK_LABEL); |
| other_date_label_string = |
| GetLocale().QueryString(IDS_FORM_OTHER_WEEK_LABEL); |
| } else { |
| today_label_string = GetLocale().QueryString(IDS_FORM_CALENDAR_TODAY); |
| other_date_label_string = |
| GetLocale().QueryString(IDS_FORM_OTHER_DATE_LABEL); |
| } |
| |
| AddString( |
| "<!DOCTYPE html><head><meta charset='UTF-8'><meta name='color-scheme' " |
| "content='light dark'><style>\n", |
| data); |
| |
| data->Append(ChooserResourceLoader::GetPickerCommonStyleSheet()); |
| if (!features::IsFormControlsRefreshEnabled()) |
| data->Append(ChooserResourceLoader::GetPickerButtonStyleSheet()); |
| data->Append(ChooserResourceLoader::GetSuggestionPickerStyleSheet()); |
| data->Append(ChooserResourceLoader::GetCalendarPickerStyleSheet()); |
| if (features::IsFormControlsRefreshEnabled()) { |
| data->Append(ChooserResourceLoader::GetCalendarPickerRefreshStyleSheet()); |
| if (parameters_->type == input_type_names::kTime || |
| parameters_->type == input_type_names::kDatetimeLocal) { |
| data->Append(ChooserResourceLoader::GetTimePickerStyleSheet()); |
| } |
| } |
| AddString( |
| "</style></head><body><div id=main>Loading...</div><script>\n" |
| "window.dialogArguments = {\n", |
| data); |
| AddProperty("anchorRectInScreen", parameters_->anchor_rect_in_screen, data); |
| AddProperty("zoomFactor", ScaledZoomFactor(), data); |
| AddProperty("min", |
| ValueToDateTimeString(parameters_->minimum, parameters_->type), |
| data); |
| AddProperty("max", |
| ValueToDateTimeString(parameters_->maximum, parameters_->type), |
| data); |
| AddProperty("step", step_string, data); |
| AddProperty("stepBase", step_base_string, data); |
| AddProperty("required", parameters_->required, data); |
| AddProperty( |
| "currentValue", |
| ValueToDateTimeString(parameters_->double_value, parameters_->type), |
| data); |
| AddProperty("focusedFieldIndex", parameters_->focused_field_index, data); |
| AddProperty("locale", parameters_->locale.GetString(), data); |
| AddProperty("todayLabel", today_label_string, data); |
| AddLocalizedProperty("clearLabel", IDS_FORM_CALENDAR_CLEAR, data); |
| AddLocalizedProperty("weekLabel", IDS_FORM_WEEK_NUMBER_LABEL, data); |
| AddLocalizedProperty("axShowMonthSelector", |
| IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR, data); |
| AddLocalizedProperty("axShowNextMonth", IDS_AX_CALENDAR_SHOW_NEXT_MONTH, |
| data); |
| AddLocalizedProperty("axShowPreviousMonth", |
| IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH, data); |
| AddLocalizedProperty("axHourLabel", IDS_AX_HOUR_FIELD_TEXT, data); |
| AddLocalizedProperty("axMinuteLabel", IDS_AX_MINUTE_FIELD_TEXT, data); |
| AddLocalizedProperty("axSecondLabel", IDS_AX_SECOND_FIELD_TEXT, data); |
| AddLocalizedProperty("axMillisecondLabel", IDS_AX_MILLISECOND_FIELD_TEXT, |
| data); |
| AddLocalizedProperty("axAmPmLabel", IDS_AX_AM_PM_FIELD_TEXT, data); |
| AddProperty("weekStartDay", locale_->FirstDayOfWeek(), data); |
| AddProperty("shortMonthLabels", locale_->ShortMonthLabels(), data); |
| AddProperty("dayLabels", locale_->WeekDayShortLabels(), data); |
| AddProperty("ampmLabels", locale_->TimeAMPMLabels(), data); |
| AddProperty("isLocaleRTL", locale_->IsRTL(), data); |
| AddProperty("isRTL", parameters_->is_anchor_element_rtl, data); |
| AddProperty("isFormControlsRefreshEnabled", |
| features::IsFormControlsRefreshEnabled(), data); |
| #if defined(OS_MAC) |
| AddProperty("isBorderTransparent", features::IsFormControlsRefreshEnabled(), |
| data); |
| #endif |
| AddProperty("mode", parameters_->type.GetString(), data); |
| AddProperty("isAMPMFirst", parameters_->is_ampm_first, data); |
| AddProperty("hasAMPM", parameters_->has_ampm, data); |
| AddProperty("hasSecond", parameters_->has_second, data); |
| AddProperty("hasMillisecond", parameters_->has_millisecond, data); |
| if (parameters_->suggestions.size()) { |
| Vector<String> suggestion_values; |
| Vector<String> localized_suggestion_values; |
| Vector<String> suggestion_labels; |
| for (unsigned i = 0; i < parameters_->suggestions.size(); i++) { |
| suggestion_values.push_back(ValueToDateTimeString( |
| parameters_->suggestions[i]->value, parameters_->type)); |
| localized_suggestion_values.push_back( |
| parameters_->suggestions[i]->localized_value); |
| suggestion_labels.push_back(parameters_->suggestions[i]->label); |
| } |
| AddProperty("suggestionValues", suggestion_values, data); |
| AddProperty("localizedSuggestionValues", localized_suggestion_values, data); |
| AddProperty("suggestionLabels", suggestion_labels, data); |
| AddProperty( |
| "inputWidth", |
| static_cast<unsigned>(parameters_->anchor_rect_in_screen.Width()), |
| data); |
| AddProperty( |
| "showOtherDateEntry", |
| LayoutTheme::GetTheme().SupportsCalendarPicker(parameters_->type), |
| data); |
| AddProperty("otherDateLabel", other_date_label_string, data); |
| |
| const ComputedStyle* style = OwnerElement().GetComputedStyle(); |
| mojom::blink::ColorScheme color_scheme = |
| style ? style->UsedColorScheme() : mojom::blink::ColorScheme::kLight; |
| |
| AddProperty("suggestionHighlightColor", |
| LayoutTheme::GetTheme() |
| .ActiveListBoxSelectionBackgroundColor(color_scheme) |
| .Serialized(), |
| data); |
| AddProperty("suggestionHighlightTextColor", |
| LayoutTheme::GetTheme() |
| .ActiveListBoxSelectionForegroundColor(color_scheme) |
| .Serialized(), |
| data); |
| } |
| AddString("}\n", data); |
| |
| data->Append(ChooserResourceLoader::GetPickerCommonJS()); |
| data->Append(ChooserResourceLoader::GetSuggestionPickerJS()); |
| if (features::IsFormControlsRefreshEnabled()) { |
| data->Append(ChooserResourceLoader::GetMonthPickerJS()); |
| if (parameters_->type == input_type_names::kTime) { |
| data->Append(ChooserResourceLoader::GetTimePickerJS()); |
| } else if (parameters_->type == input_type_names::kDatetimeLocal) { |
| data->Append(ChooserResourceLoader::GetTimePickerJS()); |
| data->Append(ChooserResourceLoader::GetDateTimeLocalPickerJS()); |
| } |
| } |
| data->Append(ChooserResourceLoader::GetCalendarPickerJS()); |
| AddString("</script></body>\n", data); |
| } |
| |
| Element& DateTimeChooserImpl::OwnerElement() { |
| return client_->OwnerElement(); |
| } |
| |
| ChromeClient& DateTimeChooserImpl::GetChromeClient() { |
| return *frame_->View()->GetChromeClient(); |
| } |
| |
| Locale& DateTimeChooserImpl::GetLocale() { |
| return *locale_; |
| } |
| |
| void DateTimeChooserImpl::SetValueAndClosePopup(int num_value, |
| const String& string_value) { |
| if (num_value >= 0) |
| SetValue(string_value); |
| EndChooser(); |
| } |
| |
| void DateTimeChooserImpl::SetValue(const String& value) { |
| client_->DidChooseValue(value); |
| } |
| |
| void DateTimeChooserImpl::CancelPopup() { |
| EndChooser(); |
| } |
| |
| void DateTimeChooserImpl::DidClosePopup() { |
| DCHECK(client_); |
| popup_ = nullptr; |
| client_->DidEndChooser(); |
| } |
| |
| } // namespace blink |