2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 #include "HTMLMeterElement.h"
25 #include "Attribute.h"
26 #include "EventNames.h"
27 #include "ExceptionCode.h"
28 #include "FormDataList.h"
29 #include "HTMLFormElement.h"
30 #include "HTMLNames.h"
31 #include "HTMLParserIdioms.h"
32 #include "MeterShadowElement.h"
33 #include "RenderMeter.h"
34 #include "ShadowRoot.h"
35 #include <wtf/StdLibExtras.h>
39 using namespace HTMLNames;
41 HTMLMeterElement::HTMLMeterElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
42 : HTMLFormControlElement(tagName, document, form)
44 ASSERT(hasTagName(meterTag));
47 HTMLMeterElement::~HTMLMeterElement()
51 PassRefPtr<HTMLMeterElement> HTMLMeterElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
53 RefPtr<HTMLMeterElement> meter = adoptRef(new HTMLMeterElement(tagName, document, form));
54 meter->createShadowSubtree();
58 RenderObject* HTMLMeterElement::createRenderer(RenderArena* arena, RenderStyle*)
60 return new (arena) RenderMeter(this);
63 const AtomicString& HTMLMeterElement::formControlType() const
65 DEFINE_STATIC_LOCAL(const AtomicString, meter, ("meter"));
69 bool HTMLMeterElement::supportsFocus() const
71 return Node::supportsFocus() && !disabled();
74 void HTMLMeterElement::parseMappedAttribute(Attribute* attribute)
76 if (attribute->name() == valueAttr || attribute->name() == minAttr || attribute->name() == maxAttr || attribute->name() == lowAttr || attribute->name() == highAttr || attribute->name() == optimumAttr)
77 didElementStateChange();
79 HTMLFormControlElement::parseMappedAttribute(attribute);
82 void HTMLMeterElement::attach()
84 HTMLFormControlElement::attach();
85 didElementStateChange();
88 double HTMLMeterElement::min() const
91 parseToDoubleForNumberType(getAttribute(minAttr), &min);
95 void HTMLMeterElement::setMin(double min, ExceptionCode& ec)
98 ec = NOT_SUPPORTED_ERR;
101 setAttribute(minAttr, String::number(min));
104 double HTMLMeterElement::max() const
106 double max = std::max(1.0, min());
107 parseToDoubleForNumberType(getAttribute(maxAttr), &max);
108 return std::max(max, min());
111 void HTMLMeterElement::setMax(double max, ExceptionCode& ec)
113 if (!isfinite(max)) {
114 ec = NOT_SUPPORTED_ERR;
117 setAttribute(maxAttr, String::number(max));
120 double HTMLMeterElement::value() const
123 parseToDoubleForNumberType(getAttribute(valueAttr), &value);
124 return std::min(std::max(value, min()), max());
127 void HTMLMeterElement::setValue(double value, ExceptionCode& ec)
129 if (!isfinite(value)) {
130 ec = NOT_SUPPORTED_ERR;
133 setAttribute(valueAttr, String::number(value));
136 double HTMLMeterElement::low() const
139 parseToDoubleForNumberType(getAttribute(lowAttr), &low);
140 return std::min(std::max(low, min()), max());
143 void HTMLMeterElement::setLow(double low, ExceptionCode& ec)
145 if (!isfinite(low)) {
146 ec = NOT_SUPPORTED_ERR;
149 setAttribute(lowAttr, String::number(low));
152 double HTMLMeterElement::high() const
155 parseToDoubleForNumberType(getAttribute(highAttr), &high);
156 return std::min(std::max(high, low()), max());
159 void HTMLMeterElement::setHigh(double high, ExceptionCode& ec)
161 if (!isfinite(high)) {
162 ec = NOT_SUPPORTED_ERR;
165 setAttribute(highAttr, String::number(high));
168 double HTMLMeterElement::optimum() const
170 double optimum = (max() + min()) / 2;
171 parseToDoubleForNumberType(getAttribute(optimumAttr), &optimum);
172 return std::min(std::max(optimum, min()), max());
175 void HTMLMeterElement::setOptimum(double optimum, ExceptionCode& ec)
177 if (!isfinite(optimum)) {
178 ec = NOT_SUPPORTED_ERR;
181 setAttribute(optimumAttr, String::number(optimum));
184 HTMLMeterElement::GaugeRegion HTMLMeterElement::gaugeRegion() const
186 double lowValue = low();
187 double highValue = high();
188 double theValue = value();
189 double optimumValue = optimum();
191 if (optimumValue < lowValue) {
192 // The optimum range stays under low
193 if (theValue <= lowValue)
194 return GaugeRegionOptimum;
195 if (theValue <= highValue)
196 return GaugeRegionSuboptimal;
197 return GaugeRegionEvenLessGood;
200 if (highValue < optimumValue) {
201 // The optimum range stays over high
202 if (highValue <= theValue)
203 return GaugeRegionOptimum;
204 if (lowValue <= theValue)
205 return GaugeRegionSuboptimal;
206 return GaugeRegionEvenLessGood;
209 // The optimum range stays between high and low.
210 // According to the standard, <meter> never show GaugeRegionEvenLessGood in this case
211 // because the value is never less or greater than min or max.
212 if (lowValue <= theValue && theValue <= highValue)
213 return GaugeRegionOptimum;
214 return GaugeRegionSuboptimal;
217 double HTMLMeterElement::valueRatio() const
219 double min = this->min();
220 double max = this->max();
221 double value = this->value();
225 return (value - min) / (max - min);
228 void HTMLMeterElement::didElementStateChange()
230 m_value->setWidthPercentage(valueRatio()*100);
233 void HTMLMeterElement::createShadowSubtree()
235 RefPtr<MeterBarElement> bar = MeterBarElement::create(document());
236 m_value = MeterValueElement::create(document());
237 ExceptionCode ec = 0;
238 bar->appendChild(m_value, ec);
239 ensureShadowRoot()->appendChild(bar, ec);