Home | History | Annotate | Download | only in accessibility
      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