2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
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.
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.
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.
23 #include "core/html/HTMLProgressElement.h"
25 #include "HTMLNames.h"
26 #include "bindings/v8/ExceptionMessages.h"
27 #include "bindings/v8/ExceptionState.h"
28 #include "bindings/v8/ExceptionStatePlaceholder.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"
37 using namespace HTMLNames;
39 const double HTMLProgressElement::IndeterminatePosition = -1;
40 const double HTMLProgressElement::InvalidPosition = -2;
42 HTMLProgressElement::HTMLProgressElement(Document& document)
43 : LabelableElement(progressTag, document)
46 ScriptWrappable::init(this);
49 HTMLProgressElement::~HTMLProgressElement()
53 PassRefPtrWillBeRawPtr<HTMLProgressElement> HTMLProgressElement::create(Document& document)
55 RefPtrWillBeRawPtr<HTMLProgressElement> progress = adoptRefWillBeRefCountedGarbageCollected(new HTMLProgressElement(document));
56 progress->ensureUserAgentShadowRoot();
57 return progress.release();
60 RenderObject* HTMLProgressElement::createRenderer(RenderStyle* style)
62 if (!style->hasAppearance() || hasAuthorShadowRoot())
63 return RenderObject::createObject(this, style);
65 return new RenderProgress(this);
68 RenderProgress* HTMLProgressElement::renderProgress() const
70 if (renderer() && renderer()->isProgress())
71 return toRenderProgress(renderer());
73 RenderObject* renderObject = userAgentShadowRoot()->firstChild()->renderer();
74 ASSERT_WITH_SECURITY_IMPLICATION(!renderObject || renderObject->isProgress());
75 return toRenderProgress(renderObject);
78 void HTMLProgressElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
80 if (name == valueAttr)
81 didElementStateChange();
82 else if (name == maxAttr)
83 didElementStateChange();
85 LabelableElement::parseAttribute(name, value);
88 void HTMLProgressElement::attach(const AttachContext& context)
90 LabelableElement::attach(context);
91 if (RenderProgress* render = renderProgress())
92 render->updateFromElement();
95 double HTMLProgressElement::value() const
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());
106 void HTMLProgressElement::setValue(double value)
108 setFloatingPointAttribute(valueAttr, std::max(value, 0.));
111 double HTMLProgressElement::max() const
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;
120 void HTMLProgressElement::setMax(double max)
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);
126 double HTMLProgressElement::position() const
128 if (!isDeterminate())
129 return HTMLProgressElement::IndeterminatePosition;
130 return value() / max();
133 bool HTMLProgressElement::isDeterminate() const
135 return fastHasAttribute(valueAttr);
138 void HTMLProgressElement::didElementStateChange()
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);
149 void HTMLProgressElement::didAddUserAgentShadowRoot(ShadowRoot& root)
153 RefPtr<ProgressInnerElement> inner = ProgressInnerElement::create(document());
154 inner->setShadowPseudoId(AtomicString("-webkit-progress-inner-element", AtomicString::ConstructFromLiteral));
155 root.appendChild(inner);
157 RefPtr<ProgressBarElement> bar = ProgressBarElement::create(document());
158 bar->setShadowPseudoId(AtomicString("-webkit-progress-bar", AtomicString::ConstructFromLiteral));
159 RefPtr<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);
165 inner->appendChild(bar);
168 bool HTMLProgressElement::shouldAppearIndeterminate() const
170 return !isDeterminate();