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 (m_optionElement->hasTagName(optgroupTag)) 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 static_cast<HTMLOptionElement*>(m_optionElement)->selected(); 84 } 85 86 IntRect AccessibilityListBoxOption::elementRect() const 87 { 88 IntRect rect; 89 if (!m_optionElement) 90 return rect; 91 92 HTMLSelectElement* listBoxParentNode = listBoxOptionParentNode(); 93 if (!listBoxParentNode) 94 return rect; 95 96 RenderObject* listBoxRenderer = listBoxParentNode->renderer(); 97 if (!listBoxRenderer) 98 return rect; 99 100 IntRect parentRect = listBoxRenderer->document()->axObjectCache()->getOrCreate(listBoxRenderer)->boundingBoxRect(); 101 int index = listBoxOptionIndex(); 102 if (index != -1) 103 rect = toRenderListBox(listBoxRenderer)->itemBoundingBoxRect(parentRect.x(), parentRect.y(), index); 104 105 return rect; 106 } 107 108 bool AccessibilityListBoxOption::accessibilityIsIgnored() const 109 { 110 if (!m_optionElement) 111 return true; 112 113 if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "true")) 114 return true; 115 116 return parentObject()->accessibilityIsIgnored(); 117 } 118 119 bool AccessibilityListBoxOption::canSetSelectedAttribute() const 120 { 121 if (!m_optionElement) 122 return false; 123 124 if (!m_optionElement->hasTagName(optionTag)) 125 return false; 126 127 if (m_optionElement->disabled()) 128 return false; 129 130 HTMLSelectElement* selectElement = listBoxOptionParentNode(); 131 if (selectElement && selectElement->disabled()) 132 return false; 133 134 return true; 135 } 136 137 String AccessibilityListBoxOption::stringValue() const 138 { 139 if (!m_optionElement) 140 return String(); 141 142 const AtomicString& ariaLabel = getAttribute(aria_labelAttr); 143 if (!ariaLabel.isNull()) 144 return ariaLabel; 145 146 if (m_optionElement->hasTagName(optionTag)) 147 return static_cast<HTMLOptionElement*>(m_optionElement)->text(); 148 149 if (m_optionElement->hasTagName(optgroupTag)) 150 return static_cast<HTMLOptGroupElement*>(m_optionElement)->groupLabelText(); 151 152 return String(); 153 } 154 155 Element* AccessibilityListBoxOption::actionElement() const 156 { 157 return m_optionElement; 158 } 159 160 AccessibilityObject* AccessibilityListBoxOption::parentObject() const 161 { 162 HTMLSelectElement* parentNode = listBoxOptionParentNode(); 163 if (!parentNode) 164 return 0; 165 166 return m_optionElement->document()->axObjectCache()->getOrCreate(parentNode->renderer()); 167 } 168 169 void AccessibilityListBoxOption::setSelected(bool selected) 170 { 171 HTMLSelectElement* selectElement = listBoxOptionParentNode(); 172 if (!selectElement) 173 return; 174 175 if (!canSetSelectedAttribute()) 176 return; 177 178 bool isOptionSelected = isSelected(); 179 if ((isOptionSelected && selected) || (!isOptionSelected && !selected)) 180 return; 181 182 // Convert from the entire list index to the option index. 183 int optionIndex = static_cast<SelectElement*>(selectElement)->listToOptionIndex(listBoxOptionIndex()); 184 selectElement->accessKeySetSelectedIndex(optionIndex); 185 } 186 187 HTMLSelectElement* AccessibilityListBoxOption::listBoxOptionParentNode() const 188 { 189 if (!m_optionElement) 190 return 0; 191 192 if (m_optionElement->hasTagName(optionTag)) 193 return static_cast<HTMLOptionElement*>(m_optionElement)->ownerSelectElement(); 194 195 if (m_optionElement->hasTagName(optgroupTag)) 196 return static_cast<HTMLOptGroupElement*>(m_optionElement)->ownerSelectElement(); 197 198 return 0; 199 } 200 201 int AccessibilityListBoxOption::listBoxOptionIndex() const 202 { 203 if (!m_optionElement) 204 return -1; 205 206 HTMLSelectElement* selectElement = listBoxOptionParentNode(); 207 if (!selectElement) 208 return -1; 209 210 const Vector<Element*>& listItems = selectElement->listItems(); 211 unsigned length = listItems.size(); 212 for (unsigned i = 0; i < length; i++) 213 if (listItems[i] == m_optionElement) 214 return i; 215 216 return -1; 217 } 218 219 } // namespace WebCore 220