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 "core/accessibility/AccessibilityListBoxOption.h" 31 32 #include "core/accessibility/AXObjectCache.h" 33 #include "core/html/HTMLOptGroupElement.h" 34 #include "core/html/HTMLOptionElement.h" 35 #include "core/html/HTMLSelectElement.h" 36 #include "core/rendering/RenderListBox.h" 37 38 using namespace std; 39 40 namespace WebCore { 41 42 using namespace HTMLNames; 43 44 AccessibilityListBoxOption::AccessibilityListBoxOption() 45 : m_optionElement(0) 46 { 47 } 48 49 AccessibilityListBoxOption::~AccessibilityListBoxOption() 50 { 51 } 52 53 PassRefPtr<AccessibilityListBoxOption> AccessibilityListBoxOption::create() 54 { 55 return adoptRef(new AccessibilityListBoxOption()); 56 } 57 58 bool AccessibilityListBoxOption::isEnabled() const 59 { 60 if (!m_optionElement) 61 return false; 62 63 if (isHTMLOptGroupElement(m_optionElement)) 64 return false; 65 66 if (equalIgnoringCase(getAttribute(aria_disabledAttr), "true")) 67 return false; 68 69 if (m_optionElement->hasAttribute(disabledAttr)) 70 return false; 71 72 return true; 73 } 74 75 bool AccessibilityListBoxOption::isSelected() const 76 { 77 if (!m_optionElement) 78 return false; 79 80 if (!m_optionElement->hasTagName(optionTag)) 81 return false; 82 83 return toHTMLOptionElement(m_optionElement)->selected(); 84 } 85 86 bool AccessibilityListBoxOption::isSelectedOptionActive() const 87 { 88 HTMLSelectElement* listBoxParentNode = listBoxOptionParentNode(); 89 if (!listBoxParentNode) 90 return false; 91 92 return listBoxParentNode->activeSelectionEndListIndex() == listBoxOptionIndex(); 93 } 94 95 LayoutRect AccessibilityListBoxOption::elementRect() const 96 { 97 LayoutRect rect; 98 if (!m_optionElement) 99 return rect; 100 101 HTMLSelectElement* listBoxParentNode = listBoxOptionParentNode(); 102 if (!listBoxParentNode) 103 return rect; 104 105 RenderObject* listBoxRenderer = listBoxParentNode->renderer(); 106 if (!listBoxRenderer) 107 return rect; 108 109 LayoutRect parentRect = listBoxRenderer->document()->axObjectCache()->getOrCreate(listBoxRenderer)->elementRect(); 110 int index = listBoxOptionIndex(); 111 if (index != -1) 112 rect = toRenderListBox(listBoxRenderer)->itemBoundingBoxRect(parentRect.location(), index); 113 114 return rect; 115 } 116 117 bool AccessibilityListBoxOption::computeAccessibilityIsIgnored() const 118 { 119 if (!m_optionElement) 120 return true; 121 122 if (accessibilityIsIgnoredByDefault()) 123 return true; 124 125 return parentObject()->accessibilityIsIgnored(); 126 } 127 128 bool AccessibilityListBoxOption::canSetSelectedAttribute() const 129 { 130 if (!m_optionElement) 131 return false; 132 133 if (!m_optionElement->hasTagName(optionTag)) 134 return false; 135 136 if (m_optionElement->isDisabledFormControl()) 137 return false; 138 139 HTMLSelectElement* selectElement = listBoxOptionParentNode(); 140 if (selectElement && selectElement->isDisabledFormControl()) 141 return false; 142 143 return true; 144 } 145 146 String AccessibilityListBoxOption::stringValue() const 147 { 148 if (!m_optionElement) 149 return String(); 150 151 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); 152 if (!ariaLabel.isNull()) 153 return ariaLabel; 154 155 if (m_optionElement->hasTagName(optionTag)) 156 return toHTMLOptionElement(m_optionElement)->text(); 157 158 if (isHTMLOptGroupElement(m_optionElement)) 159 return toHTMLOptGroupElement(m_optionElement)->groupLabelText(); 160 161 return String(); 162 } 163 164 Element* AccessibilityListBoxOption::actionElement() const 165 { 166 return m_optionElement; 167 } 168 169 AccessibilityObject* AccessibilityListBoxOption::parentObject() const 170 { 171 HTMLSelectElement* parentNode = listBoxOptionParentNode(); 172 if (!parentNode) 173 return 0; 174 175 return m_optionElement->document()->axObjectCache()->getOrCreate(parentNode); 176 } 177 178 void AccessibilityListBoxOption::setSelected(bool selected) 179 { 180 HTMLSelectElement* selectElement = listBoxOptionParentNode(); 181 if (!selectElement) 182 return; 183 184 if (!canSetSelectedAttribute()) 185 return; 186 187 bool isOptionSelected = isSelected(); 188 if ((isOptionSelected && selected) || (!isOptionSelected && !selected)) 189 return; 190 191 // Convert from the entire list index to the option index. 192 int optionIndex = selectElement->listToOptionIndex(listBoxOptionIndex()); 193 selectElement->accessKeySetSelectedIndex(optionIndex); 194 } 195 196 HTMLSelectElement* AccessibilityListBoxOption::listBoxOptionParentNode() const 197 { 198 if (!m_optionElement) 199 return 0; 200 201 if (m_optionElement->hasTagName(optionTag)) 202 return toHTMLOptionElement(m_optionElement)->ownerSelectElement(); 203 204 if (isHTMLOptGroupElement(m_optionElement)) 205 return toHTMLOptGroupElement(m_optionElement)->ownerSelectElement(); 206 207 return 0; 208 } 209 210 int AccessibilityListBoxOption::listBoxOptionIndex() const 211 { 212 if (!m_optionElement) 213 return -1; 214 215 HTMLSelectElement* selectElement = listBoxOptionParentNode(); 216 if (!selectElement) 217 return -1; 218 219 const Vector<HTMLElement*>& listItems = selectElement->listItems(); 220 unsigned length = listItems.size(); 221 for (unsigned i = 0; i < length; i++) 222 if (listItems[i] == m_optionElement) 223 return i; 224 225 return -1; 226 } 227 228 } // namespace WebCore 229