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