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 "AccessibilityListBox.h" 31 32 #include "AXObjectCache.h" 33 #include "AccessibilityListBoxOption.h" 34 #include "HTMLNames.h" 35 #include "HTMLSelectElement.h" 36 #include "HitTestResult.h" 37 #include "RenderListBox.h" 38 #include "RenderObject.h" 39 40 using namespace std; 41 42 namespace WebCore { 43 44 using namespace HTMLNames; 45 46 AccessibilityListBox::AccessibilityListBox(RenderObject* renderer) 47 : AccessibilityRenderObject(renderer) 48 { 49 } 50 51 AccessibilityListBox::~AccessibilityListBox() 52 { 53 } 54 55 PassRefPtr<AccessibilityListBox> AccessibilityListBox::create(RenderObject* renderer) 56 { 57 return adoptRef(new AccessibilityListBox(renderer)); 58 } 59 60 bool AccessibilityListBox::canSetSelectedChildrenAttribute() const 61 { 62 Node* selectNode = m_renderer->node(); 63 if (!selectNode) 64 return false; 65 66 return !static_cast<HTMLSelectElement*>(selectNode)->disabled(); 67 } 68 69 void AccessibilityListBox::addChildren() 70 { 71 Node* selectNode = m_renderer->node(); 72 if (!selectNode) 73 return; 74 75 m_haveChildren = true; 76 77 const Vector<Element*>& listItems = static_cast<HTMLSelectElement*>(selectNode)->listItems(); 78 unsigned length = listItems.size(); 79 for (unsigned i = 0; i < length; i++) { 80 // The cast to HTMLElement below is safe because the only other possible listItem type 81 // would be a WMLElement, but WML builds don't use accessibility features at all. 82 AccessibilityObject* listOption = listBoxOptionAccessibilityObject(static_cast<HTMLElement*>(listItems[i])); 83 if (listOption) 84 m_children.append(listOption); 85 } 86 } 87 88 void AccessibilityListBox::setSelectedChildren(AccessibilityChildrenVector& children) 89 { 90 if (!canSetSelectedChildrenAttribute()) 91 return; 92 93 Node* selectNode = m_renderer->node(); 94 if (!selectNode) 95 return; 96 97 // disable any selected options 98 unsigned length = m_children.size(); 99 for (unsigned i = 0; i < length; i++) { 100 AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(m_children[i].get()); 101 if (listBoxOption->isSelected()) 102 listBoxOption->setSelected(false); 103 } 104 105 length = children.size(); 106 for (unsigned i = 0; i < length; i++) { 107 AccessibilityObject* obj = children[i].get(); 108 if (obj->roleValue() != ListBoxOptionRole) 109 continue; 110 111 static_cast<AccessibilityListBoxOption*>(obj)->setSelected(true); 112 } 113 } 114 115 void AccessibilityListBox::selectedChildren(AccessibilityChildrenVector& result) 116 { 117 ASSERT(result.isEmpty()); 118 119 if (!hasChildren()) 120 addChildren(); 121 122 unsigned length = m_children.size(); 123 for (unsigned i = 0; i < length; i++) { 124 if (static_cast<AccessibilityListBoxOption*>(m_children[i].get())->isSelected()) 125 result.append(m_children[i]); 126 } 127 } 128 129 void AccessibilityListBox::visibleChildren(AccessibilityChildrenVector& result) 130 { 131 ASSERT(result.isEmpty()); 132 133 if (!hasChildren()) 134 addChildren(); 135 136 unsigned length = m_children.size(); 137 for (unsigned i = 0; i < length; i++) { 138 if (toRenderListBox(m_renderer)->listIndexIsVisible(i)) 139 result.append(m_children[i]); 140 } 141 } 142 143 AccessibilityObject* AccessibilityListBox::listBoxOptionAccessibilityObject(HTMLElement* element) const 144 { 145 // skip hr elements 146 if (!element || element->hasTagName(hrTag)) 147 return 0; 148 149 AccessibilityObject* listBoxObject = m_renderer->document()->axObjectCache()->getOrCreate(ListBoxOptionRole); 150 static_cast<AccessibilityListBoxOption*>(listBoxObject)->setHTMLElement(element); 151 152 return listBoxObject; 153 } 154 155 AccessibilityObject* AccessibilityListBox::doAccessibilityHitTest(const IntPoint& point) const 156 { 157 // the internal HTMLSelectElement methods for returning a listbox option at a point 158 // ignore optgroup elements. 159 if (!m_renderer) 160 return 0; 161 162 Node* node = m_renderer->node(); 163 if (!node) 164 return 0; 165 166 IntRect parentRect = boundingBoxRect(); 167 168 const Vector<Element*>& listItems = static_cast<HTMLSelectElement*>(node)->listItems(); 169 unsigned length = listItems.size(); 170 for (unsigned i = 0; i < length; i++) { 171 IntRect rect = toRenderListBox(m_renderer)->itemBoundingBoxRect(parentRect.x(), parentRect.y(), i); 172 // The cast to HTMLElement below is safe because the only other possible listItem type 173 // would be a WMLElement, but WML builds don't use accessibility features at all. 174 if (rect.contains(point)) 175 return listBoxOptionAccessibilityObject(static_cast<HTMLElement*>(listItems[i])); 176 } 177 178 return axObjectCache()->getOrCreate(m_renderer); 179 } 180 181 } // namespace WebCore 182