RenderObject::document() should return a reference.
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityListBoxOption.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "AccessibilityListBoxOption.h"
31
32 #include "AXObjectCache.h"
33 #include "AccessibilityListBox.h"
34 #include "Element.h"
35 #include "HTMLElement.h"
36 #include "HTMLNames.h"
37 #include "HTMLOptGroupElement.h"
38 #include "HTMLOptionElement.h"
39 #include "HTMLSelectElement.h"
40 #include "IntRect.h"
41 #include "RenderListBox.h"
42 #include "RenderObject.h"
43
44 using namespace std;
45
46 namespace WebCore {
47
48 using namespace HTMLNames;
49     
50 AccessibilityListBoxOption::AccessibilityListBoxOption()
51     : m_optionElement(0)
52 {
53 }
54
55 AccessibilityListBoxOption::~AccessibilityListBoxOption()
56 {
57 }    
58     
59 PassRefPtr<AccessibilityListBoxOption> AccessibilityListBoxOption::create()
60 {
61     return adoptRef(new AccessibilityListBoxOption());
62 }
63     
64 bool AccessibilityListBoxOption::isEnabled() const
65 {
66     if (!m_optionElement)
67         return false;
68     
69     if (isHTMLOptGroupElement(m_optionElement))
70         return false;
71
72     if (equalIgnoringCase(getAttribute(aria_disabledAttr), "true"))
73         return false;
74
75     if (m_optionElement->hasAttribute(disabledAttr))
76         return false;
77     
78     return true;
79 }
80     
81 bool AccessibilityListBoxOption::isSelected() const
82 {
83     if (!m_optionElement)
84         return false;
85
86     if (!isHTMLOptionElement(m_optionElement))
87         return false;
88
89     return toHTMLOptionElement(m_optionElement)->selected();
90 }
91
92 bool AccessibilityListBoxOption::isSelectedOptionActive() const
93 {
94     HTMLSelectElement* listBoxParentNode = listBoxOptionParentNode();
95     if (!listBoxParentNode)
96         return false;
97
98     return listBoxParentNode->activeSelectionEndListIndex() == listBoxOptionIndex();
99 }
100
101 LayoutRect AccessibilityListBoxOption::elementRect() const
102 {
103     LayoutRect rect;
104     if (!m_optionElement)
105         return rect;
106     
107     HTMLSelectElement* listBoxParentNode = listBoxOptionParentNode();
108     if (!listBoxParentNode)
109         return rect;
110     
111     RenderObject* listBoxRenderer = listBoxParentNode->renderer();
112     if (!listBoxRenderer)
113         return rect;
114     
115     LayoutRect parentRect = listBoxRenderer->document().axObjectCache()->getOrCreate(listBoxRenderer)->boundingBoxRect();
116     int index = listBoxOptionIndex();
117     if (index != -1)
118         rect = toRenderListBox(listBoxRenderer)->itemBoundingBoxRect(parentRect.location(), index);
119     
120     return rect;
121 }
122
123 bool AccessibilityListBoxOption::computeAccessibilityIsIgnored() const
124 {
125     if (!m_optionElement)
126         return true;
127
128     if (accessibilityIsIgnoredByDefault())
129         return true;
130     
131     return parentObject()->accessibilityIsIgnored();
132 }
133     
134 bool AccessibilityListBoxOption::canSetSelectedAttribute() const
135 {
136     if (!m_optionElement)
137         return false;
138     
139     if (!isHTMLOptionElement(m_optionElement))
140         return false;
141     
142     if (m_optionElement->isDisabledFormControl())
143         return false;
144     
145     HTMLSelectElement* selectElement = listBoxOptionParentNode();
146     if (selectElement && selectElement->isDisabledFormControl())
147         return false;
148     
149     return true;
150 }
151     
152 String AccessibilityListBoxOption::stringValue() const
153 {
154     if (!m_optionElement)
155         return String();
156     
157     const AtomicString& ariaLabel = getAttribute(aria_labelAttr);
158     if (!ariaLabel.isNull())
159         return ariaLabel;
160     
161     if (isHTMLOptionElement(m_optionElement))
162         return toHTMLOptionElement(m_optionElement)->text();
163     
164     if (isHTMLOptGroupElement(m_optionElement))
165         return toHTMLOptGroupElement(m_optionElement)->groupLabelText();
166     
167     return String();
168 }
169
170 Element* AccessibilityListBoxOption::actionElement() const
171 {
172     return m_optionElement;
173 }
174
175 AccessibilityObject* AccessibilityListBoxOption::parentObject() const
176 {
177     HTMLSelectElement* parentNode = listBoxOptionParentNode();
178     if (!parentNode)
179         return 0;
180     
181     return m_optionElement->document()->axObjectCache()->getOrCreate(parentNode);
182 }
183
184 void AccessibilityListBoxOption::setSelected(bool selected)
185 {
186     HTMLSelectElement* selectElement = listBoxOptionParentNode();
187     if (!selectElement)
188         return;
189     
190     if (!canSetSelectedAttribute())
191         return;
192     
193     bool isOptionSelected = isSelected();
194     if ((isOptionSelected && selected) || (!isOptionSelected && !selected))
195         return;
196     
197     // Convert from the entire list index to the option index.
198     int optionIndex = selectElement->listToOptionIndex(listBoxOptionIndex());
199     selectElement->accessKeySetSelectedIndex(optionIndex);
200 }
201
202 HTMLSelectElement* AccessibilityListBoxOption::listBoxOptionParentNode() const
203 {
204     if (!m_optionElement)
205         return 0;
206
207     if (isHTMLOptionElement(m_optionElement))
208         return toHTMLOptionElement(m_optionElement)->ownerSelectElement();
209
210     if (isHTMLOptGroupElement(m_optionElement))
211         return toHTMLOptGroupElement(m_optionElement)->ownerSelectElement();
212
213     return 0;
214 }
215
216 int AccessibilityListBoxOption::listBoxOptionIndex() const
217 {
218     if (!m_optionElement)
219         return -1;
220     
221     HTMLSelectElement* selectElement = listBoxOptionParentNode();
222     if (!selectElement) 
223         return -1;
224     
225     const Vector<HTMLElement*>& listItems = selectElement->listItems();
226     unsigned length = listItems.size();
227     for (unsigned i = 0; i < length; i++)
228         if (listItems[i] == m_optionElement)
229             return i;
230
231     return -1;
232 }
233
234 } // namespace WebCore