From 8c3c55100190c43f6241a2e3bab7e8ff17358f34 Mon Sep 17 00:00:00 2001 From: "hyatt%netscape.com" Date: Mon, 30 Aug 1999 00:01:09 +0000 Subject: [PATCH] Changes to the cell map to support incremental insertion and removal of rows. Currently only used by the tree widget. --- layout/html/table/src/nsCellMap.cpp | 66 +++++++++++++++++++- layout/html/table/src/nsCellMap.h | 9 +++ layout/html/table/src/nsTableFrame.cpp | 75 ++++++++++++++++++++++- layout/html/table/src/nsTableFrame.h | 9 +++ layout/html/table/src/nsTableRowFrame.cpp | 30 +++++++-- layout/html/table/src/nsTableRowFrame.h | 1 + layout/tables/nsCellMap.cpp | 66 +++++++++++++++++++- layout/tables/nsCellMap.h | 9 +++ layout/tables/nsTableFrame.cpp | 75 ++++++++++++++++++++++- layout/tables/nsTableFrame.h | 9 +++ layout/tables/nsTableRowFrame.cpp | 30 +++++++-- layout/tables/nsTableRowFrame.h | 1 + 12 files changed, 364 insertions(+), 16 deletions(-) diff --git a/layout/html/table/src/nsCellMap.cpp b/layout/html/table/src/nsCellMap.cpp index ccf5340c708..17ea7682d8b 100644 --- a/layout/html/table/src/nsCellMap.cpp +++ b/layout/html/table/src/nsCellMap.cpp @@ -54,7 +54,7 @@ nsCellMap::~nsCellMap() PRInt32 colX; for (PRInt32 rowX = 0; rowX < mapRowCount; rowX++) { nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(rowX)); - for (colX = 0; colX <= colCount; colX++) { + for (colX = 0; colX < colCount; colX++) { CellData* data = (CellData *)(row->ElementAt(colX)); if (data) { delete data; @@ -137,8 +137,70 @@ void nsCellMap::Grow(PRInt32 aNumMapRows, } } +void nsCellMap::InsertRowIntoMap(PRInt32 aRowIndex) +{ + // XXX This function does not yet handle spans. + // XXX Does this function need to worry about adjusting the collapsed row/col arrays? + nsVoidArray* row; + PRInt32 origNumCols = mNumCellsOrigInCol.Count(); + + row = (0 == origNumCols) ? new nsVoidArray() : new nsVoidArray(origNumCols); + + if (row) { + mRows.InsertElementAt(row, aRowIndex); + } + + PRInt32* val = new PRInt32(0); + if (val) { + mNumCellsOrigInRow.InsertElementAt(val, aRowIndex); + } + + mRowCount++; + mNextAvailRowIndex++; +} + +void nsCellMap::RemoveRowFromMap(PRInt32 aRowIndex) +{ + // XXX This function does not yet handle spans. + // XXX Does this function need to worry about adjusting the collapsed row/col arrays? + + PRInt32 colCount = mNumCellsOrigInCol.Count(); + for (PRInt32 i = 0; i < colCount; i++) { + // Adjust the column counts. + PRInt32 span; + PRBool originates; + GetCellInfoAt(aRowIndex, i, &originates, &span); + if (originates) { + // Decrement the column count. + PRInt32* cols = (PRInt32*)(mNumCellsOrigInCol.ElementAt(i)); + *cols = *cols-1; + } + } + + // Delete the originating row info. + PRInt32* numOrig = (PRInt32 *)mNumCellsOrigInRow.ElementAt(aRowIndex); + mNumCellsOrigInRow.RemoveElementAt(aRowIndex); + if (numOrig) + delete numOrig; + + // Delete our row information. + nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(aRowIndex)); + for (PRInt32 colX = 0; colX < colCount; colX++) { + CellData* data = (CellData *)(row->ElementAt(colX)); + if (data) { + delete data; + } + } + mRows.RemoveElementAt(aRowIndex); + delete row; + + // Decrement our row and next available index counts. + mRowCount--; + mNextAvailRowIndex--; +} + PRInt32 nsCellMap::AppendCell(nsTableCellFrame* aCellFrame, - PRInt32 aRowIndex) + PRInt32 aRowIndex) { NS_ASSERTION(aCellFrame, "bad cell frame"); diff --git a/layout/html/table/src/nsCellMap.h b/layout/html/table/src/nsCellMap.h index 390905b1311..31ca92db90a 100644 --- a/layout/html/table/src/nsCellMap.h +++ b/layout/html/table/src/nsCellMap.h @@ -56,6 +56,15 @@ public: CellData* GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) const; + /** insert a new row into the map + makes a blank row and adjusts spans + */ + void InsertRowIntoMap(PRInt32 aRowIndex); + + /** removes a row from the map and adjusts spans + */ + void RemoveRowFromMap(PRInt32 aRowIndex); + /** append the cellFrame at the end of the row at aRowIndex and return the col index */ PRInt32 AppendCell(nsTableCellFrame* aCellFrame, diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index f3d2e7fd625..f6a2945e76b 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -607,6 +607,80 @@ PRInt32 nsTableFrame::GetEffectiveCOLSAttribute() return result; } +NS_IMETHODIMP nsTableFrame::AdjustRowIndices(nsIFrame* aRowGroup, + PRInt32 aRowIndex, + PRInt32 anAdjustment) +{ + nsresult rv = NS_OK; + nsIFrame *rowFrame; + aRowGroup->FirstChild(nsnull, &rowFrame); + for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(&rowFrame)) + { + const nsStyleDisplay *rowDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay); + if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay) + { + PRInt32 index = ((nsTableRowFrame*)rowFrame)->GetRowIndex(); + if (index >= aRowIndex) + ((nsTableRowFrame *)rowFrame)->SetRowIndex(index+anAdjustment); + } + else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP==rowDisplay->mDisplay) + { + AdjustRowIndices(rowFrame, aRowIndex, anAdjustment); + } + } + return rv; +} + +NS_IMETHODIMP nsTableFrame::RemoveRowFromMap(nsTableRowFrame* aRow, PRInt32 aRowIndex) +{ + nsresult rv=NS_OK; + + // Create a new row in the cell map at the specified index. + mCellMap->RemoveRowFromMap(aRowIndex); + + // Iterate over our row groups and increment the row indices of all rows whose index + // is >= aRowIndex. + nsIFrame *rowGroupFrame=mFrames.FirstChild(); + for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(&rowGroupFrame)) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowGroupDisplay); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { + AdjustRowIndices(rowGroupFrame, aRowIndex, -1); + } + } + + return rv; +} + +NS_IMETHODIMP nsTableFrame::InsertRowIntoMap(nsTableRowFrame* aRow, PRInt32 aRowIndex) +{ + nsresult rv=NS_OK; + + // Create a new row in the cell map at the specified index. + mCellMap->InsertRowIntoMap(aRowIndex); + + // Iterate over our row groups and increment the row indices of all rows whose index + // is >= aRowIndex. + nsIFrame *rowGroupFrame=mFrames.FirstChild(); + for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(&rowGroupFrame)) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowGroupDisplay); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { + AdjustRowIndices(rowGroupFrame, aRowIndex, 1); + } + } + + // Init the row's index and add its cells to the cell map. + aRow->InitChildrenWithIndex(aRowIndex); + + return rv; +} + /** sum the columns represented by all nsTableColGroup objects * if the cell map says there are more columns than this, * add extra implicit columns to the content tree. @@ -762,7 +836,6 @@ PRInt32 nsTableFrame::AddCellToTable(nsTableCellFrame* aCellFrame, NS_ASSERTION(nsnull != mCellMap, "bad cellMap"); // XXX: must be called only on first-in-flow! - return mCellMap->AppendCell(aCellFrame, aRowIndex); } diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index 606f0141000..872397690d5 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/layout/html/table/src/nsTableFrame.h @@ -736,6 +736,15 @@ public: virtual void EnsureColumns (nsIPresContext& aPresContext, PRBool& aCreatedColFrames); + // These methods are used to incrementally insert and remove rows + // from the cell map without having to invalidate the entire map. + NS_IMETHOD InsertRowIntoMap(nsTableRowFrame* aRow, PRInt32 aRowIndex); + NS_IMETHOD RemoveRowFromMap(nsTableRowFrame* aRow, PRInt32 aRowIndex); + + NS_IMETHOD AdjustRowIndices(nsIFrame* aRowGroup, + PRInt32 aRowIndex, + PRInt32 anAdjustment); + protected: /** iterates all child frames and creates a new cell map */ NS_IMETHOD ReBuildCellMap(); diff --git a/layout/html/table/src/nsTableRowFrame.cpp b/layout/html/table/src/nsTableRowFrame.cpp index 9e803fbf0b0..df614e317a7 100644 --- a/layout/html/table/src/nsTableRowFrame.cpp +++ b/layout/html/table/src/nsTableRowFrame.cpp @@ -235,7 +235,7 @@ nsTableRowFrame::RemoveFrame(nsIPresContext& aPresContext, } NS_IMETHODIMP -nsTableRowFrame::InitChildren() +nsTableRowFrame::InitChildrenWithIndex(PRInt32 aRowIndex) { nsTableFrame* table = nsnull; nsresult result=NS_OK; @@ -248,8 +248,8 @@ nsTableRowFrame::InitChildren() if ((NS_OK==result) && (table != nsnull)) { mInitializedChildren=PR_TRUE; - PRInt32 rowIndex = table->GetNextAvailRowIndex(); - SetRowIndex(rowIndex); + SetRowIndex(aRowIndex); + for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) { const nsStyleDisplay *kidDisplay; @@ -258,9 +258,9 @@ nsTableRowFrame::InitChildren() { // add the cell frame to the table's cell map and get its col index PRInt32 colIndex; - colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, rowIndex); + colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, aRowIndex); // what column does this cell belong to? - // this sets the frame's notion of it's column index + // this sets the frame's notion of its column index ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex); } } @@ -269,6 +269,26 @@ nsTableRowFrame::InitChildren() return NS_OK; } +NS_IMETHODIMP +nsTableRowFrame::InitChildren() +{ + nsTableFrame* table = nsnull; + nsresult result=NS_OK; + + // each child cell can only be added to the table one time. + // for now, we remember globally whether we've added all or none + if (PR_FALSE==mInitializedChildren) + { + result = nsTableFrame::GetTableFrame(this, table); + if ((NS_OK==result) && (table != nsnull)) + { + PRInt32 rowIndex = table->GetNextAvailRowIndex(); + InitChildrenWithIndex(rowIndex); + } + } + return NS_OK; +} + /** * Post-reflow hook. This is where the table row does its post-processing */ diff --git a/layout/html/table/src/nsTableRowFrame.h b/layout/html/table/src/nsTableRowFrame.h index 22e4b944e03..729334c5cb1 100644 --- a/layout/html/table/src/nsTableRowFrame.h +++ b/layout/html/table/src/nsTableRowFrame.h @@ -90,6 +90,7 @@ public: /** Initialization of data */ NS_IMETHOD InitChildren(); + NS_IMETHOD InitChildrenWithIndex(PRInt32 aRowIndex); void ResetInitChildren(); diff --git a/layout/tables/nsCellMap.cpp b/layout/tables/nsCellMap.cpp index ccf5340c708..17ea7682d8b 100644 --- a/layout/tables/nsCellMap.cpp +++ b/layout/tables/nsCellMap.cpp @@ -54,7 +54,7 @@ nsCellMap::~nsCellMap() PRInt32 colX; for (PRInt32 rowX = 0; rowX < mapRowCount; rowX++) { nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(rowX)); - for (colX = 0; colX <= colCount; colX++) { + for (colX = 0; colX < colCount; colX++) { CellData* data = (CellData *)(row->ElementAt(colX)); if (data) { delete data; @@ -137,8 +137,70 @@ void nsCellMap::Grow(PRInt32 aNumMapRows, } } +void nsCellMap::InsertRowIntoMap(PRInt32 aRowIndex) +{ + // XXX This function does not yet handle spans. + // XXX Does this function need to worry about adjusting the collapsed row/col arrays? + nsVoidArray* row; + PRInt32 origNumCols = mNumCellsOrigInCol.Count(); + + row = (0 == origNumCols) ? new nsVoidArray() : new nsVoidArray(origNumCols); + + if (row) { + mRows.InsertElementAt(row, aRowIndex); + } + + PRInt32* val = new PRInt32(0); + if (val) { + mNumCellsOrigInRow.InsertElementAt(val, aRowIndex); + } + + mRowCount++; + mNextAvailRowIndex++; +} + +void nsCellMap::RemoveRowFromMap(PRInt32 aRowIndex) +{ + // XXX This function does not yet handle spans. + // XXX Does this function need to worry about adjusting the collapsed row/col arrays? + + PRInt32 colCount = mNumCellsOrigInCol.Count(); + for (PRInt32 i = 0; i < colCount; i++) { + // Adjust the column counts. + PRInt32 span; + PRBool originates; + GetCellInfoAt(aRowIndex, i, &originates, &span); + if (originates) { + // Decrement the column count. + PRInt32* cols = (PRInt32*)(mNumCellsOrigInCol.ElementAt(i)); + *cols = *cols-1; + } + } + + // Delete the originating row info. + PRInt32* numOrig = (PRInt32 *)mNumCellsOrigInRow.ElementAt(aRowIndex); + mNumCellsOrigInRow.RemoveElementAt(aRowIndex); + if (numOrig) + delete numOrig; + + // Delete our row information. + nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(aRowIndex)); + for (PRInt32 colX = 0; colX < colCount; colX++) { + CellData* data = (CellData *)(row->ElementAt(colX)); + if (data) { + delete data; + } + } + mRows.RemoveElementAt(aRowIndex); + delete row; + + // Decrement our row and next available index counts. + mRowCount--; + mNextAvailRowIndex--; +} + PRInt32 nsCellMap::AppendCell(nsTableCellFrame* aCellFrame, - PRInt32 aRowIndex) + PRInt32 aRowIndex) { NS_ASSERTION(aCellFrame, "bad cell frame"); diff --git a/layout/tables/nsCellMap.h b/layout/tables/nsCellMap.h index 390905b1311..31ca92db90a 100644 --- a/layout/tables/nsCellMap.h +++ b/layout/tables/nsCellMap.h @@ -56,6 +56,15 @@ public: CellData* GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) const; + /** insert a new row into the map + makes a blank row and adjusts spans + */ + void InsertRowIntoMap(PRInt32 aRowIndex); + + /** removes a row from the map and adjusts spans + */ + void RemoveRowFromMap(PRInt32 aRowIndex); + /** append the cellFrame at the end of the row at aRowIndex and return the col index */ PRInt32 AppendCell(nsTableCellFrame* aCellFrame, diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index f3d2e7fd625..f6a2945e76b 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -607,6 +607,80 @@ PRInt32 nsTableFrame::GetEffectiveCOLSAttribute() return result; } +NS_IMETHODIMP nsTableFrame::AdjustRowIndices(nsIFrame* aRowGroup, + PRInt32 aRowIndex, + PRInt32 anAdjustment) +{ + nsresult rv = NS_OK; + nsIFrame *rowFrame; + aRowGroup->FirstChild(nsnull, &rowFrame); + for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(&rowFrame)) + { + const nsStyleDisplay *rowDisplay; + rowFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay); + if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay) + { + PRInt32 index = ((nsTableRowFrame*)rowFrame)->GetRowIndex(); + if (index >= aRowIndex) + ((nsTableRowFrame *)rowFrame)->SetRowIndex(index+anAdjustment); + } + else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP==rowDisplay->mDisplay) + { + AdjustRowIndices(rowFrame, aRowIndex, anAdjustment); + } + } + return rv; +} + +NS_IMETHODIMP nsTableFrame::RemoveRowFromMap(nsTableRowFrame* aRow, PRInt32 aRowIndex) +{ + nsresult rv=NS_OK; + + // Create a new row in the cell map at the specified index. + mCellMap->RemoveRowFromMap(aRowIndex); + + // Iterate over our row groups and increment the row indices of all rows whose index + // is >= aRowIndex. + nsIFrame *rowGroupFrame=mFrames.FirstChild(); + for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(&rowGroupFrame)) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowGroupDisplay); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { + AdjustRowIndices(rowGroupFrame, aRowIndex, -1); + } + } + + return rv; +} + +NS_IMETHODIMP nsTableFrame::InsertRowIntoMap(nsTableRowFrame* aRow, PRInt32 aRowIndex) +{ + nsresult rv=NS_OK; + + // Create a new row in the cell map at the specified index. + mCellMap->InsertRowIntoMap(aRowIndex); + + // Iterate over our row groups and increment the row indices of all rows whose index + // is >= aRowIndex. + nsIFrame *rowGroupFrame=mFrames.FirstChild(); + for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(&rowGroupFrame)) + { + const nsStyleDisplay *rowGroupDisplay; + rowGroupFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowGroupDisplay); + if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay)) + { + AdjustRowIndices(rowGroupFrame, aRowIndex, 1); + } + } + + // Init the row's index and add its cells to the cell map. + aRow->InitChildrenWithIndex(aRowIndex); + + return rv; +} + /** sum the columns represented by all nsTableColGroup objects * if the cell map says there are more columns than this, * add extra implicit columns to the content tree. @@ -762,7 +836,6 @@ PRInt32 nsTableFrame::AddCellToTable(nsTableCellFrame* aCellFrame, NS_ASSERTION(nsnull != mCellMap, "bad cellMap"); // XXX: must be called only on first-in-flow! - return mCellMap->AppendCell(aCellFrame, aRowIndex); } diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 606f0141000..872397690d5 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -736,6 +736,15 @@ public: virtual void EnsureColumns (nsIPresContext& aPresContext, PRBool& aCreatedColFrames); + // These methods are used to incrementally insert and remove rows + // from the cell map without having to invalidate the entire map. + NS_IMETHOD InsertRowIntoMap(nsTableRowFrame* aRow, PRInt32 aRowIndex); + NS_IMETHOD RemoveRowFromMap(nsTableRowFrame* aRow, PRInt32 aRowIndex); + + NS_IMETHOD AdjustRowIndices(nsIFrame* aRowGroup, + PRInt32 aRowIndex, + PRInt32 anAdjustment); + protected: /** iterates all child frames and creates a new cell map */ NS_IMETHOD ReBuildCellMap(); diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 9e803fbf0b0..df614e317a7 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -235,7 +235,7 @@ nsTableRowFrame::RemoveFrame(nsIPresContext& aPresContext, } NS_IMETHODIMP -nsTableRowFrame::InitChildren() +nsTableRowFrame::InitChildrenWithIndex(PRInt32 aRowIndex) { nsTableFrame* table = nsnull; nsresult result=NS_OK; @@ -248,8 +248,8 @@ nsTableRowFrame::InitChildren() if ((NS_OK==result) && (table != nsnull)) { mInitializedChildren=PR_TRUE; - PRInt32 rowIndex = table->GetNextAvailRowIndex(); - SetRowIndex(rowIndex); + SetRowIndex(aRowIndex); + for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) { const nsStyleDisplay *kidDisplay; @@ -258,9 +258,9 @@ nsTableRowFrame::InitChildren() { // add the cell frame to the table's cell map and get its col index PRInt32 colIndex; - colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, rowIndex); + colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, aRowIndex); // what column does this cell belong to? - // this sets the frame's notion of it's column index + // this sets the frame's notion of its column index ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex); } } @@ -269,6 +269,26 @@ nsTableRowFrame::InitChildren() return NS_OK; } +NS_IMETHODIMP +nsTableRowFrame::InitChildren() +{ + nsTableFrame* table = nsnull; + nsresult result=NS_OK; + + // each child cell can only be added to the table one time. + // for now, we remember globally whether we've added all or none + if (PR_FALSE==mInitializedChildren) + { + result = nsTableFrame::GetTableFrame(this, table); + if ((NS_OK==result) && (table != nsnull)) + { + PRInt32 rowIndex = table->GetNextAvailRowIndex(); + InitChildrenWithIndex(rowIndex); + } + } + return NS_OK; +} + /** * Post-reflow hook. This is where the table row does its post-processing */ diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index 22e4b944e03..729334c5cb1 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -90,6 +90,7 @@ public: /** Initialization of data */ NS_IMETHOD InitChildren(); + NS_IMETHOD InitChildrenWithIndex(PRInt32 aRowIndex); void ResetInitChildren();