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 "AccessibilityTableColumn.h" 31 32 #include "AXObjectCache.h" 33 #include "AccessibilityTableCell.h" 34 #include "HTMLNames.h" 35 #include "RenderTable.h" 36 #include "RenderTableCell.h" 37 #include "RenderTableSection.h" 38 39 using namespace std; 40 41 namespace WebCore { 42 43 using namespace HTMLNames; 44 45 AccessibilityTableColumn::AccessibilityTableColumn() 46 : m_parentTable(0) 47 { 48 } 49 50 AccessibilityTableColumn::~AccessibilityTableColumn() 51 { 52 } 53 54 PassRefPtr<AccessibilityTableColumn> AccessibilityTableColumn::create() 55 { 56 return adoptRef(new AccessibilityTableColumn()); 57 } 58 59 void AccessibilityTableColumn::setParentTable(AccessibilityTable* table) 60 { 61 m_parentTable = table; 62 63 clearChildren(); 64 } 65 66 IntRect AccessibilityTableColumn::elementRect() const 67 { 68 // this will be filled in when addChildren is called 69 return m_columnRect; 70 } 71 72 IntSize AccessibilityTableColumn::size() const 73 { 74 return elementRect().size(); 75 } 76 77 const AccessibilityObject::AccessibilityChildrenVector& AccessibilityTableColumn::children() 78 { 79 if (!m_haveChildren) 80 addChildren(); 81 return m_children; 82 } 83 84 AccessibilityObject* AccessibilityTableColumn::headerObject() 85 { 86 if (!m_parentTable) 87 return 0; 88 89 RenderObject* renderer = m_parentTable->renderer(); 90 if (!renderer) 91 return 0; 92 93 if (m_parentTable->isAriaTable()) { 94 AccessibilityChildrenVector rowChildren = children(); 95 unsigned childrenCount = rowChildren.size(); 96 for (unsigned i = 0; i < childrenCount; ++i) { 97 AccessibilityObject* cell = rowChildren[i].get(); 98 if (cell->ariaRoleAttribute() == ColumnHeaderRole) 99 return cell; 100 } 101 102 return 0; 103 } 104 105 if (!renderer->isTable()) 106 return 0; 107 108 RenderTable* table = toRenderTable(renderer); 109 110 AccessibilityObject* headerObject = 0; 111 112 // try the <thead> section first. this doesn't require th tags 113 headerObject = headerObjectForSection(table->header(), false); 114 115 if (headerObject) 116 return headerObject; 117 118 // now try for <th> tags in the first body 119 headerObject = headerObjectForSection(table->firstBody(), true); 120 121 return headerObject; 122 } 123 124 AccessibilityObject* AccessibilityTableColumn::headerObjectForSection(RenderTableSection* section, bool thTagRequired) 125 { 126 if (!section) 127 return 0; 128 129 int numCols = section->numColumns(); 130 if (m_columnIndex >= numCols) 131 return 0; 132 133 if (!section->numRows()) 134 return 0; 135 136 RenderTableCell* cell = 0; 137 // also account for cells that have a span 138 for (int testCol = m_columnIndex; testCol >= 0; --testCol) { 139 RenderTableCell* testCell = section->primaryCellAt(0, testCol); 140 if (!testCell) 141 continue; 142 143 // we've reached a cell that doesn't even overlap our column 144 // it can't be our header 145 if ((testCell->col() + (testCell->colSpan()-1)) < m_columnIndex) 146 break; 147 148 Node* node = testCell->node(); 149 if (!node) 150 continue; 151 152 if (thTagRequired && !node->hasTagName(thTag)) 153 continue; 154 155 cell = testCell; 156 } 157 158 if (!cell) 159 return 0; 160 161 return m_parentTable->axObjectCache()->getOrCreate(cell); 162 } 163 164 bool AccessibilityTableColumn::accessibilityIsIgnored() const 165 { 166 if (!m_parentTable) 167 return true; 168 169 #if PLATFORM(GTK) 170 return true; 171 #endif 172 173 return m_parentTable->accessibilityIsIgnored(); 174 } 175 176 void AccessibilityTableColumn::addChildren() 177 { 178 ASSERT(!m_haveChildren); 179 180 m_haveChildren = true; 181 if (!m_parentTable) 182 return; 183 184 int numRows = m_parentTable->rowCount(); 185 186 for (int i = 0; i < numRows; i++) { 187 AccessibilityTableCell* cell = m_parentTable->cellForColumnAndRow(m_columnIndex, i); 188 if (!cell) 189 continue; 190 191 // make sure the last one isn't the same as this one (rowspan cells) 192 if (m_children.size() > 0 && m_children.last() == cell) 193 continue; 194 195 m_children.append(cell); 196 m_columnRect.unite(cell->elementRect()); 197 } 198 } 199 200 } // namespace WebCore 201