Home | History | Annotate | Download | only in web
      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 
     47 namespace blink {
     48 
     49 DateTimeChooserImpl::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 
     61 PassRefPtr<DateTimeChooserImpl> DateTimeChooserImpl::create(ChromeClientImpl* chromeClient, DateTimeChooserClient* client, const DateTimeChooserParameters& parameters)
     62 {
     63     return adoptRef(new DateTimeChooserImpl(chromeClient, client, parameters));
     64 }
     65 
     66 DateTimeChooserImpl::~DateTimeChooserImpl()
     67 {
     68 }
     69 
     70 void DateTimeChooserImpl::endChooser()
     71 {
     72     if (!m_popup)
     73         return;
     74     m_chromeClient->closePagePopup(m_popup);
     75 }
     76 
     77 AXObject* DateTimeChooserImpl::rootAXObject()
     78 {
     79     return m_popup ? m_popup->rootAXObject() : 0;
     80 }
     81 
     82 IntSize DateTimeChooserImpl::contentSize()
     83 {
     84     return IntSize(0, 0);
     85 }
     86 
     87 static 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 
    105 void 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 
    176 Element& DateTimeChooserImpl::ownerElement()
    177 {
    178     return m_client->ownerElement();
    179 }
    180 
    181 Locale& DateTimeChooserImpl::locale()
    182 {
    183     return *m_locale;
    184 }
    185 
    186 void DateTimeChooserImpl::setValueAndClosePopup(int numValue, const String& stringValue)
    187 {
    188     RefPtr<DateTimeChooserImpl> protector(this);
    189     if (numValue >= 0)
    190         setValue(stringValue);
    191     endChooser();
    192 }
    193 
    194 void DateTimeChooserImpl::setValue(const String& value)
    195 {
    196     m_client->didChooseValue(value);
    197 }
    198 
    199 void DateTimeChooserImpl::closePopup()
    200 {
    201     endChooser();
    202 }
    203 
    204 void 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