Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / 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
23 #include "core/html/HTMLProgressElement.h"
24
25 #include "bindings/core/v8/ExceptionMessages.h"
26 #include "bindings/core/v8/ExceptionState.h"
27 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
28 #include "core/HTMLNames.h"
29 #include "core/dom/ExceptionCode.h"
30 #include "core/dom/shadow/ShadowRoot.h"
31 #include "core/frame/UseCounter.h"
32 #include "core/html/parser/HTMLParserIdioms.h"
33 #include "core/html/shadow/ProgressShadowElement.h"
34 #include "core/rendering/RenderProgress.h"
35
36 namespace blink {
37
38 using namespace HTMLNames;
39
40 const double HTMLProgressElement::IndeterminatePosition = -1;
41 const double HTMLProgressElement::InvalidPosition = -2;
42
43 HTMLProgressElement::HTMLProgressElement(Document& document)
44     : LabelableElement(progressTag, document)
45     , m_value(nullptr)
46 {
47     ScriptWrappable::init(this);
48     UseCounter::count(document, UseCounter::ProgressElement);
49 }
50
51 HTMLProgressElement::~HTMLProgressElement()
52 {
53 }
54
55 PassRefPtrWillBeRawPtr<HTMLProgressElement> HTMLProgressElement::create(Document& document)
56 {
57     RefPtrWillBeRawPtr<HTMLProgressElement> progress = adoptRefWillBeNoop(new HTMLProgressElement(document));
58     progress->ensureUserAgentShadowRoot();
59     return progress.release();
60 }
61
62 RenderObject* HTMLProgressElement::createRenderer(RenderStyle* style)
63 {
64     if (!style->hasAppearance() || hasAuthorShadowRoot())
65         return RenderObject::createObject(this, style);
66
67     return new RenderProgress(this);
68 }
69
70 RenderProgress* HTMLProgressElement::renderProgress() const
71 {
72     if (renderer() && renderer()->isProgress())
73         return toRenderProgress(renderer());
74
75     RenderObject* renderObject = userAgentShadowRoot()->firstChild()->renderer();
76     ASSERT_WITH_SECURITY_IMPLICATION(!renderObject || renderObject->isProgress());
77     return toRenderProgress(renderObject);
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::attach(const AttachContext& context)
91 {
92     LabelableElement::attach(context);
93     if (RenderProgress* render = renderProgress())
94         render->updateFromElement();
95 }
96
97 double HTMLProgressElement::value() const
98 {
99     double value = getFloatingPointAttribute(valueAttr);
100     // Otherwise, if the parsed value was greater than or equal to the maximum
101     // value, then the current value of the progress bar is the maximum value
102     // of the progress bar. Otherwise, if parsing the value attribute's value
103     // resulted in an error, or a number less than or equal to zero, then the
104     // current value of the progress bar is zero.
105     return !std::isfinite(value) || value < 0 ? 0 : std::min(value, max());
106 }
107
108 void HTMLProgressElement::setValue(double value)
109 {
110     setFloatingPointAttribute(valueAttr, std::max(value, 0.));
111 }
112
113 double HTMLProgressElement::max() const
114 {
115     double max = getFloatingPointAttribute(maxAttr);
116     // Otherwise, if the element has no max attribute, or if it has one but
117     // parsing it resulted in an error, or if the parsed value was less than or
118     // equal to zero, then the maximum value of the progress bar is 1.0.
119     return !std::isfinite(max) || max <= 0 ? 1 : max;
120 }
121
122 void HTMLProgressElement::setMax(double max)
123 {
124     // FIXME: The specification says we should ignore the input value if it is inferior or equal to 0.
125     setFloatingPointAttribute(maxAttr, max > 0 ? max : 1);
126 }
127
128 double HTMLProgressElement::position() const
129 {
130     if (!isDeterminate())
131         return HTMLProgressElement::IndeterminatePosition;
132     return value() / max();
133 }
134
135 bool HTMLProgressElement::isDeterminate() const
136 {
137     return fastHasAttribute(valueAttr);
138 }
139
140 void HTMLProgressElement::didElementStateChange()
141 {
142     m_value->setWidthPercentage(position() * 100);
143     if (RenderProgress* render = renderProgress()) {
144         bool wasDeterminate = render->isDeterminate();
145         render->updateFromElement();
146         if (wasDeterminate != isDeterminate())
147             didAffectSelector(AffectedSelectorIndeterminate);
148     }
149 }
150
151 void HTMLProgressElement::didAddUserAgentShadowRoot(ShadowRoot& root)
152 {
153     ASSERT(!m_value);
154
155     RefPtrWillBeRawPtr<ProgressInnerElement> inner = ProgressInnerElement::create(document());
156     inner->setShadowPseudoId(AtomicString("-webkit-progress-inner-element", AtomicString::ConstructFromLiteral));
157     root.appendChild(inner);
158
159     RefPtrWillBeRawPtr<ProgressBarElement> bar = ProgressBarElement::create(document());
160     bar->setShadowPseudoId(AtomicString("-webkit-progress-bar", AtomicString::ConstructFromLiteral));
161     RefPtrWillBeRawPtr<ProgressValueElement> value = ProgressValueElement::create(document());
162     m_value = value.get();
163     m_value->setShadowPseudoId(AtomicString("-webkit-progress-value", AtomicString::ConstructFromLiteral));
164     m_value->setWidthPercentage(HTMLProgressElement::IndeterminatePosition * 100);
165     bar->appendChild(m_value);
166
167     inner->appendChild(bar);
168 }
169
170 bool HTMLProgressElement::shouldAppearIndeterminate() const
171 {
172     return !isDeterminate();
173 }
174
175 void HTMLProgressElement::trace(Visitor* visitor)
176 {
177     visitor->trace(m_value);
178     LabelableElement::trace(visitor);
179 }
180
181 } // namespace