• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "MeterShadowElement.h"
33 #include "RenderMeter.h"
34 #include "ShadowRoot.h"
35 #include <wtf/StdLibExtras.h>
36 
37 namespace WebCore {
38 
39 using namespace HTMLNames;
40 
HTMLMeterElement(const QualifiedName & tagName,Document * document,HTMLFormElement * form)41 HTMLMeterElement::HTMLMeterElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
42     : HTMLFormControlElement(tagName, document, form)
43 {
44     ASSERT(hasTagName(meterTag));
45 }
46 
~HTMLMeterElement()47 HTMLMeterElement::~HTMLMeterElement()
48 {
49 }
50 
create(const QualifiedName & tagName,Document * document,HTMLFormElement * form)51 PassRefPtr<HTMLMeterElement> HTMLMeterElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
52 {
53     RefPtr<HTMLMeterElement> meter = adoptRef(new HTMLMeterElement(tagName, document, form));
54     meter->createShadowSubtree();
55     return meter;
56 }
57 
createRenderer(RenderArena * arena,RenderStyle *)58 RenderObject* HTMLMeterElement::createRenderer(RenderArena* arena, RenderStyle*)
59 {
60     return new (arena) RenderMeter(this);
61 }
62 
formControlType() const63 const AtomicString& HTMLMeterElement::formControlType() const
64 {
65     DEFINE_STATIC_LOCAL(const AtomicString, meter, ("meter"));
66     return meter;
67 }
68 
parseMappedAttribute(Attribute * attribute)69 void HTMLMeterElement::parseMappedAttribute(Attribute* attribute)
70 {
71     if (attribute->name() == valueAttr || attribute->name() == minAttr || attribute->name() == maxAttr || attribute->name() == lowAttr || attribute->name() == highAttr || attribute->name() == optimumAttr)
72         didElementStateChange();
73     else
74         HTMLFormControlElement::parseMappedAttribute(attribute);
75 }
76 
attach()77 void HTMLMeterElement::attach()
78 {
79     HTMLFormControlElement::attach();
80     didElementStateChange();
81 }
82 
min() const83 double HTMLMeterElement::min() const
84 {
85     double min = 0;
86     parseToDoubleForNumberType(getAttribute(minAttr), &min);
87     return min;
88 }
89 
setMin(double min,ExceptionCode & ec)90 void HTMLMeterElement::setMin(double min, ExceptionCode& ec)
91 {
92     if (!isfinite(min)) {
93         ec = NOT_SUPPORTED_ERR;
94         return;
95     }
96     setAttribute(minAttr, String::number(min));
97 }
98 
max() const99 double HTMLMeterElement::max() const
100 {
101     double max = std::max(1.0, min());
102     parseToDoubleForNumberType(getAttribute(maxAttr), &max);
103     return std::max(max, min());
104 }
105 
setMax(double max,ExceptionCode & ec)106 void HTMLMeterElement::setMax(double max, ExceptionCode& ec)
107 {
108     if (!isfinite(max)) {
109         ec = NOT_SUPPORTED_ERR;
110         return;
111     }
112     setAttribute(maxAttr, String::number(max));
113 }
114 
value() const115 double HTMLMeterElement::value() const
116 {
117     double value = 0;
118     parseToDoubleForNumberType(getAttribute(valueAttr), &value);
119     return std::min(std::max(value, min()), max());
120 }
121 
setValue(double value,ExceptionCode & ec)122 void HTMLMeterElement::setValue(double value, ExceptionCode& ec)
123 {
124     if (!isfinite(value)) {
125         ec = NOT_SUPPORTED_ERR;
126         return;
127     }
128     setAttribute(valueAttr, String::number(value));
129 }
130 
low() const131 double HTMLMeterElement::low() const
132 {
133     double low = min();
134     parseToDoubleForNumberType(getAttribute(lowAttr), &low);
135     return std::min(std::max(low, min()), max());
136 }
137 
setLow(double low,ExceptionCode & ec)138 void HTMLMeterElement::setLow(double low, ExceptionCode& ec)
139 {
140     if (!isfinite(low)) {
141         ec = NOT_SUPPORTED_ERR;
142         return;
143     }
144     setAttribute(lowAttr, String::number(low));
145 }
146 
high() const147 double HTMLMeterElement::high() const
148 {
149     double high = max();
150     parseToDoubleForNumberType(getAttribute(highAttr), &high);
151     return std::min(std::max(high, low()), max());
152 }
153 
setHigh(double high,ExceptionCode & ec)154 void HTMLMeterElement::setHigh(double high, ExceptionCode& ec)
155 {
156     if (!isfinite(high)) {
157         ec = NOT_SUPPORTED_ERR;
158         return;
159     }
160     setAttribute(highAttr, String::number(high));
161 }
162 
optimum() const163 double HTMLMeterElement::optimum() const
164 {
165     double optimum = (max() + min()) / 2;
166     parseToDoubleForNumberType(getAttribute(optimumAttr), &optimum);
167     return std::min(std::max(optimum, min()), max());
168 }
169 
setOptimum(double optimum,ExceptionCode & ec)170 void HTMLMeterElement::setOptimum(double optimum, ExceptionCode& ec)
171 {
172     if (!isfinite(optimum)) {
173         ec = NOT_SUPPORTED_ERR;
174         return;
175     }
176     setAttribute(optimumAttr, String::number(optimum));
177 }
178 
gaugeRegion() const179 HTMLMeterElement::GaugeRegion HTMLMeterElement::gaugeRegion() const
180 {
181     double lowValue = low();
182     double highValue = high();
183     double theValue = value();
184     double optimumValue = optimum();
185 
186     if (optimumValue < lowValue) {
187         // The optimum range stays under low
188         if (theValue <= lowValue)
189             return GaugeRegionOptimum;
190         if (theValue <= highValue)
191             return GaugeRegionSuboptimal;
192         return GaugeRegionEvenLessGood;
193     }
194 
195     if (highValue < optimumValue) {
196         // The optimum range stays over high
197         if (highValue <= theValue)
198             return GaugeRegionOptimum;
199         if (lowValue <= theValue)
200             return GaugeRegionSuboptimal;
201         return GaugeRegionEvenLessGood;
202     }
203 
204     // The optimum range stays between high and low.
205     // According to the standard, <meter> never show GaugeRegionEvenLessGood in this case
206     // because the value is never less or greater than min or max.
207     if (lowValue <= theValue && theValue <= highValue)
208         return GaugeRegionOptimum;
209     return GaugeRegionSuboptimal;
210 }
211 
valueRatio() const212 double HTMLMeterElement::valueRatio() const
213 {
214     double min = this->min();
215     double max = this->max();
216     double value = this->value();
217 
218     if (max <= min)
219         return 0;
220     return (value - min) / (max - min);
221 }
222 
didElementStateChange()223 void HTMLMeterElement::didElementStateChange()
224 {
225     m_value->setWidthPercentage(valueRatio()*100);
226 }
227 
createShadowSubtree()228 void HTMLMeterElement::createShadowSubtree()
229 {
230     RefPtr<MeterBarElement> bar = MeterBarElement::create(document());
231     m_value = MeterValueElement::create(document());
232     ExceptionCode ec = 0;
233     bar->appendChild(m_value, ec);
234     ensureShadowRoot()->appendChild(bar, ec);
235 }
236 
237 } // namespace
238 #endif
239