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 39 using namespace std; 40 41 namespace WebCore { 42 43 AccessibilityARIAGrid::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 53 AccessibilityARIAGrid::~AccessibilityARIAGrid() 54 { 55 } 56 57 PassRefPtr<AccessibilityARIAGrid> AccessibilityARIAGrid::create(RenderObject* renderer) 58 { 59 return adoptRef(new AccessibilityARIAGrid(renderer)); 60 } 61 62 void 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 82 void AccessibilityARIAGrid::addChildren() 83 { 84 ASSERT(!m_haveChildren); 85 86 if (!isDataTable()) { 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 m_children.append(column); 122 } 123 124 AccessibilityObject* headerContainerObject = headerContainer(); 125 if (headerContainerObject) 126 m_children.append(headerContainerObject); 127 } 128 129 AccessibilityTableCell* AccessibilityARIAGrid::cellForColumnAndRow(unsigned column, unsigned row) 130 { 131 if (!m_renderer) 132 return 0; 133 134 if (!hasChildren()) 135 addChildren(); 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