15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1.  Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2.  Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     its contributors may be used to endorse or promote products derived
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     from this software without specific prior written permission.
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
30bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "core/accessibility/AXTableCell.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/accessibility/AXObjectCache.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderTableCell.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
3702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)AXTableCell::AXTableCell(RenderObject* renderer)
41bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    : AXRenderObject(renderer)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)AXTableCell::~AXTableCell()
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
49bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)PassRefPtr<AXTableCell> AXTableCell::create(RenderObject* renderer)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
51bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return adoptRef(new AXTableCell(renderer));
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
54bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)bool AXTableCell::computeAccessibilityIsIgnored() const
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
56bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    AXObjectInclusion decision = defaultObjectInclusion();
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (decision == IncludeObject)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (decision == IgnoreObject)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
6102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isTableCell())
63bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return AXRenderObject::computeAccessibilityIsIgnored();
6402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
68bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)AXObject* AXTableCell::parentTable() const
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_renderer || !m_renderer->isTableCell())
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
72926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // If the document no longer exists, we might not have an axObjectCache.
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!axObjectCache())
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
7602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // Do not use getOrCreate. parentTable() can be called while the render tree is being modified
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // by javascript, and creating a table element may try to access the render tree while in a bad state.
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // By using only get() implies that the AXTable must be created before AXTableCells. This should
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // always be the case when AT clients access a table.
8102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // https://bugs.webkit.org/show_bug.cgi?id=42652
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return axObjectCache()->get(toRenderTableCell(m_renderer)->table());
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
8402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
85bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)bool AXTableCell::isTableCell() const
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
87bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    AXObject* parent = parentObjectUnignored();
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!parent || !parent->isTableRow())
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
9002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
9302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
94bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)AccessibilityRole AXTableCell::determineAccessibilityRole()
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isTableCell())
97bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return AXRenderObject::determineAccessibilityRole();
9802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return CellRole;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
10102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
102bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void AXTableCell::rowIndexRange(pair<unsigned, unsigned>& rowRange)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_renderer || !m_renderer->isTableCell())
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
10602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTableCell* renderCell = toRenderTableCell(m_renderer);
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rowRange.first = renderCell->rowIndex();
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rowRange.second = renderCell->rowSpan();
11002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // since our table might have multiple sections, we have to offset our row appropriately
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTableSection* section = renderCell->section();
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTable* table = renderCell->table();
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!table || !section)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    RenderTableSection* tableSection = table->topSection();
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned rowOffset = 0;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (tableSection) {
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (tableSection == section)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        rowOffset += tableSection->numRows();
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        tableSection = table->sectionBelow(tableSection, SkipEmptySections);
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    rowRange.first += rowOffset;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
129bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void AXTableCell::columnIndexRange(pair<unsigned, unsigned>& columnRange)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_renderer || !m_renderer->isTableCell())
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
13302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTableCell* renderCell = toRenderTableCell(m_renderer);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    columnRange.first = renderCell->col();
13602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    columnRange.second = renderCell->colSpan();
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
139bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)AXObject* AXTableCell::titleUIElement() const
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Try to find if the first cell in this row is a <th>. If it is,
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // then it can act as the title ui element. (This is only in the
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // case when the table is not appearing as an AXTable.)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isTableCell() || !m_renderer || !m_renderer->isTableCell())
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Table cells that are th cannot have title ui elements, since by definition
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // they are title ui elements
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* node = m_renderer->node();
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (node && node->hasTagName(thTag))
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
15202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTableCell* renderCell = toRenderTableCell(m_renderer);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If this cell is in the first column, there is no need to continue.
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int col = renderCell->col();
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!col)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int row = renderCell->rowIndex();
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTableSection* section = renderCell->section();
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!section)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
16502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderTableCell* headerCell = section->primaryCellAt(row, 0);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!headerCell || headerCell == renderCell)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* cellElement = headerCell->node();
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!cellElement || !cellElement->hasTagName(thTag))
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
17302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return axObjectCache()->getOrCreate(headerCell);
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
178