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