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/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