1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 33 #include "DateTimeChooserImpl.h" 34 35 #include "CalendarPicker.h" 36 #include "ChromeClientImpl.h" 37 #include "InputTypeNames.h" 38 #include "PickerCommon.h" 39 #include "WebViewImpl.h" 40 #include "core/frame/FrameView.h" 41 #include "core/rendering/RenderTheme.h" 42 #include "platform/DateComponents.h" 43 #include "platform/DateTimeChooserClient.h" 44 #include "platform/Language.h" 45 #include "platform/text/PlatformLocale.h" 46 47 using namespace WebCore; 48 49 namespace blink { 50 51 DateTimeChooserImpl::DateTimeChooserImpl(ChromeClientImpl* chromeClient, WebCore::DateTimeChooserClient* client, const WebCore::DateTimeChooserParameters& parameters) 52 : m_chromeClient(chromeClient) 53 , m_client(client) 54 , m_popup(0) 55 , m_parameters(parameters) 56 , m_locale(WebCore::Locale::create(parameters.locale)) 57 { 58 ASSERT(m_chromeClient); 59 ASSERT(m_client); 60 m_popup = m_chromeClient->openPagePopup(this, m_parameters.anchorRectInRootView); 61 } 62 63 PassRefPtr<DateTimeChooserImpl> DateTimeChooserImpl::create(ChromeClientImpl* chromeClient, WebCore::DateTimeChooserClient* client, const WebCore::DateTimeChooserParameters& parameters) 64 { 65 return adoptRef(new DateTimeChooserImpl(chromeClient, client, parameters)); 66 } 67 68 DateTimeChooserImpl::~DateTimeChooserImpl() 69 { 70 } 71 72 void DateTimeChooserImpl::endChooser() 73 { 74 if (!m_popup) 75 return; 76 m_chromeClient->closePagePopup(m_popup); 77 } 78 79 WebCore::IntSize DateTimeChooserImpl::contentSize() 80 { 81 return WebCore::IntSize(0, 0); 82 } 83 84 static String valueToDateTimeString(double value, AtomicString type) 85 { 86 WebCore::DateComponents components; 87 if (type == WebCore::InputTypeNames::date) 88 components.setMillisecondsSinceEpochForDate(value); 89 else if (type == WebCore::InputTypeNames::datetime_local) 90 components.setMillisecondsSinceEpochForDateTimeLocal(value); 91 else if (type == WebCore::InputTypeNames::month) 92 components.setMonthsSinceEpoch(value); 93 else if (type == WebCore::InputTypeNames::time) 94 components.setMillisecondsSinceMidnight(value); 95 else if (type == WebCore::InputTypeNames::week) 96 components.setMillisecondsSinceEpochForWeek(value); 97 else 98 ASSERT_NOT_REACHED(); 99 return components.type() == WebCore::DateComponents::Invalid ? String() : components.toString(); 100 } 101 102 void DateTimeChooserImpl::writeDocument(WebCore::DocumentWriter& writer) 103 { 104 String stepString = String::number(m_parameters.step); 105 String stepBaseString = String::number(m_parameters.stepBase, 11, WTF::TruncateTrailingZeros); 106 IntRect anchorRectInScreen = m_chromeClient->rootViewToScreen(m_parameters.anchorRectInRootView); 107 String todayLabelString; 108 String otherDateLabelString; 109 if (m_parameters.type == WebCore::InputTypeNames::month) { 110 todayLabelString = locale().queryString(WebLocalizedString::ThisMonthButtonLabel); 111 otherDateLabelString = locale().queryString(WebLocalizedString::OtherMonthLabel); 112 } else if (m_parameters.type == WebCore::InputTypeNames::week) { 113 todayLabelString = locale().queryString(WebLocalizedString::ThisWeekButtonLabel); 114 otherDateLabelString = locale().queryString(WebLocalizedString::OtherWeekLabel); 115 } else { 116 todayLabelString = locale().queryString(WebLocalizedString::CalendarToday); 117 otherDateLabelString = locale().queryString(WebLocalizedString::OtherDateLabel); 118 } 119 120 addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", writer); 121 writer.addData(pickerCommonCss, sizeof(pickerCommonCss)); 122 writer.addData(pickerButtonCss, sizeof(pickerButtonCss)); 123 writer.addData(suggestionPickerCss, sizeof(suggestionPickerCss)); 124 writer.addData(calendarPickerCss, sizeof(calendarPickerCss)); 125 addString("</style></head><body><div id=main>Loading...</div><script>\n" 126 "window.dialogArguments = {\n", writer); 127 addProperty("anchorRectInScreen", anchorRectInScreen, writer); 128 addProperty("min", valueToDateTimeString(m_parameters.minimum, m_parameters.type), writer); 129 addProperty("max", valueToDateTimeString(m_parameters.maximum, m_parameters.type), writer); 130 addProperty("step", stepString, writer); 131 addProperty("stepBase", stepBaseString, writer); 132 addProperty("required", m_parameters.required, writer); 133 addProperty("currentValue", valueToDateTimeString(m_parameters.doubleValue, m_parameters.type), writer); 134 addProperty("locale", m_parameters.locale.string(), writer); 135 addProperty("todayLabel", todayLabelString, writer); 136 addProperty("clearLabel", locale().queryString(WebLocalizedString::CalendarClear), writer); 137 addProperty("weekLabel", locale().queryString(WebLocalizedString::WeekNumberLabel), writer); 138 addProperty("weekStartDay", m_locale->firstDayOfWeek(), writer); 139 addProperty("shortMonthLabels", m_locale->shortMonthLabels(), writer); 140 addProperty("dayLabels", m_locale->weekDayShortLabels(), writer); 141 addProperty("isLocaleRTL", m_locale->isRTL(), writer); 142 addProperty("isRTL", m_parameters.isAnchorElementRTL, writer); 143 addProperty("mode", m_parameters.type.string(), writer); 144 if (m_parameters.suggestions.size()) { 145 Vector<String> suggestionValues; 146 Vector<String> localizedSuggestionValues; 147 Vector<String> suggestionLabels; 148 for (unsigned i = 0; i < m_parameters.suggestions.size(); i++) { 149 suggestionValues.append(valueToDateTimeString(m_parameters.suggestions[i].value, m_parameters.type)); 150 localizedSuggestionValues.append(m_parameters.suggestions[i].localizedValue); 151 suggestionLabels.append(m_parameters.suggestions[i].label); 152 } 153 addProperty("suggestionValues", suggestionValues, writer); 154 addProperty("localizedSuggestionValues", localizedSuggestionValues, writer); 155 addProperty("suggestionLabels", suggestionLabels, writer); 156 addProperty("inputWidth", static_cast<unsigned>(m_parameters.anchorRectInRootView.width()), writer); 157 addProperty("showOtherDateEntry", WebCore::RenderTheme::theme().supportsCalendarPicker(m_parameters.type), writer); 158 addProperty("otherDateLabel", otherDateLabelString, writer); 159 addProperty("suggestionHighlightColor", WebCore::RenderTheme::theme().activeListBoxSelectionBackgroundColor().serialized(), writer); 160 addProperty("suggestionHighlightTextColor", WebCore::RenderTheme::theme().activeListBoxSelectionForegroundColor().serialized(), writer); 161 } 162 addString("}\n", writer); 163 164 writer.addData(pickerCommonJs, sizeof(pickerCommonJs)); 165 writer.addData(suggestionPickerJs, sizeof(suggestionPickerJs)); 166 writer.addData(calendarPickerJs, sizeof(calendarPickerJs)); 167 addString("</script></body>\n", writer); 168 } 169 170 WebCore::Locale& DateTimeChooserImpl::locale() 171 { 172 return *m_locale; 173 } 174 175 void DateTimeChooserImpl::setValueAndClosePopup(int numValue, const String& stringValue) 176 { 177 RefPtr<DateTimeChooserImpl> protector(this); 178 if (numValue >= 0) 179 setValue(stringValue); 180 endChooser(); 181 } 182 183 void DateTimeChooserImpl::setValue(const String& value) 184 { 185 m_client->didChooseValue(value); 186 } 187 188 void DateTimeChooserImpl::closePopup() 189 { 190 endChooser(); 191 } 192 193 void DateTimeChooserImpl::didClosePopup() 194 { 195 ASSERT(m_client); 196 m_popup = 0; 197 m_client->didEndChooser(); 198 } 199 200 } // namespace blink 201 202 #endif // ENABLE(INPUT_MULTIPLE_FIELDS_UI) 203