void AXTableCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange) { if (!m_layoutObject || !m_layoutObject->isTableCell()) return; LayoutTableCell* layoutCell = toLayoutTableCell(m_layoutObject); rowRange.first = layoutCell->rowIndex(); rowRange.second = layoutCell->rowSpan(); // since our table might have multiple sections, we have to offset our row appropriately LayoutTableSection* section = layoutCell->section(); LayoutTable* table = layoutCell->table(); if (!table || !section) return; LayoutTableSection* tableSection = table->topSection(); unsigned rowOffset = 0; while (tableSection) { if (tableSection == section) break; rowOffset += tableSection->numRows(); tableSection = table->sectionBelow(tableSection, SkipEmptySections); } rowRange.first += rowOffset; }
void AXTableColumn::headerObjectsForColumn(AXObjectVector& headers) { if (!m_parent) return; LayoutObject* layoutObject = m_parent->getLayoutObject(); if (!layoutObject) return; if (!m_parent->isAXTable()) return; if (toAXTable(m_parent)->isAriaTable()) { for (const auto& cell : children()) { if (cell->roleValue() == ColumnHeaderRole) headers.append(cell); } return; } if (!layoutObject->isTable()) return; LayoutTable* table = toLayoutTable(layoutObject); LayoutTableSection* tableSection = table->topSection(); for (; tableSection; tableSection = table->sectionBelow(tableSection, SkipEmptySections)) { unsigned numCols = tableSection->numEffectiveColumns(); if (m_columnIndex >= numCols) continue; unsigned numRows = tableSection->numRows(); for (unsigned r = 0; r < numRows; r++) { LayoutTableCell* layoutCell = tableSection->primaryCellAt(r, m_columnIndex); if (!layoutCell) continue; AXObject* cell = axObjectCache().getOrCreate(layoutCell->node()); if (!cell || !cell->isTableCell() || headers.contains(cell)) continue; if (toAXTableCell(cell)->scanToDecideHeaderRole() == ColumnHeaderRole) headers.append(cell); } } }
void AXTable::addChildren() { ASSERT(!isDetached()); if (!isAXTable()) { AXLayoutObject::addChildren(); return; } ASSERT(!m_haveChildren); m_haveChildren = true; if (!m_layoutObject || !m_layoutObject->isTable()) return; LayoutTable* table = toLayoutTable(m_layoutObject); AXObjectCacheImpl& axCache = axObjectCache(); Node* tableNode = table->node(); if (!isHTMLTableElement(tableNode)) return; // Add caption if (HTMLTableCaptionElement* caption = toHTMLTableElement(tableNode)->caption()) { AXObject* captionObject = axCache.getOrCreate(caption); if (captionObject && !captionObject->accessibilityIsIgnored()) m_children.append(captionObject); } // Go through all the available sections to pull out the rows and add them as children. table->recalcSectionsIfNeeded(); LayoutTableSection* tableSection = table->topSection(); if (!tableSection) return; LayoutTableSection* initialTableSection = tableSection; while (tableSection) { HeapHashSet<Member<AXObject>> appendedRows; unsigned numRows = tableSection->numRows(); for (unsigned rowIndex = 0; rowIndex < numRows; ++rowIndex) { LayoutTableRow* layoutRow = tableSection->rowLayoutObjectAt(rowIndex); if (!layoutRow) continue; AXObject* rowObject = axCache.getOrCreate(layoutRow); if (!rowObject || !rowObject->isTableRow()) continue; AXTableRow* row = toAXTableRow(rowObject); // We need to check every cell for a new row, because cell spans // can cause us to miss rows if we just check the first column. if (appendedRows.contains(row)) continue; row->setRowIndex(static_cast<int>(m_rows.size())); m_rows.append(row); if (!row->accessibilityIsIgnored()) m_children.append(row); appendedRows.add(row); } tableSection = table->sectionBelow(tableSection, SkipEmptySections); } // make the columns based on the number of columns in the first body unsigned length = initialTableSection->numEffectiveColumns(); for (unsigned i = 0; i < length; ++i) { AXTableColumn* column = toAXTableColumn(axCache.getOrCreate(ColumnRole)); column->setColumnIndex((int)i); column->setParent(this); m_columns.append(column); if (!column->accessibilityIsIgnored()) m_children.append(column); } AXObject* headerContainerObject = headerContainer(); if (headerContainerObject && !headerContainerObject->accessibilityIsIgnored()) m_children.append(headerContainerObject); }