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