AccessibilityARIAGrid.cpp revision cad810f21b803229eb11403f9209855525a25d57
1/* 2 * Copyright (C) 2009 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 "AccessibilityARIAGrid.h" 31 32#include "AXObjectCache.h" 33#include "AccessibilityTableCell.h" 34#include "AccessibilityTableColumn.h" 35#include "AccessibilityTableHeaderContainer.h" 36#include "AccessibilityTableRow.h" 37#include "RenderObject.h" 38 39using namespace std; 40 41namespace WebCore { 42 43AccessibilityARIAGrid::AccessibilityARIAGrid(RenderObject* renderer) 44 : AccessibilityTable(renderer) 45{ 46#if ACCESSIBILITY_TABLES 47 m_isAccessibilityTable = true; 48#else 49 m_isAccessibilityTable = false; 50#endif 51} 52 53AccessibilityARIAGrid::~AccessibilityARIAGrid() 54{ 55} 56 57PassRefPtr<AccessibilityARIAGrid> AccessibilityARIAGrid::create(RenderObject* renderer) 58{ 59 return adoptRef(new AccessibilityARIAGrid(renderer)); 60} 61 62void AccessibilityARIAGrid::addChild(AccessibilityObject* child, HashSet<AccessibilityObject*>& appendedRows, unsigned& columnCount) 63{ 64 if (!child || !child->isTableRow() || child->ariaRoleAttribute() != RowRole) 65 return; 66 67 AccessibilityTableRow* row = static_cast<AccessibilityTableRow*>(child); 68 if (appendedRows.contains(row)) 69 return; 70 71 // store the maximum number of columns 72 unsigned rowCellCount = row->children().size(); 73 if (rowCellCount > columnCount) 74 columnCount = rowCellCount; 75 76 row->setRowIndex((int)m_rows.size()); 77 m_rows.append(row); 78 m_children.append(row); 79 appendedRows.add(row); 80} 81 82void AccessibilityARIAGrid::addChildren() 83{ 84 ASSERT(!m_haveChildren); 85 86 if (!isAccessibilityTable()) { 87 AccessibilityRenderObject::addChildren(); 88 return; 89 } 90 91 m_haveChildren = true; 92 if (!m_renderer) 93 return; 94 95 AXObjectCache* axCache = m_renderer->document()->axObjectCache(); 96 97 // add only rows that are labeled as aria rows 98 HashSet<AccessibilityObject*> appendedRows; 99 unsigned columnCount = 0; 100 for (RefPtr<AccessibilityObject> child = firstChild(); child; child = child->nextSibling()) { 101 102 // in case the render tree doesn't match the expected ARIA hierarchy, look at the children 103 if (child->accessibilityIsIgnored()) { 104 if (!child->hasChildren()) 105 child->addChildren(); 106 107 AccessibilityChildrenVector children = child->children(); 108 unsigned length = children.size(); 109 for (unsigned i = 0; i < length; ++i) 110 addChild(children[i].get(), appendedRows, columnCount); 111 } else 112 addChild(child.get(), appendedRows, columnCount); 113 } 114 115 // make the columns based on the number of columns in the first body 116 for (unsigned i = 0; i < columnCount; ++i) { 117 AccessibilityTableColumn* column = static_cast<AccessibilityTableColumn*>(axCache->getOrCreate(ColumnRole)); 118 column->setColumnIndex((int)i); 119 column->setParentTable(this); 120 m_columns.append(column); 121 if (!column->accessibilityIsIgnored()) 122 m_children.append(column); 123 } 124 125 AccessibilityObject* headerContainerObject = headerContainer(); 126 if (headerContainerObject && !headerContainerObject->accessibilityIsIgnored()) 127 m_children.append(headerContainerObject); 128} 129 130AccessibilityTableCell* AccessibilityARIAGrid::cellForColumnAndRow(unsigned column, unsigned row) 131{ 132 if (!m_renderer) 133 return 0; 134 135 updateChildrenIfNecessary(); 136 137 if (column >= columnCount() || row >= rowCount()) 138 return 0; 139 140 AccessibilityObject* tableRow = m_rows[row].get(); 141 if (!tableRow) 142 return 0; 143 144 AccessibilityChildrenVector children = tableRow->children(); 145 // in case this row had fewer columns than other rows 146 AccessibilityObject* tableCell = 0; 147 if (column >= children.size()) 148 return 0; 149 150 tableCell = children[column].get(); 151 return static_cast<AccessibilityTableCell*>(tableCell); 152} 153 154} // namespace WebCore 155