Title: [113416] trunk/Source
Revision
113416
Author
[email protected]
Date
2012-04-06 00:45:48 -0700 (Fri, 06 Apr 2012)

Log Message

Calendar Picker: Add code to open/close the calendar picker
https://bugs.webkit.org/show_bug.cgi?id=83258

Reviewed by Hajime Morita.

Source/WebCore:

No new tests. This code is not used because of no ENABLE_INPUT_TYPE_DATE.

* WebCore.gypi: Add existing header files.

* html/DateInputType.cpp:
(WebCore::DateInputType::DateInputType):
Moved from DateInputType.h because the constructor depends on
CalendarPickerElement.
(WebCore::DateInputType::createShadowSubtree):
Store a CalendarPickerElement object.
(WebCore::DateInputType::destroyShadowSubtree):
Release the CalendarPickerElement object.
(WebCore::DateInputType::handleBlurEvent):
Close the calendar picker when the input loses focus.
* html/DateInputType.h:
(DateInputType):
- Move the constructor definition to DateInputType.cpp
- Add function declarations
- Add m_pickerElement data member.

* html/shadow/CalendarPickerElement.cpp:
(WebCore::CalendarPickerElement::hostInput): A helper to get the host <input>.
(WebCore::CalendarPickerElement::defaultEventHandler):
If the element is clicked, open a calendar picker.
(WebCore::CalendarPickerElement::openPopup):
Opens a calendar picker by ChromeClient::openPagePopup().
(WebCore::CalendarPickerElement::closePopup):
Closes a calendar picker by ChromeClient::closePagePopup().
(WebCore::CalendarPickerElement::detach):
Closes a calendar picker when the element loses a renderer.

(WebCore::CalendarPickerElement::contentSize):
Provides the initial size of a popup.
(WebCore::addString): A helper for writeDocument().
(WebCore::addJavaScriptString): ditto.
(WebCore::addProperty): ditto.
(WebCore::CalendarPickerElement::writeDocument):
Provides the source of a popup. The function creates a complete HTML with:
- WebCore/Resources/calendarPicker.css
- WebCore/Resources/calendarPicker.js
- An object to pass localization strings and <input> state
(WebCore::CalendarPickerElement::setValueAndClosePopup):
Sets the value from a calendar picker to the <input>.
(WebCore::CalendarPickerElement::didClosePopup):
Clear the popup object.
* html/shadow/CalendarPickerElement.h:
(CalendarPickerElement): Add declarations.

* platform/text/LocalizedCalendarICU.cpp:
(WebCore::getFirstDayOfWeek): Make sure this is 0-base. UCAL_SUNDAY is 1.

Source/WebKit/chromium:

* features.gypi: Enable ENABLE_PAGE_POPUP for non-Android
platforms. This is needed because ENABLE_CALENDAR_PICKER now depends on
ENABLE_PAGE_POPUP.
* src/ChroemClientImpl.cpp: Add stubs.
(WebKit::ChromeClientImpl::openPagePopup):
(WebKit::ChromeClientImpl::closePagePopup):
* src/ChromeClientImpl.h: Add declarations of openPagePopup() and closePagePopup().

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (113415 => 113416)


--- trunk/Source/WebCore/ChangeLog	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebCore/ChangeLog	2012-04-06 07:45:48 UTC (rev 113416)
@@ -1,3 +1,61 @@
+2012-04-06  Kent Tamura  <[email protected]>
+
+        Calendar Picker: Add code to open/close the calendar picker
+        https://bugs.webkit.org/show_bug.cgi?id=83258
+
+        Reviewed by Hajime Morita.
+
+        No new tests. This code is not used because of no ENABLE_INPUT_TYPE_DATE.
+
+        * WebCore.gypi: Add existing header files.
+
+        * html/DateInputType.cpp:
+        (WebCore::DateInputType::DateInputType):
+        Moved from DateInputType.h because the constructor depends on
+        CalendarPickerElement.
+        (WebCore::DateInputType::createShadowSubtree):
+        Store a CalendarPickerElement object.
+        (WebCore::DateInputType::destroyShadowSubtree):
+        Release the CalendarPickerElement object.
+        (WebCore::DateInputType::handleBlurEvent):
+        Close the calendar picker when the input loses focus.
+        * html/DateInputType.h:
+        (DateInputType):
+        - Move the constructor definition to DateInputType.cpp
+        - Add function declarations
+        - Add m_pickerElement data member.
+
+        * html/shadow/CalendarPickerElement.cpp:
+        (WebCore::CalendarPickerElement::hostInput): A helper to get the host <input>.
+        (WebCore::CalendarPickerElement::defaultEventHandler):
+        If the element is clicked, open a calendar picker.
+        (WebCore::CalendarPickerElement::openPopup):
+        Opens a calendar picker by ChromeClient::openPagePopup().
+        (WebCore::CalendarPickerElement::closePopup):
+        Closes a calendar picker by ChromeClient::closePagePopup().
+        (WebCore::CalendarPickerElement::detach):
+        Closes a calendar picker when the element loses a renderer.
+
+        (WebCore::CalendarPickerElement::contentSize):
+        Provides the initial size of a popup.
+        (WebCore::addString): A helper for writeDocument().
+        (WebCore::addJavaScriptString): ditto.
+        (WebCore::addProperty): ditto.
+        (WebCore::CalendarPickerElement::writeDocument):
+        Provides the source of a popup. The function creates a complete HTML with:
+        - WebCore/Resources/calendarPicker.css
+        - WebCore/Resources/calendarPicker.js
+        - An object to pass localization strings and <input> state
+        (WebCore::CalendarPickerElement::setValueAndClosePopup):
+        Sets the value from a calendar picker to the <input>.
+        (WebCore::CalendarPickerElement::didClosePopup):
+        Clear the popup object.
+        * html/shadow/CalendarPickerElement.h:
+        (CalendarPickerElement): Add declarations.
+
+        * platform/text/LocalizedCalendarICU.cpp:
+        (WebCore::getFirstDayOfWeek): Make sure this is 0-base. UCAL_SUNDAY is 1.
+
 2012-04-05  Adele Peterson  <[email protected]>
 
         <rdar://problem/11133179> and https://bugs.webkit.org/show_bug.cgi?id=74129

Modified: trunk/Source/WebCore/WebCore.gypi (113415 => 113416)


--- trunk/Source/WebCore/WebCore.gypi	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebCore/WebCore.gypi	2012-04-06 07:45:48 UTC (rev 113416)
@@ -238,6 +238,8 @@
             'page/MemoryInfo.h',
             'page/Page.h',
             'page/PageGroup.h',
+            'page/PagePopup.h',
+            'page/PagePopupClient.h',
             'page/PageSerializer.h',
             'page/PageVisibilityState.h',
             'page/PrintContext.h',

Modified: trunk/Source/WebCore/html/DateInputType.cpp (113415 => 113416)


--- trunk/Source/WebCore/html/DateInputType.cpp	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebCore/html/DateInputType.cpp	2012-04-06 07:45:48 UTC (rev 113416)
@@ -46,6 +46,11 @@
 static const double dateDefaultStep = 1.0;
 static const double dateStepScaleFactor = 86400000.0;
 
+inline DateInputType::DateInputType(HTMLInputElement* element)
+    : BaseDateAndTimeInputType(element)
+{
+}
+
 PassOwnPtr<InputType> DateInputType::create(HTMLInputElement* element)
 {
     return adoptPtr(new DateInputType(element));
@@ -103,9 +108,16 @@
 void DateInputType::createShadowSubtree()
 {
     BaseDateAndTimeInputType::createShadowSubtree();
-    containerElement()->insertBefore(CalendarPickerElement::create(element()->document()), innerBlockElement()->nextSibling(), ASSERT_NO_EXCEPTION);
+    m_pickerElement = CalendarPickerElement::create(element()->document());
+    containerElement()->insertBefore(m_pickerElement.get(), innerBlockElement()->nextSibling(), ASSERT_NO_EXCEPTION);
 }
 
+void DateInputType::destroyShadowSubtree()
+{
+    TextFieldInputType::destroyShadowSubtree();
+    m_pickerElement.clear();
+}
+
 bool DateInputType::needsContainer() const
 {
     return true;
@@ -115,6 +127,12 @@
 {
     return false;
 }
+
+void DateInputType::handleBlurEvent()
+{
+    if (m_pickerElement)
+        m_pickerElement->closePopup();
+}
 #endif // ENABLE(CALENDAR_PICKER)
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/DateInputType.h (113415 => 113416)


--- trunk/Source/WebCore/html/DateInputType.h	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebCore/html/DateInputType.h	2012-04-06 07:45:48 UTC (rev 113416)
@@ -32,17 +32,20 @@
 #define DateInputType_h
 
 #include "BaseDateAndTimeInputType.h"
+#include <wtf/RefPtr.h>
 
 #if ENABLE(INPUT_TYPE_DATE)
 
 namespace WebCore {
 
+class CalendarPickerElement;
+
 class DateInputType : public BaseDateAndTimeInputType {
 public:
     static PassOwnPtr<InputType> create(HTMLInputElement*);
 
 private:
-    DateInputType(HTMLInputElement* element) : BaseDateAndTimeInputType(element) { }
+    DateInputType(HTMLInputElement*);
     virtual const AtomicString& formControlType() const OVERRIDE;
     virtual DateComponents::Type dateType() const OVERRIDE;
     virtual double minimum() const OVERRIDE;
@@ -54,10 +57,14 @@
     virtual bool setMillisecondToDateComponents(double, DateComponents*) const OVERRIDE;
 #if ENABLE(CALENDAR_PICKER)
     virtual void createShadowSubtree() OVERRIDE;
+    virtual void destroyShadowSubtree() OVERRIDE;
+    virtual void handleBlurEvent() OVERRIDE;
 
     // TextFieldInputType functions
     virtual bool needsContainer() const OVERRIDE;
     virtual bool shouldHaveSpinButton() const OVERRIDE;
+
+    RefPtr<CalendarPickerElement> m_pickerElement;
 #endif
 };
 

Modified: trunk/Source/WebCore/html/shadow/CalendarPickerElement.cpp (113415 => 113416)


--- trunk/Source/WebCore/html/shadow/CalendarPickerElement.cpp	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebCore/html/shadow/CalendarPickerElement.cpp	2012-04-06 07:45:48 UTC (rev 113416)
@@ -33,8 +33,21 @@
 
 #if ENABLE(CALENDAR_PICKER)
 
+#include "CalendarPicker.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "DateComponents.h"
+#include "DocumentWriter.h"
+#include "Event.h"
+#include "FrameView.h"
+#include "HTMLInputElement.h"
 #include "HTMLNames.h"
+#include "Language.h"
+#include "LocalizedCalendar.h"
+#include "LocalizedStrings.h"
+#include "Page.h"
 #include "RenderDetailsMarker.h"
+#include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
@@ -56,6 +69,155 @@
     return new (arena) RenderDetailsMarker(this);
 }
 
+inline HTMLInputElement* CalendarPickerElement::hostInput()
+{
+    ASSERT(shadowAncestorNode());
+    ASSERT(shadowAncestorNode()->hasTagName(inputTag));
+    return static_cast<HTMLInputElement*>(shadowAncestorNode());
 }
 
+void CalendarPickerElement::defaultEventHandler(Event* event)
+{
+    HTMLInputElement* input = hostInput();
+    if (input->readOnly() || input->disabled())
+        return;
+
+    if (event->type() == eventNames().clickEvent) {
+        openPopup();
+        event->setDefaultHandled();
+    }
+
+    if (!event->defaultHandled())
+        HTMLDivElement::defaultEventHandler(event);
+}
+
+void CalendarPickerElement::openPopup()
+{
+    if (m_popup)
+        return;
+    if (!document()->page())
+        return;
+    Chrome* chrome = document()->page()->chrome();
+    if (!chrome)
+        return;
+    if (!document()->view())
+        return;
+    IntRect elementRectInRootView = document()->view()->contentsToRootView(hostInput()->getRect());
+    m_popup = chrome->client()->openPagePopup(this, elementRectInRootView);
+}
+
+void CalendarPickerElement::closePopup()
+{
+    if (!m_popup)
+        return;
+    if (!document()->page())
+        return;
+    Chrome* chrome = document()->page()->chrome();
+    if (!chrome)
+        return;
+    chrome->client()->closePagePopup(m_popup);
+}
+
+void CalendarPickerElement::detach()
+{
+    closePopup();
+    HTMLDivElement::detach();
+}
+
+IntSize CalendarPickerElement::contentSize()
+{
+    return IntSize(320, 256);
+}
+
+#define addLiteral(literal, writer)    writer.addData(literal, sizeof(literal) - 1)
+
+static inline void addString(const String& str, DocumentWriter& writer)
+{
+    CString str8 = str.utf8();
+    writer.addData(str8.data(), str8.length());
+}
+
+static void addJavaScriptString(const String& str, DocumentWriter& writer)
+{
+    addLiteral("\"", writer);
+    StringBuilder builder;
+    builder.reserveCapacity(str.length());
+    for (unsigned i = 0; i < str.length(); ++i) {
+        if (str[i] == '\\' || str[i] == '"')
+            builder.append('\\');
+        builder.append(str[i]);
+    }
+    addString(builder.toString(), writer);
+    addLiteral("\"", writer);
+}
+
+static void addProperty(const char* name, const String& value, DocumentWriter& writer)
+{
+    writer.addData(name, strlen(name));
+    addLiteral(": ", writer);
+    addJavaScriptString(value, writer);
+    addLiteral(",\n", writer);
+}
+
+static void addProperty(const char* name, const Vector<String>& values, DocumentWriter& writer)
+{
+    writer.addData(name, strlen(name));
+    addLiteral(": [", writer);
+    for (unsigned i = 0; i < values.size(); ++i) {
+        if (i)
+            addLiteral(",", writer);
+        addJavaScriptString(values[i], writer);
+    }
+    addLiteral("],\n", writer);
+}
+
+void CalendarPickerElement::writeDocument(DocumentWriter& writer)
+{
+    HTMLInputElement* input = hostInput();
+    DateComponents date;
+    date.setMillisecondsSinceEpochForDate(input->minimum());
+    String minString = date.toString();
+    date.setMillisecondsSinceEpochForDate(input->maximum());
+    String maxString = date.toString();
+    double step;
+    String stepString = input->fastGetAttribute(stepAttr);
+    if (stepString.isEmpty() || !input->getAllowedValueStep(&step))
+        stepString = "1";
+
+    addLiteral("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", writer);
+    writer.addData(calendarPickerCss, sizeof(calendarPickerCss));
+    addLiteral("</style></head><body><div id=main>Loading...</div><script>\n"
+               "window.dialogArguments = {\n", writer);
+    addProperty("min", minString, writer);
+    addProperty("max", maxString, writer);
+    addProperty("step", stepString, writer);
+    addProperty("required", input->required() ? "true" : "false", writer);
+    addProperty("currentValue", input->value(), writer);
+    addProperty("locale", defaultLanguage(), writer);
+    addProperty("todayLabel", calendarTodayText(), writer);
+    addProperty("clearLabel", calendarClearText(), writer);
+    addProperty("weekStartDay", String::number(firstDayOfWeek()), writer);
+    addProperty("monthLabels", monthLabels(), writer);
+    addProperty("dayLabels", weekDayShortLabels(), writer);
+    addLiteral("}\n", writer);
+
+    writer.addData(calendarPickerJs, sizeof(calendarPickerJs));
+    addLiteral("</script></body>\n", writer);
+}
+
+void CalendarPickerElement::setValueAndClosePopup(int numValue, const String& stringValue)
+{
+    ASSERT(m_popup);
+    closePopup();
+    if (numValue >= 0)
+        hostInput()->setValue(stringValue, DispatchChangeEvent);
+}
+
+void CalendarPickerElement::didClosePopup()
+{
+    m_popup = 0;
+}
+
+}
+
 #endif

Modified: trunk/Source/WebCore/html/shadow/CalendarPickerElement.h (113415 => 113416)


--- trunk/Source/WebCore/html/shadow/CalendarPickerElement.h	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebCore/html/shadow/CalendarPickerElement.h	2012-04-06 07:45:48 UTC (rev 113416)
@@ -31,19 +31,38 @@
 #ifndef CalendarPickerElement_h
 #define CalendarPickerElement_h
 
+#if ENABLE(CALENDAR_PICKER)
 #include "HTMLDivElement.h"
+#include "PagePopupClient.h"
 
 namespace WebCore {
 
-class CalendarPickerElement : public HTMLDivElement {
+class HTMLInputElement;
+class PagePopup;
+
+class CalendarPickerElement : public HTMLDivElement, public PagePopupClient {
 public:
     static PassRefPtr<CalendarPickerElement> create(Document*);
+    void closePopup();
 
 private:
     CalendarPickerElement(Document*);
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
-    // FIXME: add click handling.
+    virtual void defaultEventHandler(Event*) OVERRIDE;
+    virtual void detach() OVERRIDE;
+
+    // PagePopupClient functions:
+    virtual IntSize contentSize() OVERRIDE;
+    virtual void writeDocument(DocumentWriter&) OVERRIDE;
+    virtual void setValueAndClosePopup(int, const String&) OVERRIDE;
+    virtual void didClosePopup() OVERRIDE;
+
+    HTMLInputElement* hostInput();
+    void openPopup();
+
+    PagePopup* m_popup;
 };
 
 }
 #endif
+#endif

Modified: trunk/Source/WebCore/platform/text/LocalizedCalendarICU.cpp (113415 => 113416)


--- trunk/Source/WebCore/platform/text/LocalizedCalendarICU.cpp	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebCore/platform/text/LocalizedCalendarICU.cpp	2012-04-06 07:45:48 UTC (rev 113416)
@@ -147,7 +147,7 @@
     ScopedDateFormat dateFormat;
     if (!dateFormat.get())
         return 0;
-    unsigned firstDay = ucal_getAttribute(udat_getCalendar(dateFormat.get()), UCAL_FIRST_DAY_OF_WEEK);
+    unsigned firstDay = ucal_getAttribute(udat_getCalendar(dateFormat.get()), UCAL_FIRST_DAY_OF_WEEK) - UCAL_SUNDAY;
     return firstDay;
 }
 

Modified: trunk/Source/WebKit/chromium/ChangeLog (113415 => 113416)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-04-06 07:45:48 UTC (rev 113416)
@@ -1,3 +1,18 @@
+2012-04-06  Kent Tamura  <[email protected]>
+
+        Calendar Picker: Add code to open/close the calendar picker
+        https://bugs.webkit.org/show_bug.cgi?id=83258
+
+        Reviewed by Hajime Morita.
+
+        * features.gypi: Enable ENABLE_PAGE_POPUP for non-Android
+        platforms. This is needed because ENABLE_CALENDAR_PICKER now depends on
+        ENABLE_PAGE_POPUP.
+        * src/ChroemClientImpl.cpp: Add stubs.
+        (WebKit::ChromeClientImpl::openPagePopup):
+        (WebKit::ChromeClientImpl::closePagePopup):
+        * src/ChromeClientImpl.h: Add declarations of openPagePopup() and closePagePopup().
+
 2012-04-05  Hironori Bono  <[email protected]>
 
         [Chromium] moving a cursor on a misspelled word should not remove a misspelled underline

Modified: trunk/Source/WebKit/chromium/features.gypi (113415 => 113416)


--- trunk/Source/WebKit/chromium/features.gypi	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebKit/chromium/features.gypi	2012-04-06 07:45:48 UTC (rev 113416)
@@ -130,11 +130,13 @@
       ['OS=="android"', {
         'feature_defines': [
           'ENABLE_CALENDAR_PICKER=0',
+          'ENABLE_PAGE_POPUP=0',
           'ENABLE_WEB_AUDIO=0',
         ],
       }, {
         'feature_defines': [
           'ENABLE_CALENDAR_PICKER=1',
+          'ENABLE_PAGE_POPUP=1',
           'ENABLE_WEB_AUDIO=1',
         ],
       }],

Modified: trunk/Source/WebKit/chromium/src/ChromeClientImpl.cpp (113415 => 113416)


--- trunk/Source/WebKit/chromium/src/ChromeClientImpl.cpp	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebKit/chromium/src/ChromeClientImpl.cpp	2012-04-06 07:45:48 UTC (rev 113416)
@@ -988,6 +988,19 @@
     return adoptRef(new SearchPopupMenuChromium(client));
 }
 
+#if ENABLE(PAGE_POPUP)
+PagePopup* ChromeClientImpl::openPagePopup(PagePopupClient*, const IntRect&)
+{
+    // FIXME: Impelement this.
+    return 0;
+}
+
+void ChromeClientImpl::closePagePopup(PagePopup*)
+{
+    // FIXME: Implement this.
+}
+#endif
+
 bool ChromeClientImpl::willAddTextFieldDecorationsTo(HTMLInputElement* input)
 {
     ASSERT(input);

Modified: trunk/Source/WebKit/chromium/src/ChromeClientImpl.h (113415 => 113416)


--- trunk/Source/WebKit/chromium/src/ChromeClientImpl.h	2012-04-06 05:23:25 UTC (rev 113415)
+++ trunk/Source/WebKit/chromium/src/ChromeClientImpl.h	2012-04-06 07:45:48 UTC (rev 113416)
@@ -195,6 +195,10 @@
     virtual bool hasOpenedPopup() const OVERRIDE;
     virtual PassRefPtr<WebCore::PopupMenu> createPopupMenu(WebCore::PopupMenuClient*) const;
     virtual PassRefPtr<WebCore::SearchPopupMenu> createSearchPopupMenu(WebCore::PopupMenuClient*) const;
+#if ENABLE(PAGE_POPUP)
+    virtual WebCore::PagePopup* openPagePopup(WebCore::PagePopupClient*, const WebCore::IntRect&) OVERRIDE;
+    virtual void closePagePopup(WebCore::PagePopup*) OVERRIDE;
+#endif
     virtual bool willAddTextFieldDecorationsTo(WebCore::HTMLInputElement*) OVERRIDE;
     virtual void addTextFieldDecorationsTo(WebCore::HTMLInputElement*) OVERRIDE;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to