diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp')
-rw-r--r-- | src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp | 491 |
1 files changed, 0 insertions, 491 deletions
diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp deleted file mode 100644 index ee54496..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "AccessibilityTable.h" - -#include "AccessibilityTableCell.h" -#include "AccessibilityTableColumn.h" -#include "AccessibilityTableHeaderContainer.h" -#include "AccessibilityTableRow.h" -#include "AXObjectCache.h" -#include "HTMLNames.h" -#include "HTMLTableElement.h" -#include "HTMLTableCaptionElement.h" -#include "HTMLTableCellElement.h" -#include "RenderObject.h" -#include "RenderTable.h" -#include "RenderTableCell.h" -#include "RenderTableSection.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityTable::AccessibilityTable(RenderObject* renderer) - : AccessibilityRenderObject(renderer), - m_headerContainer(0) -{ - // FIXME: We need to disable Accessibility Tables entirely on the Mac until <rdar://problem/6372481> is resolved. -#if PLATFORM(MAC) - m_isAccessibilityTable = false; -#else - m_isAccessibilityTable = isTableExposableThroughAccessibility(); -#endif - -} - -AccessibilityTable::~AccessibilityTable() -{ -} - -PassRefPtr<AccessibilityTable> AccessibilityTable::create(RenderObject* renderer) -{ - return adoptRef(new AccessibilityTable(renderer)); -} - -bool AccessibilityTable::isTableExposableThroughAccessibility() -{ - // the following is a heuristic used to determine if a - // <table> should be exposed as an AXTable. The goal - // is to only show "data" tables - - if (!m_renderer || !m_renderer->isTable()) - return false; - - // if the developer assigned an aria role to this, then we shouldn't - // expose it as a table, unless, of course, the aria role is a table - AccessibilityRole ariaRole = ariaRoleAttribute(); - if (ariaRole == TableRole) - return true; - if (ariaRole != UnknownRole) - return false; - - RenderTable* table = static_cast<RenderTable*>(m_renderer); - - // this employs a heuristic to determine if this table should appear. - // Only "data" tables should be exposed as tables. - // Unfortunately, there is no good way to determine the difference - // between a "layout" table and a "data" table - - Node* tableNode = table->element(); - if (!tableNode || !tableNode->hasTagName(tableTag)) - return false; - - // if there is a caption element, summary, THEAD, or TFOOT section, it's most certainly a data table - HTMLTableElement* tableElement = static_cast<HTMLTableElement*>(tableNode); - if (!tableElement->summary().isEmpty() || tableElement->tHead() || tableElement->tFoot() || tableElement->caption()) - return true; - - // if someone used "rules" attribute than the table should appear - if (!tableElement->rules().isEmpty()) - return true; - - // go through the cell's and check for tell-tale signs of "data" table status - // cells have borders, or use attributes like headers, abbr, scope or axis - RenderTableSection* firstBody = table->firstBody(); - if (!firstBody) - return false; - - int numCols = firstBody->numColumns(); - int numRows = firstBody->numRows(); - - // if there's only one cell, it's not a good AXTable candidate - if (numRows == 1 && numCols == 1) - return false; - - // store the background color of the table to check against cell's background colors - RenderStyle* tableStyle = table->style(); - if (!tableStyle) - return false; - Color tableBGColor = tableStyle->backgroundColor(); - - // check enough of the cells to find if the table matches our criteria - // Criteria: - // 1) must have at least one valid cell (and) - // 2) at least half of cells have borders (or) - // 3) at least half of cells have different bg colors than the table, and there is cell spacing - unsigned validCellCount = 0; - unsigned borderedCellCount = 0; - unsigned backgroundDifferenceCellCount = 0; - - for (int row = 0; row < numRows; ++row) { - for (int col = 0; col < numCols; ++col) { - RenderTableCell* cell = firstBody->cellAt(row, col).cell; - if (!cell) - continue; - Node* cellNode = cell->element(); - if (!cellNode) - continue; - - if (cell->width() < 1 || cell->height() < 1) - continue; - - validCellCount++; - - HTMLTableCellElement* cellElement = static_cast<HTMLTableCellElement*>(cellNode); - - // in this case, the developer explicitly assigned a "data" table attribute - if (!cellElement->headers().isEmpty() || !cellElement->abbr().isEmpty() || - !cellElement->axis().isEmpty() || !cellElement->scope().isEmpty()) - return true; - - RenderStyle* renderStyle = cell->style(); - if (!renderStyle) - continue; - - // a cell needs to have matching bordered sides, before it can be considered a bordered cell. - if ((cell->borderTop() > 0 && cell->borderBottom() > 0) || - (cell->borderLeft() > 0 && cell->borderRight() > 0)) - borderedCellCount++; - - // if the cell has a different color from the table and there is cell spacing, - // then it is probably a data table cell (spacing and colors take the place of borders) - Color cellColor = renderStyle->backgroundColor(); - if (table->hBorderSpacing() > 0 && table->vBorderSpacing() > 0 && - tableBGColor != cellColor && cellColor.alpha() != 1) - backgroundDifferenceCellCount++; - - // if we've found 10 "good" cells, we don't need to keep searching - if (borderedCellCount >= 10 || backgroundDifferenceCellCount >= 10) - return true; - } - } - - // if there is less than two valid cells, it's not a data table - if (validCellCount <= 1) - return false; - - // half of the cells had borders, it's a data table - unsigned neededCellCount = validCellCount / 2; - if (borderedCellCount >= neededCellCount) - return true; - - // half had different background colors, it's a data table - if (backgroundDifferenceCellCount >= neededCellCount) - return true; - - return false; -} - -void AccessibilityTable::clearChildren() -{ - m_children.clear(); - m_rows.clear(); - m_columns.clear(); - m_haveChildren = false; -} - -void AccessibilityTable::addChildren() -{ - if (!isDataTable()) { - AccessibilityRenderObject::addChildren(); - return; - } - - ASSERT(!m_haveChildren); - - m_haveChildren = true; - if (!m_renderer) - return; - - RenderTable* table = static_cast<RenderTable*>(m_renderer); - AXObjectCache* axCache = m_renderer->document()->axObjectCache(); - - // go through all the available sections to pull out the rows - // and add them as children - RenderTableSection* tableSection = table->header(); - if (!tableSection) - tableSection = table->firstBody(); - - if (!tableSection) - return; - - RenderTableSection* initialTableSection = tableSection; - - while (tableSection) { - - HashSet<AccessibilityObject*> appendedRows; - - unsigned numRows = tableSection->numRows(); - unsigned numCols = tableSection->numColumns(); - for (unsigned rowIndex = 0; rowIndex < numRows; ++rowIndex) { - for (unsigned colIndex = 0; colIndex < numCols; ++colIndex) { - - RenderTableCell* cell = tableSection->cellAt(rowIndex, colIndex).cell; - if (!cell) - continue; - - AccessibilityObject* rowObject = axCache->get(cell->parent()); - if (!rowObject->isTableRow()) - continue; - - AccessibilityTableRow* row = static_cast<AccessibilityTableRow*>(rowObject); - // we need to check every cell for a new row, because cell spans - // can cause us to mess rows if we just check the first column - if (appendedRows.contains(row)) - continue; - - row->setRowIndex((int)m_rows.size()); - m_rows.append(row); - m_children.append(row); - appendedRows.add(row); - } - } - - tableSection = table->sectionBelow(tableSection, true); - } - - // make the columns based on the number of columns in the first body - unsigned length = initialTableSection->numColumns(); - for (unsigned i = 0; i < length; ++i) { - AccessibilityTableColumn* column = static_cast<AccessibilityTableColumn*>(axCache->get(ColumnRole)); - column->setColumnIndex((int)i); - column->setParentTable(this); - m_columns.append(column); - m_children.append(column); - } - - AccessibilityObject* headerContainerObject = headerContainer(); - if (headerContainerObject) - m_children.append(headerContainerObject); -} - -AccessibilityObject* AccessibilityTable::headerContainer() -{ - if (m_headerContainer) - return m_headerContainer; - - m_headerContainer = static_cast<AccessibilityTableHeaderContainer*>(axObjectCache()->get(TableHeaderContainerRole)); - m_headerContainer->setParentTable(this); - - return m_headerContainer; -} - -AccessibilityObject::AccessibilityChildrenVector& AccessibilityTable::columns() -{ - if (!hasChildren()) - addChildren(); - - return m_columns; -} - -AccessibilityObject::AccessibilityChildrenVector& AccessibilityTable::rows() -{ - if (!hasChildren()) - addChildren(); - - return m_rows; -} - -void AccessibilityTable::rowHeaders(AccessibilityChildrenVector& headers) -{ - if (!m_renderer) - return; - - if (!hasChildren()) - addChildren(); - - unsigned rowCount = m_rows.size(); - for (unsigned k = 0; k < rowCount; ++k) { - AccessibilityObject* header = static_cast<AccessibilityTableRow*>(m_rows[k].get())->headerObject(); - if (!header) - continue; - headers.append(header); - } -} - -void AccessibilityTable::columnHeaders(AccessibilityChildrenVector& headers) -{ - if (!m_renderer) - return; - - if (!hasChildren()) - addChildren(); - - unsigned colCount = m_columns.size(); - for (unsigned k = 0; k < colCount; ++k) { - AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_columns[k].get())->headerObject(); - if (!header) - continue; - headers.append(header); - } -} - -void AccessibilityTable::cells(AccessibilityObject::AccessibilityChildrenVector& cells) -{ - if (!m_renderer) - return; - - if (!hasChildren()) - addChildren(); - - int numRows = m_rows.size(); - for (int row = 0; row < numRows; ++row) { - AccessibilityChildrenVector rowChildren = m_rows[row]->children(); - cells.append(rowChildren); - } -} - -const unsigned AccessibilityTable::columnCount() -{ - if (!hasChildren()) - addChildren(); - - return m_columns.size(); -} - -const unsigned AccessibilityTable::rowCount() -{ - if (!hasChildren()) - addChildren(); - - return m_rows.size(); -} - -AccessibilityTableCell* AccessibilityTable::cellForColumnAndRow(unsigned column, unsigned row) -{ - if (!m_renderer) - return 0; - - if (!hasChildren()) - addChildren(); - - RenderTable* table = static_cast<RenderTable*>(m_renderer); - RenderTableSection* tableSection = table->header(); - if (!tableSection) - tableSection = table->firstBody(); - - RenderTableCell* cell = 0; - unsigned rowCount = 0; - unsigned rowOffset = 0; - while (tableSection) { - - rowCount += tableSection->numRows(); - unsigned numCols = tableSection->numColumns(); - - if (row < rowCount && column < numCols) { - int sectionSpecificRow = row - rowOffset; - cell = tableSection->cellAt(sectionSpecificRow, column).cell; - - // we didn't find the cell, which means there's spanning happening - // search backwards to find the spanning cell - if (!cell) { - - // first try rows - for (int testRow = sectionSpecificRow-1; testRow >= 0; --testRow) { - cell = tableSection->cellAt(testRow, column).cell; - // cell overlapped. use this one - if (cell && ((cell->row() + (cell->rowSpan()-1)) >= (int)sectionSpecificRow)) - break; - cell = 0; - } - - if (!cell) { - // try cols - for (int testCol = column-1; testCol >= 0; --testCol) { - cell = tableSection->cellAt(sectionSpecificRow, testCol).cell; - // cell overlapped. use this one - if (cell && ((cell->col() + (cell->colSpan()-1)) >= (int)column)) - break; - cell = 0; - } - } - } - } - - if (cell) - break; - - rowOffset += rowCount; - // we didn't find anything between the rows we should have - if (row < rowOffset) - break; - tableSection = table->sectionBelow(tableSection, true); - } - - if (!cell) - return 0; - - AccessibilityObject* cellObject = axObjectCache()->get(cell); - ASSERT(cellObject->isTableCell()); - - return static_cast<AccessibilityTableCell*>(cellObject); -} - -AccessibilityRole AccessibilityTable::roleValue() const -{ - if (!isDataTable()) - return AccessibilityRenderObject::roleValue(); - - return TableRole; -} - -bool AccessibilityTable::accessibilityIsIgnored() const -{ - if (!isDataTable()) - return AccessibilityRenderObject::accessibilityIsIgnored(); - - return false; -} - -String AccessibilityTable::title() const -{ - if (!isDataTable()) - return AccessibilityRenderObject::title(); - - String title; - if (!m_renderer) - return title; - - // see if there is a caption - Node *tableElement = m_renderer->element(); - if (tableElement) { - HTMLTableCaptionElement* caption = static_cast<HTMLTableElement*>(tableElement)->caption(); - if (caption) - title = caption->innerText(); - } - - // try the standard - if (title.isEmpty()) - title = AccessibilityRenderObject::title(); - - return title; -} - -bool AccessibilityTable::isDataTable() const -{ - if (!m_renderer) - return false; - - return m_isAccessibilityTable; -} - -} // namespace WebCore |