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 "web/DateTimeChooserImpl.h" 34 35#include "core/InputTypeNames.h" 36#include "core/frame/FrameView.h" 37#include "core/html/forms/DateTimeChooserClient.h" 38#include "core/page/PagePopup.h" 39#include "core/rendering/RenderTheme.h" 40#include "platform/DateComponents.h" 41#include "platform/Language.h" 42#include "platform/text/PlatformLocale.h" 43#include "public/platform/Platform.h" 44#include "web/ChromeClientImpl.h" 45#include "web/WebViewImpl.h" 46 47namespace blink { 48 49DateTimeChooserImpl::DateTimeChooserImpl(ChromeClientImpl* chromeClient, DateTimeChooserClient* client, const DateTimeChooserParameters& parameters) 50 : m_chromeClient(chromeClient) 51 , m_client(client) 52 , m_popup(0) 53 , m_parameters(parameters) 54 , m_locale(Locale::create(parameters.locale)) 55{ 56 ASSERT(m_chromeClient); 57 ASSERT(m_client); 58 m_popup = m_chromeClient->openPagePopup(this, m_parameters.anchorRectInRootView); 59} 60 61PassRefPtr<DateTimeChooserImpl> DateTimeChooserImpl::create(ChromeClientImpl* chromeClient, DateTimeChooserClient* client, const DateTimeChooserParameters& parameters) 62{ 63 return adoptRef(new DateTimeChooserImpl(chromeClient, client, parameters)); 64} 65 66DateTimeChooserImpl::~DateTimeChooserImpl() 67{ 68} 69 70void DateTimeChooserImpl::endChooser() 71{ 72 if (!m_popup) 73 return; 74 m_chromeClient->closePagePopup(m_popup); 75} 76 77AXObject* DateTimeChooserImpl::rootAXObject() 78{ 79 return m_popup ? m_popup->rootAXObject() : 0; 80} 81 82IntSize DateTimeChooserImpl::contentSize() 83{ 84 return IntSize(0, 0); 85} 86 87static String valueToDateTimeString(double value, AtomicString type) 88{ 89 DateComponents components; 90 if (type == InputTypeNames::date) 91 components.setMillisecondsSinceEpochForDate(value); 92 else if (type == InputTypeNames::datetime_local) 93 components.setMillisecondsSinceEpochForDateTimeLocal(value); 94 else if (type == InputTypeNames::month) 95 components.setMonthsSinceEpoch(value); 96 else if (type == InputTypeNames::time) 97 components.setMillisecondsSinceMidnight(value); 98 else if (type == InputTypeNames::week) 99 components.setMillisecondsSinceEpochForWeek(value); 100 else 101 ASSERT_NOT_REACHED(); 102 return components.type() == DateComponents::Invalid ? String() : components.toString(); 103} 104 105void DateTimeChooserImpl::writeDocument(SharedBuffer* data) 106{ 107 String stepString = String::number(m_parameters.step); 108 String stepBaseString = String::number(m_parameters.stepBase, 11, WTF::TruncateTrailingZeros); 109 IntRect anchorRectInScreen = m_chromeClient->rootViewToScreen(m_parameters.anchorRectInRootView); 110 String todayLabelString; 111 String otherDateLabelString; 112 if (m_parameters.type == InputTypeNames::month) { 113 todayLabelString = locale().queryString(WebLocalizedString::ThisMonthButtonLabel); 114 otherDateLabelString = locale().queryString(WebLocalizedString::OtherMonthLabel); 115 } else if (m_parameters.type == InputTypeNames::week) { 116 todayLabelString = locale().queryString(WebLocalizedString::ThisWeekButtonLabel); 117 otherDateLabelString = locale().queryString(WebLocalizedString::OtherWeekLabel); 118 } else { 119 todayLabelString = locale().queryString(WebLocalizedString::CalendarToday); 120 otherDateLabelString = locale().queryString(WebLocalizedString::OtherDateLabel); 121 } 122 123 addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data); 124 data->append(Platform::current()->loadResource("pickerCommon.css")); 125 data->append(Platform::current()->loadResource("pickerButton.css")); 126 data->append(Platform::current()->loadResource("suggestionPicker.css")); 127 data->append(Platform::current()->loadResource("calendarPicker.css")); 128 addString("</style></head><body><div id=main>Loading...</div><script>\n" 129 "window.dialogArguments = {\n", data); 130 addProperty("anchorRectInScreen", anchorRectInScreen, data); 131 addProperty("min", valueToDateTimeString(m_parameters.minimum, m_parameters.type), data); 132 addProperty("max", valueToDateTimeString(m_parameters.maximum, m_parameters.type), data); 133 addProperty("step", stepString, data); 134 addProperty("stepBase", stepBaseString, data); 135 addProperty("required", m_parameters.required, data); 136 addProperty("currentValue", valueToDateTimeString(m_parameters.doubleValue, m_parameters.type), data); 137 addProperty("locale", m_parameters.locale.string(), data); 138 addProperty("todayLabel", todayLabelString, data); 139 addProperty("clearLabel", locale().queryString(WebLocalizedString::CalendarClear), data); 140 addProperty("weekLabel", locale().queryString(WebLocalizedString::WeekNumberLabel), data); 141 addProperty("axShowMonthSelector", locale().queryString(WebLocalizedString::AXCalendarShowMonthSelector), data); 142 addProperty("axShowNextMonth", locale().queryString(WebLocalizedString::AXCalendarShowNextMonth), data); 143 addProperty("axShowPreviousMonth", locale().queryString(WebLocalizedString::AXCalendarShowPreviousMonth), data); 144 addProperty("weekStartDay", m_locale->firstDayOfWeek(), data); 145 addProperty("shortMonthLabels", m_locale->shortMonthLabels(), data); 146 addProperty("dayLabels", m_locale->weekDayShortLabels(), data); 147 addProperty("isLocaleRTL", m_locale->isRTL(), data); 148 addProperty("isRTL", m_parameters.isAnchorElementRTL, data); 149 addProperty("mode", m_parameters.type.string(), data); 150 if (m_parameters.suggestions.size()) { 151 Vector<String> suggestionValues; 152 Vector<String> localizedSuggestionValues; 153 Vector<String> suggestionLabels; 154 for (unsigned i = 0; i < m_parameters.suggestions.size(); i++) { 155 suggestionValues.append(valueToDateTimeString(m_parameters.suggestions[i].value, m_parameters.type)); 156 localizedSuggestionValues.append(m_parameters.suggestions[i].localizedValue); 157 suggestionLabels.append(m_parameters.suggestions[i].label); 158 } 159 addProperty("suggestionValues", suggestionValues, data); 160 addProperty("localizedSuggestionValues", localizedSuggestionValues, data); 161 addProperty("suggestionLabels", suggestionLabels, data); 162 addProperty("inputWidth", static_cast<unsigned>(m_parameters.anchorRectInRootView.width()), data); 163 addProperty("showOtherDateEntry", RenderTheme::theme().supportsCalendarPicker(m_parameters.type), data); 164 addProperty("otherDateLabel", otherDateLabelString, data); 165 addProperty("suggestionHighlightColor", RenderTheme::theme().activeListBoxSelectionBackgroundColor().serialized(), data); 166 addProperty("suggestionHighlightTextColor", RenderTheme::theme().activeListBoxSelectionForegroundColor().serialized(), data); 167 } 168 addString("}\n", data); 169 170 data->append(Platform::current()->loadResource("pickerCommon.js")); 171 data->append(Platform::current()->loadResource("suggestionPicker.js")); 172 data->append(Platform::current()->loadResource("calendarPicker.js")); 173 addString("</script></body>\n", data); 174} 175 176Element& DateTimeChooserImpl::ownerElement() 177{ 178 return m_client->ownerElement(); 179} 180 181Locale& DateTimeChooserImpl::locale() 182{ 183 return *m_locale; 184} 185 186void DateTimeChooserImpl::setValueAndClosePopup(int numValue, const String& stringValue) 187{ 188 RefPtr<DateTimeChooserImpl> protector(this); 189 if (numValue >= 0) 190 setValue(stringValue); 191 endChooser(); 192} 193 194void DateTimeChooserImpl::setValue(const String& value) 195{ 196 m_client->didChooseValue(value); 197} 198 199void DateTimeChooserImpl::closePopup() 200{ 201 endChooser(); 202} 203 204void DateTimeChooserImpl::didClosePopup() 205{ 206 ASSERT(m_client); 207 m_popup = 0; 208 m_client->didEndChooser(); 209} 210 211} // namespace blink 212 213#endif // ENABLE(INPUT_MULTIPLE_FIELDS_UI) 214