blob: 7c839945bbb5711fdf4185ec7e7670e63601643e [file] [log] [blame]
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +00001/*
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
weinig@apple.comc3608932010-05-19 17:48:06 +000025#include "Attribute.h"
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000026#include "EventNames.h"
kinuko@chromium.org6d95dee2010-06-07 20:55:00 +000027#include "ExceptionCode.h"
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000028#include "FormDataList.h"
29#include "HTMLFormElement.h"
30#include "HTMLNames.h"
darin@apple.com2f2a9802010-09-13 23:42:02 +000031#include "HTMLParserIdioms.h"
morrita@google.comca4194d2011-04-05 02:01:56 +000032#include "MeterShadowElement.h"
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000033#include "RenderMeter.h"
tkent@chromium.org553b1722011-04-08 06:03:31 +000034#include "ShadowRoot.h"
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000035#include <wtf/StdLibExtras.h>
36
37namespace WebCore {
38
39using namespace HTMLNames;
40
yael.aharon@nokia.com4920c932010-12-01 00:13:33 +000041HTMLMeterElement::HTMLMeterElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
42 : HTMLFormControlElement(tagName, document, form)
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000043{
44 ASSERT(hasTagName(meterTag));
45}
46
morrita@google.comca4194d2011-04-05 02:01:56 +000047HTMLMeterElement::~HTMLMeterElement()
48{
49}
50
yael.aharon@nokia.com4920c932010-12-01 00:13:33 +000051PassRefPtr<HTMLMeterElement> HTMLMeterElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000052{
morrita@google.comca4194d2011-04-05 02:01:56 +000053 RefPtr<HTMLMeterElement> meter = adoptRef(new HTMLMeterElement(tagName, document, form));
54 meter->createShadowSubtree();
55 return meter;
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000056}
57
58RenderObject* HTMLMeterElement::createRenderer(RenderArena* arena, RenderStyle*)
59{
60 return new (arena) RenderMeter(this);
61}
62
63const AtomicString& HTMLMeterElement::formControlType() const
64{
65 DEFINE_STATIC_LOCAL(const AtomicString, meter, ("meter"));
66 return meter;
67}
68
commit-queue@webkit.org12ad3822011-05-16 05:59:46 +000069bool HTMLMeterElement::supportsFocus() const
70{
71 return Node::supportsFocus() && !disabled();
72}
73
kling@webkit.org8a3d4af2012-02-06 02:21:57 +000074void HTMLMeterElement::parseAttribute(Attribute* attribute)
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000075{
morrita@google.comca4194d2011-04-05 02:01:56 +000076 if (attribute->name() == valueAttr || attribute->name() == minAttr || attribute->name() == maxAttr || attribute->name() == lowAttr || attribute->name() == highAttr || attribute->name() == optimumAttr)
77 didElementStateChange();
78 else
kling@webkit.org8a3d4af2012-02-06 02:21:57 +000079 HTMLFormControlElement::parseAttribute(attribute);
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000080}
81
morrita@google.comb172c47a2010-12-08 04:21:20 +000082void HTMLMeterElement::attach()
83{
84 HTMLFormControlElement::attach();
morrita@google.comca4194d2011-04-05 02:01:56 +000085 didElementStateChange();
morrita@google.comb172c47a2010-12-08 04:21:20 +000086}
87
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000088double HTMLMeterElement::min() const
89{
90 double min = 0;
commit-queue@webkit.org03477c82011-09-02 17:07:51 +000091 parseToDoubleForNumberType(getAttribute(minAttr), &min);
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +000092 return min;
93}
94
95void HTMLMeterElement::setMin(double min, ExceptionCode& ec)
96{
97 if (!isfinite(min)) {
98 ec = NOT_SUPPORTED_ERR;
99 return;
100 }
101 setAttribute(minAttr, String::number(min));
102}
103
104double HTMLMeterElement::max() const
105{
106 double max = std::max(1.0, min());
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000107 parseToDoubleForNumberType(getAttribute(maxAttr), &max);
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +0000108 return std::max(max, min());
109}
110
111void HTMLMeterElement::setMax(double max, ExceptionCode& ec)
112{
113 if (!isfinite(max)) {
114 ec = NOT_SUPPORTED_ERR;
115 return;
116 }
117 setAttribute(maxAttr, String::number(max));
118}
119
120double HTMLMeterElement::value() const
121{
122 double value = 0;
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000123 parseToDoubleForNumberType(getAttribute(valueAttr), &value);
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +0000124 return std::min(std::max(value, min()), max());
125}
126
127void HTMLMeterElement::setValue(double value, ExceptionCode& ec)
128{
129 if (!isfinite(value)) {
130 ec = NOT_SUPPORTED_ERR;
131 return;
132 }
133 setAttribute(valueAttr, String::number(value));
134}
135
136double HTMLMeterElement::low() const
137{
138 double low = min();
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000139 parseToDoubleForNumberType(getAttribute(lowAttr), &low);
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +0000140 return std::min(std::max(low, min()), max());
141}
142
143void HTMLMeterElement::setLow(double low, ExceptionCode& ec)
144{
145 if (!isfinite(low)) {
146 ec = NOT_SUPPORTED_ERR;
147 return;
148 }
149 setAttribute(lowAttr, String::number(low));
150}
151
152double HTMLMeterElement::high() const
153{
154 double high = max();
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000155 parseToDoubleForNumberType(getAttribute(highAttr), &high);
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +0000156 return std::min(std::max(high, low()), max());
157}
158
159void HTMLMeterElement::setHigh(double high, ExceptionCode& ec)
160{
161 if (!isfinite(high)) {
162 ec = NOT_SUPPORTED_ERR;
163 return;
164 }
165 setAttribute(highAttr, String::number(high));
166}
167
168double HTMLMeterElement::optimum() const
169{
170 double optimum = (max() + min()) / 2;
commit-queue@webkit.org03477c82011-09-02 17:07:51 +0000171 parseToDoubleForNumberType(getAttribute(optimumAttr), &optimum);
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +0000172 return std::min(std::max(optimum, min()), max());
173}
174
175void HTMLMeterElement::setOptimum(double optimum, ExceptionCode& ec)
176{
177 if (!isfinite(optimum)) {
178 ec = NOT_SUPPORTED_ERR;
179 return;
180 }
181 setAttribute(optimumAttr, String::number(optimum));
182}
183
morrita@google.coma70a8f42010-06-08 06:26:06 +0000184HTMLMeterElement::GaugeRegion HTMLMeterElement::gaugeRegion() const
185{
186 double lowValue = low();
187 double highValue = high();
188 double theValue = value();
189 double optimumValue = optimum();
190
morrita@google.com2611bce2010-10-29 09:47:03 +0000191 if (optimumValue < lowValue) {
morrita@google.coma70a8f42010-06-08 06:26:06 +0000192 // The optimum range stays under low
193 if (theValue <= lowValue)
194 return GaugeRegionOptimum;
195 if (theValue <= highValue)
196 return GaugeRegionSuboptimal;
197 return GaugeRegionEvenLessGood;
198 }
199
morrita@google.com2611bce2010-10-29 09:47:03 +0000200 if (highValue < optimumValue) {
morrita@google.coma70a8f42010-06-08 06:26:06 +0000201 // The optimum range stays over high
202 if (highValue <= theValue)
203 return GaugeRegionOptimum;
204 if (lowValue <= theValue)
205 return GaugeRegionSuboptimal;
206 return GaugeRegionEvenLessGood;
207 }
208
morrita@google.com2611bce2010-10-29 09:47:03 +0000209 // 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)
morrita@google.coma70a8f42010-06-08 06:26:06 +0000213 return GaugeRegionOptimum;
morrita@google.coma70a8f42010-06-08 06:26:06 +0000214 return GaugeRegionSuboptimal;
215}
216
morrita@google.comca4194d2011-04-05 02:01:56 +0000217double HTMLMeterElement::valueRatio() const
218{
219 double min = this->min();
220 double max = this->max();
221 double value = this->value();
222
223 if (max <= min)
224 return 0;
225 return (value - min) / (max - min);
226}
227
228void HTMLMeterElement::didElementStateChange()
229{
230 m_value->setWidthPercentage(valueRatio()*100);
morrita@google.comf1987562011-09-21 05:41:27 +0000231 if (RenderObject* render = renderer())
232 render->updateFromElement();
morrita@google.comca4194d2011-04-05 02:01:56 +0000233}
234
235void HTMLMeterElement::createShadowSubtree()
236{
commit-queue@webkit.org36762182012-02-14 12:48:24 +0000237 ASSERT(!hasShadowRoot());
morrita@google.com6b18c3f2012-02-09 05:46:57 +0000238
morrita@google.comca4194d2011-04-05 02:01:56 +0000239 RefPtr<MeterBarElement> bar = MeterBarElement::create(document());
240 m_value = MeterValueElement::create(document());
241 ExceptionCode ec = 0;
242 bar->appendChild(m_value, ec);
morrita@google.com6b18c3f2012-02-09 05:46:57 +0000243
commit-queue@webkit.org792213f2012-02-09 09:54:04 +0000244 RefPtr<ShadowRoot> root = ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot);
morrita@google.com6b18c3f2012-02-09 05:46:57 +0000245 root->appendChild(bar, ec);
morrita@google.comca4194d2011-04-05 02:01:56 +0000246}
247
yael.aharon@nokia.com666f4b82010-05-15 16:41:06 +0000248} // namespace
249#endif