Use is<>() / downcast<>() for all remaining RenderObject subclasses
[WebKit-https.git] / Source / WebCore / html / HTMLProgressElement.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 #include "HTMLProgressElement.h"
23
24 #include "Attribute.h"
25 #include "ElementIterator.h"
26 #include "EventNames.h"
27 #include "ExceptionCode.h"
28 #include "HTMLNames.h"
29 #include "HTMLParserIdioms.h"
30 #include "ProgressShadowElement.h"
31 #include "RenderProgress.h"
32 #include "ShadowRoot.h"
33
34 namespace WebCore {
35
36 using namespace HTMLNames;
37
38 const double HTMLProgressElement::IndeterminatePosition = -1;
39 const double HTMLProgressElement::InvalidPosition = -2;
40
41 HTMLProgressElement::HTMLProgressElement(const QualifiedName& tagName, Document& document)
42     : LabelableElement(tagName, document)
43     , m_value(0)
44 {
45     ASSERT(hasTagName(progressTag));
46     setHasCustomStyleResolveCallbacks();
47 }
48
49 HTMLProgressElement::~HTMLProgressElement()
50 {
51 }
52
53 PassRefPtr<HTMLProgressElement> HTMLProgressElement::create(const QualifiedName& tagName, Document& document)
54 {
55     RefPtr<HTMLProgressElement> progress = adoptRef(new HTMLProgressElement(tagName, document));
56     progress->ensureUserAgentShadowRoot();
57     return progress.release();
58 }
59
60 RenderPtr<RenderElement> HTMLProgressElement::createElementRenderer(PassRef<RenderStyle> style)
61 {
62     if (!style.get().hasAppearance())
63         return RenderElement::createFor(*this, WTF::move(style));
64
65     return createRenderer<RenderProgress>(*this, WTF::move(style));
66 }
67
68 bool HTMLProgressElement::childShouldCreateRenderer(const Node& child) const
69 {
70     return hasShadowRootParent(child) && HTMLElement::childShouldCreateRenderer(child);
71 }
72
73 RenderProgress* HTMLProgressElement::renderProgress() const
74 {
75     if (is<RenderProgress>(renderer()))
76         return downcast<RenderProgress>(renderer());
77     return downcast<RenderProgress>(descendantsOfType<Element>(*userAgentShadowRoot()).first()->renderer());
78 }
79
80 void HTMLProgressElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
81 {
82     if (name == valueAttr)
83         didElementStateChange();
84     else if (name == maxAttr)
85         didElementStateChange();
86     else
87         LabelableElement::parseAttribute(name, value);
88 }
89
90 void HTMLProgressElement::didAttachRenderers()
91 {
92     if (RenderProgress* render = renderProgress())
93         render->updateFromElement();
94 }
95
96 double HTMLProgressElement::value() const
97 {
98     double value = parseToDoubleForNumberType(fastGetAttribute(valueAttr));
99     return !std::isfinite(value) || value < 0 ? 0 : std::min(value, max());
100 }
101
102 void HTMLProgressElement::setValue(double value, ExceptionCode& ec)
103 {
104     if (!std::isfinite(value)) {
105         ec = NOT_SUPPORTED_ERR;
106         return;
107     }
108     setAttribute(valueAttr, AtomicString::number(value >= 0 ? value : 0));
109 }
110
111 double HTMLProgressElement::max() const
112 {
113     double max = parseToDoubleForNumberType(fastGetAttribute(maxAttr));
114     return !std::isfinite(max) || max <= 0 ? 1 : max;
115 }
116
117 void HTMLProgressElement::setMax(double max, ExceptionCode& ec)
118 {
119     if (!std::isfinite(max)) {
120         ec = NOT_SUPPORTED_ERR;
121         return;
122     }
123     setAttribute(maxAttr, AtomicString::number(max > 0 ? max : 1));
124 }
125
126 double HTMLProgressElement::position() const
127 {
128     if (!isDeterminate())
129         return HTMLProgressElement::IndeterminatePosition;
130     return value() / max();
131 }
132
133 bool HTMLProgressElement::isDeterminate() const
134 {
135     return fastHasAttribute(valueAttr);
136 }
137     
138 void HTMLProgressElement::didElementStateChange()
139 {
140     m_value->setWidthPercentage(position() * 100);
141     if (RenderProgress* render = renderProgress()) {
142         bool wasDeterminate = render->isDeterminate();
143         render->updateFromElement();
144         if (wasDeterminate != isDeterminate())
145             didAffectSelector(AffectedSelectorIndeterminate);
146     }
147 }
148
149 void HTMLProgressElement::didAddUserAgentShadowRoot(ShadowRoot* root)
150 {
151     ASSERT(!m_value);
152
153     RefPtr<ProgressInnerElement> inner = ProgressInnerElement::create(document());
154     root->appendChild(inner);
155
156     RefPtr<ProgressBarElement> bar = ProgressBarElement::create(document());
157     RefPtr<ProgressValueElement> value = ProgressValueElement::create(document());
158     m_value = value.get();
159     m_value->setWidthPercentage(HTMLProgressElement::IndeterminatePosition * 100);
160     bar->appendChild(m_value, ASSERT_NO_EXCEPTION);
161
162     inner->appendChild(bar, ASSERT_NO_EXCEPTION);
163 }
164
165 bool HTMLProgressElement::shouldAppearIndeterminate() const
166 {
167     return !isDeterminate();
168 }
169
170 } // namespace