AccessibilityTableCell* AccessibilityTable::cellForColumnAndRow(unsigned column, unsigned row)
{
    updateChildrenIfNecessary();
    if (column >= columnCount() || row >= rowCount())
        return 0;
    
    // Iterate backwards through the rows in case the desired cell has a rowspan and exists in a previous row.
    for (unsigned rowIndexCounter = row + 1; rowIndexCounter > 0; --rowIndexCounter) {
        unsigned rowIndex = rowIndexCounter - 1;
        const auto& children = m_rows[rowIndex]->children();
        // Since some cells may have colspans, we have to check the actual range of each
        // cell to determine which is the right one.
        for (unsigned colIndexCounter = std::min(static_cast<unsigned>(children.size()), column + 1); colIndexCounter > 0; --colIndexCounter) {
            unsigned colIndex = colIndexCounter - 1;
            AccessibilityObject* child = children[colIndex].get();
            ASSERT(child->isTableCell());
            if (!child->isTableCell())
                continue;
            
            std::pair<unsigned, unsigned> columnRange;
            std::pair<unsigned, unsigned> rowRange;
            AccessibilityTableCell* tableCellChild = toAccessibilityTableCell(child);
            tableCellChild->columnIndexRange(columnRange);
            tableCellChild->rowIndexRange(rowRange);
            
            if ((column >= columnRange.first && column < (columnRange.first + columnRange.second))
                && (row >= rowRange.first && row < (rowRange.first + rowRange.second)))
                return tableCellChild;
        }
    }
    
    return 0;
}
Example #2
0
void AccessibilityTableCell::columnHeaders(AccessibilityChildrenVector& headers)
{
    AccessibilityTable* parent = parentTable();
    if (!parent)
        return;

    // Choose columnHeaders as the place where the "headers" attribute is reported.
    ariaElementsFromAttribute(headers, headersAttr);
    // If the headers attribute returned valid values, then do not further search for column headers.
    if (!headers.isEmpty())
        return;
    
    std::pair<unsigned, unsigned> rowRange;
    rowIndexRange(rowRange);
    
    std::pair<unsigned, unsigned> colRange;
    columnIndexRange(colRange);
    
    for (unsigned row = 0; row < rowRange.first; row++) {
        AccessibilityTableCell* tableCell = parent->cellForColumnAndRow(colRange.first, row);
        if (!tableCell || tableCell == this || headers.contains(tableCell))
            continue;

        std::pair<unsigned, unsigned> childRowRange;
        tableCell->rowIndexRange(childRowRange);
            
        const AtomicString& scope = tableCell->getAttribute(scopeAttr);
        if (scope == "col" || tableCell->isTableHeaderCell())
            headers.append(tableCell);
        else if (scope == "colgroup" && isTableCellInSameColGroup(tableCell))
            headers.append(tableCell);
    }
}
void AccessibilityTableCell::columnHeaders(AccessibilityChildrenVector& headers)
{
    AccessibilityTable* parent = parentTable();
    if (!parent)
        return;

    std::pair<unsigned, unsigned> rowRange;
    rowIndexRange(rowRange);
    
    std::pair<unsigned, unsigned> colRange;
    columnIndexRange(colRange);
    
    for (unsigned row = 0; row < rowRange.first; row++) {
        AccessibilityTableCell* tableCell = parent->cellForColumnAndRow(colRange.first, row);
        if (tableCell == this || headers.contains(tableCell))
            continue;

        std::pair<unsigned, unsigned> childRowRange;
        tableCell->rowIndexRange(childRowRange);
            
        const AtomicString& scope = tableCell->getAttribute(scopeAttr);
        if (scope == "col" || tableCell->isTableHeaderCell())
            headers.append(tableCell);
        else if (scope == "colgroup" && isTableCellInSameColGroup(tableCell))
            headers.append(tableCell);
    }
}
void AccessibilityTableColumn::addChildren()
{
    ASSERT(!m_haveChildren); 
    
    m_haveChildren = true;
    if (!is<AccessibilityTable>(m_parent))
        return;

    auto& parentTable = downcast<AccessibilityTable>(*m_parent);
    if (!parentTable.isExposableThroughAccessibility())
        return;
    
    int numRows = parentTable.rowCount();
    
    for (int i = 0; i < numRows; ++i) {
        AccessibilityTableCell* cell = parentTable.cellForColumnAndRow(m_columnIndex, i);
        if (!cell)
            continue;
        
        // make sure the last one isn't the same as this one (rowspan cells)
        if (m_children.size() > 0 && m_children.last() == cell)
            continue;
            
        m_children.append(cell);
        m_columnRect.unite(cell->elementRect());
    }
}
static AtkObject* webkit_accessible_table_ref_at(AtkTable* table, gint row, gint column)
{
    AccessibilityTableCell* AXCell = cell(table, row, column);
    if (!AXCell)
        return 0;
    return AXCell->wrapper();
}
static gint webkit_accessible_table_get_row_extent_at(AtkTable* table, gint row, gint column)
{
    AccessibilityTableCell* AXCell = cell(table, row, column);
    if (AXCell) {
        pair<int, int> rowRange;
        AXCell->rowIndexRange(rowRange);
        return rowRange.second;
    }
    return 0;
}
static gint webkitAccessibleTableGetRowExtentAt(AtkTable* table, gint row, gint column)
{
    AccessibilityTableCell* axCell = cell(table, row, column);
    if (axCell) {
        pair<unsigned, unsigned> rowRange;
        axCell->rowIndexRange(rowRange);
        return rowRange.second;
    }
    return 0;
}
static gint webkitAccessibleTableGetRowAtIndex(AtkTable* table, gint index)
{
    AccessibilityTableCell* axCell = cellAtIndex(table, index);
    if (axCell) {
        pair<unsigned, unsigned> rowRange;
        axCell->rowIndexRange(rowRange);
        return rowRange.first;
    }
    return -1;
}
static gint webkitAccessibleTableGetColumnAtIndex(AtkTable* table, gint index)
{
    AccessibilityTableCell* axCell = cellAtIndex(table, index);
    if (axCell) {
        pair<unsigned, unsigned> columnRange;
        axCell->columnIndexRange(columnRange);
        return columnRange.first;
    }
    return -1;
}
static gint webkitAccessibleTableGetRowExtentAt(AtkTable* table, gint row, gint column)
{
    g_return_val_if_fail(ATK_TABLE(table), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);

    AccessibilityTableCell* axCell = cell(table, row, column);
    if (axCell) {
        pair<unsigned, unsigned> rowRange;
        axCell->rowIndexRange(rowRange);
        return rowRange.second;
    }
    return 0;
}
static gint webkitAccessibleTableGetRowAtIndex(AtkTable* table, gint index)
{
    g_return_val_if_fail(ATK_TABLE(table), -1);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), -1);

    AccessibilityTableCell* axCell = cellAtIndex(table, index);
    if (axCell) {
        pair<unsigned, unsigned> rowRange;
        axCell->rowIndexRange(rowRange);
        return rowRange.first;
    }
    return -1;
}
static AtkObject* webkitAccessibleTableRefAt(AtkTable* table, gint row, gint column)
{
    AccessibilityTableCell* axCell = cell(table, row, column);
    if (!axCell)
        return 0;

    AtkObject* cell = axCell->wrapper();
    if (!cell)
        return 0;

    // This method transfers full ownership over the returned
    // AtkObject, so an extra reference is needed here.
    return ATK_OBJECT(g_object_ref(cell));
}
static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row)
{
    AccessibilityObject* accTable = core(table);
    if (accTable->isAccessibilityRenderObject()) {
        AccessibilityObject::AccessibilityChildrenVector allRowHeaders;
        static_cast<AccessibilityTable*>(accTable)->rowHeaders(allRowHeaders);
        unsigned rowCount = allRowHeaders.size();
        for (unsigned k = 0; k < rowCount; ++k) {
            pair<unsigned, unsigned> rowRange;
            AccessibilityTableCell* cell = static_cast<AccessibilityTableCell*>(allRowHeaders.at(k).get());
            cell->rowIndexRange(rowRange);
            if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second)
                return allRowHeaders[k]->wrapper();
        }
    }
    return 0;
}
static AtkObject* webkitAccessibleTableRefAt(AtkTable* table, gint row, gint column)
{
    g_return_val_if_fail(ATK_TABLE(table), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);

    AccessibilityTableCell* axCell = cell(table, row, column);
    if (!axCell)
        return 0;

    AtkObject* cell = axCell->wrapper();
    if (!cell)
        return 0;

    // This method transfers full ownership over the returned
    // AtkObject, so an extra reference is needed here.
    return ATK_OBJECT(g_object_ref(cell));
}
AccessibilityTableCell* AccessibilityARIAGrid::cellForColumnAndRow(unsigned column, unsigned row)
{
    if (!m_renderer)
        return 0;
    
    updateChildrenIfNecessary();
    
    if (column >= columnCount() || row >= rowCount())
        return 0;
    
    int intRow = (int)row;
    int intColumn = (int)column;

    pair<int, int> columnRange;
    pair<int, int> rowRange;
    
    // Iterate backwards through the rows in case the desired cell has a rowspan and exists
    // in a previous row.
    for (; intRow >= 0; --intRow) {
        AccessibilityObject* tableRow = m_rows[intRow].get();
        if (!tableRow)
            continue;
        
        AccessibilityChildrenVector children = tableRow->children();
        unsigned childrenLength = children.size();
        
        // Since some cells may have colspans, we have to check the actual range of each
        // cell to determine which is the right one.
        for (unsigned k = 0; k < childrenLength; ++k) {
            AccessibilityObject* child = children[k].get();
            if (!child->isTableCell()) 
                continue;
            
            AccessibilityTableCell* tableCellChild = static_cast<AccessibilityTableCell*>(child);
            tableCellChild->columnIndexRange(columnRange);
            tableCellChild->rowIndexRange(rowRange);
            
            if ((intColumn >= columnRange.first && intColumn < (columnRange.first + columnRange.second))
                && (intRow >= rowRange.first && intRow < (rowRange.first + rowRange.second)))
                return tableCellChild;
        }
    }

    return 0;
}
static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row)
{
    g_return_val_if_fail(ATK_TABLE(table), 0);
    returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0);

    AccessibilityObject* accTable = core(table);
    if (accTable->isAccessibilityRenderObject()) {
        AccessibilityObject::AccessibilityChildrenVector allRowHeaders;
        toAccessibilityTable(accTable)->rowHeaders(allRowHeaders);
        unsigned rowCount = allRowHeaders.size();
        for (unsigned k = 0; k < rowCount; ++k) {
            pair<unsigned, unsigned> rowRange;
            AccessibilityTableCell* cell = toAccessibilityTableCell(allRowHeaders.at(k).get());
            cell->rowIndexRange(rowRange);
            if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second)
                return allRowHeaders[k]->wrapper();
        }
    }
    return 0;
}
void AccessibilityTableColumn::addChildren()
{
    ASSERT(!m_haveChildren); 
    
    m_haveChildren = true;
    if (!m_parentTable)
        return;
    
    int numRows = m_parentTable->rowCount();
    
    for (int i = 0; i < numRows; i++) {
        AccessibilityTableCell* cell = m_parentTable->cellForColumnAndRow(m_columnIndex, i);
        if (!cell)
            continue;
        
        // make sure the last one isn't the same as this one (rowspan cells)
        if (m_children.size() > 0 && m_children.last() == cell)
            continue;
            
        m_children.append(cell);
        m_columnRect.unite(cell->elementRect());
    }
}
void AccessibilityTableCell::rowHeaders(AccessibilityChildrenVector& headers)
{
    AccessibilityTable* parent = parentTable();
    if (!parent)
        return;

    std::pair<unsigned, unsigned> rowRange;
    rowIndexRange(rowRange);

    std::pair<unsigned, unsigned> colRange;
    columnIndexRange(colRange);

    for (unsigned column = 0; column < colRange.first; column++) {
        AccessibilityTableCell* tableCell = parent->cellForColumnAndRow(column, rowRange.first);
        if (tableCell == this || headers.contains(tableCell))
            continue;
        
        const AtomicString& scope = tableCell->getAttribute(scopeAttr);
        if (scope == "row")
            headers.append(tableCell);
        else if (scope == "rowgroup" && isTableCellInSameRowGroup(tableCell))
            headers.append(tableCell);
    }
}