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 "AccessibilityProgressIndicator.h"
23
24#include "AXObjectCache.h"
25#include "FloatConversion.h"
26#include "HTMLMeterElement.h"
27#include "HTMLNames.h"
28#include "HTMLProgressElement.h"
29#include "LocalizedStrings.h"
30#include "RenderMeter.h"
31#include "RenderObject.h"
32#include "RenderProgress.h"
33
34namespace WebCore {
35
36using namespace HTMLNames;
37
38AccessibilityProgressIndicator::AccessibilityProgressIndicator(RenderProgress* renderer)
39 : AccessibilityRenderObject(renderer)
40{
41}
42
43Ref<AccessibilityProgressIndicator> AccessibilityProgressIndicator::create(RenderProgress* renderer)
44{
45 return adoptRef(*new AccessibilityProgressIndicator(renderer));
46}
47
48#if ENABLE(METER_ELEMENT)
49AccessibilityProgressIndicator::AccessibilityProgressIndicator(RenderMeter* renderer)
50 : AccessibilityRenderObject(renderer)
51{
52}
53
54Ref<AccessibilityProgressIndicator> AccessibilityProgressIndicator::create(RenderMeter* renderer)
55{
56 return adoptRef(*new AccessibilityProgressIndicator(renderer));
57}
58#endif
59
60bool AccessibilityProgressIndicator::computeAccessibilityIsIgnored() const
61{
62 return accessibilityIsIgnoredByDefault();
63}
64
65String AccessibilityProgressIndicator::valueDescription() const
66{
67 // If the author has explicitly provided a value through aria-valuetext, use it.
68 String description = AccessibilityRenderObject::valueDescription();
69 if (!description.isEmpty())
70 return description;
71
72#if ENABLE(METER_ELEMENT)
73 if (!m_renderer->isMeter())
74 return String();
75
76 HTMLMeterElement* meter = meterElement();
77 if (!meter)
78 return String();
79
80 // The HTML spec encourages authors to include a textual representation of the meter's state in
81 // the element's contents. We'll fall back on that if there is not a more accessible alternative.
82 AccessibilityObject* axMeter = axObjectCache()->getOrCreate(meter);
83 if (is<AccessibilityNodeObject>(axMeter)) {
84 description = downcast<AccessibilityNodeObject>(axMeter)->accessibilityDescriptionForChildren();
85 if (!description.isEmpty())
86 return description;
87 }
88
89 return meter->textContent();
90#endif
91
92 return String();
93}
94
95float AccessibilityProgressIndicator::valueForRange() const
96{
97 if (!m_renderer)
98 return 0.0;
99
100 if (m_renderer->isProgress()) {
101 HTMLProgressElement* progress = progressElement();
102 if (progress && progress->position() >= 0)
103 return narrowPrecisionToFloat(progress->value());
104 }
105
106#if ENABLE(METER_ELEMENT)
107 if (m_renderer->isMeter()) {
108 if (HTMLMeterElement* meter = meterElement())
109 return narrowPrecisionToFloat(meter->value());
110 }
111#endif
112
113 // Indeterminate progress bar should return 0.
114 return 0.0;
115}
116
117float AccessibilityProgressIndicator::maxValueForRange() const
118{
119 if (!m_renderer)
120 return 0.0;
121
122 if (m_renderer->isProgress()) {
123 if (HTMLProgressElement* progress = progressElement())
124 return narrowPrecisionToFloat(progress->max());
125 }
126
127#if ENABLE(METER_ELEMENT)
128 if (m_renderer->isMeter()) {
129 if (HTMLMeterElement* meter = meterElement())
130 return narrowPrecisionToFloat(meter->max());
131 }
132#endif
133
134 return 0.0;
135}
136
137float AccessibilityProgressIndicator::minValueForRange() const
138{
139 if (!m_renderer)
140 return 0.0;
141
142 if (m_renderer->isProgress())
143 return 0.0;
144
145#if ENABLE(METER_ELEMENT)
146 if (m_renderer->isMeter()) {
147 if (HTMLMeterElement* meter = meterElement())
148 return narrowPrecisionToFloat(meter->min());
149 }
150#endif
151
152 return 0.0;
153}
154
155AccessibilityRole AccessibilityProgressIndicator::roleValue() const
156{
157#if ENABLE(METER_ELEMENT)
158 if (meterElement())
159 return AccessibilityRole::Meter;
160#endif
161 return AccessibilityRole::ProgressIndicator;
162}
163
164HTMLProgressElement* AccessibilityProgressIndicator::progressElement() const
165{
166 if (!is<RenderProgress>(*m_renderer))
167 return nullptr;
168
169 return downcast<RenderProgress>(*m_renderer).progressElement();
170}
171
172#if ENABLE(METER_ELEMENT)
173HTMLMeterElement* AccessibilityProgressIndicator::meterElement() const
174{
175 if (!is<RenderMeter>(*m_renderer))
176 return nullptr;
177
178 return downcast<RenderMeter>(*m_renderer).meterElement();
179}
180
181String AccessibilityProgressIndicator::gaugeRegionValueDescription() const
182{
183#if PLATFORM(COCOA)
184 if (!m_renderer || !m_renderer->isMeter())
185 return String();
186
187 // Only expose this when the author has explicitly specified the following attributes.
188 if (!hasAttribute(lowAttr) && !hasAttribute(highAttr) && !hasAttribute(optimumAttr))
189 return String();
190
191 if (HTMLMeterElement* element = meterElement()) {
192 switch (element->gaugeRegion()) {
193 case HTMLMeterElement::GaugeRegionOptimum:
194 return AXMeterGaugeRegionOptimumText();
195 case HTMLMeterElement::GaugeRegionSuboptimal:
196 return AXMeterGaugeRegionSuboptimalText();
197 case HTMLMeterElement::GaugeRegionEvenLessGood:
198 return AXMeterGaugeRegionLessGoodText();
199 default:
200 break;
201 }
202 }
203#endif
204 return String();
205}
206#endif
207
208Element* AccessibilityProgressIndicator::element() const
209{
210 if (m_renderer->isProgress())
211 return progressElement();
212
213#if ENABLE(METER_ELEMENT)
214 if (m_renderer->isMeter())
215 return meterElement();
216#endif
217
218 return AccessibilityObject::element();
219}
220
221} // namespace WebCore
222
223