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 "core/html/shadow/PickerIndicatorElement.h" 34 35 #include "core/events/Event.h" 36 #include "core/html/shadow/ShadowElementNames.h" 37 #include "core/page/Chrome.h" 38 #include "core/page/Page.h" 39 #include "core/rendering/RenderDetailsMarker.h" 40 #include "wtf/TemporaryChange.h" 41 42 using namespace WTF::Unicode; 43 44 namespace WebCore { 45 46 using namespace HTMLNames; 47 48 inline PickerIndicatorElement::PickerIndicatorElement(Document& document, PickerIndicatorOwner& pickerIndicatorOwner) 49 : HTMLDivElement(document) 50 , m_pickerIndicatorOwner(&pickerIndicatorOwner) 51 , m_isInOpenPopup(false) 52 { 53 } 54 55 PassRefPtrWillBeRawPtr<PickerIndicatorElement> PickerIndicatorElement::create(Document& document, PickerIndicatorOwner& pickerIndicatorOwner) 56 { 57 RefPtrWillBeRawPtr<PickerIndicatorElement> element = adoptRefWillBeNoop(new PickerIndicatorElement(document, pickerIndicatorOwner)); 58 element->setShadowPseudoId(AtomicString("-webkit-calendar-picker-indicator", AtomicString::ConstructFromLiteral)); 59 element->setAttribute(idAttr, ShadowElementNames::pickerIndicator()); 60 return element.release(); 61 } 62 63 PickerIndicatorElement::~PickerIndicatorElement() 64 { 65 } 66 67 RenderObject* PickerIndicatorElement::createRenderer(RenderStyle*) 68 { 69 return new RenderDetailsMarker(this); 70 } 71 72 void PickerIndicatorElement::defaultEventHandler(Event* event) 73 { 74 if (!renderer()) 75 return; 76 if (!m_pickerIndicatorOwner || m_pickerIndicatorOwner->isPickerIndicatorOwnerDisabledOrReadOnly()) 77 return; 78 79 if (event->type() == EventTypeNames::click) { 80 openPopup(); 81 event->setDefaultHandled(); 82 } 83 84 if (!event->defaultHandled()) 85 HTMLDivElement::defaultEventHandler(event); 86 } 87 88 bool PickerIndicatorElement::willRespondToMouseClickEvents() 89 { 90 if (renderer() && m_pickerIndicatorOwner && !m_pickerIndicatorOwner->isPickerIndicatorOwnerDisabledOrReadOnly()) 91 return true; 92 93 return HTMLDivElement::willRespondToMouseClickEvents(); 94 } 95 96 void PickerIndicatorElement::didChooseValue(const String& value) 97 { 98 if (!m_pickerIndicatorOwner) 99 return; 100 m_pickerIndicatorOwner->pickerIndicatorChooseValue(value); 101 } 102 103 void PickerIndicatorElement::didChooseValue(double value) 104 { 105 if (m_pickerIndicatorOwner) 106 m_pickerIndicatorOwner->pickerIndicatorChooseValue(value); 107 } 108 109 void PickerIndicatorElement::didEndChooser() 110 { 111 m_chooser.clear(); 112 } 113 114 void PickerIndicatorElement::openPopup() 115 { 116 // The m_isInOpenPopup flag is unnecessary in production. 117 // MockPagePopupDriver allows to execute JavaScript code in 118 // DateTimeChooserImpl constructor. It might create another DateTimeChooser. 119 if (m_isInOpenPopup) 120 return; 121 TemporaryChange<bool> reentrancyProtector(m_isInOpenPopup, true); 122 if (m_chooser) 123 return; 124 if (!document().page()) 125 return; 126 if (!m_pickerIndicatorOwner) 127 return; 128 DateTimeChooserParameters parameters; 129 if (!m_pickerIndicatorOwner->setupDateTimeChooserParameters(parameters)) 130 return; 131 m_chooser = document().page()->chrome().openDateTimeChooser(this, parameters); 132 } 133 134 void PickerIndicatorElement::closePopup() 135 { 136 if (!m_chooser) 137 return; 138 m_chooser->endChooser(); 139 } 140 141 void PickerIndicatorElement::detach(const AttachContext& context) 142 { 143 closePopup(); 144 HTMLDivElement::detach(context); 145 } 146 147 bool PickerIndicatorElement::isPickerIndicatorElement() const 148 { 149 return true; 150 } 151 152 void PickerIndicatorElement::trace(Visitor* visitor) 153 { 154 visitor->trace(m_pickerIndicatorOwner); 155 visitor->trace(m_chooser); 156 HTMLDivElement::trace(visitor); 157 DateTimeChooserClient::trace(visitor); 158 } 159 160 } 161 162 #endif 163