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