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