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