Bug 410052 - Fix our nsHTMLAccessibleTable class so GetIndexAt and GetRowAtIndex and GetColumnAtIndex behave consistently, patch=me, marcoz, r=marcoz, me, bernd, sr=roc, blocking1.9+=dsicore

This commit is contained in:
surkov.alexander@gmail.com 2008-02-06 23:03:26 -08:00
parent 26c047f2bc
commit d8aebfb510
8 changed files with 287 additions and 50 deletions

View File

@ -531,20 +531,11 @@ nsHTMLTableAccessible::GetIndexAt(PRInt32 aRow, PRInt32 aColumn,
NS_ENSURE_TRUE(IsValidRow(aRow) && IsValidColumn(aColumn), NS_ERROR_INVALID_ARG);
nsresult rv = NS_OK;
nsCOMPtr<nsIDOMElement> domElement;
rv = GetCellAt(aRow, aColumn, *getter_AddRefs(domElement));
nsITableLayout *tableLayout = nsnull;
nsresult rv = GetTableLayout(&tableLayout);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAccessible> accessible;
GetAccService()->GetCachedAccessible(domElement, mWeakShell, getter_AddRefs(accessible));
if (accessible) {
rv = accessible->GetIndexInParent(aIndex);
} else {
// not found the corresponding cell
*aIndex = -1;
}
return rv;
return tableLayout->GetIndexByRowAndColumn(aRow, aColumn, aIndex);
}
NS_IMETHODIMP
@ -552,16 +543,12 @@ nsHTMLTableAccessible::GetColumnAtIndex(PRInt32 aIndex, PRInt32 *aColumn)
{
NS_ENSURE_ARG_POINTER(aColumn);
nsCOMPtr<nsIAccessible> child;
GetChildAt(aIndex, getter_AddRefs(child));
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
nsCOMPtr<nsPIAccessNode> childNode(do_QueryInterface(child));
NS_ASSERTION(childNode, "childNode not valid in GetColumnAtIndex!");
nsIFrame* frame = childNode->GetFrame();
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
nsCOMPtr<nsITableCellLayout> cellLayout(do_QueryInterface(frame));
NS_ENSURE_TRUE(cellLayout, NS_ERROR_FAILURE);
return cellLayout->GetColIndex(*aColumn);
nsITableLayout *tableLayout = nsnull;
nsresult rv = GetTableLayout(&tableLayout);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 row;
return tableLayout->GetRowAndColumnByIndex(aIndex, &row, aColumn);
}
NS_IMETHODIMP
@ -569,16 +556,12 @@ nsHTMLTableAccessible::GetRowAtIndex(PRInt32 aIndex, PRInt32 *aRow)
{
NS_ENSURE_ARG_POINTER(aRow);
nsCOMPtr<nsIAccessible> child;
GetChildAt(aIndex, getter_AddRefs(child));
NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
nsCOMPtr<nsPIAccessNode> childNode(do_QueryInterface(child));
NS_ASSERTION(childNode, "childNode not valid in GetRowAtIndex!");
nsIFrame* frame = childNode->GetFrame();
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
nsCOMPtr<nsITableCellLayout> cellLayout(do_QueryInterface(frame));
NS_ENSURE_TRUE(cellLayout, NS_ERROR_FAILURE);
return cellLayout->GetRowIndex(*aRow);
nsITableLayout *tableLayout = nsnull;
nsresult rv = GetTableLayout(&tableLayout);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 column;
return tableLayout->GetRowAndColumnByIndex(aIndex, aRow, &column);
}
NS_IMETHODIMP

View File

@ -891,7 +891,83 @@ nsTableCellMap::GetCellInfoAt(PRInt32 aRowIndex,
}
return nsnull;
}
PRInt32
nsTableCellMap::GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn) const
{
PRInt32 index = 0;
PRInt32 colCount = mCols.Count();
PRInt32 rowIndex = aRow;
nsCellMap* cellMap = mFirstMap;
while (cellMap) {
PRInt32 rowCount = cellMap->GetRowCount();
if (rowCount < rowIndex) {
// If the rowCount is less than the rowIndex, this means that the index is
// not within the current map. If so, get the index of the last cell in
// the last row.
PRInt32 cellMapIdx = cellMap->GetIndexByRowAndColumn(colCount,
rowCount - 1,
colCount - 1);
if (cellMapIdx != -1) {
index += cellMapIdx;
rowIndex -= rowCount;
}
} else {
// Index is in valid range for this cellmap, so get the index of rowIndex
// and aColumn.
PRInt32 cellMapIdx = cellMap->GetIndexByRowAndColumn(colCount, rowIndex,
aColumn);
if (cellMapIdx != -1) {
index += cellMapIdx;
return index; // no need to look through further maps here
}
}
cellMap = cellMap->GetNextSibling();
}
return -1;
}
void
nsTableCellMap::GetRowAndColumnByIndex(PRInt32 aIndex,
PRInt32 *aRow, PRInt32 *aColumn) const
{
*aRow = -1;
*aColumn = -1;
PRInt32 colCount = mCols.Count();
PRInt32 previousRows = 0;
PRInt32 index = aIndex;
nsCellMap* cellMap = mFirstMap;
while (cellMap) {
PRInt32 rowCount = cellMap->GetRowCount();
// Determine the highest possible index in this map to see
// if wanted index is in here.
PRInt32 cellMapIdx = cellMap->GetIndexByRowAndColumn(colCount,
rowCount - 1,
colCount - 1);
if (cellMapIdx != -1) {
if (index > cellMapIdx) {
// The index is not within this map, so decrease it by the cellMapIdx
// determined index and increase the total row index accordingly.
index -= cellMapIdx;
previousRows += rowCount;
} else {
cellMap->GetRowAndColumnByIndex(colCount, index, aRow, aColumn);
// If there were previous indexes, take them into account.
*aRow += previousRows;
return; // no need to look any further.
}
}
cellMap = cellMap->GetNextSibling();
}
}
PRBool nsTableCellMap::RowIsSpannedInto(PRInt32 aRowIndex,
PRInt32 aNumEffCols) const
@ -1250,6 +1326,57 @@ nsCellMap::GetCellFrame(PRInt32 aRowIndexIn,
return nsnull;
}
PRInt32
nsCellMap::GetIndexByRowAndColumn(PRInt32 aColCount,
PRInt32 aRow, PRInt32 aColumn) const
{
PRInt32 index = -1;
if (aRow >= mRows.Length())
return index;
PRInt32 lastColsIdx = aColCount - 1;
for (PRInt32 rowIdx = 0; rowIdx <= aRow; rowIdx++) {
const CellDataArray& row = mRows[rowIdx];
PRInt32 colCount = (rowIdx == aRow) ? aColumn : lastColsIdx;
for (PRInt32 colIdx = 0; colIdx <= colCount; colIdx++) {
CellData* data = row.SafeElementAt(colIdx);
if (data && data->IsOrig())
index++;
}
}
return index;
}
void
nsCellMap::GetRowAndColumnByIndex(PRInt32 aColCount, PRInt32 aIndex,
PRInt32 *aRow, PRInt32 *aColumn) const
{
*aRow = -1;
*aColumn = -1;
PRInt32 index = aIndex;
PRInt32 rowCount = mRows.Length();
for (PRInt32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
const CellDataArray& row = mRows[rowIdx];
for (PRInt32 colIdx = 0; colIdx < aColCount; colIdx++) {
CellData* data = row.SafeElementAt(colIdx);
if (data && data->IsOrig())
index--;
if (index < 0) {
*aRow = rowIdx;
*aColumn = colIdx;
return;
}
}
}
}
PRBool nsCellMap::Grow(nsTableCellMap& aMap,
PRInt32 aNumRows,
PRInt32 aRowIndex)

View File

@ -173,6 +173,29 @@ public:
PRBool* aOriginates = nsnull,
PRInt32* aColSpan = nsnull) const;
/**
* Returns the index at the given row and column coordinates.
*
* @see nsITableLayout::GetIndexByRowAndColumn()
*
* @param aRow [in] the row coordinate
* @param aColumn [in] the column coordinate
* @returns the index for the cell
*/
PRInt32 GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn) const;
/**
* Retrieves the row and column coordinates for the given index.
*
* @see nsITableLayout::GetRowAndColumnByIndex()
*
* @param aIndex [in] the index for which coordinates are to be retrieved
* @param aRow [out] the row coordinate to be returned
* @param aColumn [out] the column coordinate to be returned
*/
void GetRowAndColumnByIndex(PRInt32 aIndex,
PRInt32 *aRow, PRInt32 *aColumn) const;
void AddColsAtEnd(PRUint32 aNumCols);
void RemoveColsAtEnd();
@ -301,6 +324,31 @@ public:
CellData& aData,
PRBool aUseRowSpanIfOverlap) const;
/**
* Returns the index of the given row and column coordinates.
*
* @see nsITableLayout::GetIndexByRowAndColumn()
*
* @param aColCount [in] the number of columns in a row
* @param aRow [in] the row coordinate
* @param aColumn [in] the column coordinate
*/
PRInt32 GetIndexByRowAndColumn(PRInt32 aColCount,
PRInt32 aRow, PRInt32 aColumn) const;
/**
* Get the row and column coordinates at the given index.
*
* @see nsITableLayout::GetRowAndColumnByIndex()
*
* @param aColCount [in] the number of columns in a row
* @param aIndex [in] the index for which coordinates are to be retrieved
* @param aRow [out] the row coordinate to be returned
* @param aColumn [out] the column coordinate to be returned
*/
void GetRowAndColumnByIndex(PRInt32 aColCount, PRInt32 aIndex,
PRInt32 *aRow, PRInt32 *aColumn) const;
/** append the cellFrame at an empty or dead cell or finally at the end of
* the row at aRowIndex and return a pointer to the celldata entry in the
* cellmap

View File

@ -43,7 +43,7 @@ class nsIDOMElement;
// IID for the nsITableLayout interface
// A9222E6B-437E-11d3-B227-004095E27A10
#define NS_ITABLELAYOUT_IID \
{ 0xa9222e6b, 0x437e, 0x11d3, { 0xb2, 0x27, 0x0, 0x40, 0x95, 0xe2, 0x7a, 0x10 }}
{ 0xf8363dea, 0x11ad, 0x483a, { 0xba, 0xea, 0xf6, 0xf2, 0xc3, 0x58, 0x8d, 0xde }}
/**
* nsITableLayout
@ -87,6 +87,31 @@ public:
* which displays as a ragged-right edge table
*/
NS_IMETHOD GetTableSize(PRInt32& aRowCount, PRInt32& aColCount)=0;
/**
* Retrieves the index of the cell at the given coordinates.
*
* @note The index is the order number of the cell calculated from top left
* cell to the right bottom cell of the table.
*
* @param aRow [in] the row the cell is in
* @param aColumn [in] the column the cell is in
* @param aIndex [out] the index to be returned
*/
NS_IMETHOD GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aIndex) = 0;
/**
* Retrieves the coordinates of the cell at the given index.
*
* @see nsITableLayout::GetIndexByRowAndColumn()
*
* @param aIndex [in] the index for which the coordinates are to be retrieved
* @param aRow [out] the resulting row coordinate
* @param aColumn [out] the resulting column coordinate
*/
NS_IMETHOD GetRowAndColumnByIndex(PRInt32 aIndex,
PRInt32 *aRow, PRInt32 *aColumn) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsITableLayout, NS_ITABLELAYOUT_IID)

View File

@ -3880,6 +3880,39 @@ NS_IMETHODIMP nsTableFrame::GetTableSize(PRInt32& aRowCount, PRInt32& aColCount)
return NS_OK;
}
NS_IMETHODIMP
nsTableFrame::GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aIndex)
{
NS_ENSURE_ARG_POINTER(aIndex);
*aIndex = -1;
nsTableCellMap* cellMap = GetCellMap();
if (!cellMap)
return NS_ERROR_NOT_INITIALIZED;
*aIndex = cellMap->GetIndexByRowAndColumn(aRow, aColumn);
return NS_OK;
}
NS_IMETHODIMP
nsTableFrame::GetRowAndColumnByIndex(PRInt32 aIndex,
PRInt32 *aRow, PRInt32 *aColumn)
{
NS_ENSURE_ARG_POINTER(aRow);
*aRow = -1;
NS_ENSURE_ARG_POINTER(aColumn);
*aColumn = -1;
nsTableCellMap* cellMap = GetCellMap();
if (!cellMap)
return NS_ERROR_NOT_INITIALIZED;
cellMap->GetRowAndColumnByIndex(aIndex, aRow, aColumn);
return NS_OK;
}
/*---------------- end of nsITableLayout implementation ------------------*/
PRInt32 nsTableFrame::GetNumCellsOriginatingInCol(PRInt32 aColIndex) const

View File

@ -469,6 +469,8 @@ public:
PRBool aRemoveFromCache,
PRBool aRemoveFromCellMap);
NS_IMETHOD GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex);
NS_IMETHOD GetRowAndColumnByIndex(PRInt32 aIndex, PRInt32 *aRow, PRInt32 *aColumn);
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;

View File

@ -1342,25 +1342,41 @@ nsTableOuterFrame::GetCellDataAt(PRInt32 aRowIndex, PRInt32 aColIndex,
PRInt32& aActualRowSpan, PRInt32& aActualColSpan,
PRBool& aIsSelected)
{
if (!mInnerTableFrame) { return NS_ERROR_NOT_INITIALIZED; }
nsITableLayout *inner;
if (NS_SUCCEEDED(CallQueryInterface(mInnerTableFrame, &inner))) {
return (inner->GetCellDataAt(aRowIndex, aColIndex, aCell,
aStartRowIndex, aStartColIndex,
aRowSpan, aColSpan, aActualRowSpan, aActualColSpan,
aIsSelected));
}
return NS_ERROR_NULL_POINTER;
NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
mInnerTableFrame->GetCellDataAt(aRowIndex, aColIndex, aCell,
aStartRowIndex, aStartColIndex,
aRowSpan, aColSpan, aActualRowSpan,
aActualColSpan, aIsSelected);
}
NS_IMETHODIMP nsTableOuterFrame::GetTableSize(PRInt32& aRowCount, PRInt32& aColCount)
NS_IMETHODIMP
nsTableOuterFrame::GetTableSize(PRInt32& aRowCount, PRInt32& aColCount)
{
if (!mInnerTableFrame) { return NS_ERROR_NOT_INITIALIZED; }
nsITableLayout *inner;
if (NS_SUCCEEDED(CallQueryInterface(mInnerTableFrame, &inner))) {
return (inner->GetTableSize(aRowCount, aColCount));
}
return NS_ERROR_NULL_POINTER;
NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
mInnerTableFrame->GetTableSize(aRowCount, aColCount);
}
NS_IMETHODIMP
nsTableOuterFrame::GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn,
PRInt32 *aIndex)
{
NS_ENSURE_ARG_POINTER(aIndex);
NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
return mInnerTableFrame->GetIndexByRowAndColumn(aRow, aColumn, aIndex);
}
NS_IMETHODIMP
nsTableOuterFrame::GetRowAndColumnByIndex(PRInt32 aIndex,
PRInt32 *aRow, PRInt32 *aColumn)
{
NS_ENSURE_ARG_POINTER(aRow);
NS_ENSURE_ARG_POINTER(aColumn);
NS_ASSERTION(mInnerTableFrame, "no inner table frame yet?");
return mInnerTableFrame->GetRowAndColumnByIndex(aIndex, aRow, aColumn);
}
/*---------------- end of nsITableLayout implementation ------------------*/

View File

@ -192,6 +192,9 @@ public:
/** @see nsITableFrame::GetTableSize */
NS_IMETHOD GetTableSize(PRInt32& aRowCount, PRInt32& aColCount);
NS_IMETHOD GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aIndex);
NS_IMETHOD GetRowAndColumnByIndex(PRInt32 aIndex, PRInt32 *aRow, PRInt32 *aColumn);
PRBool IsNested(const nsHTMLReflowState& aReflowState) const;
protected: