Move WebCore into Source
[WebKit-https.git] / Source / WebCore / html / HTMLMeterElement.cpp
1 /*
2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3  *
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.
8  *
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.
13  *
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.
18  *
19  */
20
21 #include "config.h"
22 #if ENABLE(METER_TAG)
23 #include "HTMLMeterElement.h"
24
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 "RenderMeter.h"
33 #include <wtf/StdLibExtras.h>
34
35 namespace WebCore {
36
37 using namespace HTMLNames;
38
39 HTMLMeterElement::HTMLMeterElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
40     : HTMLFormControlElement(tagName, document, form)
41 {
42     ASSERT(hasTagName(meterTag));
43 }
44
45 PassRefPtr<HTMLMeterElement> HTMLMeterElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
46 {
47     return adoptRef(new HTMLMeterElement(tagName, document, form));
48 }
49
50 RenderObject* HTMLMeterElement::createRenderer(RenderArena* arena, RenderStyle*)
51 {
52     return new (arena) RenderMeter(this);
53 }
54
55 const AtomicString& HTMLMeterElement::formControlType() const
56 {
57     DEFINE_STATIC_LOCAL(const AtomicString, meter, ("meter"));
58     return meter;
59 }
60
61 void HTMLMeterElement::parseMappedAttribute(Attribute* attribute)
62 {
63     if (attribute->name() == valueAttr || attribute->name() == minAttr || attribute->name() == maxAttr || attribute->name() == lowAttr || attribute->name() == highAttr || attribute->name() == optimumAttr) {
64         if (renderer())
65             renderer()->updateFromElement();
66     } else
67         HTMLFormControlElement::parseMappedAttribute(attribute);
68 }
69
70 void HTMLMeterElement::attach()
71 {
72     HTMLFormControlElement::attach();
73     if (renderer())
74         renderer()->updateFromElement();
75 }
76
77 double HTMLMeterElement::min() const
78 {
79     double min = 0;
80     parseToDoubleForNumberType(getAttribute(minAttr), &min);
81     return min;
82 }
83
84 void HTMLMeterElement::setMin(double min, ExceptionCode& ec)
85 {
86     if (!isfinite(min)) {
87         ec = NOT_SUPPORTED_ERR;
88         return;
89     }
90     setAttribute(minAttr, String::number(min));
91 }
92
93 double HTMLMeterElement::max() const
94 {
95     double max = std::max(1.0, min());
96     parseToDoubleForNumberType(getAttribute(maxAttr), &max);
97     return std::max(max, min());
98 }
99
100 void HTMLMeterElement::setMax(double max, ExceptionCode& ec)
101 {
102     if (!isfinite(max)) {
103         ec = NOT_SUPPORTED_ERR;
104         return;
105     }
106     setAttribute(maxAttr, String::number(max));
107 }
108
109 double HTMLMeterElement::value() const
110 {
111     double value = 0;
112     parseToDoubleForNumberType(getAttribute(valueAttr), &value);
113     return std::min(std::max(value, min()), max());
114 }
115
116 void HTMLMeterElement::setValue(double value, ExceptionCode& ec)
117 {
118     if (!isfinite(value)) {
119         ec = NOT_SUPPORTED_ERR;
120         return;
121     }
122     setAttribute(valueAttr, String::number(value));
123 }
124
125 double HTMLMeterElement::low() const
126 {
127     double low = min();
128     parseToDoubleForNumberType(getAttribute(lowAttr), &low);
129     return std::min(std::max(low, min()), max());
130 }
131
132 void HTMLMeterElement::setLow(double low, ExceptionCode& ec)
133 {
134     if (!isfinite(low)) {
135         ec = NOT_SUPPORTED_ERR;
136         return;
137     }
138     setAttribute(lowAttr, String::number(low));
139 }
140
141 double HTMLMeterElement::high() const
142 {
143     double high = max();
144     parseToDoubleForNumberType(getAttribute(highAttr), &high);
145     return std::min(std::max(high, low()), max());
146 }
147
148 void HTMLMeterElement::setHigh(double high, ExceptionCode& ec)
149 {
150     if (!isfinite(high)) {
151         ec = NOT_SUPPORTED_ERR;
152         return;
153     }
154     setAttribute(highAttr, String::number(high));
155 }
156
157 double HTMLMeterElement::optimum() const
158 {
159     double optimum = (max() + min()) / 2;
160     parseToDoubleForNumberType(getAttribute(optimumAttr), &optimum);
161     return std::min(std::max(optimum, min()), max());
162 }
163
164 void HTMLMeterElement::setOptimum(double optimum, ExceptionCode& ec)
165 {
166     if (!isfinite(optimum)) {
167         ec = NOT_SUPPORTED_ERR;
168         return;
169     }
170     setAttribute(optimumAttr, String::number(optimum));
171 }
172
173 HTMLMeterElement::GaugeRegion HTMLMeterElement::gaugeRegion() const
174 {
175     double lowValue = low();
176     double highValue = high();
177     double theValue = value();
178     double optimumValue = optimum();
179
180     if (optimumValue < lowValue) {
181         // The optimum range stays under low
182         if (theValue <= lowValue)
183             return GaugeRegionOptimum;
184         if (theValue <= highValue)
185             return GaugeRegionSuboptimal;
186         return GaugeRegionEvenLessGood;
187     }
188     
189     if (highValue < optimumValue) {
190         // The optimum range stays over high
191         if (highValue <= theValue)
192             return GaugeRegionOptimum;
193         if (lowValue <= theValue)
194             return GaugeRegionSuboptimal;
195         return GaugeRegionEvenLessGood;
196     }
197
198     // The optimum range stays between high and low.
199     // According to the standard, <meter> never show GaugeRegionEvenLessGood in this case
200     // because the value is never less or greater than min or max.
201     if (lowValue <= theValue && theValue <= highValue)
202         return GaugeRegionOptimum;
203     return GaugeRegionSuboptimal;
204 }
205
206 } // namespace
207 #endif