зеркало из https://github.com/mozilla/pjs.git
collapsing rows, row groups, cols, col groups
This commit is contained in:
Родитель
53038aad55
Коммит
e844c3e177
|
@ -30,11 +30,15 @@ static const PRBool gsDebug = PR_FALSE;
|
|||
nsCellMap::nsCellMap(int aRowCount, int aColCount)
|
||||
: mRowCount(0),
|
||||
mColCount(0),
|
||||
mTotalRowCount(0)
|
||||
mTotalRowCount(0),
|
||||
mNumCollapsedRows(0),
|
||||
mNumCollapsedCols(0)
|
||||
{
|
||||
mRows = nsnull;
|
||||
mColFrames = nsnull;
|
||||
mMinColSpans = nsnull;
|
||||
mIsCollapsedRows = nsnull;
|
||||
mIsCollapsedCols = nsnull;
|
||||
Reset(aRowCount, aColCount);
|
||||
}
|
||||
|
||||
|
@ -62,6 +66,16 @@ nsCellMap::~nsCellMap()
|
|||
// mMinColSpans may be null, it is only set for tables that need it
|
||||
if (nsnull != mMinColSpans)
|
||||
delete [] mMinColSpans;
|
||||
if (nsnull != mIsCollapsedRows) {
|
||||
delete [] mIsCollapsedRows;
|
||||
mIsCollapsedRows = nsnull;
|
||||
mNumCollapsedRows = 0;
|
||||
}
|
||||
if (nsnull != mIsCollapsedCols) {
|
||||
delete [] mIsCollapsedCols;
|
||||
mIsCollapsedCols = nsnull;
|
||||
mNumCollapsedCols = 0;
|
||||
}
|
||||
mRows = nsnull;
|
||||
mColFrames = nsnull;
|
||||
mMinColSpans = nsnull;
|
||||
|
@ -97,19 +111,20 @@ void nsCellMap::Reset(int aRowCount, int aColCount)
|
|||
|
||||
// if the number of rows has increased, add the extra rows
|
||||
PRInt32 newRows = aRowCount-mTotalRowCount; // (new row count) - (total row allocation)
|
||||
for ( ; newRows>0; newRows--)
|
||||
{
|
||||
for ( ; newRows > 0; newRows--) {
|
||||
nsVoidArray *row;
|
||||
if (0!=aColCount)
|
||||
if (0 != aColCount) {
|
||||
row = new nsVoidArray(aColCount);
|
||||
else
|
||||
} else {
|
||||
row = new nsVoidArray();
|
||||
}
|
||||
mRows->AppendElement(row);
|
||||
}
|
||||
|
||||
mRowCount = aRowCount;
|
||||
mTotalRowCount = PR_MAX(mTotalRowCount, mRowCount);
|
||||
mColCount = aColCount;
|
||||
|
||||
if (gsDebug) printf("leaving Reset with mRC=%d, mCC=%d, mTRC=%d\n",
|
||||
mRowCount, mColCount, mTotalRowCount);
|
||||
}
|
||||
|
@ -413,5 +428,73 @@ PRBool nsCellMap::ColHasSpanningCells(PRInt32 aColIndex)
|
|||
return result;
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetNumCollapsedRows()
|
||||
{
|
||||
return mNumCollapsedRows;
|
||||
}
|
||||
|
||||
PRBool nsCellMap::IsRowCollapsedAt(PRInt32 aRow)
|
||||
{
|
||||
if ((aRow >= 0) && (aRow < mTotalRowCount)) {
|
||||
if (mIsCollapsedRows) {
|
||||
return mIsCollapsedRows[aRow];
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void nsCellMap::SetRowCollapsedAt(PRInt32 aRow, PRBool aValue)
|
||||
{
|
||||
if ((aRow >= 0) && (aRow < mRowCount)) {
|
||||
if (nsnull == mIsCollapsedRows) {
|
||||
mIsCollapsedRows = new PRBool[mRowCount];
|
||||
for (PRInt32 i = 0; i < mRowCount; i++) {
|
||||
mIsCollapsedRows[i] = PR_FALSE;
|
||||
}
|
||||
}
|
||||
if (mIsCollapsedRows[aRow] != aValue) {
|
||||
if (PR_TRUE == aValue) {
|
||||
mNumCollapsedRows++;
|
||||
} else {
|
||||
mNumCollapsedRows--;
|
||||
}
|
||||
mIsCollapsedRows[aRow] = aValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetNumCollapsedCols()
|
||||
{
|
||||
return mNumCollapsedCols;
|
||||
}
|
||||
|
||||
PRBool nsCellMap::IsColCollapsedAt(PRInt32 aCol)
|
||||
{
|
||||
if ((aCol >= 0) && (aCol < mColCount)) {
|
||||
if (mIsCollapsedCols) {
|
||||
return mIsCollapsedCols[aCol];
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void nsCellMap::SetColCollapsedAt(PRInt32 aCol, PRBool aValue)
|
||||
{
|
||||
if ((aCol >= 0) && (aCol < mColCount)) {
|
||||
if (nsnull == mIsCollapsedCols) {
|
||||
mIsCollapsedCols = new PRBool[mColCount];
|
||||
for (PRInt32 i = 0; i < mColCount; i++) {
|
||||
mIsCollapsedCols[i] = PR_FALSE;
|
||||
}
|
||||
}
|
||||
if (mIsCollapsedCols[aCol] != aValue) {
|
||||
if (PR_TRUE == aValue) {
|
||||
mNumCollapsedCols++;
|
||||
} else {
|
||||
mNumCollapsedCols--;
|
||||
}
|
||||
mIsCollapsedCols[aCol] = aValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,14 @@ protected:
|
|||
/** a cache of the column frames, by col index */
|
||||
nsVoidArray * mColFrames;
|
||||
|
||||
// an array of booleans where the ith element indicates if the ith row is collapsed
|
||||
PRBool* mIsCollapsedRows;
|
||||
PRInt32 mNumCollapsedRows;
|
||||
|
||||
// an array of booleans where the ith element indicates if the ith col is collapsed
|
||||
PRBool* mIsCollapsedCols;
|
||||
PRInt32 mNumCollapsedCols;
|
||||
|
||||
/** the number of rows. mRows[0] - mRows[mRowCount-1] are non-null. */
|
||||
PRInt32 mRowCount;
|
||||
|
||||
|
@ -86,6 +94,14 @@ public:
|
|||
/** assign aCellData to the cell at (aRow,aColumn) */
|
||||
void SetCellAt(CellData *aCellData, PRInt32 aRow, PRInt32 aColumn);
|
||||
|
||||
PRInt32 GetNumCollapsedRows();
|
||||
PRBool IsRowCollapsedAt(PRInt32 aRow);
|
||||
void SetRowCollapsedAt(PRInt32 aRow, PRBool aValue);
|
||||
|
||||
PRInt32 GetNumCollapsedCols();
|
||||
PRBool IsColCollapsedAt(PRInt32 aCol);
|
||||
void SetColCollapsedAt(PRInt32 aCol, PRBool aValue);
|
||||
|
||||
/** expand the CellMap to have aRowCount rows. The number of columns remains the same */
|
||||
void GrowToRow(PRInt32 aRowCount);
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
|
|||
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
|
||||
}
|
||||
}
|
||||
mCollapseOffset = nsPoint(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +169,21 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
|
|||
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
|
||||
}
|
||||
|
||||
|
||||
// if the cell originates in a row and/or col that is collapsed, the bottom and/or
|
||||
// right portion of the cell is painted by translating the rendering context.
|
||||
// XXX What about content that can leak outside the cell?
|
||||
PRBool clipState;
|
||||
aRenderingContext.PushState();
|
||||
nsPoint offset = mCollapseOffset;
|
||||
if ((0 != offset.x) || (0 != offset.y)) {
|
||||
aRenderingContext.Translate(offset.x, offset.y);
|
||||
}
|
||||
aRenderingContext.SetClipRect(nsRect(-offset.x, -offset.y, mRect.width, mRect.height),
|
||||
nsClipCombine_kIntersect, clipState);
|
||||
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
|
||||
aRenderingContext.PopState(clipState);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1062,3 +1077,19 @@ nsTableCellFrame::GetFrameName(nsString& aResult) const
|
|||
{
|
||||
return MakeFrameName("TableCell", aResult);
|
||||
}
|
||||
|
||||
void nsTableCellFrame::SetCollapseOffsetX(nscoord aXOffset)
|
||||
{
|
||||
mCollapseOffset.x = aXOffset;
|
||||
}
|
||||
|
||||
void nsTableCellFrame::SetCollapseOffsetY(nscoord aYOffset)
|
||||
{
|
||||
mCollapseOffset.y = aYOffset;
|
||||
}
|
||||
|
||||
nsPoint nsTableCellFrame::GetCollapseOffset()
|
||||
{
|
||||
return mCollapseOffset;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,11 @@ public:
|
|||
PRBool GetContentEmpty();
|
||||
void SetContentEmpty(PRBool aContentEmpty);
|
||||
|
||||
// The collapse offset is (0,0) except for cells originating in a row/col which is collapsed
|
||||
void SetCollapseOffsetX(nscoord aXOffset);
|
||||
void SetCollapseOffsetY(nscoord aYOffset);
|
||||
nsPoint GetCollapseOffset();
|
||||
|
||||
protected:
|
||||
/** implement abstract method on nsHTMLContainerFrame */
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
@ -211,6 +216,9 @@ protected:
|
|||
PRBool mIsContentEmpty; // PR_TRUE if the cell's contents take up no space
|
||||
//XXX: mIsContentEmpty should get yanked in favor of using free a bit on the frame base class
|
||||
// the FrameState slot (mState; GetFrameState/SetFrameState)
|
||||
|
||||
nsPoint mCollapseOffset;
|
||||
|
||||
public:
|
||||
nsBorderEdges mBorderEdges; // one list of border segments for each side of the table frame
|
||||
// used only for the collapsing border model
|
||||
|
|
|
@ -634,21 +634,22 @@ nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
|
|||
nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex)
|
||||
{
|
||||
nsTableColFrame *result = nsnull;
|
||||
PRInt32 count=0;
|
||||
PRInt32 count = 0;
|
||||
nsIFrame *childFrame = mFrames.FirstChild();
|
||||
while (nsnull!=childFrame)
|
||||
{
|
||||
|
||||
while (nsnull!=childFrame) {
|
||||
const nsStyleDisplay *childDisplay;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay)
|
||||
{
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay) {
|
||||
nsTableColFrame *col = (nsTableColFrame *)childFrame;
|
||||
count += col->GetSpan();
|
||||
if (aColIndex<=count)
|
||||
if (aColIndex<=count) {
|
||||
result = col;
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -385,13 +385,14 @@ NS_IMETHODIMP nsTableFrame::DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFra
|
|||
{
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
nextRow->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay);
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
|
||||
{
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay) {
|
||||
rv = ((nsTableRowFrame *)nextRow)->InitChildren();
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -947,74 +948,77 @@ NS_METHOD nsTableFrame::ReBuildCellMap()
|
|||
void nsTableFrame::DumpCellMap ()
|
||||
{
|
||||
printf("dumping CellMap:\n");
|
||||
if (nsnull != mCellMap)
|
||||
{
|
||||
if (nsnull != mCellMap) {
|
||||
PRInt32 colIndex;
|
||||
PRInt32 rowCount = mCellMap->GetRowCount();
|
||||
PRInt32 colCount = mCellMap->GetColCount();
|
||||
printf("rowCount=%d, colCount=%d\n", rowCount, colCount);
|
||||
for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++)
|
||||
{
|
||||
if (gsDebug==PR_TRUE)
|
||||
{ printf("row %d", rowIndex);
|
||||
printf(": ");
|
||||
}
|
||||
for (colIndex = 0; colIndex < colCount; colIndex++)
|
||||
{
|
||||
CellData *cd =mCellMap->GetCellAt(rowIndex, colIndex);
|
||||
if (cd != nsnull)
|
||||
{
|
||||
if (cd->mCell != nsnull)
|
||||
{
|
||||
printf("C%d,%d ", rowIndex, colIndex);
|
||||
printf(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
nsTableCellFrame *cell = cd->mRealCell->mCell;
|
||||
nsTableRowFrame *row;
|
||||
cell->GetParent((nsIFrame **)&row);
|
||||
int rr = row->GetRowIndex ();
|
||||
|
||||
for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
||||
printf("row %d : ", rowIndex);
|
||||
for (colIndex = 0; colIndex < colCount; colIndex++) {
|
||||
CellData* cd = mCellMap->GetCellAt(rowIndex, colIndex);
|
||||
if (cd != nsnull) {
|
||||
if (cd->mCell != nsnull) {
|
||||
printf("C%d,%d ", rowIndex, colIndex);
|
||||
} else {
|
||||
nsTableCellFrame* cell = cd->mRealCell->mCell;
|
||||
nsTableRowFrame* row;
|
||||
cell->GetParent((nsIFrame**)&row);
|
||||
int rr = row->GetRowIndex();
|
||||
int cc;
|
||||
cell->GetColIndex(cc);
|
||||
printf("S%d,%d ", rr, cc);
|
||||
if (cd->mOverlap != nsnull)
|
||||
{
|
||||
printf("S%d,%d ", rr, cc);
|
||||
if (cd->mOverlap != nsnull){
|
||||
cell = cd->mOverlap->mCell;
|
||||
nsTableRowFrame* row2;
|
||||
cell->GetParent((nsIFrame **)&row2);
|
||||
rr = row2->GetRowIndex ();
|
||||
cell->GetColIndex (cc);
|
||||
cell->GetParent((nsIFrame**)&row2);
|
||||
rr = row2->GetRowIndex();
|
||||
cell->GetColIndex(cc);
|
||||
printf("O%d,%c ", rr, cc);
|
||||
}
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
printf("---- ");
|
||||
}
|
||||
}
|
||||
PRBool spanners = RowHasSpanningCells(rowIndex);
|
||||
PRBool spannedInto = RowIsSpannedInto(rowIndex);
|
||||
printf (" spanners=%s spannedInto=%s\n", spanners?"T":"F", spannedInto?"T":"F");
|
||||
}
|
||||
|
||||
// output info mapping Ci,j to cell address
|
||||
PRInt32 cellCount = 0;
|
||||
for (PRInt32 rIndex = 0; rIndex < rowCount; rIndex++) {
|
||||
for (colIndex = 0; colIndex < colCount; colIndex++) {
|
||||
CellData* cd = mCellMap->GetCellAt(rIndex, colIndex);
|
||||
if (cd != nsnull) {
|
||||
if (cd->mCell != nsnull) {
|
||||
printf("C%d,%d=%p ", rIndex, colIndex, cd->mCell);
|
||||
cellCount++;
|
||||
}
|
||||
}
|
||||
if (0 == (cellCount % 4)) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// output colspan info
|
||||
for (colIndex=0; colIndex<colCount; colIndex++)
|
||||
{
|
||||
for (colIndex=0; colIndex<colCount; colIndex++) {
|
||||
PRBool colSpanners = ColHasSpanningCells(colIndex);
|
||||
PRBool colSpannedInto = ColIsSpannedInto(colIndex);
|
||||
printf ("%d colSpanners=%s colSpannedInto=%s\n",
|
||||
colIndex, colSpanners?"T":"F", colSpannedInto?"T":"F");
|
||||
}
|
||||
// output col frame info
|
||||
for (colIndex=0; colIndex<colCount; colIndex++)
|
||||
{
|
||||
for (colIndex=0; colIndex<colCount; colIndex++) {
|
||||
nsTableColFrame *colFrame = mCellMap->GetColumnFrame(colIndex);
|
||||
printf ("col index %d has frame=%p\n", colIndex, colFrame);
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
printf ("[nsnull]");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2636,7 +2640,10 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
|
|||
aDesiredSize.width = ComputeDesiredWidth(aReflowState);
|
||||
nscoord defaultHeight = state.y + borderPadding.top + borderPadding.bottom;
|
||||
aDesiredSize.height = ComputeDesiredHeight(aPresContext, aReflowState, defaultHeight);
|
||||
|
||||
|
||||
AdjustForCollapsingRows(aPresContext, aDesiredSize.height);
|
||||
AdjustForCollapsingCols(aPresContext, aDesiredSize.width);
|
||||
|
||||
// once horizontal borders are computed and all row heights are set,
|
||||
// we need to fix up length of vertical edges
|
||||
// XXX need to figure start row and end row correctly
|
||||
|
@ -2651,6 +2658,224 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
|
|||
|
||||
}
|
||||
|
||||
// collapsing row groups, rows, col groups and cols are accounted for after both passes of
|
||||
// reflow so that it has no effect on the calculations of reflow.
|
||||
NS_METHOD nsTableFrame::AdjustForCollapsingRows(nsIPresContext& aPresContext,
|
||||
nscoord& aHeight)
|
||||
{
|
||||
// determine which row groups and rows are collapsed
|
||||
nsIFrame* childFrame;
|
||||
FirstChild(nsnull, &childFrame);
|
||||
while (nsnull != childFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
if (IsRowGroup(groupDisplay->mDisplay)) {
|
||||
PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
|
||||
nsTableRowFrame* rowFrame = nsnull;
|
||||
childFrame->FirstChild(nsnull, (nsIFrame**)&rowFrame);
|
||||
PRInt32 rowX = 0;
|
||||
while (nsnull != rowFrame) {
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
|
||||
mCellMap->SetRowCollapsedAt(rowX, PR_TRUE);
|
||||
}
|
||||
}
|
||||
rowFrame->GetNextSibling((nsIFrame**)&rowFrame);
|
||||
rowX++;
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
if (mCellMap->GetNumCollapsedRows() <= 0) {
|
||||
return NS_OK; // no collapsed rows, we're done
|
||||
}
|
||||
|
||||
// collapse the rows and/or row groups
|
||||
nsIFrame* groupFrame = mFrames.FirstChild();
|
||||
nscoord yGroupOffset = 0; // total offset among rows within a single row group
|
||||
nscoord yTotalOffset = 0; // total offset among all rows in all row groups
|
||||
PRInt32 rowX = 0;
|
||||
PRBool collapseGroup;
|
||||
|
||||
while (nsnull != groupFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
if (IsRowGroup(groupDisplay->mDisplay)) {
|
||||
collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
nsIFrame* rowFrame;
|
||||
groupFrame->FirstChild(nsnull, &rowFrame);
|
||||
|
||||
while (nsnull != rowFrame) {
|
||||
const nsStyleDisplay* rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
if (collapseGroup || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
|
||||
yGroupOffset += rowRect.height;
|
||||
rowRect.height = 0;
|
||||
rowFrame->SetRect(rowRect);
|
||||
nsIFrame* cellFrame;
|
||||
rowFrame->FirstChild(nsnull, &cellFrame);
|
||||
while (nsnull != cellFrame) {
|
||||
const nsStyleDisplay* cellDisplay;
|
||||
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
|
||||
nsTableCellFrame* cFrame = (nsTableCellFrame*)cellFrame;
|
||||
nsRect cRect;
|
||||
cFrame->GetRect(cRect);
|
||||
cRect.height -= rowRect.height;
|
||||
cFrame->SetCollapseOffsetY(-yGroupOffset);
|
||||
cFrame->SetRect(cRect);
|
||||
}
|
||||
cellFrame->GetNextSibling(&cellFrame);
|
||||
}
|
||||
// check if a cell above spans into here
|
||||
//if (!collapseGroup) {
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
nsTableCellFrame* lastCell = nsnull;
|
||||
for (int colX = 0; colX < numCols; colX++) {
|
||||
CellData* cellData = mCellMap->GetCellAt(rowX, colX);
|
||||
if (cellData && !cellData->mCell) { // a cell above is spanning into here
|
||||
// adjust the real cell's rect only once
|
||||
nsTableCellFrame* realCell = cellData->mRealCell->mCell;
|
||||
if (realCell != lastCell) {
|
||||
nsRect realRect;
|
||||
realCell->GetRect(realRect);
|
||||
realRect.height -= rowRect.height;
|
||||
realCell->SetRect(realRect);
|
||||
}
|
||||
lastCell = realCell;
|
||||
}
|
||||
}
|
||||
//}
|
||||
} else { // row is not collapsed but needs to be adjusted by those that are
|
||||
rowRect.y -= yGroupOffset;
|
||||
rowFrame->SetRect(rowRect);
|
||||
}
|
||||
rowX++;
|
||||
}
|
||||
rowFrame->GetNextSibling(&rowFrame);
|
||||
} // end row frame while
|
||||
}
|
||||
nsRect groupRect;
|
||||
groupFrame->GetRect(groupRect);
|
||||
groupRect.height -= yGroupOffset;
|
||||
groupRect.y -= yTotalOffset;
|
||||
groupFrame->SetRect(groupRect);
|
||||
|
||||
yTotalOffset += yGroupOffset;
|
||||
yGroupOffset = 0;
|
||||
groupFrame->GetNextSibling(&groupFrame);
|
||||
} // end group frame while
|
||||
|
||||
aHeight -= yTotalOffset;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::AdjustForCollapsingCols(nsIPresContext& aPresContext,
|
||||
nscoord& aWidth)
|
||||
{
|
||||
// determine which col groups and cols are collapsed
|
||||
nsIFrame* childFrame = mColGroups.FirstChild();
|
||||
while (nsnull != childFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
|
||||
nsTableColFrame* colFrame = nsnull;
|
||||
childFrame->FirstChild(nsnull, (nsIFrame**)&colFrame);
|
||||
PRInt32 colX = 0;
|
||||
while (nsnull != colFrame) {
|
||||
const nsStyleDisplay *colDisplay;
|
||||
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
|
||||
if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible)) {
|
||||
mCellMap->SetColCollapsedAt(colX, PR_TRUE);
|
||||
}
|
||||
}
|
||||
colFrame->GetNextSibling((nsIFrame**)&colFrame);
|
||||
colX++;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
if (mCellMap->GetNumCollapsedCols() <= 0) {
|
||||
return NS_OK; // no collapsed cols, we're done
|
||||
}
|
||||
|
||||
// collapse the cols and/or col groups
|
||||
PRInt32 numRows = mCellMap->GetRowCount();
|
||||
nsIFrame* groupFrame = mColGroups.FirstChild();
|
||||
nscoord cellSpacingX = GetCellSpacingX();
|
||||
nscoord xOffset = 0;
|
||||
PRInt32 colX = 0;
|
||||
while (nsnull != groupFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
PRBool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
nsRect zeroRect(0, 0, 0, 0);
|
||||
nsIFrame* colFrame;
|
||||
groupFrame->FirstChild(nsnull, &colFrame);
|
||||
while (nsnull != colFrame) {
|
||||
const nsStyleDisplay* colDisplay;
|
||||
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
|
||||
PRBool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible);
|
||||
PRInt32 colSpan = ((nsTableColFrame*)colFrame)->GetSpan();
|
||||
for (PRInt32 spanX = 0; spanX < colSpan; spanX++) {
|
||||
PRInt32 colWidth = GetColumnWidth(colX+spanX);
|
||||
if (collapseGroup || collapseCol) {
|
||||
xOffset += colWidth + cellSpacingX;
|
||||
}
|
||||
nsTableCellFrame* lastCell = nsnull;
|
||||
nsTableCellFrame* cellFrame = nsnull;
|
||||
for (PRInt32 rowX = 0; rowX < numRows; rowX++) {
|
||||
CellData* cellData = mCellMap->GetCellAt(rowX, colX+spanX);
|
||||
nsRect cellRect;
|
||||
if (cellData) {
|
||||
cellFrame = cellData->mCell;
|
||||
if (cellFrame) { // the cell originates at (rowX, colX)
|
||||
cellFrame->GetRect(cellRect);
|
||||
if (collapseGroup || collapseCol) {
|
||||
if (lastCell != cellFrame) { // do it only once if there is a row span
|
||||
cellRect.width -= colWidth;
|
||||
cellFrame->SetCollapseOffsetX(-xOffset);
|
||||
}
|
||||
} else { // the cell is not in a collapsed col but needs to move
|
||||
cellRect.x -= xOffset;
|
||||
}
|
||||
cellFrame->SetRect(cellRect);
|
||||
// if the cell does not originate at (rowX, colX), adjust the real cells width
|
||||
} else if (collapseGroup || collapseCol) {
|
||||
cellFrame = cellData->mRealCell->mCell;
|
||||
if ((cellFrame) && (lastCell != cellFrame)) {
|
||||
cellFrame->GetRect(cellRect);
|
||||
cellRect.width -= colWidth + cellSpacingX;
|
||||
cellFrame->SetRect(cellRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastCell = cellFrame;
|
||||
}
|
||||
}
|
||||
colX += colSpan;
|
||||
}
|
||||
colFrame->GetNextSibling(&colFrame);
|
||||
} // inner while
|
||||
groupFrame->GetNextSibling(&groupFrame);
|
||||
} // outer while
|
||||
|
||||
aWidth -= xOffset;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
|
|
|
@ -560,6 +560,12 @@ protected:
|
|||
InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY);
|
||||
|
||||
NS_METHOD AdjustForCollapsingRows(nsIPresContext& aPresContext,
|
||||
nscoord& aHeight);
|
||||
|
||||
NS_METHOD AdjustForCollapsingCols(nsIPresContext& aPresContext,
|
||||
nscoord& aWidth);
|
||||
// end incremental reflow methods
|
||||
|
||||
/** return the desired width of this table accounting for the current
|
||||
|
|
|
@ -1421,16 +1421,6 @@ nsTableRowFrame::Reflow(nsIPresContext& aPresContext,
|
|||
break;
|
||||
}
|
||||
|
||||
// check the visibility in the final pass. If it is collapse, set our desired size to 0
|
||||
if (nsTableFrame::IsFinalPass(aReflowState)) {
|
||||
const nsStyleDisplay *display;
|
||||
GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
|
||||
aDesiredSize.width = 0;
|
||||
aDesiredSize.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// XXX TROY
|
||||
#if 0
|
||||
|
|
|
@ -643,8 +643,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
|||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
|
||||
if ((NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay) &&
|
||||
(NS_STYLE_VISIBILITY_COLLAPSE != childDisplay->mVisible))
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
|
||||
{
|
||||
// get the height of the tallest cell in the row (excluding cells that span rows)
|
||||
nscoord maxCellHeight = ((nsTableRowFrame*)rowFrame)->GetTallestChild();
|
||||
|
@ -1031,16 +1030,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
// check the visibility in the final pass. If it is collapse, set our desired size to 0
|
||||
if (nsTableFrame::IsFinalPass(aReflowState)) {
|
||||
const nsStyleDisplay *display;
|
||||
GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
|
||||
aDesiredSize.width = 0;
|
||||
aDesiredSize.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (gsDebug==PR_TRUE)
|
||||
{
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
|
|
|
@ -30,11 +30,15 @@ static const PRBool gsDebug = PR_FALSE;
|
|||
nsCellMap::nsCellMap(int aRowCount, int aColCount)
|
||||
: mRowCount(0),
|
||||
mColCount(0),
|
||||
mTotalRowCount(0)
|
||||
mTotalRowCount(0),
|
||||
mNumCollapsedRows(0),
|
||||
mNumCollapsedCols(0)
|
||||
{
|
||||
mRows = nsnull;
|
||||
mColFrames = nsnull;
|
||||
mMinColSpans = nsnull;
|
||||
mIsCollapsedRows = nsnull;
|
||||
mIsCollapsedCols = nsnull;
|
||||
Reset(aRowCount, aColCount);
|
||||
}
|
||||
|
||||
|
@ -62,6 +66,16 @@ nsCellMap::~nsCellMap()
|
|||
// mMinColSpans may be null, it is only set for tables that need it
|
||||
if (nsnull != mMinColSpans)
|
||||
delete [] mMinColSpans;
|
||||
if (nsnull != mIsCollapsedRows) {
|
||||
delete [] mIsCollapsedRows;
|
||||
mIsCollapsedRows = nsnull;
|
||||
mNumCollapsedRows = 0;
|
||||
}
|
||||
if (nsnull != mIsCollapsedCols) {
|
||||
delete [] mIsCollapsedCols;
|
||||
mIsCollapsedCols = nsnull;
|
||||
mNumCollapsedCols = 0;
|
||||
}
|
||||
mRows = nsnull;
|
||||
mColFrames = nsnull;
|
||||
mMinColSpans = nsnull;
|
||||
|
@ -97,19 +111,20 @@ void nsCellMap::Reset(int aRowCount, int aColCount)
|
|||
|
||||
// if the number of rows has increased, add the extra rows
|
||||
PRInt32 newRows = aRowCount-mTotalRowCount; // (new row count) - (total row allocation)
|
||||
for ( ; newRows>0; newRows--)
|
||||
{
|
||||
for ( ; newRows > 0; newRows--) {
|
||||
nsVoidArray *row;
|
||||
if (0!=aColCount)
|
||||
if (0 != aColCount) {
|
||||
row = new nsVoidArray(aColCount);
|
||||
else
|
||||
} else {
|
||||
row = new nsVoidArray();
|
||||
}
|
||||
mRows->AppendElement(row);
|
||||
}
|
||||
|
||||
mRowCount = aRowCount;
|
||||
mTotalRowCount = PR_MAX(mTotalRowCount, mRowCount);
|
||||
mColCount = aColCount;
|
||||
|
||||
if (gsDebug) printf("leaving Reset with mRC=%d, mCC=%d, mTRC=%d\n",
|
||||
mRowCount, mColCount, mTotalRowCount);
|
||||
}
|
||||
|
@ -413,5 +428,73 @@ PRBool nsCellMap::ColHasSpanningCells(PRInt32 aColIndex)
|
|||
return result;
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetNumCollapsedRows()
|
||||
{
|
||||
return mNumCollapsedRows;
|
||||
}
|
||||
|
||||
PRBool nsCellMap::IsRowCollapsedAt(PRInt32 aRow)
|
||||
{
|
||||
if ((aRow >= 0) && (aRow < mTotalRowCount)) {
|
||||
if (mIsCollapsedRows) {
|
||||
return mIsCollapsedRows[aRow];
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void nsCellMap::SetRowCollapsedAt(PRInt32 aRow, PRBool aValue)
|
||||
{
|
||||
if ((aRow >= 0) && (aRow < mRowCount)) {
|
||||
if (nsnull == mIsCollapsedRows) {
|
||||
mIsCollapsedRows = new PRBool[mRowCount];
|
||||
for (PRInt32 i = 0; i < mRowCount; i++) {
|
||||
mIsCollapsedRows[i] = PR_FALSE;
|
||||
}
|
||||
}
|
||||
if (mIsCollapsedRows[aRow] != aValue) {
|
||||
if (PR_TRUE == aValue) {
|
||||
mNumCollapsedRows++;
|
||||
} else {
|
||||
mNumCollapsedRows--;
|
||||
}
|
||||
mIsCollapsedRows[aRow] = aValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 nsCellMap::GetNumCollapsedCols()
|
||||
{
|
||||
return mNumCollapsedCols;
|
||||
}
|
||||
|
||||
PRBool nsCellMap::IsColCollapsedAt(PRInt32 aCol)
|
||||
{
|
||||
if ((aCol >= 0) && (aCol < mColCount)) {
|
||||
if (mIsCollapsedCols) {
|
||||
return mIsCollapsedCols[aCol];
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void nsCellMap::SetColCollapsedAt(PRInt32 aCol, PRBool aValue)
|
||||
{
|
||||
if ((aCol >= 0) && (aCol < mColCount)) {
|
||||
if (nsnull == mIsCollapsedCols) {
|
||||
mIsCollapsedCols = new PRBool[mColCount];
|
||||
for (PRInt32 i = 0; i < mColCount; i++) {
|
||||
mIsCollapsedCols[i] = PR_FALSE;
|
||||
}
|
||||
}
|
||||
if (mIsCollapsedCols[aCol] != aValue) {
|
||||
if (PR_TRUE == aValue) {
|
||||
mNumCollapsedCols++;
|
||||
} else {
|
||||
mNumCollapsedCols--;
|
||||
}
|
||||
mIsCollapsedCols[aCol] = aValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,14 @@ protected:
|
|||
/** a cache of the column frames, by col index */
|
||||
nsVoidArray * mColFrames;
|
||||
|
||||
// an array of booleans where the ith element indicates if the ith row is collapsed
|
||||
PRBool* mIsCollapsedRows;
|
||||
PRInt32 mNumCollapsedRows;
|
||||
|
||||
// an array of booleans where the ith element indicates if the ith col is collapsed
|
||||
PRBool* mIsCollapsedCols;
|
||||
PRInt32 mNumCollapsedCols;
|
||||
|
||||
/** the number of rows. mRows[0] - mRows[mRowCount-1] are non-null. */
|
||||
PRInt32 mRowCount;
|
||||
|
||||
|
@ -86,6 +94,14 @@ public:
|
|||
/** assign aCellData to the cell at (aRow,aColumn) */
|
||||
void SetCellAt(CellData *aCellData, PRInt32 aRow, PRInt32 aColumn);
|
||||
|
||||
PRInt32 GetNumCollapsedRows();
|
||||
PRBool IsRowCollapsedAt(PRInt32 aRow);
|
||||
void SetRowCollapsedAt(PRInt32 aRow, PRBool aValue);
|
||||
|
||||
PRInt32 GetNumCollapsedCols();
|
||||
PRBool IsColCollapsedAt(PRInt32 aCol);
|
||||
void SetColCollapsedAt(PRInt32 aCol, PRBool aValue);
|
||||
|
||||
/** expand the CellMap to have aRowCount rows. The number of columns remains the same */
|
||||
void GrowToRow(PRInt32 aRowCount);
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
|
|||
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
|
||||
}
|
||||
}
|
||||
mCollapseOffset = nsPoint(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +169,21 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
|
|||
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
|
||||
}
|
||||
|
||||
|
||||
// if the cell originates in a row and/or col that is collapsed, the bottom and/or
|
||||
// right portion of the cell is painted by translating the rendering context.
|
||||
// XXX What about content that can leak outside the cell?
|
||||
PRBool clipState;
|
||||
aRenderingContext.PushState();
|
||||
nsPoint offset = mCollapseOffset;
|
||||
if ((0 != offset.x) || (0 != offset.y)) {
|
||||
aRenderingContext.Translate(offset.x, offset.y);
|
||||
}
|
||||
aRenderingContext.SetClipRect(nsRect(-offset.x, -offset.y, mRect.width, mRect.height),
|
||||
nsClipCombine_kIntersect, clipState);
|
||||
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
|
||||
aRenderingContext.PopState(clipState);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1062,3 +1077,19 @@ nsTableCellFrame::GetFrameName(nsString& aResult) const
|
|||
{
|
||||
return MakeFrameName("TableCell", aResult);
|
||||
}
|
||||
|
||||
void nsTableCellFrame::SetCollapseOffsetX(nscoord aXOffset)
|
||||
{
|
||||
mCollapseOffset.x = aXOffset;
|
||||
}
|
||||
|
||||
void nsTableCellFrame::SetCollapseOffsetY(nscoord aYOffset)
|
||||
{
|
||||
mCollapseOffset.y = aYOffset;
|
||||
}
|
||||
|
||||
nsPoint nsTableCellFrame::GetCollapseOffset()
|
||||
{
|
||||
return mCollapseOffset;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,11 @@ public:
|
|||
PRBool GetContentEmpty();
|
||||
void SetContentEmpty(PRBool aContentEmpty);
|
||||
|
||||
// The collapse offset is (0,0) except for cells originating in a row/col which is collapsed
|
||||
void SetCollapseOffsetX(nscoord aXOffset);
|
||||
void SetCollapseOffsetY(nscoord aYOffset);
|
||||
nsPoint GetCollapseOffset();
|
||||
|
||||
protected:
|
||||
/** implement abstract method on nsHTMLContainerFrame */
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
@ -211,6 +216,9 @@ protected:
|
|||
PRBool mIsContentEmpty; // PR_TRUE if the cell's contents take up no space
|
||||
//XXX: mIsContentEmpty should get yanked in favor of using free a bit on the frame base class
|
||||
// the FrameState slot (mState; GetFrameState/SetFrameState)
|
||||
|
||||
nsPoint mCollapseOffset;
|
||||
|
||||
public:
|
||||
nsBorderEdges mBorderEdges; // one list of border segments for each side of the table frame
|
||||
// used only for the collapsing border model
|
||||
|
|
|
@ -634,21 +634,22 @@ nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
|
|||
nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex)
|
||||
{
|
||||
nsTableColFrame *result = nsnull;
|
||||
PRInt32 count=0;
|
||||
PRInt32 count = 0;
|
||||
nsIFrame *childFrame = mFrames.FirstChild();
|
||||
while (nsnull!=childFrame)
|
||||
{
|
||||
|
||||
while (nsnull!=childFrame) {
|
||||
const nsStyleDisplay *childDisplay;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay)
|
||||
{
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay) {
|
||||
nsTableColFrame *col = (nsTableColFrame *)childFrame;
|
||||
count += col->GetSpan();
|
||||
if (aColIndex<=count)
|
||||
if (aColIndex<=count) {
|
||||
result = col;
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -385,13 +385,14 @@ NS_IMETHODIMP nsTableFrame::DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFra
|
|||
{
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
nextRow->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay);
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
|
||||
{
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay) {
|
||||
rv = ((nsTableRowFrame *)nextRow)->InitChildren();
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -947,74 +948,77 @@ NS_METHOD nsTableFrame::ReBuildCellMap()
|
|||
void nsTableFrame::DumpCellMap ()
|
||||
{
|
||||
printf("dumping CellMap:\n");
|
||||
if (nsnull != mCellMap)
|
||||
{
|
||||
if (nsnull != mCellMap) {
|
||||
PRInt32 colIndex;
|
||||
PRInt32 rowCount = mCellMap->GetRowCount();
|
||||
PRInt32 colCount = mCellMap->GetColCount();
|
||||
printf("rowCount=%d, colCount=%d\n", rowCount, colCount);
|
||||
for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++)
|
||||
{
|
||||
if (gsDebug==PR_TRUE)
|
||||
{ printf("row %d", rowIndex);
|
||||
printf(": ");
|
||||
}
|
||||
for (colIndex = 0; colIndex < colCount; colIndex++)
|
||||
{
|
||||
CellData *cd =mCellMap->GetCellAt(rowIndex, colIndex);
|
||||
if (cd != nsnull)
|
||||
{
|
||||
if (cd->mCell != nsnull)
|
||||
{
|
||||
printf("C%d,%d ", rowIndex, colIndex);
|
||||
printf(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
nsTableCellFrame *cell = cd->mRealCell->mCell;
|
||||
nsTableRowFrame *row;
|
||||
cell->GetParent((nsIFrame **)&row);
|
||||
int rr = row->GetRowIndex ();
|
||||
|
||||
for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
||||
printf("row %d : ", rowIndex);
|
||||
for (colIndex = 0; colIndex < colCount; colIndex++) {
|
||||
CellData* cd = mCellMap->GetCellAt(rowIndex, colIndex);
|
||||
if (cd != nsnull) {
|
||||
if (cd->mCell != nsnull) {
|
||||
printf("C%d,%d ", rowIndex, colIndex);
|
||||
} else {
|
||||
nsTableCellFrame* cell = cd->mRealCell->mCell;
|
||||
nsTableRowFrame* row;
|
||||
cell->GetParent((nsIFrame**)&row);
|
||||
int rr = row->GetRowIndex();
|
||||
int cc;
|
||||
cell->GetColIndex(cc);
|
||||
printf("S%d,%d ", rr, cc);
|
||||
if (cd->mOverlap != nsnull)
|
||||
{
|
||||
printf("S%d,%d ", rr, cc);
|
||||
if (cd->mOverlap != nsnull){
|
||||
cell = cd->mOverlap->mCell;
|
||||
nsTableRowFrame* row2;
|
||||
cell->GetParent((nsIFrame **)&row2);
|
||||
rr = row2->GetRowIndex ();
|
||||
cell->GetColIndex (cc);
|
||||
cell->GetParent((nsIFrame**)&row2);
|
||||
rr = row2->GetRowIndex();
|
||||
cell->GetColIndex(cc);
|
||||
printf("O%d,%c ", rr, cc);
|
||||
}
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
printf("---- ");
|
||||
}
|
||||
}
|
||||
PRBool spanners = RowHasSpanningCells(rowIndex);
|
||||
PRBool spannedInto = RowIsSpannedInto(rowIndex);
|
||||
printf (" spanners=%s spannedInto=%s\n", spanners?"T":"F", spannedInto?"T":"F");
|
||||
}
|
||||
|
||||
// output info mapping Ci,j to cell address
|
||||
PRInt32 cellCount = 0;
|
||||
for (PRInt32 rIndex = 0; rIndex < rowCount; rIndex++) {
|
||||
for (colIndex = 0; colIndex < colCount; colIndex++) {
|
||||
CellData* cd = mCellMap->GetCellAt(rIndex, colIndex);
|
||||
if (cd != nsnull) {
|
||||
if (cd->mCell != nsnull) {
|
||||
printf("C%d,%d=%p ", rIndex, colIndex, cd->mCell);
|
||||
cellCount++;
|
||||
}
|
||||
}
|
||||
if (0 == (cellCount % 4)) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// output colspan info
|
||||
for (colIndex=0; colIndex<colCount; colIndex++)
|
||||
{
|
||||
for (colIndex=0; colIndex<colCount; colIndex++) {
|
||||
PRBool colSpanners = ColHasSpanningCells(colIndex);
|
||||
PRBool colSpannedInto = ColIsSpannedInto(colIndex);
|
||||
printf ("%d colSpanners=%s colSpannedInto=%s\n",
|
||||
colIndex, colSpanners?"T":"F", colSpannedInto?"T":"F");
|
||||
}
|
||||
// output col frame info
|
||||
for (colIndex=0; colIndex<colCount; colIndex++)
|
||||
{
|
||||
for (colIndex=0; colIndex<colCount; colIndex++) {
|
||||
nsTableColFrame *colFrame = mCellMap->GetColumnFrame(colIndex);
|
||||
printf ("col index %d has frame=%p\n", colIndex, colFrame);
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
printf ("[nsnull]");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2636,7 +2640,10 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
|
|||
aDesiredSize.width = ComputeDesiredWidth(aReflowState);
|
||||
nscoord defaultHeight = state.y + borderPadding.top + borderPadding.bottom;
|
||||
aDesiredSize.height = ComputeDesiredHeight(aPresContext, aReflowState, defaultHeight);
|
||||
|
||||
|
||||
AdjustForCollapsingRows(aPresContext, aDesiredSize.height);
|
||||
AdjustForCollapsingCols(aPresContext, aDesiredSize.width);
|
||||
|
||||
// once horizontal borders are computed and all row heights are set,
|
||||
// we need to fix up length of vertical edges
|
||||
// XXX need to figure start row and end row correctly
|
||||
|
@ -2651,6 +2658,224 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
|
|||
|
||||
}
|
||||
|
||||
// collapsing row groups, rows, col groups and cols are accounted for after both passes of
|
||||
// reflow so that it has no effect on the calculations of reflow.
|
||||
NS_METHOD nsTableFrame::AdjustForCollapsingRows(nsIPresContext& aPresContext,
|
||||
nscoord& aHeight)
|
||||
{
|
||||
// determine which row groups and rows are collapsed
|
||||
nsIFrame* childFrame;
|
||||
FirstChild(nsnull, &childFrame);
|
||||
while (nsnull != childFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
if (IsRowGroup(groupDisplay->mDisplay)) {
|
||||
PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
|
||||
nsTableRowFrame* rowFrame = nsnull;
|
||||
childFrame->FirstChild(nsnull, (nsIFrame**)&rowFrame);
|
||||
PRInt32 rowX = 0;
|
||||
while (nsnull != rowFrame) {
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
|
||||
mCellMap->SetRowCollapsedAt(rowX, PR_TRUE);
|
||||
}
|
||||
}
|
||||
rowFrame->GetNextSibling((nsIFrame**)&rowFrame);
|
||||
rowX++;
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
if (mCellMap->GetNumCollapsedRows() <= 0) {
|
||||
return NS_OK; // no collapsed rows, we're done
|
||||
}
|
||||
|
||||
// collapse the rows and/or row groups
|
||||
nsIFrame* groupFrame = mFrames.FirstChild();
|
||||
nscoord yGroupOffset = 0; // total offset among rows within a single row group
|
||||
nscoord yTotalOffset = 0; // total offset among all rows in all row groups
|
||||
PRInt32 rowX = 0;
|
||||
PRBool collapseGroup;
|
||||
|
||||
while (nsnull != groupFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
if (IsRowGroup(groupDisplay->mDisplay)) {
|
||||
collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
nsIFrame* rowFrame;
|
||||
groupFrame->FirstChild(nsnull, &rowFrame);
|
||||
|
||||
while (nsnull != rowFrame) {
|
||||
const nsStyleDisplay* rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
if (collapseGroup || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
|
||||
yGroupOffset += rowRect.height;
|
||||
rowRect.height = 0;
|
||||
rowFrame->SetRect(rowRect);
|
||||
nsIFrame* cellFrame;
|
||||
rowFrame->FirstChild(nsnull, &cellFrame);
|
||||
while (nsnull != cellFrame) {
|
||||
const nsStyleDisplay* cellDisplay;
|
||||
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
|
||||
nsTableCellFrame* cFrame = (nsTableCellFrame*)cellFrame;
|
||||
nsRect cRect;
|
||||
cFrame->GetRect(cRect);
|
||||
cRect.height -= rowRect.height;
|
||||
cFrame->SetCollapseOffsetY(-yGroupOffset);
|
||||
cFrame->SetRect(cRect);
|
||||
}
|
||||
cellFrame->GetNextSibling(&cellFrame);
|
||||
}
|
||||
// check if a cell above spans into here
|
||||
//if (!collapseGroup) {
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
nsTableCellFrame* lastCell = nsnull;
|
||||
for (int colX = 0; colX < numCols; colX++) {
|
||||
CellData* cellData = mCellMap->GetCellAt(rowX, colX);
|
||||
if (cellData && !cellData->mCell) { // a cell above is spanning into here
|
||||
// adjust the real cell's rect only once
|
||||
nsTableCellFrame* realCell = cellData->mRealCell->mCell;
|
||||
if (realCell != lastCell) {
|
||||
nsRect realRect;
|
||||
realCell->GetRect(realRect);
|
||||
realRect.height -= rowRect.height;
|
||||
realCell->SetRect(realRect);
|
||||
}
|
||||
lastCell = realCell;
|
||||
}
|
||||
}
|
||||
//}
|
||||
} else { // row is not collapsed but needs to be adjusted by those that are
|
||||
rowRect.y -= yGroupOffset;
|
||||
rowFrame->SetRect(rowRect);
|
||||
}
|
||||
rowX++;
|
||||
}
|
||||
rowFrame->GetNextSibling(&rowFrame);
|
||||
} // end row frame while
|
||||
}
|
||||
nsRect groupRect;
|
||||
groupFrame->GetRect(groupRect);
|
||||
groupRect.height -= yGroupOffset;
|
||||
groupRect.y -= yTotalOffset;
|
||||
groupFrame->SetRect(groupRect);
|
||||
|
||||
yTotalOffset += yGroupOffset;
|
||||
yGroupOffset = 0;
|
||||
groupFrame->GetNextSibling(&groupFrame);
|
||||
} // end group frame while
|
||||
|
||||
aHeight -= yTotalOffset;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::AdjustForCollapsingCols(nsIPresContext& aPresContext,
|
||||
nscoord& aWidth)
|
||||
{
|
||||
// determine which col groups and cols are collapsed
|
||||
nsIFrame* childFrame = mColGroups.FirstChild();
|
||||
while (nsnull != childFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
|
||||
nsTableColFrame* colFrame = nsnull;
|
||||
childFrame->FirstChild(nsnull, (nsIFrame**)&colFrame);
|
||||
PRInt32 colX = 0;
|
||||
while (nsnull != colFrame) {
|
||||
const nsStyleDisplay *colDisplay;
|
||||
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
|
||||
if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible)) {
|
||||
mCellMap->SetColCollapsedAt(colX, PR_TRUE);
|
||||
}
|
||||
}
|
||||
colFrame->GetNextSibling((nsIFrame**)&colFrame);
|
||||
colX++;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
|
||||
if (mCellMap->GetNumCollapsedCols() <= 0) {
|
||||
return NS_OK; // no collapsed cols, we're done
|
||||
}
|
||||
|
||||
// collapse the cols and/or col groups
|
||||
PRInt32 numRows = mCellMap->GetRowCount();
|
||||
nsIFrame* groupFrame = mColGroups.FirstChild();
|
||||
nscoord cellSpacingX = GetCellSpacingX();
|
||||
nscoord xOffset = 0;
|
||||
PRInt32 colX = 0;
|
||||
while (nsnull != groupFrame) {
|
||||
const nsStyleDisplay* groupDisplay;
|
||||
groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
|
||||
PRBool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
|
||||
nsRect zeroRect(0, 0, 0, 0);
|
||||
nsIFrame* colFrame;
|
||||
groupFrame->FirstChild(nsnull, &colFrame);
|
||||
while (nsnull != colFrame) {
|
||||
const nsStyleDisplay* colDisplay;
|
||||
colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
|
||||
PRBool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible);
|
||||
PRInt32 colSpan = ((nsTableColFrame*)colFrame)->GetSpan();
|
||||
for (PRInt32 spanX = 0; spanX < colSpan; spanX++) {
|
||||
PRInt32 colWidth = GetColumnWidth(colX+spanX);
|
||||
if (collapseGroup || collapseCol) {
|
||||
xOffset += colWidth + cellSpacingX;
|
||||
}
|
||||
nsTableCellFrame* lastCell = nsnull;
|
||||
nsTableCellFrame* cellFrame = nsnull;
|
||||
for (PRInt32 rowX = 0; rowX < numRows; rowX++) {
|
||||
CellData* cellData = mCellMap->GetCellAt(rowX, colX+spanX);
|
||||
nsRect cellRect;
|
||||
if (cellData) {
|
||||
cellFrame = cellData->mCell;
|
||||
if (cellFrame) { // the cell originates at (rowX, colX)
|
||||
cellFrame->GetRect(cellRect);
|
||||
if (collapseGroup || collapseCol) {
|
||||
if (lastCell != cellFrame) { // do it only once if there is a row span
|
||||
cellRect.width -= colWidth;
|
||||
cellFrame->SetCollapseOffsetX(-xOffset);
|
||||
}
|
||||
} else { // the cell is not in a collapsed col but needs to move
|
||||
cellRect.x -= xOffset;
|
||||
}
|
||||
cellFrame->SetRect(cellRect);
|
||||
// if the cell does not originate at (rowX, colX), adjust the real cells width
|
||||
} else if (collapseGroup || collapseCol) {
|
||||
cellFrame = cellData->mRealCell->mCell;
|
||||
if ((cellFrame) && (lastCell != cellFrame)) {
|
||||
cellFrame->GetRect(cellRect);
|
||||
cellRect.width -= colWidth + cellSpacingX;
|
||||
cellFrame->SetRect(cellRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastCell = cellFrame;
|
||||
}
|
||||
}
|
||||
colX += colSpan;
|
||||
}
|
||||
colFrame->GetNextSibling(&colFrame);
|
||||
} // inner while
|
||||
groupFrame->GetNextSibling(&groupFrame);
|
||||
} // outer while
|
||||
|
||||
aWidth -= xOffset;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
|
|
|
@ -560,6 +560,12 @@ protected:
|
|||
InnerTableReflowState& aReflowState,
|
||||
nsIFrame* aKidFrame,
|
||||
nscoord aDeltaY);
|
||||
|
||||
NS_METHOD AdjustForCollapsingRows(nsIPresContext& aPresContext,
|
||||
nscoord& aHeight);
|
||||
|
||||
NS_METHOD AdjustForCollapsingCols(nsIPresContext& aPresContext,
|
||||
nscoord& aWidth);
|
||||
// end incremental reflow methods
|
||||
|
||||
/** return the desired width of this table accounting for the current
|
||||
|
|
|
@ -1421,16 +1421,6 @@ nsTableRowFrame::Reflow(nsIPresContext& aPresContext,
|
|||
break;
|
||||
}
|
||||
|
||||
// check the visibility in the final pass. If it is collapse, set our desired size to 0
|
||||
if (nsTableFrame::IsFinalPass(aReflowState)) {
|
||||
const nsStyleDisplay *display;
|
||||
GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
|
||||
aDesiredSize.width = 0;
|
||||
aDesiredSize.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// XXX TROY
|
||||
#if 0
|
||||
|
|
|
@ -643,8 +643,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
|
|||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
|
||||
if ((NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay) &&
|
||||
(NS_STYLE_VISIBILITY_COLLAPSE != childDisplay->mVisible))
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
|
||||
{
|
||||
// get the height of the tallest cell in the row (excluding cells that span rows)
|
||||
nscoord maxCellHeight = ((nsTableRowFrame*)rowFrame)->GetTallestChild();
|
||||
|
@ -1031,16 +1030,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
// check the visibility in the final pass. If it is collapse, set our desired size to 0
|
||||
if (nsTableFrame::IsFinalPass(aReflowState)) {
|
||||
const nsStyleDisplay *display;
|
||||
GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
|
||||
aDesiredSize.width = 0;
|
||||
aDesiredSize.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (gsDebug==PR_TRUE)
|
||||
{
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
|
|
Загрузка…
Ссылка в новой задаче