Changes to the cell map to support incremental insertion and removal of rows. Currently

only used by the tree widget.
This commit is contained in:
hyatt%netscape.com 1999-08-30 00:01:09 +00:00
Родитель ef1b8514bd
Коммит 8c3c551001
12 изменённых файлов: 364 добавлений и 16 удалений

Просмотреть файл

@ -54,7 +54,7 @@ nsCellMap::~nsCellMap()
PRInt32 colX; PRInt32 colX;
for (PRInt32 rowX = 0; rowX < mapRowCount; rowX++) { for (PRInt32 rowX = 0; rowX < mapRowCount; rowX++) {
nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(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)); CellData* data = (CellData *)(row->ElementAt(colX));
if (data) { if (data) {
delete 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 nsCellMap::AppendCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex) PRInt32 aRowIndex)
{ {
NS_ASSERTION(aCellFrame, "bad cell frame"); NS_ASSERTION(aCellFrame, "bad cell frame");

Просмотреть файл

@ -56,6 +56,15 @@ public:
CellData* GetCellAt(PRInt32 aRowIndex, CellData* GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex) const; 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 /** append the cellFrame at the end of the row at aRowIndex and return the col index
*/ */
PRInt32 AppendCell(nsTableCellFrame* aCellFrame, PRInt32 AppendCell(nsTableCellFrame* aCellFrame,

Просмотреть файл

@ -607,6 +607,80 @@ PRInt32 nsTableFrame::GetEffectiveCOLSAttribute()
return result; 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 /** sum the columns represented by all nsTableColGroup objects
* if the cell map says there are more columns than this, * if the cell map says there are more columns than this,
* add extra implicit columns to the content tree. * add extra implicit columns to the content tree.
@ -762,7 +836,6 @@ PRInt32 nsTableFrame::AddCellToTable(nsTableCellFrame* aCellFrame,
NS_ASSERTION(nsnull != mCellMap, "bad cellMap"); NS_ASSERTION(nsnull != mCellMap, "bad cellMap");
// XXX: must be called only on first-in-flow! // XXX: must be called only on first-in-flow!
return mCellMap->AppendCell(aCellFrame, aRowIndex); return mCellMap->AppendCell(aCellFrame, aRowIndex);
} }

Просмотреть файл

@ -736,6 +736,15 @@ public:
virtual void EnsureColumns (nsIPresContext& aPresContext, virtual void EnsureColumns (nsIPresContext& aPresContext,
PRBool& aCreatedColFrames); 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: protected:
/** iterates all child frames and creates a new cell map */ /** iterates all child frames and creates a new cell map */
NS_IMETHOD ReBuildCellMap(); NS_IMETHOD ReBuildCellMap();

Просмотреть файл

@ -235,7 +235,7 @@ nsTableRowFrame::RemoveFrame(nsIPresContext& aPresContext,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsTableRowFrame::InitChildren() nsTableRowFrame::InitChildrenWithIndex(PRInt32 aRowIndex)
{ {
nsTableFrame* table = nsnull; nsTableFrame* table = nsnull;
nsresult result=NS_OK; nsresult result=NS_OK;
@ -248,8 +248,8 @@ nsTableRowFrame::InitChildren()
if ((NS_OK==result) && (table != nsnull)) if ((NS_OK==result) && (table != nsnull))
{ {
mInitializedChildren=PR_TRUE; mInitializedChildren=PR_TRUE;
PRInt32 rowIndex = table->GetNextAvailRowIndex(); SetRowIndex(aRowIndex);
SetRowIndex(rowIndex);
for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame))
{ {
const nsStyleDisplay *kidDisplay; const nsStyleDisplay *kidDisplay;
@ -258,9 +258,9 @@ nsTableRowFrame::InitChildren()
{ {
// add the cell frame to the table's cell map and get its col index // add the cell frame to the table's cell map and get its col index
PRInt32 colIndex; PRInt32 colIndex;
colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, rowIndex); colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, aRowIndex);
// what column does this cell belong to? // 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); ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
} }
} }
@ -269,6 +269,26 @@ nsTableRowFrame::InitChildren()
return NS_OK; 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 * Post-reflow hook. This is where the table row does its post-processing
*/ */

Просмотреть файл

@ -90,6 +90,7 @@ public:
/** Initialization of data */ /** Initialization of data */
NS_IMETHOD InitChildren(); NS_IMETHOD InitChildren();
NS_IMETHOD InitChildrenWithIndex(PRInt32 aRowIndex);
void ResetInitChildren(); void ResetInitChildren();

Просмотреть файл

@ -54,7 +54,7 @@ nsCellMap::~nsCellMap()
PRInt32 colX; PRInt32 colX;
for (PRInt32 rowX = 0; rowX < mapRowCount; rowX++) { for (PRInt32 rowX = 0; rowX < mapRowCount; rowX++) {
nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(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)); CellData* data = (CellData *)(row->ElementAt(colX));
if (data) { if (data) {
delete 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 nsCellMap::AppendCell(nsTableCellFrame* aCellFrame,
PRInt32 aRowIndex) PRInt32 aRowIndex)
{ {
NS_ASSERTION(aCellFrame, "bad cell frame"); NS_ASSERTION(aCellFrame, "bad cell frame");

Просмотреть файл

@ -56,6 +56,15 @@ public:
CellData* GetCellAt(PRInt32 aRowIndex, CellData* GetCellAt(PRInt32 aRowIndex,
PRInt32 aColIndex) const; 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 /** append the cellFrame at the end of the row at aRowIndex and return the col index
*/ */
PRInt32 AppendCell(nsTableCellFrame* aCellFrame, PRInt32 AppendCell(nsTableCellFrame* aCellFrame,

Просмотреть файл

@ -607,6 +607,80 @@ PRInt32 nsTableFrame::GetEffectiveCOLSAttribute()
return result; 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 /** sum the columns represented by all nsTableColGroup objects
* if the cell map says there are more columns than this, * if the cell map says there are more columns than this,
* add extra implicit columns to the content tree. * add extra implicit columns to the content tree.
@ -762,7 +836,6 @@ PRInt32 nsTableFrame::AddCellToTable(nsTableCellFrame* aCellFrame,
NS_ASSERTION(nsnull != mCellMap, "bad cellMap"); NS_ASSERTION(nsnull != mCellMap, "bad cellMap");
// XXX: must be called only on first-in-flow! // XXX: must be called only on first-in-flow!
return mCellMap->AppendCell(aCellFrame, aRowIndex); return mCellMap->AppendCell(aCellFrame, aRowIndex);
} }

Просмотреть файл

@ -736,6 +736,15 @@ public:
virtual void EnsureColumns (nsIPresContext& aPresContext, virtual void EnsureColumns (nsIPresContext& aPresContext,
PRBool& aCreatedColFrames); 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: protected:
/** iterates all child frames and creates a new cell map */ /** iterates all child frames and creates a new cell map */
NS_IMETHOD ReBuildCellMap(); NS_IMETHOD ReBuildCellMap();

Просмотреть файл

@ -235,7 +235,7 @@ nsTableRowFrame::RemoveFrame(nsIPresContext& aPresContext,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsTableRowFrame::InitChildren() nsTableRowFrame::InitChildrenWithIndex(PRInt32 aRowIndex)
{ {
nsTableFrame* table = nsnull; nsTableFrame* table = nsnull;
nsresult result=NS_OK; nsresult result=NS_OK;
@ -248,8 +248,8 @@ nsTableRowFrame::InitChildren()
if ((NS_OK==result) && (table != nsnull)) if ((NS_OK==result) && (table != nsnull))
{ {
mInitializedChildren=PR_TRUE; mInitializedChildren=PR_TRUE;
PRInt32 rowIndex = table->GetNextAvailRowIndex(); SetRowIndex(aRowIndex);
SetRowIndex(rowIndex);
for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame))
{ {
const nsStyleDisplay *kidDisplay; const nsStyleDisplay *kidDisplay;
@ -258,9 +258,9 @@ nsTableRowFrame::InitChildren()
{ {
// add the cell frame to the table's cell map and get its col index // add the cell frame to the table's cell map and get its col index
PRInt32 colIndex; PRInt32 colIndex;
colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, rowIndex); colIndex = table->AddCellToTable((nsTableCellFrame *)kidFrame, aRowIndex);
// what column does this cell belong to? // 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); ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
} }
} }
@ -269,6 +269,26 @@ nsTableRowFrame::InitChildren()
return NS_OK; 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 * Post-reflow hook. This is where the table row does its post-processing
*/ */

Просмотреть файл

@ -90,6 +90,7 @@ public:
/** Initialization of data */ /** Initialization of data */
NS_IMETHOD InitChildren(); NS_IMETHOD InitChildren();
NS_IMETHOD InitChildrenWithIndex(PRInt32 aRowIndex);
void ResetInitChildren(); void ResetInitChildren();