Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / shadow / DateTimeEditElement.cpp
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
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
28 #include "core/html/shadow/DateTimeEditElement.h"
29
30 #include "HTMLNames.h"
31 #include "bindings/v8/ExceptionStatePlaceholder.h"
32 #include "core/dom/Text.h"
33 #include "core/events/MouseEvent.h"
34 #include "core/html/forms/DateTimeFieldsState.h"
35 #include "core/html/shadow/DateTimeFieldElements.h"
36 #include "core/html/shadow/ShadowElementNames.h"
37 #include "core/rendering/style/RenderStyle.h"
38 #include "core/rendering/style/StyleInheritedData.h"
39 #include "platform/fonts/FontCache.h"
40 #include "platform/text/DateTimeFormat.h"
41 #include "platform/text/PlatformLocale.h"
42 #include "wtf/DateMath.h"
43
44 namespace WebCore {
45
46 using namespace HTMLNames;
47 using namespace WTF::Unicode;
48
49 class DateTimeEditBuilder : private DateTimeFormat::TokenHandler {
50     WTF_MAKE_NONCOPYABLE(DateTimeEditBuilder);
51
52 public:
53     // The argument objects must be alive until this object dies.
54     DateTimeEditBuilder(DateTimeEditElement&, const DateTimeEditElement::LayoutParameters&, const DateComponents&);
55
56     bool build(const String&);
57
58 private:
59     bool needMillisecondField() const;
60     bool shouldAMPMFieldDisabled() const;
61     bool shouldDayOfMonthFieldDisabled() const;
62     bool shouldHourFieldDisabled() const;
63     bool shouldMillisecondFieldDisabled() const;
64     bool shouldMinuteFieldDisabled() const;
65     bool shouldSecondFieldDisabled() const;
66     bool shouldYearFieldDisabled() const;
67     inline const StepRange& stepRange() const { return m_parameters.stepRange; }
68     DateTimeNumericFieldElement::Step createStep(double msPerFieldUnit, double msPerFieldSize) const;
69
70     // DateTimeFormat::TokenHandler functions.
71     virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL;
72     virtual void visitLiteral(const String&) OVERRIDE FINAL;
73
74     DateTimeEditElement& m_editElement;
75     const DateComponents m_dateValue;
76     const DateTimeEditElement::LayoutParameters& m_parameters;
77     DateTimeNumericFieldElement::Range m_dayRange;
78     DateTimeNumericFieldElement::Range m_hour23Range;
79     DateTimeNumericFieldElement::Range m_minuteRange;
80     DateTimeNumericFieldElement::Range m_secondRange;
81     DateTimeNumericFieldElement::Range m_millisecondRange;
82 };
83
84 DateTimeEditBuilder::DateTimeEditBuilder(DateTimeEditElement& elemnt, const DateTimeEditElement::LayoutParameters& layoutParameters, const DateComponents& dateValue)
85     : m_editElement(elemnt)
86     , m_dateValue(dateValue)
87     , m_parameters(layoutParameters)
88     , m_dayRange(1, 31)
89     , m_hour23Range(0, 23)
90     , m_minuteRange(0, 59)
91     , m_secondRange(0, 59)
92     , m_millisecondRange(0, 999)
93 {
94     if (m_dateValue.type() == DateComponents::Date || m_dateValue.type() == DateComponents::DateTimeLocal) {
95         if (m_parameters.minimum.type() != DateComponents::Invalid
96             && m_parameters.maximum.type() != DateComponents::Invalid
97             && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
98             && m_parameters.minimum.month() == m_parameters.maximum.month()
99             && m_parameters.minimum.monthDay() <= m_parameters.maximum.monthDay()) {
100             m_dayRange.minimum = m_parameters.minimum.monthDay();
101             m_dayRange.maximum = m_parameters.maximum.monthDay();
102         }
103     }
104
105     if (m_dateValue.type() == DateComponents::Time || m_dayRange.isSingleton()) {
106         if (m_parameters.minimum.type() != DateComponents::Invalid
107             && m_parameters.maximum.type() != DateComponents::Invalid
108             && m_parameters.minimum.hour() <= m_parameters.maximum.hour()) {
109             m_hour23Range.minimum = m_parameters.minimum.hour();
110             m_hour23Range.maximum = m_parameters.maximum.hour();
111         }
112     }
113
114     if (m_hour23Range.isSingleton() && m_parameters.minimum.minute() <= m_parameters.maximum.minute()) {
115         m_minuteRange.minimum = m_parameters.minimum.minute();
116         m_minuteRange.maximum = m_parameters.maximum.minute();
117     }
118     if (m_minuteRange.isSingleton() && m_parameters.minimum.second() <= m_parameters.maximum.second()) {
119         m_secondRange.minimum = m_parameters.minimum.second();
120         m_secondRange.maximum = m_parameters.maximum.second();
121     }
122     if (m_secondRange.isSingleton() && m_parameters.minimum.millisecond() <= m_parameters.maximum.millisecond()) {
123         m_millisecondRange.minimum = m_parameters.minimum.millisecond();
124         m_millisecondRange.maximum = m_parameters.maximum.millisecond();
125     }
126 }
127
128 bool DateTimeEditBuilder::build(const String& formatString)
129 {
130     m_editElement.resetFields();
131     return DateTimeFormat::parse(formatString, *this);
132 }
133
134 bool DateTimeEditBuilder::needMillisecondField() const
135 {
136     return m_dateValue.millisecond()
137         || !stepRange().minimum().remainder(static_cast<int>(msPerSecond)).isZero()
138         || !stepRange().step().remainder(static_cast<int>(msPerSecond)).isZero();
139 }
140
141 void DateTimeEditBuilder::visitField(DateTimeFormat::FieldType fieldType, int count)
142 {
143     const int countForAbbreviatedMonth = 3;
144     const int countForFullMonth = 4;
145     const int countForNarrowMonth = 5;
146     Document& document = m_editElement.document();
147
148     switch (fieldType) {
149     case DateTimeFormat::FieldTypeDayOfMonth: {
150         RefPtr<DateTimeFieldElement> field = DateTimeDayFieldElement::create(document, m_editElement, m_parameters.placeholderForDay, m_dayRange);
151         m_editElement.addField(field);
152         if (shouldDayOfMonthFieldDisabled()) {
153             field->setValueAsDate(m_dateValue);
154             field->setDisabled();
155         }
156         return;
157     }
158
159     case DateTimeFormat::FieldTypeHour11: {
160         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerHour * 12);
161         RefPtr<DateTimeFieldElement> field = DateTimeHour11FieldElement::create(document, m_editElement, m_hour23Range, step);
162         m_editElement.addField(field);
163         if (shouldHourFieldDisabled()) {
164             field->setValueAsDate(m_dateValue);
165             field->setDisabled();
166         }
167         return;
168     }
169
170     case DateTimeFormat::FieldTypeHour12: {
171         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerHour * 12);
172         RefPtr<DateTimeFieldElement> field = DateTimeHour12FieldElement::create(document, m_editElement, m_hour23Range, step);
173         m_editElement.addField(field);
174         if (shouldHourFieldDisabled()) {
175             field->setValueAsDate(m_dateValue);
176             field->setDisabled();
177         }
178         return;
179     }
180
181     case DateTimeFormat::FieldTypeHour23: {
182         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerDay);
183         RefPtr<DateTimeFieldElement> field = DateTimeHour23FieldElement::create(document, m_editElement, m_hour23Range, step);
184         m_editElement.addField(field);
185         if (shouldHourFieldDisabled()) {
186             field->setValueAsDate(m_dateValue);
187             field->setDisabled();
188         }
189         return;
190     }
191
192     case DateTimeFormat::FieldTypeHour24: {
193         DateTimeNumericFieldElement::Step step = createStep(msPerHour, msPerDay);
194         RefPtr<DateTimeFieldElement> field = DateTimeHour24FieldElement::create(document, m_editElement, m_hour23Range, step);
195         m_editElement.addField(field);
196         if (shouldHourFieldDisabled()) {
197             field->setValueAsDate(m_dateValue);
198             field->setDisabled();
199         }
200         return;
201     }
202
203     case DateTimeFormat::FieldTypeMinute: {
204         DateTimeNumericFieldElement::Step step = createStep(msPerMinute, msPerHour);
205         RefPtr<DateTimeNumericFieldElement> field = DateTimeMinuteFieldElement::create(document, m_editElement, m_minuteRange, step);
206         m_editElement.addField(field);
207         if (shouldMinuteFieldDisabled()) {
208             field->setValueAsDate(m_dateValue);
209             field->setDisabled();
210         }
211         return;
212     }
213
214     case DateTimeFormat::FieldTypeMonth: // Fallthrough.
215     case DateTimeFormat::FieldTypeMonthStandAlone: {
216         int minMonth = 0, maxMonth = 11;
217         if (m_parameters.minimum.type() != DateComponents::Invalid
218             && m_parameters.maximum.type() != DateComponents::Invalid
219             && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
220             && m_parameters.minimum.month() <= m_parameters.maximum.month()) {
221             minMonth = m_parameters.minimum.month();
222             maxMonth = m_parameters.maximum.month();
223         }
224         RefPtr<DateTimeFieldElement> field;
225         switch (count) {
226         case countForNarrowMonth: // Fallthrough.
227         case countForAbbreviatedMonth:
228             field = DateTimeSymbolicMonthFieldElement::create(document, m_editElement, fieldType == DateTimeFormat::FieldTypeMonth ? m_parameters.locale.shortMonthLabels() : m_parameters.locale.shortStandAloneMonthLabels(), minMonth, maxMonth);
229             break;
230         case countForFullMonth:
231             field = DateTimeSymbolicMonthFieldElement::create(document, m_editElement, fieldType == DateTimeFormat::FieldTypeMonth ? m_parameters.locale.monthLabels() : m_parameters.locale.standAloneMonthLabels(), minMonth, maxMonth);
232             break;
233         default:
234             field = DateTimeMonthFieldElement::create(document, m_editElement, m_parameters.placeholderForMonth, DateTimeNumericFieldElement::Range(minMonth + 1, maxMonth + 1));
235             break;
236         }
237         m_editElement.addField(field);
238         if (minMonth == maxMonth && minMonth == m_dateValue.month() && m_dateValue.type() != DateComponents::Month) {
239             field->setValueAsDate(m_dateValue);
240             field->setDisabled();
241         }
242         return;
243     }
244
245     case DateTimeFormat::FieldTypePeriod: {
246         RefPtr<DateTimeFieldElement> field = DateTimeAMPMFieldElement::create(document, m_editElement, m_parameters.locale.timeAMPMLabels());
247         m_editElement.addField(field);
248         if (shouldAMPMFieldDisabled()) {
249             field->setValueAsDate(m_dateValue);
250             field->setDisabled();
251         }
252         return;
253     }
254
255     case DateTimeFormat::FieldTypeSecond: {
256         DateTimeNumericFieldElement::Step step = createStep(msPerSecond, msPerMinute);
257         RefPtr<DateTimeNumericFieldElement> field = DateTimeSecondFieldElement::create(document, m_editElement, m_secondRange, step);
258         m_editElement.addField(field);
259         if (shouldSecondFieldDisabled()) {
260             field->setValueAsDate(m_dateValue);
261             field->setDisabled();
262         }
263
264         if (needMillisecondField()) {
265             visitLiteral(m_parameters.locale.localizedDecimalSeparator());
266             visitField(DateTimeFormat::FieldTypeFractionalSecond, 3);
267         }
268         return;
269     }
270
271     case DateTimeFormat::FieldTypeFractionalSecond: {
272         DateTimeNumericFieldElement::Step step = createStep(1, msPerSecond);
273         RefPtr<DateTimeNumericFieldElement> field = DateTimeMillisecondFieldElement::create(document, m_editElement, m_millisecondRange, step);
274         m_editElement.addField(field);
275         if (shouldMillisecondFieldDisabled()) {
276             field->setValueAsDate(m_dateValue);
277             field->setDisabled();
278         }
279         return;
280     }
281
282     case DateTimeFormat::FieldTypeWeekOfYear: {
283         DateTimeNumericFieldElement::Range range(DateComponents::minimumWeekNumber, DateComponents::maximumWeekNumber);
284         if (m_parameters.minimum.type() != DateComponents::Invalid
285             && m_parameters.maximum.type() != DateComponents::Invalid
286             && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
287             && m_parameters.minimum.week() <= m_parameters.maximum.week()) {
288             range.minimum = m_parameters.minimum.week();
289             range.maximum = m_parameters.maximum.week();
290         }
291         m_editElement.addField(DateTimeWeekFieldElement::create(document, m_editElement, range));
292         return;
293     }
294
295     case DateTimeFormat::FieldTypeYear: {
296         DateTimeYearFieldElement::Parameters yearParams;
297         if (m_parameters.minimum.type() == DateComponents::Invalid) {
298             yearParams.minimumYear = DateComponents::minimumYear();
299             yearParams.minIsSpecified = false;
300         } else {
301             yearParams.minimumYear = m_parameters.minimum.fullYear();
302             yearParams.minIsSpecified = true;
303         }
304         if (m_parameters.maximum.type() == DateComponents::Invalid) {
305             yearParams.maximumYear = DateComponents::maximumYear();
306             yearParams.maxIsSpecified = false;
307         } else {
308             yearParams.maximumYear = m_parameters.maximum.fullYear();
309             yearParams.maxIsSpecified = true;
310         }
311         if (yearParams.minimumYear > yearParams.maximumYear) {
312             std::swap(yearParams.minimumYear, yearParams.maximumYear);
313             std::swap(yearParams.minIsSpecified, yearParams.maxIsSpecified);
314         }
315         yearParams.placeholder = m_parameters.placeholderForYear;
316         RefPtr<DateTimeFieldElement> field = DateTimeYearFieldElement::create(document, m_editElement, yearParams);
317         m_editElement.addField(field);
318         if (shouldYearFieldDisabled()) {
319             field->setValueAsDate(m_dateValue);
320             field->setDisabled();
321         }
322         return;
323     }
324
325     default:
326         return;
327     }
328 }
329
330 bool DateTimeEditBuilder::shouldAMPMFieldDisabled() const
331 {
332     return shouldHourFieldDisabled()
333         || (m_hour23Range.minimum < 12 && m_hour23Range.maximum < 12 && m_dateValue.hour() < 12)
334         || (m_hour23Range.minimum >= 12 && m_hour23Range.maximum >= 12 && m_dateValue.hour() >= 12);
335 }
336
337 bool DateTimeEditBuilder::shouldDayOfMonthFieldDisabled() const
338 {
339     return m_dayRange.isSingleton() && m_dayRange.minimum == m_dateValue.monthDay() && m_dateValue.type() != DateComponents::Date;
340 }
341
342 bool DateTimeEditBuilder::shouldHourFieldDisabled() const
343 {
344     if (m_hour23Range.isSingleton() && m_hour23Range.minimum == m_dateValue.hour()
345         && !(shouldMinuteFieldDisabled() && shouldSecondFieldDisabled() && shouldMillisecondFieldDisabled()))
346         return true;
347
348     if (m_dateValue.type() == DateComponents::Time)
349         return false;
350     ASSERT(m_dateValue.type() == DateComponents::DateTimeLocal);
351
352     if (shouldDayOfMonthFieldDisabled()) {
353         ASSERT(m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear());
354         ASSERT(m_parameters.minimum.month() == m_parameters.maximum.month());
355         return false;
356     }
357
358     const Decimal decimalMsPerDay(static_cast<int>(msPerDay));
359     Decimal hourPartOfMinimum = (stepRange().minimum().abs().remainder(decimalMsPerDay) / static_cast<int>(msPerHour)).floor();
360     return hourPartOfMinimum == m_dateValue.hour() && stepRange().step().remainder(decimalMsPerDay).isZero();
361 }
362
363 bool DateTimeEditBuilder::shouldMillisecondFieldDisabled() const
364 {
365     if (m_millisecondRange.isSingleton() && m_millisecondRange.minimum == m_dateValue.millisecond())
366         return true;
367
368     const Decimal decimalMsPerSecond(static_cast<int>(msPerSecond));
369     return stepRange().minimum().abs().remainder(decimalMsPerSecond) == m_dateValue.millisecond() && stepRange().step().remainder(decimalMsPerSecond).isZero();
370 }
371
372 bool DateTimeEditBuilder::shouldMinuteFieldDisabled() const
373 {
374     if (m_minuteRange.isSingleton() && m_minuteRange.minimum == m_dateValue.minute())
375         return true;
376
377     const Decimal decimalMsPerHour(static_cast<int>(msPerHour));
378     Decimal minutePartOfMinimum = (stepRange().minimum().abs().remainder(decimalMsPerHour) / static_cast<int>(msPerMinute)).floor();
379     return minutePartOfMinimum == m_dateValue.minute() && stepRange().step().remainder(decimalMsPerHour).isZero();
380 }
381
382 bool DateTimeEditBuilder::shouldSecondFieldDisabled() const
383 {
384     if (m_secondRange.isSingleton() && m_secondRange.minimum == m_dateValue.second())
385         return true;
386
387     const Decimal decimalMsPerMinute(static_cast<int>(msPerMinute));
388     Decimal secondPartOfMinimum = (stepRange().minimum().abs().remainder(decimalMsPerMinute) / static_cast<int>(msPerSecond)).floor();
389     return secondPartOfMinimum == m_dateValue.second() && stepRange().step().remainder(decimalMsPerMinute).isZero();
390 }
391
392 bool DateTimeEditBuilder::shouldYearFieldDisabled() const
393 {
394     return m_parameters.minimum.type() != DateComponents::Invalid
395         && m_parameters.maximum.type() != DateComponents::Invalid
396         && m_parameters.minimum.fullYear() == m_parameters.maximum.fullYear()
397         && m_parameters.minimum.fullYear() == m_dateValue.fullYear();
398 }
399
400 void DateTimeEditBuilder::visitLiteral(const String& text)
401 {
402     DEFINE_STATIC_LOCAL(AtomicString, textPseudoId, ("-webkit-datetime-edit-text", AtomicString::ConstructFromLiteral));
403     ASSERT(text.length());
404     RefPtr<HTMLDivElement> element = HTMLDivElement::create(m_editElement.document());
405     element->setShadowPseudoId(textPseudoId);
406     if (m_parameters.locale.isRTL() && text.length()) {
407         Direction dir = direction(text[0]);
408         if (dir == SegmentSeparator || dir == WhiteSpaceNeutral || dir == OtherNeutral)
409             element->appendChild(Text::create(m_editElement.document(), String(&rightToLeftMark, 1)));
410     }
411     element->appendChild(Text::create(m_editElement.document(), text));
412     m_editElement.fieldsWrapperElement()->appendChild(element);
413 }
414
415 DateTimeNumericFieldElement::Step DateTimeEditBuilder::createStep(double msPerFieldUnit, double msPerFieldSize) const
416 {
417     const Decimal msPerFieldUnitDecimal(static_cast<int>(msPerFieldUnit));
418     const Decimal msPerFieldSizeDecimal(static_cast<int>(msPerFieldSize));
419     Decimal stepMilliseconds = stepRange().step();
420     ASSERT(!msPerFieldUnitDecimal.isZero());
421     ASSERT(!msPerFieldSizeDecimal.isZero());
422     ASSERT(!stepMilliseconds.isZero());
423
424     DateTimeNumericFieldElement::Step step(1, 0);
425
426     if (stepMilliseconds.remainder(msPerFieldSizeDecimal).isZero())
427         stepMilliseconds = msPerFieldSizeDecimal;
428
429     if (msPerFieldSizeDecimal.remainder(stepMilliseconds).isZero() && stepMilliseconds.remainder(msPerFieldUnitDecimal).isZero()) {
430         step.step = static_cast<int>((stepMilliseconds / msPerFieldUnitDecimal).toDouble());
431         step.stepBase = static_cast<int>((stepRange().stepBase() / msPerFieldUnitDecimal).floor().remainder(msPerFieldSizeDecimal / msPerFieldUnitDecimal).toDouble());
432     }
433     return step;
434 }
435
436 // ----------------------------
437
438 DateTimeEditElement::EditControlOwner::~EditControlOwner()
439 {
440 }
441
442 DateTimeEditElement::DateTimeEditElement(Document& document, EditControlOwner& editControlOwner)
443     : HTMLDivElement(document)
444     , m_editControlOwner(&editControlOwner)
445 {
446     setHasCustomStyleCallbacks();
447 }
448
449 DateTimeEditElement::~DateTimeEditElement()
450 {
451     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
452         m_fields[fieldIndex]->removeEventHandler();
453 }
454
455 inline Element* DateTimeEditElement::fieldsWrapperElement() const
456 {
457     ASSERT(firstChild());
458     return toElement(firstChild());
459 }
460
461 void DateTimeEditElement::addField(PassRefPtr<DateTimeFieldElement> field)
462 {
463     if (m_fields.size() == m_fields.capacity())
464         return;
465     m_fields.append(field.get());
466     fieldsWrapperElement()->appendChild(field);
467 }
468
469 bool DateTimeEditElement::anyEditableFieldsHaveValues() const
470 {
471     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
472         if (!m_fields[fieldIndex]->isDisabled() && m_fields[fieldIndex]->hasValue())
473             return true;
474     }
475     return false;
476 }
477
478 void DateTimeEditElement::blurByOwner()
479 {
480     if (DateTimeFieldElement* field = focusedField())
481         field->blur();
482 }
483
484 PassRefPtr<DateTimeEditElement> DateTimeEditElement::create(Document& document, EditControlOwner& editControlOwner)
485 {
486     RefPtr<DateTimeEditElement> container = adoptRef(new DateTimeEditElement(document, editControlOwner));
487     container->setShadowPseudoId(AtomicString("-webkit-datetime-edit", AtomicString::ConstructFromLiteral));
488     container->setAttribute(idAttr, ShadowElementNames::dateTimeEdit());
489     return container.release();
490 }
491
492 PassRefPtr<RenderStyle> DateTimeEditElement::customStyleForRenderer()
493 {
494     // FIXME: This is a kind of layout. We might want to introduce new renderer.
495     FontCachePurgePreventer fontCachePurgePreventer;
496     RefPtr<RenderStyle> originalStyle = originalStyleForRenderer();
497     RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
498     float width = 0;
499     for (Node* child = fieldsWrapperElement()->firstChild(); child; child = child->nextSibling()) {
500         if (!child->isElementNode())
501             continue;
502         Element* childElement = toElement(child);
503         if (childElement->isDateTimeFieldElement()) {
504             // We need to pass the Font of this element because child elements
505             // can't resolve inherited style at this timing.
506             width += static_cast<DateTimeFieldElement*>(childElement)->maximumWidth(style->font());
507         } else {
508             // ::-webkit-datetime-edit-text case. It has no
509             // border/padding/margin in html.css.
510             width += style->font().width(childElement->textContent());
511         }
512     }
513     style->setWidth(Length(ceilf(width), Fixed));
514     style->setUnique();
515     return style.release();
516 }
517
518 void DateTimeEditElement::didBlurFromField()
519 {
520     if (m_editControlOwner)
521         m_editControlOwner->didBlurFromControl();
522 }
523
524 void DateTimeEditElement::didFocusOnField()
525 {
526     if (m_editControlOwner)
527         m_editControlOwner->didFocusOnControl();
528 }
529
530 void DateTimeEditElement::disabledStateChanged()
531 {
532     updateUIState();
533 }
534
535 DateTimeFieldElement* DateTimeEditElement::fieldAt(size_t fieldIndex) const
536 {
537     return fieldIndex < m_fields.size() ? m_fields[fieldIndex] : 0;
538 }
539
540 size_t DateTimeEditElement::fieldIndexOf(const DateTimeFieldElement& field) const
541 {
542     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
543         if (m_fields[fieldIndex] == &field)
544             return fieldIndex;
545     }
546     return invalidFieldIndex;
547 }
548
549 void DateTimeEditElement::focusIfNoFocus()
550 {
551     if (focusedFieldIndex() != invalidFieldIndex)
552         return;
553     focusOnNextFocusableField(0);
554 }
555
556 void DateTimeEditElement::focusByOwner(Element* oldFocusedElement)
557 {
558     if (oldFocusedElement && oldFocusedElement->isDateTimeFieldElement()) {
559         DateTimeFieldElement* oldFocusedField = static_cast<DateTimeFieldElement*>(oldFocusedElement);
560         size_t index = fieldIndexOf(*oldFocusedField);
561         if (index != invalidFieldIndex && oldFocusedField->isFocusable()) {
562             oldFocusedField->focus();
563             return;
564         }
565     }
566     focusOnNextFocusableField(0);
567 }
568
569 DateTimeFieldElement* DateTimeEditElement::focusedField() const
570 {
571     return fieldAt(focusedFieldIndex());
572 }
573
574 size_t DateTimeEditElement::focusedFieldIndex() const
575 {
576     Element* const focusedFieldElement = document().focusedElement();
577     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
578         if (m_fields[fieldIndex] == focusedFieldElement)
579             return fieldIndex;
580     }
581     return invalidFieldIndex;
582 }
583
584 void DateTimeEditElement::fieldValueChanged()
585 {
586     if (m_editControlOwner)
587         m_editControlOwner->editControlValueChanged();
588 }
589
590 bool DateTimeEditElement::focusOnNextFocusableField(size_t startIndex)
591 {
592     for (size_t fieldIndex = startIndex; fieldIndex < m_fields.size(); ++fieldIndex) {
593         if (m_fields[fieldIndex]->isFocusable()) {
594             m_fields[fieldIndex]->focus();
595             return true;
596         }
597     }
598     return false;
599 }
600
601 bool DateTimeEditElement::focusOnNextField(const DateTimeFieldElement& field)
602 {
603     const size_t startFieldIndex = fieldIndexOf(field);
604     if (startFieldIndex == invalidFieldIndex)
605         return false;
606     return focusOnNextFocusableField(startFieldIndex + 1);
607 }
608
609 bool DateTimeEditElement::focusOnPreviousField(const DateTimeFieldElement& field)
610 {
611     const size_t startFieldIndex = fieldIndexOf(field);
612     if (startFieldIndex == invalidFieldIndex)
613         return false;
614     size_t fieldIndex = startFieldIndex;
615     while (fieldIndex > 0) {
616         --fieldIndex;
617         if (m_fields[fieldIndex]->isFocusable()) {
618             m_fields[fieldIndex]->focus();
619             return true;
620         }
621     }
622     return false;
623 }
624
625 bool DateTimeEditElement::isDateTimeEditElement() const
626 {
627     return true;
628 }
629
630 bool DateTimeEditElement::isDisabled() const
631 {
632     return m_editControlOwner && m_editControlOwner->isEditControlOwnerDisabled();
633 }
634
635 bool DateTimeEditElement::isFieldOwnerDisabled() const
636 {
637     return isDisabled();
638 }
639
640 bool DateTimeEditElement::isFieldOwnerReadOnly() const
641 {
642     return isReadOnly();
643 }
644
645 bool DateTimeEditElement::isReadOnly() const
646 {
647     return m_editControlOwner && m_editControlOwner->isEditControlOwnerReadOnly();
648 }
649
650 void DateTimeEditElement::layout(const LayoutParameters& layoutParameters, const DateComponents& dateValue)
651 {
652     DEFINE_STATIC_LOCAL(AtomicString, fieldsWrapperPseudoId, ("-webkit-datetime-edit-fields-wrapper", AtomicString::ConstructFromLiteral));
653     if (!firstChild()) {
654         RefPtr<HTMLDivElement> element = HTMLDivElement::create(document());
655         element->setShadowPseudoId(fieldsWrapperPseudoId);
656         appendChild(element.get());
657     }
658     Element* fieldsWrapper = fieldsWrapperElement();
659
660     size_t focusedFieldIndex = this->focusedFieldIndex();
661     DateTimeFieldElement* const focusedField = fieldAt(focusedFieldIndex);
662     const AtomicString focusedFieldId = focusedField ? focusedField->shadowPseudoId() : nullAtom;
663
664     DateTimeEditBuilder builder(*this, layoutParameters, dateValue);
665     Node* lastChildToBeRemoved = fieldsWrapper->lastChild();
666     if (!builder.build(layoutParameters.dateTimeFormat) || m_fields.isEmpty()) {
667         lastChildToBeRemoved = fieldsWrapper->lastChild();
668         builder.build(layoutParameters.fallbackDateTimeFormat);
669     }
670
671     if (focusedFieldIndex != invalidFieldIndex) {
672         for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) {
673             if (m_fields[fieldIndex]->shadowPseudoId() == focusedFieldId) {
674                 focusedFieldIndex = fieldIndex;
675                 break;
676             }
677         }
678         if (DateTimeFieldElement* field = fieldAt(std::min(focusedFieldIndex, m_fields.size() - 1)))
679             field->focus();
680     }
681
682     if (lastChildToBeRemoved) {
683         for (Node* childNode = fieldsWrapper->firstChild(); childNode; childNode = fieldsWrapper->firstChild()) {
684             fieldsWrapper->removeChild(childNode);
685             if (childNode == lastChildToBeRemoved)
686                 break;
687         }
688         setNeedsStyleRecalc(SubtreeStyleChange);
689     }
690 }
691
692 AtomicString DateTimeEditElement::localeIdentifier() const
693 {
694     return m_editControlOwner ? m_editControlOwner->localeIdentifier() : nullAtom;
695 }
696
697 void DateTimeEditElement::readOnlyStateChanged()
698 {
699     updateUIState();
700 }
701
702 void DateTimeEditElement::resetFields()
703 {
704     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
705         m_fields[fieldIndex]->removeEventHandler();
706     m_fields.shrink(0);
707 }
708
709 void DateTimeEditElement::defaultEventHandler(Event* event)
710 {
711     // In case of control owner forward event to control, e.g. DOM
712     // dispatchEvent method.
713     if (DateTimeFieldElement* field = focusedField()) {
714         field->defaultEventHandler(event);
715         if (event->defaultHandled())
716             return;
717     }
718
719     HTMLDivElement::defaultEventHandler(event);
720 }
721
722 void DateTimeEditElement::setValueAsDate(const LayoutParameters& layoutParameters, const DateComponents& date)
723 {
724     layout(layoutParameters, date);
725     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
726         m_fields[fieldIndex]->setValueAsDate(date);
727 }
728
729 void DateTimeEditElement::setValueAsDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState)
730 {
731     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
732         m_fields[fieldIndex]->setValueAsDateTimeFieldsState(dateTimeFieldsState);
733 }
734
735 void DateTimeEditElement::setEmptyValue(const LayoutParameters& layoutParameters, const DateComponents& dateForReadOnlyField)
736 {
737     layout(layoutParameters, dateForReadOnlyField);
738     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
739         m_fields[fieldIndex]->setEmptyValue(DateTimeFieldElement::DispatchNoEvent);
740 }
741
742 bool DateTimeEditElement::hasFocusedField()
743 {
744     return focusedFieldIndex() != invalidFieldIndex;
745 }
746
747 void DateTimeEditElement::setOnlyYearMonthDay(const DateComponents& date)
748 {
749     ASSERT(date.type() == DateComponents::Date);
750
751     if (!m_editControlOwner)
752         return;
753
754     DateTimeFieldsState dateTimeFieldsState = valueAsDateTimeFieldsState();
755     dateTimeFieldsState.setYear(date.fullYear());
756     dateTimeFieldsState.setMonth(date.month() + 1);
757     dateTimeFieldsState.setDayOfMonth(date.monthDay());
758     setValueAsDateTimeFieldsState(dateTimeFieldsState);
759     m_editControlOwner->editControlValueChanged();
760 }
761
762 void DateTimeEditElement::stepDown()
763 {
764     if (DateTimeFieldElement* const field = focusedField())
765         field->stepDown();
766 }
767
768 void DateTimeEditElement::stepUp()
769 {
770     if (DateTimeFieldElement* const field = focusedField())
771         field->stepUp();
772 }
773
774 void DateTimeEditElement::updateUIState()
775 {
776     if (isDisabled()) {
777         if (DateTimeFieldElement* field = focusedField())
778             field->blur();
779     }
780 }
781
782 String DateTimeEditElement::value() const
783 {
784     if (!m_editControlOwner)
785         return emptyString();
786     return m_editControlOwner->formatDateTimeFieldsState(valueAsDateTimeFieldsState());
787 }
788
789 DateTimeFieldsState DateTimeEditElement::valueAsDateTimeFieldsState() const
790 {
791     DateTimeFieldsState dateTimeFieldsState;
792     for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex)
793         m_fields[fieldIndex]->populateDateTimeFieldsState(dateTimeFieldsState);
794     return dateTimeFieldsState;
795 }
796
797 } // namespace WebCore
798
799 #endif