зеркало из https://github.com/mozilla/gecko-dev.git
major hackage to the table data structures. slimmer, simpler, faster
this work exposed a few bugs and slow spots, which have been fixed for the aol page, I added some additional backwards compatibility code to proportionately distribute width when a fixed-width cell has colspans
This commit is contained in:
Родитель
d75cb80e9a
Коммит
3e596fc26a
|
@ -19,16 +19,13 @@
|
|||
#include "BasicTableLayoutStrategy.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsColLayoutData.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsTableCol.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
|
||||
NS_DEF_PTR(nsTableCol);
|
||||
NS_DEF_PTR(nsIStyleContext);
|
||||
|
||||
|
||||
|
@ -64,6 +61,23 @@ struct ProportionalColumnLayoutStruct
|
|||
};
|
||||
|
||||
|
||||
/* ---------- ColSpanStruct ---------- */
|
||||
struct ColSpanStruct
|
||||
{
|
||||
PRInt32 colIndex;
|
||||
PRInt32 colSpan;
|
||||
nscoord width;
|
||||
|
||||
ColSpanStruct(PRInt32 aSpan, PRInt32 aIndex, nscoord aWidth)
|
||||
{
|
||||
colSpan = aSpan;
|
||||
colIndex = aIndex;
|
||||
width = aWidth;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* ---------- BasicTableLayoutStrategy ---------- */
|
||||
|
||||
|
@ -228,7 +242,9 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
|
||||
if (gsDebug==PR_TRUE) printf (" AssignFixedColumnWidths\n");
|
||||
nsVoidArray *spanList=nsnull;
|
||||
|
||||
nsVoidArray *colSpanList=nsnull;
|
||||
nscoord * effectiveColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
|
||||
PRBool hasColsAttribute = (PRBool)(NS_STYLE_TABLE_COLS_NONE!=mCols);
|
||||
|
||||
|
@ -240,26 +256,24 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
maxColWidthArray = new PRInt32[mNumCols];
|
||||
}
|
||||
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
|
||||
// for every column, determine it's min and max width, and keep track of the table width
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
NS_ASSERTION(nsnull != colData, "bad column data");
|
||||
nsTableColFrame *colFrame = colData->GetColFrame();
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
|
||||
// need to track min/max column width for setting min/max table widths
|
||||
// QQQ: Eventually, this will be cached in col frame
|
||||
// We'll just ask the column frame to compute this, and it'll use cached info if available
|
||||
PRInt32 minColWidth = 0;
|
||||
PRInt32 maxColWidth = 0;
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 numCells = cells->Count();
|
||||
if (gsDebug==PR_TRUE) printf (" for column %d numCells = %d\n", colIndex, numCells);
|
||||
|
||||
// Get column information
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
|
||||
// Get the columns's style
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
const nsStylePosition* colPosition = (const nsStylePosition*) colSC->GetStyleData(eStyleStruct_Position);
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
|
||||
// Get column width if it has one
|
||||
PRBool haveColWidth = PR_FALSE;
|
||||
|
@ -268,7 +282,7 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
case eStyleUnit_Coord:
|
||||
haveColWidth = PR_TRUE;
|
||||
specifiedFixedColWidth = colPosition->mWidth.GetCoordValue();
|
||||
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth); //QQQ add in margins?
|
||||
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -303,38 +317,49 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
}
|
||||
}
|
||||
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
PRInt32 firstRowIndex = -1;
|
||||
for (PRInt32 rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull == data) {
|
||||
// For cells that span rows there's only cell layout data for the first row
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
if (-1==firstRowIndex)
|
||||
firstRowIndex = rowIndex;
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
if (colIndex!=cellFrame->GetColIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetColSpan(), "col index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
nsMargin margin;
|
||||
nsresult result = data->GetMargin(margin);
|
||||
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
nsReflowMetrics * cellDesiredSize = data->GetDesiredSize();
|
||||
NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize");
|
||||
PRInt32 colSpan = data->GetCellFrame()->GetColSpan();
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d, margins %d %d\n",
|
||||
cellIndex, colSpan, cellMinSize->width, cellMinSize->height,
|
||||
cellDesiredSize->width, cellDesiredSize->height,
|
||||
margin.left, margin.right);
|
||||
printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d\n",
|
||||
rowIndex, colSpan, cellMinSize.width, cellMinSize.height,
|
||||
cellDesiredSize.width, cellDesiredSize.height);
|
||||
|
||||
switch (colPosition->mWidth.GetUnit()) {
|
||||
switch (colPosition->mWidth.GetUnit())
|
||||
{
|
||||
case eStyleUnit_Coord:
|
||||
{
|
||||
// This col has a fixed width, so set the cell's width to the
|
||||
// larger of (specified width, largest max_element_size of the
|
||||
// cells in the column)
|
||||
PRInt32 widthForThisCell = PR_MAX(cellMinSize->width, colPosition->mWidth.GetCoordValue());
|
||||
if (mTableFrame->GetColumnWidth(colIndex) < widthForThisCell)
|
||||
nscoord widthForThisCell = PR_MAX(cellMinSize.width, colPosition->mWidth.GetCoordValue());
|
||||
widthForThisCell = widthForThisCell/colSpan;
|
||||
nscoord widthFromCol = mTableFrame->GetColumnWidth(colIndex);
|
||||
if (widthFromCol < widthForThisCell)
|
||||
{
|
||||
if (gsDebug) printf (" setting fixed width to %d\n",widthForThisCell);
|
||||
mTableFrame->SetColumnWidth(colIndex, widthForThisCell); //QQQ add in margins?
|
||||
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
|
||||
maxColWidth = widthForThisCell;
|
||||
}
|
||||
}
|
||||
|
@ -347,24 +372,24 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
|
||||
// regardless of the width specification, keep track of the
|
||||
// min/max column widths
|
||||
nscoord cellMinWidth = cellMinSize->width/colSpan;
|
||||
nscoord cellDesiredWidth = cellDesiredSize->width/colSpan;
|
||||
|
||||
if (aMaxWidth!=cellDesiredSize->width)
|
||||
{
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellMinWidth)
|
||||
cellMinWidth += margin.left + margin.right;
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellDesiredWidth)
|
||||
cellDesiredWidth += margin.left + margin.right;
|
||||
}
|
||||
|
||||
nscoord cellMinWidth = cellMinSize.width/colSpan;
|
||||
nscoord cellDesiredWidth = cellDesiredSize.width/colSpan;
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
if (maxColWidth < cellDesiredWidth)
|
||||
maxColWidth = cellDesiredWidth;
|
||||
// effectiveColumnWidth is the width as if no cells with colspans existed
|
||||
if ((1==colSpan) && (effectiveColumnWidths[colIndex] < maxColWidth))
|
||||
effectiveColumnWidths[colIndex] = cellDesiredWidth;
|
||||
if (1<colSpan)
|
||||
{
|
||||
// add the cell to our list of spanners
|
||||
// add the column to our list of post-process columns
|
||||
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, cellDesiredSize.width);
|
||||
if (nsnull==colSpanList)
|
||||
colSpanList = new nsVoidArray();
|
||||
colSpanList->AppendElement(colSpanInfo);
|
||||
|
||||
// add the cell to our list of spanning cells
|
||||
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
|
||||
if (nsnull==spanList)
|
||||
spanList = new nsVoidArray();
|
||||
|
@ -372,26 +397,30 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
}
|
||||
if (gsDebug) {
|
||||
printf (" after cell %d, minColWidth = %d and maxColWidth = %d\n",
|
||||
cellIndex, minColWidth, maxColWidth);
|
||||
rowIndex, minColWidth, maxColWidth);
|
||||
}
|
||||
}
|
||||
|
||||
// do all the global bookkeeping, factoring in margins
|
||||
nsTableCellFrame * firstCellInColumn = mTableFrame->GetCellAt(firstRowIndex, colIndex);
|
||||
nsMargin colMargin;
|
||||
firstCellInColumn->GetMargin(colMargin);
|
||||
nscoord colInset = colMargin.left + colMargin.right;
|
||||
// keep a running total of the amount of space taken up by all fixed-width columns
|
||||
if (PR_TRUE==haveColWidth)
|
||||
aTotalFixedWidth += mTableFrame->GetColumnWidth(colIndex);
|
||||
aTotalFixedWidth += mTableFrame->GetColumnWidth(colIndex) + colInset;
|
||||
|
||||
if (gsDebug) {
|
||||
printf (" after col %d, aTotalFixedWidth = %d\n",
|
||||
colIndex, aTotalFixedWidth);
|
||||
}
|
||||
|
||||
// add col[i] metrics to the running totals for the table min/max width
|
||||
if (NS_UNCONSTRAINEDSIZE!=aMinTableWidth)
|
||||
aMinTableWidth += minColWidth; // SEC: insets!
|
||||
aMinTableWidth += minColWidth + colInset;
|
||||
if (aMinTableWidth<=0)
|
||||
aMinTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
|
||||
if (NS_UNCONSTRAINEDSIZE!=aMaxTableWidth)
|
||||
aMaxTableWidth += maxColWidth; // SEC: insets!
|
||||
aMaxTableWidth += maxColWidth + colInset;
|
||||
if (aMaxTableWidth<=0)
|
||||
aMaxTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
|
||||
if (PR_TRUE==hasColsAttribute)
|
||||
|
@ -441,15 +470,59 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
delete [] minColWidthArray;
|
||||
delete [] maxColWidthArray;
|
||||
}
|
||||
if (nsnull!=colSpanList)
|
||||
DistributeFixedSpace(colSpanList, effectiveColumnWidths);
|
||||
// today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in
|
||||
if (nsnull!=effectiveColumnWidths)
|
||||
delete [] effectiveColumnWidths;
|
||||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf ("%p: aMinTW=%d, aMaxTW=%d\n", mTableFrame, aMinTableWidth, aMaxTableWidth);
|
||||
|
||||
if (nsnull!=spanList)
|
||||
delete spanList;
|
||||
if (nsnull!=colSpanList)
|
||||
delete colSpanList;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// take the fixed space spanned by the columns in aColSpanList
|
||||
// and distribute it proportionately (based on desired width)
|
||||
void BasicTableLayoutStrategy::DistributeFixedSpace(nsVoidArray *aColSpanList, nscoord *aColWidths)
|
||||
{
|
||||
nscoord excess = 0;
|
||||
if (PR_TRUE==gsDebug) printf ("DistributeFixedSpace:\n");
|
||||
// for all fixed-width columns, determine the amount of the specified width each column spanned recieves
|
||||
PRInt32 numSpanningCells = aColSpanList->Count();
|
||||
for (PRInt32 nextSpanningCell=0; nextSpanningCell<numSpanningCells; nextSpanningCell++)
|
||||
{ // proportionately distributed extra space, based on the column's fixed width
|
||||
ColSpanStruct * colInfo = (ColSpanStruct *)aColSpanList->ElementAt(nextSpanningCell);
|
||||
PRInt32 colIndex = colInfo->colIndex;
|
||||
PRInt32 colSpan = colInfo->colSpan;
|
||||
nscoord totalColWidth = colInfo->width;
|
||||
|
||||
// 1. get the sum of the effective widths of the columns in the span
|
||||
nscoord totalEffectiveWidth=0;
|
||||
PRInt32 i;
|
||||
for (i = 0; i<colSpan; i++)
|
||||
{
|
||||
totalEffectiveWidth += aColWidths[colIndex+i];
|
||||
}
|
||||
|
||||
// 2. next, compute the proportion to be added to each column, and add it
|
||||
for (i = 0; i<colSpan; i++)
|
||||
{
|
||||
float percent;
|
||||
percent = ((float)(aColWidths[colIndex+i]))/((float)totalEffectiveWidth);
|
||||
nscoord colWidth = (nscoord)(totalColWidth*percent);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" assigning fixed col width for spanning cells: column %d set to %d\n",
|
||||
colIndex+i, colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex+i, colWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
|
@ -529,35 +602,37 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
|
|||
minColWidthArray = new PRInt32[mNumCols];
|
||||
}
|
||||
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 minColWidth = 0;
|
||||
PRInt32 maxColWidth = 0;
|
||||
PRInt32 numCells = cells->Count();
|
||||
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
|
||||
|
||||
// XXX need column frame to ask this question
|
||||
const nsStylePosition* colPosition = nsnull;
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
|
||||
// Get the columns's style
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
{ // this col has proportional width, so determine its width requirements
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull==data)
|
||||
{ // For cells that span rows there's only cell layout data for the first row
|
||||
for (PRInt32 rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{ // this col has non-fixed width, so determine its width requirements
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
nsMargin margin;
|
||||
data->GetMargin(margin);
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize");
|
||||
nscoord cellMinWidth = cellMinSize->width; // do we need to take into account colSpan here?
|
||||
cellMinWidth += margin.left + margin.right;
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
nscoord cellMinWidth = cellMinSize.width/colSpan;
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
}
|
||||
|
@ -624,32 +699,42 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
|
||||
PRBool result = PR_TRUE;
|
||||
nscoord tableWidth=0; // the width of the table as a result of setting column widths
|
||||
nscoord widthOfFixedTableColumns=0; // the sum of the width of all fixed-width columns
|
||||
// tableWidth - widthOfFixedTableColumns is the width of columns computed in this method
|
||||
PRInt32 totalSlices=0; // the total number of slices the proportional-width columns request
|
||||
nsVoidArray *proportionalColumnsList=nsnull; // a list of the columns that are proportional-width
|
||||
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
nscoord * effectiveColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveColumnWidths, 0, numCols*sizeof(PRInt32));
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
nscoord * effectiveColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
|
||||
PRInt32 minColWidth = 0;
|
||||
PRInt32 maxColWidth = 0;
|
||||
// Get column information
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 numCells = cells->Count();
|
||||
|
||||
// Get the columns's style
|
||||
nsTableColFrame *colFrame = colData->GetColFrame();
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
const nsStylePosition* colPosition = (const nsStylePosition*) colSC->GetStyleData(eStyleStruct_Position);
|
||||
if (gsDebug) printf("col %d has frame %p with style %p and pos %p\n",
|
||||
colIndex, colFrame, (nsIStyleContext *)colSC, colPosition);
|
||||
PRInt32 rowIndex;
|
||||
PRInt32 firstRowIndex = -1;
|
||||
nsTableCellFrame * firstCellInColumn;
|
||||
for (rowIndex=0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
firstCellInColumn = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull!=firstCellInColumn)
|
||||
break;
|
||||
}
|
||||
nsMargin colMargin;
|
||||
nscoord colInset = 0;
|
||||
if (nsnull!=firstCellInColumn)
|
||||
{
|
||||
firstCellInColumn->GetMargin(colMargin);
|
||||
colInset = colMargin.left + colMargin.right;
|
||||
}
|
||||
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
// first, deal with any cells that span into this column from a pervious column
|
||||
|
@ -676,33 +761,33 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
}
|
||||
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
for (rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{ // this col has proportional width, so determine its width requirements
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull == data) {
|
||||
// For cells that span columns there's only cell layout data for the first column
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
if (-1==firstRowIndex)
|
||||
firstRowIndex = rowIndex;
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
PRInt32 colSpan = data->GetCellFrame()->GetColSpan();
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
// distribute a portion of the spanning cell's min and max width to this column
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize");
|
||||
nsReflowMetrics * cellDesiredSize = data->GetDesiredSize();
|
||||
NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize");
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
|
||||
|
||||
nsMargin margin;
|
||||
nsresult result = data->GetMargin(margin);
|
||||
nscoord marginWidth = margin.left + margin.right;
|
||||
PRInt32 cellMinWidth = cellMinSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellMinWidth = cellMinSize.width/colSpan;
|
||||
// first get the desired size info from reflow pass 1
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize.width/colSpan;
|
||||
// then get the desired size info factoring in the cell style attributes
|
||||
nscoord specifiedCellWidth=-1;
|
||||
nsIStyleContextPtr cellSC;
|
||||
data->GetCellFrame()->GetStyleContext(aPresContext, cellSC.AssignRef());
|
||||
const nsStylePosition* cellPosition = (const nsStylePosition*)
|
||||
cellSC->GetStyleData(eStyleStruct_Position);
|
||||
const nsStylePosition* cellPosition;
|
||||
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
|
||||
switch (cellPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedCellWidth = cellPosition->mWidth.GetCoordValue();
|
||||
|
@ -730,17 +815,17 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
if (-1!=specifiedCellWidth)
|
||||
{
|
||||
if (specifiedCellWidth>cellMinWidth)
|
||||
if (specifiedCellWidth/colSpan>cellMinWidth)
|
||||
{
|
||||
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
|
||||
cellDesiredWidth, specifiedCellWidth);
|
||||
cellDesiredWidth = specifiedCellWidth; // TODO: some math needed here for colspans
|
||||
cellDesiredWidth, specifiedCellWidth/colSpan);
|
||||
cellDesiredWidth = specifiedCellWidth/colSpan; // TODO: some math needed here for colspans
|
||||
}
|
||||
}
|
||||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
|
||||
cellIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
rowIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
if (maxColWidth < cellDesiredWidth)
|
||||
|
@ -750,10 +835,10 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
effectiveColumnWidths[colIndex] = cellDesiredWidth;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d\n",
|
||||
cellIndex, minColWidth, maxColWidth,
|
||||
rowIndex, minColWidth, maxColWidth,
|
||||
colIndex, effectiveColumnWidths[colIndex]);
|
||||
if (1<colSpan)
|
||||
{ // add the cell to our list of spanners
|
||||
if ((1<colSpan) && (cellFrame->GetColIndex()==colIndex))
|
||||
{ // add this cell to span list iff we are currently processing the column the cell starts in
|
||||
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
|
||||
if (nsnull==spanList)
|
||||
spanList = new nsVoidArray();
|
||||
|
@ -863,7 +948,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
if (-1==percentage)
|
||||
{
|
||||
percentage = 100/numCols;
|
||||
percentage = 100/mNumCols;
|
||||
// base the % on the remaining available width
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
|
||||
if (gsDebug==PR_TRUE)
|
||||
|
@ -879,7 +964,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
}
|
||||
}
|
||||
tableWidth += mTableFrame->GetColumnWidth(colIndex);
|
||||
else
|
||||
{ // need to maintain this so we know how much we have left over at the end
|
||||
widthOfFixedTableColumns += mTableFrame->GetColumnWidth(colIndex) + colInset;
|
||||
}
|
||||
tableWidth += mTableFrame->GetColumnWidth(colIndex) + colInset;
|
||||
}
|
||||
|
||||
/* --- post-process if necessary --- */
|
||||
|
@ -938,9 +1027,9 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
// next, if the specified width of the table is greater than the table's computed width, expand the
|
||||
// table's computed width to match the specified width, giving the extra space to proportionately-sized
|
||||
// columns if possible.
|
||||
if ((PR_FALSE==aTableIsAutoWidth) && (aAvailWidth > tableWidth))
|
||||
if ((PR_FALSE==aTableIsAutoWidth) && (aAvailWidth > (tableWidth-widthOfFixedTableColumns)))
|
||||
{
|
||||
DistributeExcessSpace(aAvailWidth, tableWidth, effectiveColumnWidths);
|
||||
DistributeExcessSpace(aAvailWidth, tableWidth, widthOfFixedTableColumns, effectiveColumnWidths);
|
||||
}
|
||||
// today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in
|
||||
if (nsnull!=effectiveColumnWidths)
|
||||
|
@ -952,24 +1041,27 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
|
||||
// take the extra space in the table and distribute it proportionately (based on desired width)
|
||||
// give extra space to auto-width cells first, or if there are none to all cells
|
||||
void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth,
|
||||
nscoord aComputedTableWidth,
|
||||
void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aAvailWidth,
|
||||
nscoord aTableWidth,
|
||||
nscoord aWidthOfFixedTableColumns,
|
||||
nscoord *aColWidths)
|
||||
{
|
||||
nscoord excess = 0;
|
||||
if (PR_TRUE==gsDebug) printf ("DistributeExcessSpace: fixed width %d > computed table width %d\n",
|
||||
aTableFixedWidth, aComputedTableWidth);
|
||||
if (PR_TRUE==gsDebug) printf ("DistributeExcessSpace: fixed width %d > computed table width %d, woftc=%d\n",
|
||||
aAvailWidth, aTableWidth, aWidthOfFixedTableColumns);
|
||||
// if there are auto-sized columns, give them the extra space
|
||||
// the trick here is to do the math excluding non-auto width columns
|
||||
PRInt32 numAutoColumns=0;
|
||||
PRInt32 *autoColumns=nsnull;
|
||||
mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoColumns, autoColumns);
|
||||
if (0!=numAutoColumns)
|
||||
{
|
||||
nscoord computedTableWidth = aTableWidth - aWidthOfFixedTableColumns;
|
||||
// there's at least one auto-width column, so give it (them) the extra space
|
||||
// proportionately distributed extra space, based on the column's desired size
|
||||
nscoord totalEffectiveWidthOfAutoColumns = 0;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
printf(" aAvailWidth specified as %d, expanding columns by excess = %d\n", aAvailWidth, excess);
|
||||
// 1. first, get the total width of the auto columns
|
||||
PRInt32 i;
|
||||
for (i = 0; i<numAutoColumns; i++)
|
||||
|
@ -979,12 +1071,12 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth,
|
|||
else
|
||||
totalEffectiveWidthOfAutoColumns += mTableFrame->GetColumnWidth(autoColumns[i]);
|
||||
}
|
||||
excess = aTableFixedWidth - aComputedTableWidth;
|
||||
excess = aAvailWidth - computedTableWidth;
|
||||
// 2. next, compute the proportion to be added to each column, and add it
|
||||
for (i = 0; i<numAutoColumns; i++)
|
||||
{
|
||||
PRInt32 colIndex = autoColumns[i];
|
||||
nscoord oldColWidth = aColWidths[colIndex];
|
||||
nscoord oldColWidth = mTableFrame->GetColumnWidth(colIndex);//aColWidths[colIndex];
|
||||
float percent;
|
||||
if (0!=totalEffectiveWidthOfAutoColumns)
|
||||
percent = ((float)(aColWidths[colIndex]))/((float)totalEffectiveWidthOfAutoColumns);
|
||||
|
@ -1002,25 +1094,25 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth,
|
|||
// (they must be all fixed and percentage-width columns, or we would have gone into the block above)
|
||||
else
|
||||
{
|
||||
excess = aTableFixedWidth - aComputedTableWidth;
|
||||
nscoord excessPerColumn = excess/mNumCols;
|
||||
excess = aAvailWidth - (aTableWidth-aWidthOfFixedTableColumns);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
printf(" aAvailWidth specified as %d, expanding columns by excess = %d\n",
|
||||
aAvailWidth, excess);
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nscoord oldColWidth = aColWidths[colIndex];
|
||||
nscoord oldColWidth=0;// = aColWidths[colIndex];
|
||||
if (0==oldColWidth)
|
||||
oldColWidth = mTableFrame->GetColumnWidth(colIndex);
|
||||
float percent;
|
||||
if (0!=aComputedTableWidth)
|
||||
percent = (float)oldColWidth/(float)aComputedTableWidth;
|
||||
if (0!=aTableWidth)
|
||||
percent = (float)oldColWidth/(float)aTableWidth;
|
||||
else
|
||||
percent = (float)1/(float)mNumCols;
|
||||
nscoord excessForThisColumn = (nscoord)(excess*percent);
|
||||
nscoord colWidth = excessForThisColumn+oldColWidth;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" distribute excess to all columns: column %d was %d, now set to %d\n",
|
||||
colIndex, aColWidths[colIndex], colWidth);
|
||||
printf(" distribute excess to all columns: column %d was %d, now set to %d from % = %f\n",
|
||||
colIndex, oldColWidth, colWidth, percent);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
}
|
||||
|
@ -1051,29 +1143,40 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
// proportional-width columns are equal (if any are anything other than 1)
|
||||
PRBool atLeastOneAutoWidthColumn = PR_FALSE; // true if at least one column is auto-width, requiring us to post-process
|
||||
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
nscoord * effectiveMaxColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMaxColumnWidths, 0, numCols*sizeof(PRInt32));
|
||||
nscoord * effectiveMinColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMinColumnWidths, 0, numCols*sizeof(PRInt32));
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
nscoord * effectiveMaxColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMaxColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
nscoord * effectiveMinColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMinColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
|
||||
nscoord minColWidth = 0;
|
||||
nscoord maxColWidth = 0;
|
||||
|
||||
// Get column information
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 numCells = cells->Count();
|
||||
|
||||
// Get the columns's style
|
||||
nsTableColFrame *colFrame = colData->GetColFrame();
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
const nsStylePosition* colPosition = (const nsStylePosition*) colSC->GetStyleData(eStyleStruct_Position);
|
||||
// Get the columns's style and margins
|
||||
PRInt32 rowIndex;
|
||||
PRInt32 firstRowIndex = -1;
|
||||
nsTableCellFrame * firstCellInColumn;
|
||||
for (rowIndex=0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
firstCellInColumn = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull!=firstCellInColumn)
|
||||
break;
|
||||
}
|
||||
nsMargin colMargin;
|
||||
nscoord colInset = 0;
|
||||
if (nsnull!=firstCellInColumn)
|
||||
{
|
||||
firstCellInColumn->GetMargin(colMargin);
|
||||
colInset = colMargin.left + colMargin.right;
|
||||
}
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
|
@ -1100,33 +1203,30 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
}
|
||||
}
|
||||
}
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
{ // this col has proportional width, so determine its width requirements
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull == data) {
|
||||
// For cells that span rows there's only cell layout data for the first row
|
||||
for (rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
PRInt32 colSpan = data->GetCellFrame()->GetColSpan();
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize");
|
||||
nsReflowMetrics * cellDesiredSize = data->GetDesiredSize();
|
||||
NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize");
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
|
||||
|
||||
nsMargin margin;
|
||||
nsresult result = data->GetMargin(margin);
|
||||
nscoord marginWidth = margin.left + margin.right;
|
||||
|
||||
PRInt32 cellMinWidth = cellMinSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellMinWidth = cellMinSize.width/colSpan;
|
||||
// first get the desired size info from reflow pass 1
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize.width/colSpan;
|
||||
// then get the desired size info factoring in the cell style attributes
|
||||
nscoord specifiedCellWidth=-1;
|
||||
nsIStyleContextPtr cellSC;
|
||||
data->GetCellFrame()->GetStyleContext(aPresContext, cellSC.AssignRef());
|
||||
const nsStylePosition* cellPosition = (const nsStylePosition*)
|
||||
cellSC->GetStyleData(eStyleStruct_Position);
|
||||
const nsStylePosition* cellPosition;
|
||||
cellFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)cellPosition);
|
||||
switch (cellPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedCellWidth = cellPosition->mWidth.GetCoordValue();
|
||||
|
@ -1164,7 +1264,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
|
||||
cellIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
rowIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
// remember the widest min cell width
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
|
@ -1179,7 +1279,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
effectiveMaxColumnWidths[colIndex] = cellDesiredWidth;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d,%d\n",
|
||||
cellIndex, minColWidth, maxColWidth,
|
||||
rowIndex, minColWidth, maxColWidth,
|
||||
colIndex, effectiveMaxColumnWidths[colIndex], effectiveMaxColumnWidths[colIndex]);
|
||||
if (1<colSpan)
|
||||
{
|
||||
|
@ -1236,7 +1336,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
printf (" 4 (0): col %d set to min width = %d because style set proportionalWidth=0\n",
|
||||
colIndex, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
else if (1==numCols)
|
||||
else if (1==mNumCols)
|
||||
{ // there is only one column, and we know that it's desired width doesn't fit
|
||||
// so the column should be as wide as the available space allows it to be
|
||||
if (gsDebug==PR_TRUE) printf (" 4 one-column: col %d set to width = %d\n", colIndex, aAvailWidth);
|
||||
|
@ -1300,7 +1400,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
}
|
||||
if (-1==percentage)
|
||||
{
|
||||
percentage = 100/numCols;
|
||||
percentage = 100/mNumCols;
|
||||
// base the % on the remaining available width
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
|
||||
if (gsDebug==PR_TRUE)
|
||||
|
@ -1417,16 +1517,52 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableFixedWidt
|
|||
else
|
||||
percent = ((float)1)/((float)numAutoColumns);
|
||||
nscoord colWidth = (nscoord)(availWidth*percent);
|
||||
if (colWidth<aMinColWidths[colIndex])
|
||||
{
|
||||
availWidth -= (aMinColWidths[colIndex]-colWidth);
|
||||
colWidth=aMinColWidths[colIndex];
|
||||
}
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" distribute width to auto columns: column %d was %d, now set to %d\n",
|
||||
colIndex, aMaxColWidths[colIndex], colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
EnsureCellMinWidths(aMinColWidths);
|
||||
}
|
||||
}
|
||||
|
||||
void BasicTableLayoutStrategy::EnsureCellMinWidths(nscoord *aMinColWidths)
|
||||
{
|
||||
PRBool atLeastOne = PR_TRUE;
|
||||
while (PR_TRUE==atLeastOne)
|
||||
{
|
||||
atLeastOne=PR_FALSE;
|
||||
PRInt32 colIndex;
|
||||
nscoord addedWidth = 0;
|
||||
// first, bump up cells that are below their min to their min width
|
||||
for (colIndex=0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nscoord colWidth = mTableFrame->GetColumnWidth(colIndex);
|
||||
if (colWidth<aMinColWidths[colIndex])
|
||||
{
|
||||
addedWidth += (aMinColWidths[colIndex]-colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex, aMinColWidths[colIndex]);
|
||||
atLeastOne=PR_TRUE;
|
||||
}
|
||||
}
|
||||
// second, remove the added space from cells that can afford to slim down
|
||||
//QQQ boy is this slow! there has to be a faster way that is still guaranteed to be accurate...
|
||||
while ((addedWidth>0))
|
||||
{ // while we still have some extra space, and last time we were able to take some off...
|
||||
for (colIndex=0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nscoord colWidth = mTableFrame->GetColumnWidth(colIndex);
|
||||
if (colWidth>aMinColWidths[colIndex])
|
||||
{
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth-1);
|
||||
addedWidth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0<addedWidth)
|
||||
{ // all our cells are at their min width, so no use doing anything else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "nsITableLayoutStrategy.h"
|
||||
#include "nsCoord.h"
|
||||
|
||||
class nsVoidArray;
|
||||
class nsTableFrame;
|
||||
struct nsStylePosition;
|
||||
|
||||
|
@ -164,18 +165,31 @@ public:
|
|||
nscoord aMinTableWidth,
|
||||
nscoord aMaxTableWidth);
|
||||
|
||||
/** post-process to AssignFixedColumnWidths
|
||||
*
|
||||
* @param aColSpanList a list of fixed-width columns that have colspans
|
||||
* @param aColWidths the effective column widths (ignoring col span cells)
|
||||
*
|
||||
* NOTE: does not yet properly handle overlapping col spans
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
virtual void DistributeFixedSpace(nsVoidArray *aColSpanList, nscoord *aColWidths);
|
||||
|
||||
/** starting with a partially balanced table, compute the amount
|
||||
* of space to pad each column by to completely balance the table.
|
||||
* set the column widths in mTableFrame based on these computations.
|
||||
*
|
||||
* @param aTableFixedWidth the specified width of the table. If there is none,
|
||||
* this param is 0
|
||||
* @param aComputedTableWidth the width of the table before this final step.
|
||||
* @param aAvailWidth the space still to be allocated within the table
|
||||
* @param aTableWidth the sum of all columns widths
|
||||
* @param aWidthOfFixedTableColumns the sum of the widths of fixed-width columns
|
||||
* @param aColWidths the effective column widths (ignoring col span cells)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
virtual void DistributeExcessSpace(nscoord aTableFixedWidth,
|
||||
nscoord aComputedTableWidth,
|
||||
virtual void DistributeExcessSpace(nscoord aAvailWidth,
|
||||
nscoord aTableWidth,
|
||||
nscoord aWidthOfFixedTableColumns,
|
||||
nscoord *aColWidths);
|
||||
|
||||
/** starting with a partially balanced table, compute the amount
|
||||
|
@ -193,6 +207,11 @@ public:
|
|||
nscoord *aMinColWidths,
|
||||
nscoord *aMaxColWidths);
|
||||
|
||||
/** force all cells to be at least their minimum width, removing any excess space
|
||||
* created in the process from fat cells that can afford to lose a little tonnage.
|
||||
*/
|
||||
virtual void EnsureCellMinWidths(nscoord *aMinColWidths);
|
||||
|
||||
/** return true if the style indicates that the width is a specific width
|
||||
* for the purposes of column width determination.
|
||||
* return false if the width changes based on content, parent size, etc.
|
||||
|
|
|
@ -24,13 +24,12 @@ LIBRARY_NAME = raptorhtmltable_s
|
|||
# Note the sophisticated alphabetical ordering :-|
|
||||
CPPSRCS = \
|
||||
BasicTableLayoutStrategy.cpp \
|
||||
nsCellLayoutData.cpp \
|
||||
nsCellMap.cpp \
|
||||
nsColLayoutData.cpp \
|
||||
nsTableCaption.cpp \
|
||||
nsTableCell.cpp \
|
||||
nsTableCellFrame.cpp \
|
||||
nsTableCol.cpp \
|
||||
nsTableColFrame.cpp \
|
||||
nsTableColGroup.cpp \
|
||||
nsTableColGroupFrame.cpp \
|
||||
nsTableContent.cpp \
|
||||
|
|
|
@ -23,18 +23,21 @@ REQUIRES=xpcom raptor js
|
|||
|
||||
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
|
||||
|
||||
CPPSRCS=nsCellLayoutData.cpp nsCellMap.cpp nsColLayoutData.cpp \
|
||||
nsTableCaption.cpp nsTableCell.cpp \
|
||||
nsTableCellFrame.cpp nsTableCol.cpp nsTableColGroup.cpp \
|
||||
nsTableColGroupFrame.cpp nsTableContent.cpp nsTableFrame.cpp \
|
||||
nsTableOuterFrame.cpp nsTablePart.cpp nsTableRow.cpp \
|
||||
nsTableRowFrame.cpp nsTableRowGroup.cpp nsTableRowGroupFrame.cpp \
|
||||
CPPSRCS= nsCellMap.cpp \
|
||||
nsTableCaption.cpp \
|
||||
nsTableCell.cpp nsTableCol.cpp \
|
||||
nsTableCellFrame.cpp nsTableColFrame.cpp \
|
||||
nsTableColGroup.cpp nsTableColGroupFrame.cpp \
|
||||
nsTableContent.cpp nsTableFrame.cpp \
|
||||
nsTableOuterFrame.cpp nsTablePart.cpp \
|
||||
nsTableRow.cpp nsTableRowFrame.cpp \
|
||||
nsTableRowGroup.cpp nsTableRowGroupFrame.cpp \
|
||||
BasicTableLayoutStrategy.cpp
|
||||
|
||||
CPP_OBJS=.\$(OBJDIR)\nsCellLayoutData.obj .\$(OBJDIR)\nsCellMap.obj \
|
||||
.\$(OBJDIR)\nsColLayoutData.obj .\$(OBJDIR)\nsTableCaption.obj \
|
||||
.\$(OBJDIR)\nsTableCell.obj \
|
||||
.\$(OBJDIR)\nsTableCellFrame.obj .\$(OBJDIR)\nsTableCol.obj \
|
||||
CPP_OBJS= .\$(OBJDIR)\nsCellMap.obj \
|
||||
.\$(OBJDIR)\nsTableCaption.obj \
|
||||
.\$(OBJDIR)\nsTableCell.obj .\$(OBJDIR)\nsTableCol.obj \
|
||||
.\$(OBJDIR)\nsTableCellFrame.obj .\$(OBJDIR)\nsTableColFrame.obj \
|
||||
.\$(OBJDIR)\nsTableColGroup.obj .\$(OBJDIR)\nsTableColGroupFrame.obj \
|
||||
.\$(OBJDIR)\nsTableContent.obj .\$(OBJDIR)\nsTableFrame.obj \
|
||||
.\$(OBJDIR)\nsTableOuterFrame.obj .\$(OBJDIR)\nsTablePart.obj \
|
||||
|
|
|
@ -1,573 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsTableCellFrame.h" // should be removed, make only generic nsIFrame calls
|
||||
#include "nsCRT.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIPtr.h"
|
||||
|
||||
#include <stdio.h>/* XXX */ // for printf
|
||||
|
||||
|
||||
nsCellLayoutData::nsCellLayoutData(nsTableCellFrame *aCellFrame,
|
||||
nsReflowMetrics * aDesiredSize, nsSize * aMaxElementSize)
|
||||
: mDesiredSize(nsnull)
|
||||
{
|
||||
// IMPORTANT: Always intialize instance variables to null
|
||||
mColLayoutData = nsnull;
|
||||
mCellFrame = nsnull;
|
||||
mMargin.top = mMargin.bottom = mMargin.left = mMargin.right = 0;
|
||||
|
||||
for (PRInt32 i = 0; i < 4; i++)
|
||||
mBorderFrame[i] = nsnull;
|
||||
|
||||
// IMPORTANT: call setters: this
|
||||
// guarentees addrefs/releases are called if needed - gpk
|
||||
SetCellFrame(aCellFrame);
|
||||
SetDesiredSize(aDesiredSize);
|
||||
SetMaxElementSize(aMaxElementSize);
|
||||
|
||||
mCalculated = NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// don't delete mCellFrame, I didn't allocate it
|
||||
nsCellLayoutData::~nsCellLayoutData()
|
||||
{
|
||||
mCellFrame = nsnull;
|
||||
mColLayoutData = nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the style context for this object (determined, by
|
||||
* asking for the frame
|
||||
*
|
||||
**/
|
||||
nsIStyleContext* nsCellLayoutData::GetStyleContext()
|
||||
{
|
||||
if (mCellFrame != nsnull) {
|
||||
nsIStyleContext* styleContext;
|
||||
mCellFrame->GetStyleContext(nsnull, styleContext);
|
||||
return styleContext;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of nsCellLayoutData and a index, get the style context for
|
||||
* that element in the list
|
||||
*
|
||||
**/
|
||||
nsIFrame* nsCellLayoutData::GetFrameAt(nsVoidArray* aList, PRInt32 aIndex)
|
||||
{
|
||||
nsIFrame* result = nsnull;
|
||||
|
||||
if (aList != nsnull)
|
||||
{
|
||||
nsCellLayoutData* data = (nsCellLayoutData*)aList->ElementAt(aIndex);
|
||||
if (data != nsnull)
|
||||
result = data->GetCellFrame();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a frame and an edge, find the margin
|
||||
*
|
||||
**/
|
||||
nscoord nsCellLayoutData::GetMargin(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin margin;
|
||||
spacing->CalcMarginFor(aFrame, margin);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = margin.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = margin.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = margin.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = margin.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a style context and an edge, find the border width
|
||||
*
|
||||
**/
|
||||
nscoord nsCellLayoutData::GetBorderWidth(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin border;
|
||||
spacing->CalcBorderFor(aFrame, border);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = border.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = border.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = border.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = border.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a style context and an edge, find the padding
|
||||
*
|
||||
**/
|
||||
nscoord nsCellLayoutData::GetPadding(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin padding;
|
||||
spacing->CalcPaddingFor(aFrame, padding);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = padding.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = padding.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = padding.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = padding.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Given an Edge, find the opposing edge (top<-->bottom, left<-->right)
|
||||
*
|
||||
**/
|
||||
PRUint8 nsCellLayoutData::GetOpposingEdge(PRUint8 aEdge)
|
||||
{
|
||||
PRUint8 result;
|
||||
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_LEFT:
|
||||
result = NS_SIDE_RIGHT;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = NS_SIDE_LEFT;
|
||||
break;
|
||||
|
||||
case NS_SIDE_TOP:
|
||||
result = NS_SIDE_BOTTOM;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = NS_SIDE_TOP;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = NS_SIDE_TOP;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Determine border style for two cells.
|
||||
*
|
||||
1.If the adjacent elements are of the same type, the wider of the two borders is used.
|
||||
"Wider" takes into account the border-style of 'none', so a "1px solid" border
|
||||
will take precedence over a "20px none" border.
|
||||
|
||||
2.If there are two or more with the same width, but different style,
|
||||
then the one with a style near the start of the following list will be drawn:
|
||||
|
||||
'blank', 'double', 'solid', 'dashed', 'dotted', 'ridge', 'groove', 'none'
|
||||
|
||||
3.If the borders are of the same width, the border on the element occurring first is used.
|
||||
|
||||
First is defined as aStyle for this method.
|
||||
|
||||
NOTE: This assumes left-to-right, top-to-bottom bias. -- gpk
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
nsIFrame* nsCellLayoutData::CompareCellBorders(nsIFrame* aFrame1,
|
||||
PRUint8 aEdge1,
|
||||
nsIFrame* aFrame2,
|
||||
PRUint8 aEdge2)
|
||||
{
|
||||
PRInt32 width1 = GetBorderWidth(aFrame1,aEdge1);
|
||||
PRInt32 width2 = GetBorderWidth(aFrame2,aEdge2);
|
||||
|
||||
nsIFrame* result = nsnull;
|
||||
|
||||
if (width1 > width2)
|
||||
result = aFrame1;
|
||||
else if (width1 < width2)
|
||||
result = aFrame2;
|
||||
else // width1 == width2
|
||||
{
|
||||
const nsStyleSpacing* border1;
|
||||
const nsStyleSpacing* border2;
|
||||
aFrame1->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)border1);
|
||||
aFrame2->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)border2);
|
||||
if (border1->mBorderStyle[aEdge1] >= border2->mBorderStyle[aEdge2])
|
||||
result = aFrame1;
|
||||
else
|
||||
result = aFrame2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a List of cell layout data, compare the edges to see which has the
|
||||
* border with the highest precidence.
|
||||
*
|
||||
**/
|
||||
|
||||
nsIFrame* nsCellLayoutData::FindHighestPrecedentBorder(nsVoidArray* aList,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* result = nsnull;
|
||||
PRInt32 index = 0;
|
||||
PRInt32 count = 0;
|
||||
|
||||
|
||||
NS_ASSERTION(aList,"a List must be valid");
|
||||
count = aList->Count();
|
||||
if (count)
|
||||
{
|
||||
nsIFrame* frame1;
|
||||
nsIFrame* frame2;
|
||||
|
||||
frame1 = GetFrameAt(aList,index++);
|
||||
while (index < count)
|
||||
{
|
||||
frame2 = GetFrameAt(aList,index++);
|
||||
if (GetMargin(frame2,aEdge) == 0) {
|
||||
frame1 = CompareCellBorders(frame1, aEdge, frame2, aEdge);
|
||||
}
|
||||
}
|
||||
if ((nsnull != frame1) && (GetMargin(frame1, aEdge) != 0))
|
||||
result = frame1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nsIFrame* nsCellLayoutData::FindInnerBorder(nsVoidArray* aList, PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* result = nsnull;
|
||||
PRUint8 opposite = GetOpposingEdge(aEdge);
|
||||
|
||||
if (GetMargin(mCellFrame, aEdge) == 0)
|
||||
{
|
||||
nsIFrame* altFrame = FindHighestPrecedentBorder(aList,opposite);
|
||||
if (nsnull != altFrame)
|
||||
result = CompareCellBorders(mCellFrame, aEdge, altFrame, opposite);
|
||||
else
|
||||
result = mCellFrame;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* FindRelevantBorder recursively searches up the frame hierarchy for the border
|
||||
* style that is applicable to the cell. If at any point the frame has a margin
|
||||
* or the parent frame has padding, then the outer frame for this object takes
|
||||
* presendence over the inner frame.
|
||||
|
||||
1.Borders on 'table' elements take precedence over borders on any other table elements.
|
||||
2.Borders on 'row-groups' take precedence over borders on 'rows',
|
||||
and likewise borders on 'column-groups' take precedence over borders on 'columns'.
|
||||
3.Borders on any other type of table element take precedence over 'table-cell' elements.
|
||||
|
||||
*
|
||||
* NOTE: This method assumes that the table cell potentially shares a border.
|
||||
* It should not be called for internal cells
|
||||
*
|
||||
* NOTE: COLUMNS AND COLGROUPS NEED TO BE FIGURED INTO THE ALGORITHM -- GPK!!!
|
||||
*
|
||||
*
|
||||
*/
|
||||
nsIFrame* nsCellLayoutData::FindOuterBorder( nsTableFrame* aTableFrame,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* frame = mCellFrame; // By default, return our frame
|
||||
PRBool done = PR_FALSE;
|
||||
|
||||
|
||||
// The table frame is the outer most frame we test against
|
||||
while (done == PR_FALSE)
|
||||
{
|
||||
done = PR_TRUE; // where done unless the frame's margin is zero
|
||||
// and the parent's padding is zero
|
||||
|
||||
nscoord margin = GetMargin(frame,aEdge);
|
||||
|
||||
// if the margin for this style is zero then check to see if the paddding
|
||||
// for the parent frame is also zero
|
||||
if (margin == 0)
|
||||
{
|
||||
nsIFrame* parentFrame;
|
||||
|
||||
frame->GetGeometricParent(parentFrame);
|
||||
|
||||
// if the padding for the parent style is zero just
|
||||
// recursively call this routine
|
||||
PRInt32 padding = GetPadding(parentFrame,aEdge);
|
||||
if ((nsnull != parentFrame) && (padding == 0))
|
||||
{
|
||||
frame = parentFrame;
|
||||
// If this frame represents the table frame then
|
||||
// the table style is used
|
||||
done = PRBool(frame != (nsIFrame*)aTableFrame);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Border Resolution
|
||||
1.Borders on 'table' elements take precedence over borders on any other table elements.
|
||||
2.Borders on 'row-groups' take precedence over borders on 'rows', and likewise borders on 'column-groups' take
|
||||
precedence over borders on 'columns'.
|
||||
3.Borders on any other type of table element take precedence over 'table-cell' elements.
|
||||
4.If the adjacent elements are of the same type, the wider of the two borders is used. "Wider" takes into account
|
||||
the border-style of 'none', so a "1px solid" border will take precedence over a "20px none" border.
|
||||
5.If the borders are of the same width, the border on the element occurring first is used.
|
||||
|
||||
|
||||
How to compare
|
||||
1.Those of the one or two cells that have an edge here.
|
||||
Less than two can occur at the edge of the table, but also
|
||||
at the edges of "holes" (unoccupied grid cells).
|
||||
2.Those of the columns that have an edge here.
|
||||
3.Those of the column groups that have an edge here.
|
||||
4.Those of the rows that have an edge here.
|
||||
5.Those of the row groups that have an edge here.
|
||||
6.Those of the table, if this is the edge of the table.
|
||||
|
||||
*
|
||||
* @param aIsFirst -- TRUE if this is the first cell in the row
|
||||
* @param aIsLast -- TRUE if this is the last cell in the row
|
||||
* @param aIsTop -- TRUE if this is the top cell in the column
|
||||
* @param aIsBottom -- TRUE if this is the last cell in the column
|
||||
*/
|
||||
|
||||
nsIFrame* nsCellLayoutData::FindBorderFrame(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aList,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* frame = nsnull;
|
||||
|
||||
if (aList && aList->Count() == 0)
|
||||
frame = FindOuterBorder(aTableFrame, aEdge);
|
||||
else
|
||||
frame = FindInnerBorder(aList, aEdge);
|
||||
|
||||
if (! frame)
|
||||
frame = mCellFrame;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a List of cell layout data, compare the edges to see which has the
|
||||
* border with the highest precidence.
|
||||
*
|
||||
**/
|
||||
nscoord nsCellLayoutData::FindLargestMargin(nsVoidArray* aList,PRUint8 aEdge)
|
||||
{
|
||||
nscoord result = 0;
|
||||
PRInt32 index = 0;
|
||||
PRInt32 count = 0;
|
||||
|
||||
|
||||
NS_ASSERTION(aList,"a List must be valid");
|
||||
count = aList->Count();
|
||||
if (count)
|
||||
{
|
||||
nsIFrame* frame;
|
||||
|
||||
nscoord value = 0;
|
||||
while (index < count)
|
||||
{
|
||||
frame = GetFrameAt(aList,index++);
|
||||
value = GetMargin(frame, aEdge);
|
||||
if (value > result)
|
||||
result = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nsCellLayoutData::CalculateMargins(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
{
|
||||
// By default the margin is just the margin found in the
|
||||
// table cells style
|
||||
const nsStyleSpacing* spacing;
|
||||
mCellFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
spacing->CalcMarginFor(mCellFrame, mMargin);
|
||||
|
||||
// Left and Top Margins are collapsed with their neightbors
|
||||
// Right and Bottom Margins are simple left as they are
|
||||
nscoord value;
|
||||
|
||||
// The left and top sides margins are the difference between
|
||||
// their inherint value and the value of the margin of the
|
||||
// object to the left or right of them.
|
||||
|
||||
value = FindLargestMargin(aBoundaryCells[NS_SIDE_LEFT],NS_SIDE_RIGHT);
|
||||
if (value > mMargin.left)
|
||||
mMargin.left = 0;
|
||||
else
|
||||
mMargin.left -= value;
|
||||
|
||||
value = FindLargestMargin(aBoundaryCells[NS_SIDE_TOP],NS_SIDE_BOTTOM);
|
||||
if (value > mMargin.top)
|
||||
mMargin.top = 0;
|
||||
else
|
||||
mMargin.top -= value;
|
||||
}
|
||||
|
||||
|
||||
void nsCellLayoutData::RecalcLayoutData(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
|
||||
{
|
||||
CalculateBorders(aTableFrame, aBoundaryCells);
|
||||
CalculateMargins(aTableFrame, aBoundaryCells);
|
||||
mCalculated = NS_OK;
|
||||
}
|
||||
|
||||
void nsCellLayoutData::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
PRInt32 indent;
|
||||
|
||||
nsIContent* cell;
|
||||
|
||||
mCellFrame->GetContent(cell);
|
||||
if (cell != nsnull)
|
||||
{
|
||||
/*
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"RowSpan = %d ColSpan = %d \n",cell->GetRowSpan(),cell->GetColSpan());
|
||||
*/
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Margin -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.top),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.left),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.right));
|
||||
|
||||
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
|
||||
nscoord top,left,bottom,right;
|
||||
|
||||
top = (mBorderFrame[NS_SIDE_TOP] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_TOP], NS_SIDE_TOP) : 0);
|
||||
left = (mBorderFrame[NS_SIDE_LEFT] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_LEFT], NS_SIDE_LEFT) : 0);
|
||||
bottom = (mBorderFrame[NS_SIDE_BOTTOM] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_BOTTOM], NS_SIDE_BOTTOM) : 0);
|
||||
right = (mBorderFrame[NS_SIDE_RIGHT] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_RIGHT], NS_SIDE_RIGHT) : 0);
|
||||
|
||||
|
||||
fprintf(out,"Border -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(top),
|
||||
NS_TWIPS_TO_POINTS_INT(left),
|
||||
NS_TWIPS_TO_POINTS_INT(bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(right));
|
||||
|
||||
|
||||
|
||||
cell->List(out,aIndent);
|
||||
NS_RELEASE(cell);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef nsCellLayoutData_h__
|
||||
#define nsCellLayoutData_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
class nsTableCellFrame;
|
||||
class nsColLayoutData;
|
||||
class nsTableFrame;
|
||||
class nsIStyleContext;
|
||||
class nsVoidArray;
|
||||
struct nsStyleSpacing;
|
||||
|
||||
|
||||
/** Simple data class that represents in-process reflow information about a cell.
|
||||
* Each cell is represented by a nsTableCellFrame together with the results
|
||||
* of the "first pass" layout results (where "first pass" means the cell was told
|
||||
* to lay itself out with unrestricted height and width.)
|
||||
* There is one nsCellLayoutData object per nsTableFrame for each cell.
|
||||
*
|
||||
* TODO: All methods will be inline.
|
||||
*/
|
||||
class nsCellLayoutData
|
||||
{
|
||||
public:
|
||||
|
||||
/** public constructor. Does not allocate any of its own data.
|
||||
* @param aCellFrame the frame representing the cell
|
||||
* @param aDesiredSize the max size of the cell if given infinite height and width
|
||||
* @param aMaxElementSize the min size of the largest indivisible element within the cell
|
||||
*/
|
||||
nsCellLayoutData(nsTableCellFrame *aCellFrame,
|
||||
nsReflowMetrics * aDesiredSize, nsSize * aMaxElementSize);
|
||||
|
||||
/** destructor, not responsible for destroying any of the stored data */
|
||||
virtual ~nsCellLayoutData();
|
||||
|
||||
/** return the frame mapping the cell */
|
||||
nsTableCellFrame * GetCellFrame();
|
||||
|
||||
/** set the frame mapping the cell */
|
||||
void SetCellFrame(nsTableCellFrame * aCellFrame);
|
||||
|
||||
/** return the max size of the cell if given infinite height and width */
|
||||
nsReflowMetrics * GetDesiredSize();
|
||||
|
||||
/** set the max size of the cell if given infinite height and width.
|
||||
* called after pass 1 of table reflow is complete.
|
||||
*/
|
||||
void SetDesiredSize(nsReflowMetrics * aDesiredSize);
|
||||
|
||||
/** get the min size of the largest indivisible element within the cell */
|
||||
nsSize * GetMaxElementSize();
|
||||
|
||||
/** set the min size of the largest indivisible element within the cell.
|
||||
* called after pass 1 of table reflow is complete.
|
||||
*/
|
||||
void SetMaxElementSize(nsSize * aMaxElementSize);
|
||||
|
||||
/** debug method outputs data about this cell to FILE *out */
|
||||
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
|
||||
/** returns the style context associated with this cell */
|
||||
nsIStyleContext* GetStyleContext();
|
||||
|
||||
private:
|
||||
|
||||
// All these methods are support methods for RecalcLayoutData
|
||||
nsIFrame* GetFrameAt(nsVoidArray* aList, PRInt32 aIndex);
|
||||
|
||||
nscoord GetMargin(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
nscoord GetBorderWidth(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
nscoord GetPadding(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
PRUint8 GetOpposingEdge(PRUint8 aEdge);
|
||||
|
||||
nsIFrame* CompareCellBorders(nsIFrame* aFrame1,
|
||||
PRUint8 aEdge1,
|
||||
nsIFrame* aFrame2,
|
||||
PRUint8 aEdge2);
|
||||
|
||||
|
||||
nsIFrame* FindHighestPrecedentBorder(nsVoidArray* aList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
|
||||
|
||||
nsIFrame* FindInnerBorder( nsVoidArray* aList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
nsIFrame* FindOuterBorder( nsTableFrame* aTableFrame,
|
||||
PRUint8 aEdge);
|
||||
|
||||
nsIFrame* FindBorderFrame(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aCellList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
void CalculateBorders(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
nscoord FindLargestMargin(nsVoidArray* aList,PRUint8 aEdge);
|
||||
|
||||
|
||||
void CalculateMargins(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
public:
|
||||
void RecalcLayoutData(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
|
||||
NS_IMETHOD GetMargin(nsMargin& aMargin);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
#if 0 // these come on line when we do character-based cell content alignment
|
||||
/** the kinds of width information stored */
|
||||
enum {WIDTH_NORMAL=0, WIDTH_LEFT_ALIGNED=1, WIDTH_RIGHT_ALIGNED=2};
|
||||
|
||||
/** the width information for a cell */
|
||||
PRInt32 mWidth[3];
|
||||
#endif
|
||||
|
||||
nsColLayoutData *mColLayoutData;
|
||||
nsTableCellFrame *mCellFrame;
|
||||
nsReflowMetrics mDesiredSize;
|
||||
nsSize mMaxElementSize;
|
||||
|
||||
nsresult mCalculated;
|
||||
nsMargin mMargin;
|
||||
nsIFrame* mBorderFrame[4]; // the frame whose border is used
|
||||
};
|
||||
|
||||
inline nsTableCellFrame * nsCellLayoutData::GetCellFrame()
|
||||
{ return mCellFrame; }
|
||||
|
||||
inline void nsCellLayoutData::SetCellFrame(nsTableCellFrame * aCellFrame)
|
||||
{ mCellFrame = aCellFrame; }
|
||||
|
||||
inline nsReflowMetrics * nsCellLayoutData::GetDesiredSize()
|
||||
{ return &mDesiredSize; }
|
||||
|
||||
inline void nsCellLayoutData::SetDesiredSize(nsReflowMetrics * aDesiredSize)
|
||||
{
|
||||
if (nsnull!=aDesiredSize)
|
||||
mDesiredSize = *aDesiredSize;
|
||||
}
|
||||
|
||||
inline nsSize * nsCellLayoutData::GetMaxElementSize()
|
||||
{ return &mMaxElementSize; }
|
||||
|
||||
inline void nsCellLayoutData::SetMaxElementSize(nsSize * aMaxElementSize)
|
||||
{
|
||||
if (nsnull!=aMaxElementSize)
|
||||
mMaxElementSize = *aMaxElementSize;
|
||||
}
|
||||
|
||||
inline void nsCellLayoutData::CalculateBorders(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
{
|
||||
|
||||
for (PRInt32 edge = 0; edge < 4; edge++)
|
||||
mBorderFrame[edge] = FindBorderFrame(aTableFrame, aBoundaryCells[edge], edge);
|
||||
}
|
||||
|
||||
inline NS_METHOD nsCellLayoutData::GetMargin(nsMargin& aMargin)
|
||||
{
|
||||
if (mCalculated == NS_OK)
|
||||
{
|
||||
aMargin = mMargin;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,7 +15,9 @@
|
|||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCellMap.h"
|
||||
#include "nsTableFrame.h"
|
||||
|
||||
|
@ -25,17 +27,20 @@ static PRBool gsDebug1 = PR_FALSE;
|
|||
static const PRBool gsDebug1 = PR_FALSE;
|
||||
#endif
|
||||
|
||||
static PRInt32 gBytesPerPointer = sizeof(PRInt32);
|
||||
static const PRInt32 gBytesPerPointer = sizeof(PRInt32);
|
||||
|
||||
nsCellMap::nsCellMap(int aRows, int aColumns)
|
||||
: mRowCount(aRows),
|
||||
mColCount(aColumns)
|
||||
{
|
||||
mCells = nsnull;
|
||||
mColFrames = nsnull;
|
||||
Reset(aRows, aColumns);
|
||||
}
|
||||
|
||||
nsCellMap::~nsCellMap()
|
||||
{
|
||||
if (nsnull!=mCells)
|
||||
{
|
||||
for (int i=0;i<mRowCount;i++)
|
||||
{
|
||||
|
@ -51,12 +56,21 @@ nsCellMap::~nsCellMap()
|
|||
}
|
||||
}
|
||||
delete [] mCells;
|
||||
}
|
||||
if (nsnull!= mColFrames)
|
||||
delete mColFrames;
|
||||
mCells = nsnull;
|
||||
mColFrames = nsnull;
|
||||
};
|
||||
|
||||
|
||||
void nsCellMap::Reset(int aRows, int aColumns)
|
||||
{
|
||||
if (nsnull==mColFrames)
|
||||
{
|
||||
mColFrames = new nsVoidArray();
|
||||
}
|
||||
|
||||
// needs to be more efficient, to reuse space if possible
|
||||
if (nsnull!=mCells)
|
||||
{
|
||||
|
@ -67,6 +81,7 @@ void nsCellMap::Reset(int aRows, int aColumns)
|
|||
mColCount = aColumns;
|
||||
mCells = new PRInt32 [mRowCount*mColCount*gBytesPerPointer];
|
||||
nsCRT::memset (mCells, 0, (mRowCount*mColCount)*gBytesPerPointer);
|
||||
|
||||
}
|
||||
|
||||
void nsCellMap::GrowTo(int aColCount)
|
||||
|
@ -110,4 +125,9 @@ void nsCellMap::SetCellAt(CellData *aCell, int aRow, int aColumn)
|
|||
mCells[index] = (PRInt32)aCell;
|
||||
}
|
||||
|
||||
nsTableColFrame* nsCellMap::GetColumnFrame(PRInt32 aColIndex)
|
||||
{
|
||||
return (nsTableColFrame *)(mColFrames->ElementAt(aColIndex));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
#define nsCellMap_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "CellData.h"
|
||||
|
||||
class CellData;
|
||||
class nsVoidArray;
|
||||
class nsTableColFrame;
|
||||
class nsTableCellFrame;
|
||||
|
||||
/** nsCellMap is a support class for nsTablePart.
|
||||
* It maintains an Rows x Columns grid onto which the cells of the table are mapped.
|
||||
|
@ -40,55 +43,94 @@ protected:
|
|||
/** storage for CellData pointers */
|
||||
PRInt32 *mCells; ///XXX CellData *?
|
||||
|
||||
/** a cache of the column frames, by col index */
|
||||
nsVoidArray * mColFrames;
|
||||
|
||||
/** the number of rows */
|
||||
int mRowCount; // in java, we could just do fCellMap.length;
|
||||
PRInt32 mRowCount; // in java, we could just do fCellMap.length;
|
||||
|
||||
/** the number of columns (the max of all row lengths) */
|
||||
int mColCount; // in java, we could just do fCellMap[i].length
|
||||
PRInt32 mColCount;
|
||||
|
||||
public:
|
||||
nsCellMap(int aRows, int aColumns);
|
||||
nsCellMap(PRInt32 aRows, PRInt32 aColumns);
|
||||
|
||||
// NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
|
||||
~nsCellMap();
|
||||
|
||||
/** initialize the CellMap to (aRows x aColumns) */
|
||||
void Reset(int aRows, int aColumns);
|
||||
void Reset(PRInt32 aRows, PRInt32 aColumns);
|
||||
|
||||
/** return the CellData for the cell at (aRow,aColumn) */
|
||||
CellData * GetCellAt(int aRow, int aColumn) const;
|
||||
/** return the CellData for the cell at (aRowIndex,aColIndex) */
|
||||
CellData * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) const;
|
||||
|
||||
/** return the nsTableCellFrame for the cell at (aRowIndex, aColIndex) */
|
||||
nsTableCellFrame * GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex) const;
|
||||
|
||||
/** assign aCellData to the cell at (aRow,aColumn) */
|
||||
void SetCellAt(CellData *aCellData, int aRow, int aColumn);
|
||||
void SetCellAt(CellData *aCellData, PRInt32 aRow, PRInt32 aColumn);
|
||||
|
||||
/** expand the CellMap to have aColCount columns. The number of rows remains the same */
|
||||
void GrowTo(int aColCount);
|
||||
void GrowTo(PRInt32 aColCount);
|
||||
|
||||
/** return the total number of columns in the table represented by this CellMap */
|
||||
int GetColCount() const;
|
||||
PRInt32 GetColCount() const;
|
||||
|
||||
/** return the total number of rows in the table represented by this CellMap */
|
||||
int GetRowCount() const;
|
||||
PRInt32 GetRowCount() const;
|
||||
|
||||
/** for debugging, print out this CellMap */
|
||||
nsTableColFrame * GetColumnFrame(PRInt32 aColIndex);
|
||||
|
||||
void AppendColumnFrame(nsTableColFrame *aColFrame);
|
||||
|
||||
PRBool RowImpactedBySpanningCell(PRInt32 aRowIndex);
|
||||
|
||||
PRBool ColumnImpactedBySpanningCell(PRInt32 aColIndex);
|
||||
|
||||
/** for debugging */
|
||||
void DumpCellMap() const;
|
||||
|
||||
};
|
||||
|
||||
inline CellData * nsCellMap::GetCellAt(int aRow, int aColumn) const
|
||||
/* ----- inline methods ----- */
|
||||
|
||||
inline CellData * nsCellMap::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) const
|
||||
{
|
||||
int index = (aRow*mColCount)+aColumn;
|
||||
NS_PRECONDITION(0<=aRowIndex && aRowIndex < mRowCount, "bad aRowIndex arg");
|
||||
NS_PRECONDITION(0<=aColIndex && aColIndex < mColCount, "bad aColIndex arg");
|
||||
|
||||
PRInt32 index = (aRowIndex*mColCount)+aColIndex;
|
||||
return (CellData *)mCells[index];
|
||||
}
|
||||
|
||||
inline int nsCellMap::GetColCount() const
|
||||
inline nsTableCellFrame * nsCellMap::GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex) const
|
||||
{
|
||||
NS_PRECONDITION(0<=aRowIndex && aRowIndex < mRowCount, "bad aRowIndex arg");
|
||||
NS_PRECONDITION(0<=aColIndex && aColIndex < mColCount, "bad aColIndex arg");
|
||||
|
||||
nsTableCellFrame *result = nsnull;
|
||||
CellData * cellData = GetCellAt(aRowIndex, aColIndex);
|
||||
if (nsnull!=cellData)
|
||||
result = cellData->mCell;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline PRInt32 nsCellMap::GetColCount() const
|
||||
{
|
||||
return mColCount;
|
||||
}
|
||||
|
||||
inline int nsCellMap::GetRowCount() const
|
||||
inline PRInt32 nsCellMap::GetRowCount() const
|
||||
{
|
||||
return mRowCount;
|
||||
}
|
||||
|
||||
inline void nsCellMap::AppendColumnFrame(nsTableColFrame *aColFrame)
|
||||
{
|
||||
mColFrames->AppendElement(aColFrame);
|
||||
// sanity check
|
||||
NS_ASSERTION(mColFrames->Count()<=mColCount, "too many columns appended to CellMap");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsColLayoutData.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
|
||||
nsColLayoutData::nsColLayoutData(nsTableColFrame* aColFrame, PRInt32 aNumRows)
|
||||
{
|
||||
mColFrame = aColFrame;
|
||||
mCells = new nsVoidArray(aNumRows);
|
||||
}
|
||||
|
||||
nsColLayoutData::~nsColLayoutData()
|
||||
{
|
||||
if (nsnull!=mCells)
|
||||
{
|
||||
PRInt32 count = mCells->Count();
|
||||
for (PRInt32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCellLayoutData *data = (nsCellLayoutData *)(mCells->ElementAt(i));
|
||||
delete data;
|
||||
}
|
||||
delete mCells;
|
||||
}
|
||||
mCells = 0;
|
||||
}
|
||||
|
||||
PRInt32 nsColLayoutData::IndexOf(nsIContent* aCell) const
|
||||
{
|
||||
PRInt32 count = this->Count();
|
||||
PRInt32 result = -1;
|
||||
if (aCell != nsnull)
|
||||
{
|
||||
for (PRInt32 index = 0; index < count; index++)
|
||||
{
|
||||
nsCellLayoutData* cellData = ElementAt(index);
|
||||
if (cellData != nsnull)
|
||||
{
|
||||
nsTableCellFrame* frame = cellData->GetCellFrame();
|
||||
if (frame != nsnull)
|
||||
{
|
||||
nsIContent* cell;
|
||||
|
||||
frame->GetContent(cell);
|
||||
if (cell == aCell)
|
||||
{
|
||||
result = index;
|
||||
NS_RELEASE(cell);
|
||||
break;
|
||||
}
|
||||
NS_IF_RELEASE(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
nsCellLayoutData* nsColLayoutData::GetNext(nsCellLayoutData* aCellLayoutData) const
|
||||
{
|
||||
PRInt32 index = IndexOf(aCellLayoutData);
|
||||
if (index != -1)
|
||||
return ElementAt(index+1);
|
||||
return (nsCellLayoutData*)nsnull;
|
||||
}
|
||||
|
||||
nsCellLayoutData* nsColLayoutData::GetPrevious(nsCellLayoutData* aCellLayoutData) const
|
||||
{
|
||||
PRInt32 index = IndexOf(aCellLayoutData);
|
||||
if (index != -1)
|
||||
return ElementAt(index-1);
|
||||
return (nsCellLayoutData*)nsnull;
|
||||
}
|
||||
|
||||
|
||||
void nsColLayoutData::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
if (nsnull!=mCells)
|
||||
{
|
||||
PRInt32 count = mCells->Count();
|
||||
for (PRInt32 i = 0; i < count; i++)
|
||||
{
|
||||
for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Cell Data [%d] \n",i);
|
||||
|
||||
nsCellLayoutData *data = (nsCellLayoutData *)(mCells->ElementAt(i));
|
||||
data->List(out,aIndent+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef nsColLayoutData_h__
|
||||
#define nsColLayoutData_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsCellLayoutData;
|
||||
class nsTableFrame;
|
||||
class nsTableColFrame;
|
||||
class nsIContent;
|
||||
|
||||
|
||||
/** Simple data class that represents in-process reflow information about a column.
|
||||
*/
|
||||
class nsColLayoutData
|
||||
{
|
||||
public:
|
||||
nsColLayoutData(nsTableColFrame* aColFrame, PRInt32 aNumRows);
|
||||
|
||||
// NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
|
||||
~nsColLayoutData();
|
||||
|
||||
nsTableColFrame *GetColFrame();
|
||||
|
||||
nsVoidArray * GetCells();
|
||||
|
||||
PRInt32 Count() const;
|
||||
|
||||
nsCellLayoutData* ElementAt(PRInt32 aIndex) const;
|
||||
|
||||
PRInt32 IndexOf(nsCellLayoutData* aCellLayoutData) const;
|
||||
PRInt32 IndexOf(nsIContent* aTableCell) const;
|
||||
|
||||
nsCellLayoutData* GetNext(nsCellLayoutData* aCellLayoutData) const;
|
||||
|
||||
nsCellLayoutData* GetPrevious(nsCellLayoutData* aCellLayoutData) const;
|
||||
|
||||
|
||||
|
||||
PRBool AppendElement(nsCellLayoutData* aCellLayoutData);
|
||||
|
||||
PRBool ReplaceElementAt(nsCellLayoutData* aCellLayoutData, PRInt32 aIndex);
|
||||
|
||||
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
nsTableColFrame *mColFrame;
|
||||
nsVoidArray *mCells;
|
||||
|
||||
};
|
||||
|
||||
/* ---------- inlines ---------- */
|
||||
|
||||
inline nsTableColFrame * nsColLayoutData::GetColFrame()
|
||||
{ return mColFrame;}
|
||||
|
||||
inline nsCellLayoutData* nsColLayoutData::ElementAt(PRInt32 aIndex) const
|
||||
{ return (nsCellLayoutData*)mCells->ElementAt(aIndex);}
|
||||
|
||||
inline PRBool nsColLayoutData::AppendElement(nsCellLayoutData* aCellLayoutData)
|
||||
{ return mCells->AppendElement((void*)aCellLayoutData);}
|
||||
|
||||
inline PRBool nsColLayoutData::ReplaceElementAt(nsCellLayoutData* aCellLayoutData, PRInt32 aIndex)
|
||||
{ return mCells->ReplaceElementAt((void*)aCellLayoutData,aIndex);}
|
||||
|
||||
inline nsVoidArray * nsColLayoutData::GetCells()
|
||||
{ return mCells; }
|
||||
|
||||
inline PRInt32 nsColLayoutData::Count() const
|
||||
{ return mCells->Count(); }
|
||||
|
||||
|
||||
inline PRInt32 nsColLayoutData::IndexOf(nsCellLayoutData* aCellLayoutData) const
|
||||
{ return mCells->IndexOf((void*)aCellLayoutData);}
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -16,7 +16,6 @@
|
|||
* Reserved.
|
||||
*/
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsBodyFrame.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
#include "nsIStyleContext.h"
|
||||
|
@ -53,21 +52,24 @@ static const PRBool gsDebugNT = PR_FALSE;
|
|||
*/
|
||||
nsTableCellFrame::nsTableCellFrame(nsIContent* aContent,
|
||||
nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aParentFrame),
|
||||
mCellLayoutData(nsnull)
|
||||
: nsContainerFrame(aContent, aParentFrame)
|
||||
{
|
||||
mRowSpan=1;
|
||||
mColSpan=1;
|
||||
mColIndex=0;
|
||||
mPriorAvailWidth=0;
|
||||
mPriorDesiredSize.width=0;
|
||||
mPriorDesiredSize.height=0;
|
||||
mDesiredSize.width=0;
|
||||
mDesiredSize.height=0;
|
||||
mMaxElementSize.width=0;
|
||||
mMaxElementSize.height=0;
|
||||
mPass1DesiredSize.width=0;
|
||||
mPass1DesiredSize.height=0;
|
||||
mPass1MaxElementSize.width=0;
|
||||
mPass1MaxElementSize.height=0;
|
||||
}
|
||||
|
||||
nsTableCellFrame::~nsTableCellFrame()
|
||||
{
|
||||
if (nsnull!=mCellLayoutData)
|
||||
delete mCellLayoutData;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
|
||||
|
@ -291,7 +293,6 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
|||
mFirstChild->WillReflow(*aPresContext);
|
||||
mFirstChild->MoveTo(leftInset, topInset);
|
||||
aStatus = ReflowChild(mFirstChild, aPresContext, kidSize, kidReflowState);
|
||||
SetPriorDesiredSize(kidSize);
|
||||
|
||||
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
||||
{
|
||||
|
@ -325,10 +326,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
|||
// first, compute the height
|
||||
// the height can be set w/o being restricted by aMaxSize.height
|
||||
nscoord cellHeight = kidSize.height;
|
||||
if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.height)
|
||||
{
|
||||
cellHeight += topInset + bottomInset;
|
||||
}
|
||||
if (PR_TRUE==gsDebugNT)
|
||||
printf(" %p cellFrame height set to %d from kidSize=%d and insets %d,%d\n",
|
||||
this, cellHeight, kidSize.height, topInset, bottomInset);
|
||||
|
@ -369,6 +367,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
|||
aDesiredSize.maxElementSize->height += topInset + bottomInset;
|
||||
aDesiredSize.maxElementSize->width += leftInset + rightInset;
|
||||
}
|
||||
SetDesiredSize(aDesiredSize);
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
SetMaxElementSize(*(aDesiredSize.maxElementSize));
|
||||
|
||||
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
||||
printf(" %p cellFrame returning aDesiredSize=%d,%d\n",
|
||||
|
@ -590,6 +591,505 @@ nsresult nsTableCellFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* ----- methods from CellLayoutData ----- */
|
||||
|
||||
/**
|
||||
* Given a frame and an edge, find the margin
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::GetMargin(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin margin;
|
||||
spacing->CalcMarginFor(aFrame, margin);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = margin.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = margin.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = margin.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = margin.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a style context and an edge, find the border width
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::GetBorderWidth(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin border;
|
||||
spacing->CalcBorderFor(aFrame, border);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = border.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = border.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = border.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = border.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a style context and an edge, find the padding
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::GetPadding(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin padding;
|
||||
spacing->CalcPaddingFor(aFrame, padding);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = padding.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = padding.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = padding.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = padding.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Given an Edge, find the opposing edge (top<-->bottom, left<-->right)
|
||||
*
|
||||
**/
|
||||
PRUint8 nsTableCellFrame::GetOpposingEdge(PRUint8 aEdge)
|
||||
{
|
||||
PRUint8 result;
|
||||
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_LEFT:
|
||||
result = NS_SIDE_RIGHT;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = NS_SIDE_LEFT;
|
||||
break;
|
||||
|
||||
case NS_SIDE_TOP:
|
||||
result = NS_SIDE_BOTTOM;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = NS_SIDE_TOP;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = NS_SIDE_TOP;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Determine border style for two cells.
|
||||
*
|
||||
1.If the adjacent elements are of the same type, the wider of the two borders is used.
|
||||
"Wider" takes into account the border-style of 'none', so a "1px solid" border
|
||||
will take precedence over a "20px none" border.
|
||||
|
||||
2.If there are two or more with the same width, but different style,
|
||||
then the one with a style near the start of the following list will be drawn:
|
||||
|
||||
'blank', 'double', 'solid', 'dashed', 'dotted', 'ridge', 'groove', 'none'
|
||||
|
||||
3.If the borders are of the same width, the border on the element occurring first is used.
|
||||
|
||||
First is defined as aStyle for this method.
|
||||
|
||||
NOTE: This assumes left-to-right, top-to-bottom bias. -- gpk
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
nsIFrame* nsTableCellFrame::CompareCellBorders(nsIFrame* aFrame1,
|
||||
PRUint8 aEdge1,
|
||||
nsIFrame* aFrame2,
|
||||
PRUint8 aEdge2)
|
||||
{
|
||||
PRInt32 width1 = GetBorderWidth(aFrame1,aEdge1);
|
||||
PRInt32 width2 = GetBorderWidth(aFrame2,aEdge2);
|
||||
|
||||
nsIFrame* result = nsnull;
|
||||
|
||||
if (width1 > width2)
|
||||
result = aFrame1;
|
||||
else if (width1 < width2)
|
||||
result = aFrame2;
|
||||
else // width1 == width2
|
||||
{
|
||||
const nsStyleSpacing* border1;
|
||||
const nsStyleSpacing* border2;
|
||||
aFrame1->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)border1);
|
||||
aFrame2->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)border2);
|
||||
if (border1->mBorderStyle[aEdge1] >= border2->mBorderStyle[aEdge2])
|
||||
result = aFrame1;
|
||||
else
|
||||
result = aFrame2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a List of cell layout data, compare the edges to see which has the
|
||||
* border with the highest precidence.
|
||||
*
|
||||
**/
|
||||
|
||||
nsIFrame* nsTableCellFrame::FindHighestPrecedentBorder(nsVoidArray* aList,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* result = nsnull;
|
||||
PRInt32 index = 0;
|
||||
PRInt32 count = 0;
|
||||
|
||||
|
||||
NS_ASSERTION(aList,"a List must be valid");
|
||||
count = aList->Count();
|
||||
if (count)
|
||||
{
|
||||
nsIFrame* frame1;
|
||||
nsIFrame* frame2;
|
||||
|
||||
frame1 = (nsIFrame*)(aList->ElementAt(index++));
|
||||
while (index < count)
|
||||
{
|
||||
frame2 = (nsIFrame*)(aList->ElementAt(index++));
|
||||
if (GetMargin(frame2,aEdge) == 0) {
|
||||
frame1 = CompareCellBorders(frame1, aEdge, frame2, aEdge);
|
||||
}
|
||||
}
|
||||
if ((nsnull != frame1) && (GetMargin(frame1, aEdge) != 0))
|
||||
result = frame1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nsIFrame* nsTableCellFrame::FindInnerBorder(nsVoidArray* aList, PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* result = nsnull;
|
||||
PRUint8 opposite = GetOpposingEdge(aEdge);
|
||||
|
||||
if (GetMargin(this, aEdge) == 0)
|
||||
{
|
||||
nsIFrame* altFrame = FindHighestPrecedentBorder(aList,opposite);
|
||||
if (nsnull != altFrame)
|
||||
result = CompareCellBorders(this, aEdge, altFrame, opposite);
|
||||
else
|
||||
result = this;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* FindRelevantBorder recursively searches up the frame hierarchy for the border
|
||||
* style that is applicable to the cell. If at any point the frame has a margin
|
||||
* or the parent frame has padding, then the outer frame for this object takes
|
||||
* presendence over the inner frame.
|
||||
|
||||
1.Borders on 'table' elements take precedence over borders on any other table elements.
|
||||
2.Borders on 'row-groups' take precedence over borders on 'rows',
|
||||
and likewise borders on 'column-groups' take precedence over borders on 'columns'.
|
||||
3.Borders on any other type of table element take precedence over 'table-cell' elements.
|
||||
|
||||
*
|
||||
* NOTE: This method assumes that the table cell potentially shares a border.
|
||||
* It should not be called for internal cells
|
||||
*
|
||||
* NOTE: COLUMNS AND COLGROUPS NEED TO BE FIGURED INTO THE ALGORITHM -- GPK!!!
|
||||
*
|
||||
*
|
||||
*/
|
||||
nsIFrame* nsTableCellFrame::FindOuterBorder( nsTableFrame* aTableFrame,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* frame = this; // By default, return our frame
|
||||
PRBool done = PR_FALSE;
|
||||
|
||||
|
||||
// The table frame is the outer most frame we test against
|
||||
while (done == PR_FALSE)
|
||||
{
|
||||
done = PR_TRUE; // where done unless the frame's margin is zero
|
||||
// and the parent's padding is zero
|
||||
|
||||
nscoord margin = GetMargin(frame,aEdge);
|
||||
|
||||
// if the margin for this style is zero then check to see if the paddding
|
||||
// for the parent frame is also zero
|
||||
if (margin == 0)
|
||||
{
|
||||
nsIFrame* parentFrame;
|
||||
|
||||
frame->GetGeometricParent(parentFrame);
|
||||
|
||||
// if the padding for the parent style is zero just
|
||||
// recursively call this routine
|
||||
PRInt32 padding = GetPadding(parentFrame,aEdge);
|
||||
if ((nsnull != parentFrame) && (padding == 0))
|
||||
{
|
||||
frame = parentFrame;
|
||||
// If this frame represents the table frame then
|
||||
// the table style is used
|
||||
done = PRBool(frame != (nsIFrame*)aTableFrame);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Border Resolution
|
||||
1.Borders on 'table' elements take precedence over borders on any other table elements.
|
||||
2.Borders on 'row-groups' take precedence over borders on 'rows', and likewise borders on 'column-groups' take
|
||||
precedence over borders on 'columns'.
|
||||
3.Borders on any other type of table element take precedence over 'table-cell' elements.
|
||||
4.If the adjacent elements are of the same type, the wider of the two borders is used. "Wider" takes into account
|
||||
the border-style of 'none', so a "1px solid" border will take precedence over a "20px none" border.
|
||||
5.If the borders are of the same width, the border on the element occurring first is used.
|
||||
|
||||
|
||||
How to compare
|
||||
1.Those of the one or two cells that have an edge here.
|
||||
Less than two can occur at the edge of the table, but also
|
||||
at the edges of "holes" (unoccupied grid cells).
|
||||
2.Those of the columns that have an edge here.
|
||||
3.Those of the column groups that have an edge here.
|
||||
4.Those of the rows that have an edge here.
|
||||
5.Those of the row groups that have an edge here.
|
||||
6.Those of the table, if this is the edge of the table.
|
||||
|
||||
*
|
||||
* @param aIsFirst -- TRUE if this is the first cell in the row
|
||||
* @param aIsLast -- TRUE if this is the last cell in the row
|
||||
* @param aIsTop -- TRUE if this is the top cell in the column
|
||||
* @param aIsBottom -- TRUE if this is the last cell in the column
|
||||
*/
|
||||
|
||||
nsIFrame* nsTableCellFrame::FindBorderFrame(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aList,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* frame = nsnull;
|
||||
|
||||
if (aList && aList->Count() == 0)
|
||||
frame = FindOuterBorder(aTableFrame, aEdge);
|
||||
else
|
||||
frame = FindInnerBorder(aList, aEdge);
|
||||
|
||||
if (! frame)
|
||||
frame = this;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a List of cell layout data, compare the edges to see which has the
|
||||
* border with the highest precidence.
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::FindLargestMargin(nsVoidArray* aList,PRUint8 aEdge)
|
||||
{
|
||||
nscoord result = 0;
|
||||
PRInt32 index = 0;
|
||||
PRInt32 count = 0;
|
||||
|
||||
|
||||
NS_ASSERTION(aList,"a List must be valid");
|
||||
count = aList->Count();
|
||||
if (count)
|
||||
{
|
||||
nsIFrame* frame;
|
||||
|
||||
nscoord value = 0;
|
||||
while (index < count)
|
||||
{
|
||||
frame = (nsIFrame*)(aList->ElementAt(index++));
|
||||
value = GetMargin(frame, aEdge);
|
||||
if (value > result)
|
||||
result = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nsTableCellFrame::CalculateMargins(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
{
|
||||
// By default the margin is just the margin found in the
|
||||
// table cells style
|
||||
const nsStyleSpacing* spacing;
|
||||
GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
spacing->CalcMarginFor(this, mMargin);
|
||||
|
||||
// Left and Top Margins are collapsed with their neightbors
|
||||
// Right and Bottom Margins are simple left as they are
|
||||
nscoord value;
|
||||
|
||||
// The left and top sides margins are the difference between
|
||||
// their inherint value and the value of the margin of the
|
||||
// object to the left or right of them.
|
||||
|
||||
value = FindLargestMargin(aBoundaryCells[NS_SIDE_LEFT],NS_SIDE_RIGHT);
|
||||
if (value > mMargin.left)
|
||||
mMargin.left = 0;
|
||||
else
|
||||
mMargin.left -= value;
|
||||
|
||||
value = FindLargestMargin(aBoundaryCells[NS_SIDE_TOP],NS_SIDE_BOTTOM);
|
||||
if (value > mMargin.top)
|
||||
mMargin.top = 0;
|
||||
else
|
||||
mMargin.top -= value;
|
||||
}
|
||||
|
||||
|
||||
void nsTableCellFrame::RecalcLayoutData(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
|
||||
{
|
||||
CalculateBorders(aTableFrame, aBoundaryCells);
|
||||
CalculateMargins(aTableFrame, aBoundaryCells);
|
||||
mCalculated = NS_OK;
|
||||
}
|
||||
|
||||
#if 0 //QQQ
|
||||
void nsTableCellFrame::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
PRInt32 indent;
|
||||
|
||||
nsIContent* cell;
|
||||
|
||||
this->GetContent(cell);
|
||||
if (cell != nsnull)
|
||||
{
|
||||
/*
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"RowSpan = %d ColSpan = %d \n",cell->GetRowSpan(),cell->GetColSpan());
|
||||
*/
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Margin -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.top),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.left),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.right));
|
||||
|
||||
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
|
||||
nscoord top,left,bottom,right;
|
||||
|
||||
top = (mBorderFrame[NS_SIDE_TOP] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_TOP], NS_SIDE_TOP) : 0);
|
||||
left = (mBorderFrame[NS_SIDE_LEFT] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_LEFT], NS_SIDE_LEFT) : 0);
|
||||
bottom = (mBorderFrame[NS_SIDE_BOTTOM] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_BOTTOM], NS_SIDE_BOTTOM) : 0);
|
||||
right = (mBorderFrame[NS_SIDE_RIGHT] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_RIGHT], NS_SIDE_RIGHT) : 0);
|
||||
|
||||
|
||||
fprintf(out,"Border -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(top),
|
||||
NS_TWIPS_TO_POINTS_INT(left),
|
||||
NS_TWIPS_TO_POINTS_INT(bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(right));
|
||||
|
||||
|
||||
|
||||
cell->List(out,aIndent);
|
||||
NS_RELEASE(cell);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ----- debug only methods, to be removed ----- */
|
||||
|
||||
|
||||
// For Debugging ONLY
|
||||
NS_METHOD nsTableCellFrame::MoveTo(nscoord aX, nscoord aY)
|
||||
{
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "nscore.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsTableRowFrame.h" // need to actually include this here to inline GetRowIndex
|
||||
|
||||
class nsCellLayoutData;
|
||||
struct nsStyleSpacing;
|
||||
|
||||
/* eb42f7b0-079e-11d2-8f37-006008159b0c */
|
||||
|
@ -72,34 +72,124 @@ public:
|
|||
/** return the mapped cell's row span. Always >= 1. */
|
||||
virtual PRInt32 GetRowSpan();
|
||||
|
||||
// there is no set row index because row index depends on the cell's parent row only
|
||||
|
||||
/** return the mapped cell's row index (starting at 0 for the first row) */
|
||||
virtual PRInt32 GetRowIndex();
|
||||
|
||||
/** return the mapped cell's col span. Always >= 1. */
|
||||
virtual PRInt32 GetColSpan();
|
||||
|
||||
/** return the mapped cell's column index (starting at 0 for the first column) */
|
||||
virtual PRInt32 GetColIndex();
|
||||
|
||||
/** set the index of the column belonging to this cell */
|
||||
// XXX should be removed, use cell map?
|
||||
virtual void SetColIndex (int aColIndex);
|
||||
|
||||
/** return the available width given to this frame during its last reflow */
|
||||
virtual nscoord GetPriorAvailWidth();
|
||||
|
||||
/** set the available width given to this frame during its last reflow */
|
||||
virtual void SetPriorAvailWidth(nscoord aPriorAvailWidth);
|
||||
|
||||
virtual nsSize GetPriorDesiredSize();
|
||||
/** return the desired size returned by this frame during its last reflow */
|
||||
virtual nsSize GetDesiredSize();
|
||||
|
||||
virtual void SetPriorDesiredSize(const nsReflowMetrics & aDesiredSize);
|
||||
/** set the desired size returned by this frame during its last reflow */
|
||||
virtual void SetDesiredSize(const nsReflowMetrics & aDesiredSize);
|
||||
|
||||
virtual ~nsTableCellFrame();
|
||||
/** return the MaxElement size returned by this frame during its last reflow
|
||||
* not counting reflows where MaxElementSize is not requested.
|
||||
* That is, the cell frame will always remember the last non-null MaxElementSize
|
||||
*/
|
||||
virtual nsSize GetMaxElementSize();
|
||||
|
||||
// Get the TableFrame that contains this cell frame
|
||||
/** set the MaxElement size returned by this frame during its last reflow.
|
||||
* should never be called with a null MaxElementSize
|
||||
*/
|
||||
virtual void SetMaxElementSize(const nsSize & aMaxElementSize);
|
||||
|
||||
/** return the desired size returned by this frame during its last reflow */
|
||||
virtual nsSize GetPass1DesiredSize();
|
||||
|
||||
/** set the desired size returned by this frame during its last reflow */
|
||||
virtual void SetPass1DesiredSize(const nsReflowMetrics & aDesiredSize);
|
||||
|
||||
/** return the MaxElement size returned by this frame during its last reflow
|
||||
* not counting reflows where MaxElementSize is not requested.
|
||||
* That is, the cell frame will always remember the last non-null MaxElementSize
|
||||
*/
|
||||
virtual nsSize GetPass1MaxElementSize();
|
||||
|
||||
/** set the MaxElement size returned by this frame during its last reflow.
|
||||
* should never be called with a null MaxElementSize
|
||||
*/
|
||||
virtual void SetPass1MaxElementSize(const nsSize & aMaxElementSize);
|
||||
|
||||
|
||||
|
||||
/** Get the TableFrame that contains this cell frame */
|
||||
virtual nsTableFrame* GetTableFrame();
|
||||
|
||||
nsCellLayoutData * GetCellLayoutData();
|
||||
void SetCellLayoutData(nsCellLayoutData *aData);
|
||||
void RecalcLayoutData(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
// For DEBUGGING Purposes Only
|
||||
|
||||
NS_IMETHOD GetMargin(nsMargin& aMargin);
|
||||
|
||||
|
||||
/** destructor */
|
||||
virtual ~nsTableCellFrame();
|
||||
|
||||
|
||||
// For DEBUGGING Purposes Only, to be removed
|
||||
NS_IMETHOD MoveTo(nscoord aX, nscoord aY);
|
||||
NS_IMETHOD SizeTo(nscoord aWidth, nscoord aHeight);
|
||||
|
||||
private:
|
||||
|
||||
// All these methods are support methods for RecalcLayoutData
|
||||
nsIFrame* GetFrameAt(nsVoidArray* aList, PRInt32 aIndex);
|
||||
|
||||
nscoord GetMargin(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
nscoord GetBorderWidth(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
nscoord GetPadding(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
PRUint8 GetOpposingEdge(PRUint8 aEdge);
|
||||
|
||||
nsIFrame* CompareCellBorders(nsIFrame* aFrame1,
|
||||
PRUint8 aEdge1,
|
||||
nsIFrame* aFrame2,
|
||||
PRUint8 aEdge2);
|
||||
|
||||
|
||||
nsIFrame* FindHighestPrecedentBorder(nsVoidArray* aList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
|
||||
|
||||
nsIFrame* FindInnerBorder( nsVoidArray* aList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
nsIFrame* FindOuterBorder( nsTableFrame* aTableFrame,
|
||||
PRUint8 aEdge);
|
||||
|
||||
nsIFrame* FindBorderFrame(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aCellList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
void CalculateBorders(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
nscoord FindLargestMargin(nsVoidArray* aList,PRUint8 aEdge);
|
||||
|
||||
|
||||
void CalculateMargins(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
protected:
|
||||
|
||||
/** protected constructor.
|
||||
|
@ -132,9 +222,17 @@ protected:
|
|||
/** the available width we were given in our previous reflow */
|
||||
nscoord mPriorAvailWidth;
|
||||
|
||||
nsSize mPriorDesiredSize;
|
||||
/** these are the last computed desired and max element sizes */
|
||||
nsSize mDesiredSize;
|
||||
nsSize mMaxElementSize;
|
||||
|
||||
nsCellLayoutData *mCellLayoutData;
|
||||
/** these are the Pass 1 unconstrained desired and max element sizes */
|
||||
nsSize mPass1DesiredSize;
|
||||
nsSize mPass1MaxElementSize;
|
||||
|
||||
nsresult mCalculated;
|
||||
nsMargin mMargin;
|
||||
nsIFrame* mBorderFrame[4]; // the frame whose border is used
|
||||
|
||||
};
|
||||
|
||||
|
@ -151,6 +249,16 @@ inline void nsTableCellFrame::Init(PRInt32 aRowSpan, PRInt32 aColSpan, PRInt32 a
|
|||
inline PRInt32 nsTableCellFrame::GetRowSpan()
|
||||
{ return mRowSpan;}
|
||||
|
||||
inline PRInt32 nsTableCellFrame::GetRowIndex()
|
||||
{
|
||||
nsTableRowFrame * row;
|
||||
GetContentParent((nsIFrame *&)row);
|
||||
if (nsnull!=row)
|
||||
return row->GetRowIndex();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline PRInt32 nsTableCellFrame::GetColSpan()
|
||||
{ return mColSpan;}
|
||||
|
||||
|
@ -163,25 +271,64 @@ inline void nsTableCellFrame::SetColIndex (int aColIndex)
|
|||
mColIndex = aColIndex;
|
||||
}
|
||||
|
||||
inline nsCellLayoutData * nsTableCellFrame::GetCellLayoutData()
|
||||
{ return mCellLayoutData;}
|
||||
|
||||
inline void nsTableCellFrame::SetCellLayoutData(nsCellLayoutData *aData)
|
||||
{ mCellLayoutData = aData;}
|
||||
|
||||
inline nscoord nsTableCellFrame::GetPriorAvailWidth()
|
||||
{ return mPriorAvailWidth;}
|
||||
|
||||
inline void nsTableCellFrame::SetPriorAvailWidth(nscoord aPriorAvailWidth)
|
||||
{ mPriorAvailWidth = aPriorAvailWidth;}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetPriorDesiredSize()
|
||||
{ return mPriorDesiredSize; }
|
||||
inline nsSize nsTableCellFrame::GetDesiredSize()
|
||||
{ return mDesiredSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetPriorDesiredSize(const nsReflowMetrics & aDesiredSize)
|
||||
inline void nsTableCellFrame::SetDesiredSize(const nsReflowMetrics & aDesiredSize)
|
||||
{
|
||||
mPriorDesiredSize.width = aDesiredSize.width;
|
||||
mPriorDesiredSize.height = aDesiredSize.height;
|
||||
mDesiredSize.width = aDesiredSize.width;
|
||||
mDesiredSize.height = aDesiredSize.height;
|
||||
}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetMaxElementSize()
|
||||
{ return mMaxElementSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetMaxElementSize(const nsSize & aMaxElementSize)
|
||||
{
|
||||
mMaxElementSize.width = aMaxElementSize.width;
|
||||
mMaxElementSize.height = aMaxElementSize.height;
|
||||
}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetPass1DesiredSize()
|
||||
{ return mPass1DesiredSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetPass1DesiredSize(const nsReflowMetrics & aDesiredSize)
|
||||
{
|
||||
mPass1DesiredSize.width = aDesiredSize.width;
|
||||
mPass1DesiredSize.height = aDesiredSize.height;
|
||||
}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetPass1MaxElementSize()
|
||||
{ return mPass1MaxElementSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetPass1MaxElementSize(const nsSize & aMaxElementSize)
|
||||
{
|
||||
mPass1MaxElementSize.width = aMaxElementSize.width;
|
||||
mPass1MaxElementSize.height = aMaxElementSize.height;
|
||||
}
|
||||
|
||||
inline void nsTableCellFrame::CalculateBorders(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
{
|
||||
for (PRInt32 edge = 0; edge < 4; edge++)
|
||||
mBorderFrame[edge] = FindBorderFrame(aTableFrame, aBoundaryCells[edge], edge);
|
||||
}
|
||||
|
||||
inline NS_METHOD nsTableCellFrame::GetMargin(nsMargin& aMargin)
|
||||
{
|
||||
if (mCalculated == NS_OK)
|
||||
{
|
||||
aMargin = mMargin;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
#include "nsTablePart.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsHTMLContainer.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
|
@ -38,66 +36,6 @@ static const PRBool gsNoisyRefs = PR_FALSE;
|
|||
#endif
|
||||
|
||||
|
||||
nsTableColFrame::nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsFrame(aContent, aParentFrame)
|
||||
{
|
||||
mColIndex = 0;
|
||||
mRepeat = 0;
|
||||
}
|
||||
|
||||
|
||||
nsTableColFrame::~nsTableColFrame()
|
||||
{
|
||||
}
|
||||
|
||||
NS_METHOD nsTableColFrame::Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf("nsTableColFrame::Paint\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsTableColFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
NS_ASSERTION(nsnull!=aPresContext, "bad arg");
|
||||
aDesiredSize.width=0;
|
||||
aDesiredSize.height=0;
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
{
|
||||
aDesiredSize.maxElementSize->width=0;
|
||||
aDesiredSize.maxElementSize->height=0;
|
||||
}
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ----- static methods ------ */
|
||||
|
||||
nsresult nsTableColFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsIFrame* it = new nsTableColFrame(aContent, aParent);
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aInstancePtrResult = it;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//---------------------- nsTableCol implementation -----------------------------------
|
||||
|
||||
nsTableCol::nsTableCol(nsIAtom* aTag)
|
||||
: nsTableContent(aTag),
|
||||
mColGroup(0),
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
static PRBool gsNoisyRefs = PR_FALSE;
|
||||
#else
|
||||
static const PRBool gsDebug = PR_FALSE;
|
||||
static const PRBool gsNoisyRefs = PR_FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
nsTableColFrame::nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsFrame(aContent, aParentFrame)
|
||||
{
|
||||
mColIndex = 0;
|
||||
mRepeat = 0;
|
||||
}
|
||||
|
||||
|
||||
nsTableColFrame::~nsTableColFrame()
|
||||
{
|
||||
}
|
||||
|
||||
NS_METHOD nsTableColFrame::Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf("nsTableColFrame::Paint\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsTableColFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
NS_ASSERTION(nsnull!=aPresContext, "bad arg");
|
||||
aDesiredSize.width=0;
|
||||
aDesiredSize.height=0;
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
{
|
||||
aDesiredSize.maxElementSize->width=0;
|
||||
aDesiredSize.maxElementSize->height=0;
|
||||
}
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ----- static methods ------ */
|
||||
|
||||
nsresult nsTableColFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsIFrame* it = new nsTableColFrame(aContent, aParent);
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aInstancePtrResult = it;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -48,6 +48,12 @@ public:
|
|||
/** set the index of the column this content object represents. must be >= 0 */
|
||||
virtual void SetColumnIndex (int aColIndex);
|
||||
|
||||
/** convenience method, calls into cellmap */
|
||||
nsVoidArray * GetCells();
|
||||
|
||||
/** convenience method, calls into cellmap */
|
||||
PRInt32 Count() const;
|
||||
|
||||
protected:
|
||||
|
||||
nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame);
|
||||
|
@ -60,6 +66,12 @@ protected:
|
|||
/** the number of columns that the attributes of this column extend to */
|
||||
PRInt32 mRepeat;
|
||||
|
||||
nscoord mMaxWidth;
|
||||
nscoord mMinWidth;
|
||||
|
||||
nscoord mMaxEffectiveWidth;
|
||||
nscoord mMinEffectiveWidth;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -29,14 +29,12 @@
|
|||
#include "nsTableColGroupFrame.h"
|
||||
#include "nsTableRowFrame.h"
|
||||
#include "nsTableRowGroupFrame.h"
|
||||
#include "nsColLayoutData.h"
|
||||
|
||||
#include "BasicTableLayoutStrategy.h"
|
||||
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIView.h"
|
||||
|
@ -269,7 +267,6 @@ void ColumnInfoCache::GetColumnsByType(const nsStyleUnit aType,
|
|||
nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aParentFrame),
|
||||
mCellMap(nsnull),
|
||||
mColumnLayoutData(nsnull),
|
||||
mColCache(nsnull),
|
||||
mColumnWidths(nsnull),
|
||||
mTableLayoutStrategy(nsnull),
|
||||
|
@ -279,32 +276,11 @@ nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to delete all owned objects assoicated
|
||||
* with the ColumnLayoutObject instance variable
|
||||
*/
|
||||
void nsTableFrame::DeleteColumnLayoutData()
|
||||
{
|
||||
if (nsnull!=mColumnLayoutData)
|
||||
{
|
||||
PRInt32 numCols = mColumnLayoutData->Count();
|
||||
for (PRInt32 i = 0; i<numCols; i++)
|
||||
{
|
||||
nsColLayoutData *colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(i));
|
||||
delete colData;
|
||||
}
|
||||
delete mColumnLayoutData;
|
||||
mColumnLayoutData = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsTableFrame::~nsTableFrame()
|
||||
{
|
||||
if (nsnull!=mCellMap)
|
||||
delete mCellMap;
|
||||
|
||||
DeleteColumnLayoutData();
|
||||
|
||||
if (nsnull!=mColumnWidths)
|
||||
delete [] mColumnWidths;
|
||||
|
||||
|
@ -351,8 +327,7 @@ nsTableRowGroupFrame* nsTableFrame::NextRowGroupFrame(nsTableRowGroupFrame* aRow
|
|||
PRInt32 nsTableFrame::GetSpecifiedColumnCount ()
|
||||
{
|
||||
mColCount=0;
|
||||
nsIFrame * colGroup;
|
||||
ChildAt (0, (nsIFrame *&)colGroup);
|
||||
nsIFrame * colGroup = mFirstChild;
|
||||
while (nsnull!=colGroup)
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
|
@ -379,8 +354,7 @@ PRInt32 nsTableFrame::GetRowCount ()
|
|||
if (nsnull != mCellMap)
|
||||
return mCellMap->GetRowCount();
|
||||
|
||||
nsIFrame *child=nsnull;
|
||||
ChildAt(0, child);
|
||||
nsIFrame *child=mFirstChild;
|
||||
while (nsnull!=child)
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
|
@ -393,6 +367,35 @@ PRInt32 nsTableFrame::GetRowCount ()
|
|||
}
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
nsTableColFrame * nsTableFrame::GetColFrame(PRInt32 aColIndex)
|
||||
{
|
||||
nsTableColFrame *result = nsnull;
|
||||
if (nsnull!=mCellMap)
|
||||
{
|
||||
result = mCellMap->GetColumnFrame(aColIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// can return nsnull
|
||||
nsTableCellFrame * nsTableFrame::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex)
|
||||
{
|
||||
nsTableCellFrame *result = nsnull;
|
||||
if (nsnull!=mCellMap)
|
||||
{
|
||||
CellData * cellData = mCellMap->GetCellAt(aRowIndex, aColIndex);
|
||||
if (nsnull!=cellData)
|
||||
{
|
||||
result = cellData->mCell;
|
||||
if (nsnull==result)
|
||||
result = cellData->mRealCell->mCell;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// return the rows spanned by aCell starting at aRowIndex
|
||||
// note that this is different from just the rowspan of aCell
|
||||
// (that would be GetEffectiveRowSpan (indexOfRowThatContains_aCell, aCell)
|
||||
|
@ -413,13 +416,6 @@ PRInt32 nsTableFrame::GetEffectiveRowSpan (PRInt32 aRowIndex, nsTableCellFrame *
|
|||
return rowSpan;
|
||||
}
|
||||
|
||||
|
||||
// returns the actual cell map, not a copy, so don't mess with it!
|
||||
nsCellMap* nsTableFrame::GetCellMap() const
|
||||
{
|
||||
return mCellMap;
|
||||
}
|
||||
|
||||
/* call when the cell structure has changed. mCellMap will be rebuilt on demand. */
|
||||
void nsTableFrame::ResetCellMap ()
|
||||
{
|
||||
|
@ -449,10 +445,9 @@ void nsTableFrame::EnsureColumns(nsIPresContext* aPresContext,
|
|||
|
||||
PRInt32 actualColumns = 0;
|
||||
nsTableColGroupFrame *lastColGroupFrame = nsnull;
|
||||
nsIFrame * childFrame=nsnull;
|
||||
nsIFrame * firstRowGroupFrame=nsnull;
|
||||
nsIFrame * prevSibFrame=nsnull;
|
||||
ChildAt (0, (nsIFrame *&)childFrame);
|
||||
nsIFrame * childFrame=mFirstChild;
|
||||
while (nsnull!=childFrame)
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
|
@ -795,35 +790,67 @@ void nsTableFrame::GrowCellMap (PRInt32 aColCount)
|
|||
*/
|
||||
void nsTableFrame::ListColumnLayoutData(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
// if this is a continuing frame, there will be no output
|
||||
if (nsnull!=mColumnLayoutData)
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
if (this!=firstInFlow)
|
||||
{
|
||||
firstInFlow->ListColumnLayoutData(out, aIndent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsnull!=mCellMap)
|
||||
{
|
||||
fprintf(out,"Column Layout Data \n");
|
||||
|
||||
PRInt32 numCols = mColumnLayoutData->Count();
|
||||
for (PRInt32 i = 0; i<numCols; i++)
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
PRInt32 numRows = mCellMap->GetRowCount();
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
nsColLayoutData *colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(i));
|
||||
for (PRInt32 indent = aIndent; --indent >= 0; )
|
||||
fputs(" ", out);
|
||||
fprintf(out,"Column Data [%d] \n",colIndex);
|
||||
for (PRInt32 rowIndex = 0; rowIndex < numRows; rowIndex++)
|
||||
{
|
||||
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(rowIndex, colIndex);
|
||||
PRInt32 rowIndent;
|
||||
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Cell Data [%d] \n",rowIndex);
|
||||
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
||||
nsMargin margin;
|
||||
cellFrame->GetMargin(margin);
|
||||
fprintf(out,"Margin -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(margin.top),
|
||||
NS_TWIPS_TO_POINTS_INT(margin.left),
|
||||
NS_TWIPS_TO_POINTS_INT(margin.bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(margin.right));
|
||||
|
||||
for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Column Data [%d] \n",i);
|
||||
colData->List(out,aIndent+2);
|
||||
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
||||
|
||||
nscoord top,left,bottom,right;
|
||||
/*
|
||||
top = (mBorderFrame[NS_SIDE_TOP] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_TOP], NS_SIDE_TOP) : 0);
|
||||
left = (mBorderFrame[NS_SIDE_LEFT] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_LEFT], NS_SIDE_LEFT) : 0);
|
||||
bottom = (mBorderFrame[NS_SIDE_BOTTOM] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_BOTTOM], NS_SIDE_BOTTOM) : 0);
|
||||
right = (mBorderFrame[NS_SIDE_RIGHT] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_RIGHT], NS_SIDE_RIGHT) : 0);
|
||||
*/
|
||||
|
||||
fprintf(out,"Border -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(top),
|
||||
NS_TWIPS_TO_POINTS_INT(left),
|
||||
NS_TWIPS_TO_POINTS_INT(bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(right));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For the TableCell in CellData, find the CellLayoutData assocated
|
||||
* and add it to the list
|
||||
**/
|
||||
* For the TableCell in CellData, add it to the list
|
||||
*/
|
||||
void nsTableFrame::AppendLayoutData(nsVoidArray* aList, nsTableCellFrame* aTableCell)
|
||||
{
|
||||
|
||||
if (aTableCell != nsnull)
|
||||
{
|
||||
nsCellLayoutData* layoutData = GetCellLayoutData(aTableCell);
|
||||
if (layoutData != nsnull)
|
||||
aList->AppendElement((void*)layoutData);
|
||||
aList->AppendElement((void*)aTableCell);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -996,9 +1023,7 @@ void nsTableFrame::RecalcLayoutData()
|
|||
r++;
|
||||
}
|
||||
|
||||
nsCellLayoutData* cellLayoutData = GetCellLayoutData(cell);
|
||||
if (cellLayoutData != nsnull)
|
||||
cellLayoutData->RecalcLayoutData(this,boundaryCells);
|
||||
cell->RecalcLayoutData(this,boundaryCells);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1310,7 +1335,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
|
|||
if (nsnull!=prevKidFrame)
|
||||
prevKidFrame->GetNextSibling(kidFrame); // no need to check for an error, just see if it returned null...
|
||||
else
|
||||
ChildAt(0, kidFrame);
|
||||
kidFrame=mFirstChild;
|
||||
|
||||
// if this is the first time, allocate the frame
|
||||
if (nsnull==kidFrame)
|
||||
|
@ -2210,11 +2235,10 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext,
|
|||
if (gsDebug)
|
||||
printf ("BalanceColumnWidths...\n");
|
||||
|
||||
nsVoidArray *columnLayoutData = GetColumnLayoutData();
|
||||
if (nsnull==columnLayoutData)
|
||||
if (nsnull==mCellMap)
|
||||
return; // we don't have any information yet, so we can't do any useful work
|
||||
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
if (nsnull==mColumnWidths)
|
||||
{
|
||||
mColumnWidths = new PRInt32[numCols];
|
||||
|
@ -2233,9 +2257,22 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext,
|
|||
|
||||
// need to figure out the overall table width constraint
|
||||
// default case, get 100% of available space
|
||||
|
||||
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
nsIFrame * outerTableFrame = nsnull;
|
||||
const nsStylePosition* position;
|
||||
GetGeometricParent(outerTableFrame);
|
||||
outerTableFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)position));
|
||||
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED
|
||||
|
||||
|
||||
|
||||
PRInt32 maxWidth;
|
||||
/*
|
||||
const nsStylePosition* position =
|
||||
(const nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
|
||||
use this line when tableFrame contains its own position style info
|
||||
*/
|
||||
switch (position->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
maxWidth = position->mWidth.GetCoordValue();
|
||||
|
@ -2251,7 +2288,6 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext,
|
|||
// XXX for now these fall through
|
||||
|
||||
default:
|
||||
|
||||
maxWidth = aMaxSize.width;
|
||||
break;
|
||||
}
|
||||
|
@ -2293,16 +2329,20 @@ void nsTableFrame::SetTableWidth(nsIPresContext* aPresContext)
|
|||
|
||||
if (gsDebug==PR_TRUE) printf ("SetTableWidth...");
|
||||
PRInt32 tableWidth = 0;
|
||||
nsVoidArray *columnLayoutData = GetColumnLayoutData();
|
||||
if (nsnull==columnLayoutData)
|
||||
if (nsnull==mCellMap)
|
||||
return; // no info, so nothing to do
|
||||
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
for (PRInt32 i = 0; i<numCols; i++)
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
tableWidth += mColumnWidths[i];
|
||||
nscoord totalColWidth = mColumnWidths[colIndex];
|
||||
nsTableCellFrame * cellFrame = GetCellAt(0, colIndex);
|
||||
nsMargin colMargin;
|
||||
GetCellMarginData(cellFrame,colMargin);
|
||||
totalColWidth += colMargin.left + colMargin.right;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" += %d ", mColumnWidths[i]);
|
||||
printf (" += %d ", totalColWidth);
|
||||
tableWidth += totalColWidth;
|
||||
}
|
||||
|
||||
// Compute the insets (sum of border and padding)
|
||||
|
@ -2384,12 +2424,9 @@ NS_METHOD nsTableFrame::GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aCol
|
|||
{
|
||||
aColFrame = nsnull; // initialize out parameter
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
if (nsnull!=firstInFlow->mColumnLayoutData)
|
||||
if (nsnull!=firstInFlow->mCellMap)
|
||||
{ // hooray, we get to do this the easy way because the info is cached
|
||||
nsColLayoutData * colData = (nsColLayoutData *)
|
||||
(firstInFlow->mColumnLayoutData->ElementAt(aColIndex));
|
||||
NS_ASSERTION(nsnull != colData, "bad column data");
|
||||
aColFrame = colData->GetColFrame();
|
||||
aColFrame = firstInFlow->mCellMap->GetColumnFrame(aColIndex);
|
||||
NS_ASSERTION(nsnull!=aColFrame, "bad col frame");
|
||||
}
|
||||
else
|
||||
|
@ -2443,18 +2480,30 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
mColCache = new ColumnInfoCache(mColCount);
|
||||
nsIFrame * childFrame = mFirstChild;
|
||||
while (nsnull!=childFrame)
|
||||
{ // for every child, if it's a col group then get the columns
|
||||
{ // in this loop, we cache column info and set column style info from cells in first row
|
||||
const nsStyleDisplay *childDisplay;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{ // if it's a col group then get the columns and cache them in the CellMap
|
||||
nsTableColFrame *colFrame=nsnull;
|
||||
childFrame->FirstChild((nsIFrame *&)colFrame);
|
||||
while (nsnull!=colFrame)
|
||||
{
|
||||
mCellMap->AppendColumnFrame(colFrame);
|
||||
colFrame->GetNextSibling((nsIFrame *&)colFrame);
|
||||
}
|
||||
}
|
||||
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
|
||||
{ // for every cell in every row, call SetCellLayoutData with the cached info
|
||||
// QQQ we can probably just leave the info in the table cell frame, not cache it here
|
||||
{ // if it's a row group, get the cells and set the column style if appropriate
|
||||
nsIFrame *rowFrame;
|
||||
childFrame->ChildAt(0, rowFrame);
|
||||
childFrame->FirstChild(rowFrame);
|
||||
if (nsnull!=rowFrame)
|
||||
{
|
||||
nsIFrame *cellFrame;
|
||||
rowFrame->ChildAt(0, cellFrame);
|
||||
rowFrame->FirstChild(cellFrame);
|
||||
while (nsnull!=cellFrame)
|
||||
{
|
||||
/* this is the first time we are guaranteed to have both the cell frames
|
||||
|
@ -2465,9 +2514,12 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
cellFrame->GetNextSibling(cellFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
|
||||
// second time through, set column cache info for each column
|
||||
// we can't do this until the loop above has set the column style info from the cells in the first row
|
||||
childFrame = mFirstChild;
|
||||
while (nsnull!=childFrame)
|
||||
{ // for every child, if it's a col group then get the columns
|
||||
|
@ -2476,7 +2528,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
nsTableColFrame *colFrame=nsnull;
|
||||
childFrame->ChildAt(0, (nsIFrame *&)colFrame);
|
||||
childFrame->FirstChild((nsIFrame *&)colFrame);
|
||||
while (nsnull!=colFrame)
|
||||
{ // for every column, create an entry in the column cache
|
||||
// assumes that the col style has been twiddled to account for first cell width attribute
|
||||
|
@ -2489,176 +2541,14 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
|
||||
{ // for every cell in every row, call SetCellLayoutData with the cached info
|
||||
// QQQ we can probably just leave the info in the table cell frame, not cache it here
|
||||
nsIFrame *rowFrame;
|
||||
childFrame->ChildAt(0, rowFrame);
|
||||
while (nsnull!=rowFrame)
|
||||
{
|
||||
nsIFrame *cellFrame;
|
||||
rowFrame->ChildAt(0, cellFrame);
|
||||
while (nsnull!=cellFrame)
|
||||
{
|
||||
nsCellLayoutData *cld = ((nsTableCellFrame*)cellFrame)->GetCellLayoutData();
|
||||
SetCellLayoutData(aPresContext, cld, (nsTableCellFrame*)cellFrame);
|
||||
cellFrame->GetNextSibling(cellFrame);
|
||||
}
|
||||
rowFrame->GetNextSibling(rowFrame);
|
||||
}
|
||||
break; // once we hit a row group, we're done
|
||||
}
|
||||
childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nsnull is a valid return value. This is for empty tables.
|
||||
nsVoidArray * nsTableFrame::GetColumnLayoutData()
|
||||
{
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
return firstInFlow->mColumnLayoutData;
|
||||
}
|
||||
|
||||
/** Associate aData with the cell at (aRow,aCol)
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
PRBool nsTableFrame::SetCellLayoutData(nsIPresContext* aPresContext,
|
||||
nsCellLayoutData * aData, nsTableCellFrame *aCell)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aPresContext, "bad arg aPresContext");
|
||||
NS_ASSERTION(nsnull != aData, "bad arg aData");
|
||||
NS_ASSERTION(nsnull != aCell, "bad arg aCell");
|
||||
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
if (this!=firstInFlow)
|
||||
result = firstInFlow->SetCellLayoutData(aPresContext, aData, aCell);
|
||||
else
|
||||
{
|
||||
if ((kPASS_FIRST==GetReflowPass()) || (kPASS_INCREMENTAL==GetReflowPass()))
|
||||
{
|
||||
if (nsnull==mColumnLayoutData)
|
||||
{
|
||||
PRInt32 rows = GetRowCount();
|
||||
mColumnLayoutData = new nsVoidArray();
|
||||
NS_ASSERTION(nsnull != mColumnLayoutData, "bad alloc");
|
||||
PRInt32 tableKidCount = mContent->ChildCount();
|
||||
nsIFrame * colGroupFrame = mFirstChild;
|
||||
for (PRInt32 i=0; i<tableKidCount; ) // notice increment of i is done just before ChildAt call
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
colGroupFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
nsTableColFrame *colFrame=nsnull;
|
||||
colGroupFrame->ChildAt(0, (nsIFrame *&)colFrame);
|
||||
while (nsnull!=colFrame)
|
||||
{
|
||||
// TODO: unify these 2 kinds of column data
|
||||
// TODO: cache more column data, like the mWidth.GetUnit and what its value
|
||||
nsColLayoutData *colData = new nsColLayoutData(colFrame, rows);
|
||||
mColumnLayoutData->AppendElement((void *)colData);
|
||||
colFrame->GetNextSibling((nsIFrame *&)colFrame);
|
||||
}
|
||||
}
|
||||
// can't have col groups after row groups, so stop if you find a row group
|
||||
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
ChildAt(i, colGroupFrame); // can't use colGroupFrame->GetNextSibling because it hasn't been set yet
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 firstColIndex = aCell->GetColIndex();
|
||||
nsTableRowFrame *row;
|
||||
aCell->GetGeometricParent((nsIFrame*&)row);
|
||||
PRInt32 rowIndex = row->GetRowIndex();
|
||||
PRInt32 colSpan = aCell->GetColSpan();
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(firstColIndex));
|
||||
nsVoidArray *col = colData->GetCells();
|
||||
if (gsDebugCLD) printf (" ~ SetCellLayoutData with row = %d, firstCol = %d, colSpan = %d, colData = %ld, col=%ld\n",
|
||||
rowIndex, firstColIndex, colSpan, colData, col);
|
||||
/* this logic looks wrong wrong wrong
|
||||
it seems to add an entries in col (the array of cells for a column) for aCell
|
||||
based on colspan. This is weird, because you would expect one entry in each
|
||||
column spanned for aCell, not multiple entries in the same col.
|
||||
*/
|
||||
for (PRInt32 i=0; i<colSpan; i++)
|
||||
{
|
||||
nsSize * cellSize = aData->GetMaxElementSize();
|
||||
nsSize partialCellSize(*cellSize);
|
||||
partialCellSize.width = (cellSize->width)/colSpan;
|
||||
// This method will copy the nsReflowMetrics pointed at by aData->GetDesiredSize()
|
||||
nsCellLayoutData * kidLayoutData = new nsCellLayoutData(aData->GetCellFrame(),
|
||||
aData->GetDesiredSize(),
|
||||
&partialCellSize);
|
||||
NS_ASSERTION(col->Count() > rowIndex, "unexpected count");
|
||||
if (gsDebugCLD) printf (" ~ replacing rowIndex = %d\n", rowIndex);
|
||||
nsCellLayoutData* data = (nsCellLayoutData*)col->ElementAt(rowIndex);
|
||||
col->ReplaceElementAt((void *)kidLayoutData, rowIndex);
|
||||
if (data != nsnull) {
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
result = PR_FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Get the layout data associated with the cell at (aRow,aCol)
|
||||
* @return nsnull if there was an error, such as aRow or aCol being invalid
|
||||
* otherwise, the data is returned.
|
||||
*/
|
||||
nsCellLayoutData * nsTableFrame::GetCellLayoutData(nsTableCellFrame *aCell)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aCell, "bad arg");
|
||||
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
nsCellLayoutData *result = nsnull;
|
||||
if (this!=firstInFlow)
|
||||
result = firstInFlow->GetCellLayoutData(aCell);
|
||||
else
|
||||
{
|
||||
if (nsnull!=mColumnLayoutData)
|
||||
{
|
||||
PRInt32 firstColIndex = aCell->GetColIndex();
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(firstColIndex));
|
||||
nsTableRowFrame *rowFrame;
|
||||
aCell->GetGeometricParent((nsIFrame *&)rowFrame);
|
||||
PRInt32 rowIndex = rowFrame->GetRowIndex();
|
||||
result = colData->ElementAt(rowIndex);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
// Do some sanity checking
|
||||
if (nsnull != result) {
|
||||
nsIContent* inputContent;
|
||||
nsIContent* resultContent;
|
||||
result->GetCellFrame()->GetContent(resultContent);
|
||||
aCell->GetContent(inputContent);
|
||||
NS_ASSERTION(resultContent == inputContent, "unexpected cell");
|
||||
NS_IF_RELEASE(inputContent);
|
||||
NS_IF_RELEASE(resultContent);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRInt32 nsTableFrame::GetReflowPass() const
|
||||
{
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
|
@ -2698,7 +2588,7 @@ nsTableFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
|||
// add headers and footers to cf
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
nsIFrame * rg = nsnull;
|
||||
firstInFlow->ChildAt(0, rg);
|
||||
firstInFlow->FirstChild(rg);
|
||||
NS_ASSERTION (nsnull!=rg, "previous frame has no children");
|
||||
nsIAtom * tHeadTag = NS_NewAtom(nsTablePart::kRowGroupHeadTagString); // tHeadTag: REFCNT++
|
||||
nsIAtom * tFootTag = NS_NewAtom(nsTablePart::kRowGroupFootTagString); // tFootTag: REFCNT++
|
||||
|
@ -2758,9 +2648,8 @@ PRInt32 nsTableFrame::GetColumnWidth(PRInt32 aColIndex)
|
|||
{
|
||||
NS_ASSERTION(nsnull!=mColumnWidths, "illegal state");
|
||||
#ifdef DEBUG
|
||||
nsVoidArray *cld = GetColumnLayoutData();
|
||||
NS_ASSERTION(nsnull!=cld, "no column layout data");
|
||||
PRInt32 numCols = cld->Count();
|
||||
NS_ASSERTION(nsnull!=mCellMap, "no column layout data");
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
NS_ASSERTION (numCols > aColIndex, "bad arg, col index out of bounds");
|
||||
#endif
|
||||
if (nsnull!=mColumnWidths)
|
||||
|
@ -2770,11 +2659,6 @@ PRInt32 nsTableFrame::GetColumnWidth(PRInt32 aColIndex)
|
|||
//printf("GET_COL_WIDTH: %p, FIF=%p getting col %d and returning %d\n", this, firstInFlow, aColIndex, result);
|
||||
|
||||
// XXX hack
|
||||
#if 0
|
||||
if (result <= 0) {
|
||||
result = 100;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2936,9 +2820,7 @@ NS_METHOD nsTableFrame::GetCellMarginData(nsTableCellFrame* aKidFrame, nsMargin&
|
|||
|
||||
if (nsnull != aKidFrame)
|
||||
{
|
||||
nsCellLayoutData* layoutData = GetCellLayoutData(aKidFrame);
|
||||
if (layoutData)
|
||||
result = layoutData->GetMargin(aMargin);
|
||||
result = aKidFrame->GetMargin(aMargin);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -3218,37 +3100,6 @@ PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* valuable code not yet used anywhere
|
||||
|
||||
// since the table is a specified width, we need to expand the columns to fill the table
|
||||
nsVoidArray *columnLayoutData = GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
PRInt32 spaceUsed = 0;
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
spaceUsed += mColumnWidths[colIndex];
|
||||
PRInt32 spaceRemaining = spaceUsed - aMaxWidth;
|
||||
PRInt32 additionalSpaceAdded = 0;
|
||||
if (0<spaceRemaining)
|
||||
{
|
||||
for (colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
|
||||
nsStyleMolecule* colStyle =
|
||||
(nsStyleMolecule*)mStyleContext->GetData(eStyleStruct_Molecule);
|
||||
if (PR_TRUE==IsProportionalWidth(colStyle))
|
||||
{
|
||||
PRInt32 percentage = (100*mColumnWidths[colIndex]) / aMaxWidth;
|
||||
PRInt32 additionalSpace = (spaceRemaining*percentage)/100;
|
||||
mColumnWidths[colIndex] += additionalSpace;
|
||||
additionalSpaceAdded += additionalSpace;
|
||||
}
|
||||
}
|
||||
if (spaceUsed+additionalSpaceAdded < aMaxTableWidth)
|
||||
mColumnWidths[numCols-1] += (aMaxTableWidth - (spaceUsed+additionalSpaceAdded));
|
||||
}
|
||||
*/
|
||||
|
||||
// For Debugging ONLY
|
||||
NS_METHOD nsTableFrame::MoveTo(nscoord aX, nscoord aY)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "nsStyleCoord.h"
|
||||
|
||||
class nsCellMap;
|
||||
class nsCellLayoutData;
|
||||
class nsVoidArray;
|
||||
class nsTableCellFrame;
|
||||
class nsTableColFrame;
|
||||
|
@ -42,29 +41,6 @@ struct nsStyleSpacing;
|
|||
|
||||
extern const nsIID kTableFrameCID;
|
||||
|
||||
/** Data stored by nsCellMap to rationalize rowspan and colspan cells.
|
||||
* if mCell is null then mRealCell will be the rowspan/colspan source
|
||||
* in addition, if fOverlap is non-null then it will point to the
|
||||
* other cell that overlaps this position
|
||||
* @see nsCellMap
|
||||
* @see nsTableFrame::BuildCellMap
|
||||
* @see nsTableFrame::GrowCellMap
|
||||
* @see nsTableFrame::BuildCellIntoMap
|
||||
*
|
||||
*/
|
||||
class CellData
|
||||
{
|
||||
public:
|
||||
nsTableCellFrame *mCell;
|
||||
CellData *mRealCell;
|
||||
CellData *mOverlap;
|
||||
|
||||
CellData();
|
||||
|
||||
~CellData();
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================================ */
|
||||
|
||||
/** nsTableFrame maps the inner portion of a table (everything except captions.)
|
||||
|
@ -153,36 +129,12 @@ public:
|
|||
*/
|
||||
NS_METHOD GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame);
|
||||
|
||||
/** return the column layout data for this inner table frame.
|
||||
* if this is a continuing frame, return the first-in-flow's column layout data.
|
||||
* @return the column layout data array, or null if there is no info yet.
|
||||
*/
|
||||
virtual nsVoidArray *GetColumnLayoutData();
|
||||
|
||||
/** Associate aData with the cell at (aRow,aCol)
|
||||
*
|
||||
* @param aPresContext -- used to resolve style when initializing caches
|
||||
* @param aData -- the info to cache
|
||||
* @param aCell -- the content object for which layout info is being cached
|
||||
*
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
virtual PRBool SetCellLayoutData(nsIPresContext * aPresContext,
|
||||
nsCellLayoutData * aData,
|
||||
nsTableCellFrame * aCell);
|
||||
|
||||
/** Get the layout data associated with the cell at (aRow,aCol)
|
||||
* @return PR_NULL if there was an error, such as aRow or aCol being invalid
|
||||
* otherwise, the data is returned.
|
||||
*/
|
||||
virtual nsCellLayoutData * GetCellLayoutData(nsTableCellFrame *aCell);
|
||||
|
||||
/**
|
||||
* DEBUG METHOD
|
||||
*
|
||||
*/
|
||||
virtual void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
//virtual void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
|
||||
|
||||
/** return the width of the column at aColIndex */
|
||||
|
@ -236,11 +188,6 @@ protected:
|
|||
/** destructor, responsible for mColumnLayoutData and mColumnWidths */
|
||||
virtual ~nsTableFrame();
|
||||
|
||||
/** helper method to delete contents of mColumnLayoutData
|
||||
* should be called with care (ie, only by destructor)
|
||||
*/
|
||||
virtual void DeleteColumnLayoutData();
|
||||
|
||||
/** first pass of ResizeReflow.
|
||||
* lays out all table content with aMaxSize(NS_UNCONSTRAINEDSIZE,NS_UNCONSTRAINEDSIZE) and
|
||||
* a non-null aMaxElementSize so we get all the metrics we need to do column balancing.
|
||||
|
@ -380,6 +327,16 @@ protected:
|
|||
*/
|
||||
virtual void ResetCellMap ();
|
||||
|
||||
/** for debugging only
|
||||
* prints out information about the cell map
|
||||
*/
|
||||
void DumpCellMap() const;
|
||||
|
||||
/** for debugging only
|
||||
* prints out info about the table layout state, printing columns and their cells
|
||||
*/
|
||||
void ListColumnLayoutData(FILE* out, PRInt32 aIndent) const;
|
||||
|
||||
/** ResetColumns is called when the column structure of the table is changed.
|
||||
* Call with caution, only when adding or removing columns, changing
|
||||
* column attributes, changing the rowspan or colspan attribute of a cell, etc.
|
||||
|
@ -418,13 +375,6 @@ protected:
|
|||
*/
|
||||
virtual nsTableRowGroupFrame* NextRowGroupFrame (nsTableRowGroupFrame*);
|
||||
|
||||
/** returns the number of rows in this table.
|
||||
* if mCellMap has been created, it is asked for the number of rows.<br>
|
||||
* otherwise, the content is enumerated and the rows are counted.
|
||||
*/
|
||||
virtual PRInt32 GetRowCount();
|
||||
|
||||
|
||||
/** return the number of columns as specified by the input.
|
||||
* has 2 side effects:<br>
|
||||
* calls SetStartColumnIndex on each nsTableColumn<br>
|
||||
|
@ -432,9 +382,18 @@ protected:
|
|||
*/
|
||||
virtual PRInt32 GetSpecifiedColumnCount ();
|
||||
|
||||
public:
|
||||
virtual void DumpCellMap() const;
|
||||
virtual nsCellMap* GetCellMap() const;
|
||||
public: /* ----- Cell Map public methods ----- */
|
||||
|
||||
/** returns the number of rows in this table.
|
||||
* if mCellMap has been created, it is asked for the number of rows.<br>
|
||||
* otherwise, the content is enumerated and the rows are counted.
|
||||
*/
|
||||
virtual PRInt32 GetRowCount();
|
||||
|
||||
nsTableColFrame * GetColFrame(PRInt32 aColIndex);
|
||||
|
||||
nsTableCellFrame * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
@ -446,9 +405,7 @@ private:
|
|||
*/
|
||||
enum {kPASS_UNDEFINED=0, kPASS_FIRST=1, kPASS_SECOND=2, kPASS_THIRD=3, kPASS_INCREMENTAL=4};
|
||||
|
||||
nsVoidArray *mColumnLayoutData; // array of array of cellLayoutData's
|
||||
PRInt32 *mColumnWidths; // widths of each column
|
||||
//TODO: move all column info into this object
|
||||
ColumnInfoCache *mColCache; // cached information about the table columns
|
||||
PRBool mFirstPassValid; // PR_TRUE if first pass data is still legit
|
||||
PRInt32 mPass; // which Reflow pass are we currently in?
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "nsTableRowGroup.h"
|
||||
#include "nsTableCell.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsHTMLContainer.h"
|
||||
#include "nsTableRowFrame.h"
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include "nsTableFrame.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsColLayoutData.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
|
@ -37,6 +35,7 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
static PRBool gsDebug1 = PR_FALSE;
|
||||
static PRBool gsDebug2 = PR_FALSE;
|
||||
//#define NOISY
|
||||
//#define NOISY_FLOW
|
||||
#else
|
||||
static const PRBool gsDebug1 = PR_FALSE;
|
||||
static const PRBool gsDebug2 = PR_FALSE;
|
||||
|
@ -51,6 +50,9 @@ struct RowReflowState {
|
|||
// The body's available size (computed from the body's parent)
|
||||
nsSize availSize;
|
||||
|
||||
// the running x-offset
|
||||
nscoord x;
|
||||
|
||||
// Height of tallest cell (excluding cells with rowspan > 1)
|
||||
nscoord maxCellHeight; // just the height of the cell frame
|
||||
nscoord maxCellVertSpace; // the maximum MAX(cellheight + topMargin + bottomMargin)
|
||||
|
@ -68,6 +70,7 @@ struct RowReflowState {
|
|||
maxCellHeight = 0;
|
||||
maxCellVertSpace = 0;
|
||||
tableFrame = aTableFrame;
|
||||
x=0;
|
||||
}
|
||||
|
||||
~RowReflowState() {
|
||||
|
@ -111,12 +114,12 @@ nsTableRowFrame::DidReflow(nsIPresContext& aPresContext,
|
|||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(mRowIndex, cellFrame);
|
||||
if (1==rowSpan)
|
||||
{
|
||||
// Resize the cell's height
|
||||
// resize the cell's height
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
cellFrame->SizeTo(cellFrameSize.width, cellHeight);
|
||||
|
||||
// Realign cell content based on the new height
|
||||
// realign cell content based on the new height
|
||||
cellFrame->VerticallyAlignChild(&aPresContext);
|
||||
}
|
||||
|
||||
|
@ -287,6 +290,9 @@ void nsTableRowFrame::PlaceChild(nsIPresContext* aPresContext,
|
|||
// Place and size the child
|
||||
aKidFrame->SetRect(aKidRect);
|
||||
|
||||
// update the running total for the row width
|
||||
aState.x += aKidRect.width;
|
||||
|
||||
// Update the maximum element size
|
||||
PRInt32 rowSpan = ((nsTableCellFrame*)aKidFrame)->GetRowSpan();
|
||||
if (nsnull != aMaxElementSize)
|
||||
|
@ -328,6 +334,8 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
NS_PRECONDITION(nsnull != mFirstChild, "no children");
|
||||
|
||||
nsSize kidMaxElementSize;
|
||||
PRBool result = PR_TRUE;
|
||||
PRInt32 prevColIndex = -1; // remember the col index of the previous cell to handle rowspans into this row
|
||||
nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ?
|
||||
&kidMaxElementSize : nsnull;
|
||||
nscoord maxCellTopMargin = 0;
|
||||
|
@ -335,6 +343,13 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
|
||||
// Reflow each of our existing cell frames
|
||||
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
|
||||
nsSize kidAvailSize(aState.availSize);
|
||||
if (0>=kidAvailSize.height)
|
||||
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
|
||||
|
||||
nsReflowMetrics desiredSize(pKidMaxElementSize);
|
||||
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
|
||||
|
||||
// Get the frame's margins, and compare the top and bottom margin
|
||||
// against our current max values
|
||||
nsMargin kidMargin;
|
||||
|
@ -344,15 +359,49 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
if (kidMargin.bottom > maxCellBottomMargin)
|
||||
maxCellBottomMargin = kidMargin.bottom;
|
||||
|
||||
// Figure out the amount of available size for the child (subtract
|
||||
// off the top margin we are going to apply to it)
|
||||
|
||||
//XXX TROY??? unconstrainedHeight was removed from aState, what should happen here?
|
||||
/*
|
||||
if (PR_FALSE == aState.unconstrainedHeight)
|
||||
{
|
||||
kidAvailSize.height -= kidMargin.top + kidMargin.bottom;
|
||||
}
|
||||
*/
|
||||
|
||||
// left and right margins already taken into account by table layout strategy
|
||||
|
||||
// Compute the x-origin for the child
|
||||
//
|
||||
// XXX Having to re-compute the value each time from scratch is very inefficent...
|
||||
nscoord x = ComputeCellXOffset(aState, kidFrame, kidMargin);
|
||||
// Compute the x-origin for the child, taking into account straddlers (cells from prior
|
||||
// rows with rowspans > 1)
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
if (prevColIndex != (cellColIndex-1))
|
||||
{ // if this cell is not immediately adjacent to the previous cell, factor in missing col info
|
||||
for (PRInt32 colIndex=prevColIndex+1; colIndex<cellColIndex; colIndex++)
|
||||
{
|
||||
aState.x += aState.tableFrame->GetColumnWidth(colIndex);
|
||||
aState.x += kidMargin.left + kidMargin.right;
|
||||
}
|
||||
}
|
||||
aState.x += kidMargin.left;
|
||||
|
||||
// at this point, we know the column widths.
|
||||
// so we get the avail width from the known column widths
|
||||
PRInt32 cellColSpan = ((nsTableCellFrame *)kidFrame)->GetColSpan();
|
||||
nscoord availWidth = 0;
|
||||
for (PRInt32 numColSpan=0; numColSpan<cellColSpan; numColSpan++)
|
||||
{
|
||||
availWidth += aState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
|
||||
if (0<numColSpan)
|
||||
{
|
||||
availWidth += kidMargin.right;
|
||||
if (0!=cellColIndex)
|
||||
availWidth += kidMargin.left;
|
||||
}
|
||||
}
|
||||
|
||||
prevColIndex = cellColIndex + (cellColSpan-1); // remember the rightmost column this cell spans into
|
||||
|
||||
// Compute the cell available width from the column widths
|
||||
nscoord availWidth = ComputeCellAvailWidth(aState, kidFrame);
|
||||
|
||||
// If the available width is the same as last time we reflowed the cell,
|
||||
// then just use the previous desired size
|
||||
|
@ -360,7 +409,6 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
// XXX Wouldn't it be cleaner (but slightly less efficient) for the row to
|
||||
// just reflow the cell, and have the cell decide whether it could use the
|
||||
// cached value rather than having the row make that determination?
|
||||
nsReflowMetrics desiredSize(pKidMaxElementSize);
|
||||
if (availWidth != ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth())
|
||||
{
|
||||
// Always let the cell be as high as it wants. We ignore the height that's
|
||||
|
@ -370,7 +418,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
|
||||
// Reflow the child
|
||||
kidFrame->WillReflow(*aPresContext);
|
||||
kidFrame->MoveTo(x, kidMargin.top);
|
||||
kidFrame->MoveTo(aState.x, kidMargin.top);
|
||||
kidAvailSize.width = availWidth;
|
||||
nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize,
|
||||
eReflowReason_Resize);
|
||||
|
@ -393,12 +441,12 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
}
|
||||
else
|
||||
{
|
||||
nsSize priorSize = ((nsTableCellFrame *)kidFrame)->GetPriorDesiredSize();
|
||||
nsSize priorSize = ((nsTableCellFrame *)kidFrame)->GetDesiredSize();
|
||||
desiredSize.width = priorSize.width;
|
||||
desiredSize.height = priorSize.height;
|
||||
}
|
||||
|
||||
// Place the child after taking into account its margin and attributes
|
||||
// Place the child after taking into account it's margin and attributes
|
||||
nscoord specifiedHeight = 0;
|
||||
nscoord cellHeight = desiredSize.height;
|
||||
nsIStyleContextPtr kidSC;
|
||||
|
@ -423,19 +471,20 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
// begin special Nav4 compatibility code
|
||||
if (0==cellWidth)
|
||||
{
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
|
||||
}
|
||||
// end special Nav4 compatibility code
|
||||
|
||||
// Place the child
|
||||
nsRect kidRect (x, kidMargin.top, cellWidth, cellHeight);
|
||||
nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight);
|
||||
|
||||
PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
|
||||
pKidMaxElementSize);
|
||||
aState.x += kidMargin.right; // add in right margin only after cell has been placed
|
||||
|
||||
// Get the next child
|
||||
kidFrame->GetNextSibling(kidFrame);
|
||||
|
||||
}
|
||||
|
||||
SetMaxChildHeight(aState.maxCellHeight,maxCellTopMargin, maxCellBottomMargin); // remember height of tallest child who doesn't have a row span
|
||||
|
@ -448,42 +497,6 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compute the x-origin for the child by summing up the width of each
|
||||
// prior column. This correctly handles cells from prior rows with rowspans
|
||||
// > 1
|
||||
nscoord nsTableRowFrame::ComputeCellXOffset(const RowReflowState& aState,
|
||||
nsIFrame* aKidFrame,
|
||||
const nsMargin& aKidMargin) const
|
||||
{
|
||||
nscoord x = aKidMargin.left;
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)aKidFrame)->GetColIndex();
|
||||
|
||||
for (PRInt32 colIndex = 0; colIndex < cellColIndex; colIndex++)
|
||||
{
|
||||
x += aState.tableFrame->GetColumnWidth(colIndex);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// Computes the avail width for the cell. Takes into account column
|
||||
// spans
|
||||
nscoord nsTableRowFrame::ComputeCellAvailWidth(const RowReflowState& aState,
|
||||
nsIFrame* aKidFrame) const
|
||||
{
|
||||
nscoord availWidth = 0;
|
||||
nsCellLayoutData *cellData = aState.tableFrame->GetCellLayoutData((nsTableCellFrame *)aKidFrame);
|
||||
PRInt32 cellStartingCol = ((nsTableCellFrame *)aKidFrame)->GetColIndex();
|
||||
PRInt32 cellColSpan = ((nsTableCellFrame *)aKidFrame)->GetColSpan();
|
||||
|
||||
for (PRInt32 numColSpan = 0; numColSpan < cellColSpan; numColSpan++)
|
||||
{
|
||||
availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol + numColSpan);
|
||||
}
|
||||
|
||||
return availWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called for the initial reflow. Creates each table cell frame, and
|
||||
* reflows it to gets its minimum and maximum sizes
|
||||
|
@ -570,13 +583,10 @@ nsTableRowFrame::InitialReflow(nsIPresContext* aPresContext,
|
|||
|
||||
kidFrame->WillReflow(*aPresContext);
|
||||
status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState);
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1DesiredSize(kidSize);
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "unexpected child reflow status");
|
||||
|
||||
// Allocate and set the cell layout data
|
||||
nsCellLayoutData *kidLayoutData = new nsCellLayoutData((nsTableCellFrame *)kidFrame,
|
||||
&kidSize, &kidMaxElementSize);
|
||||
((nsTableCellFrame *)kidFrame)->SetCellLayoutData(kidLayoutData);
|
||||
|
||||
if (gsDebug1)
|
||||
{
|
||||
printf("reflow of cell returned result = %s with desired=%d,%d, min = %d,%d\n",
|
||||
|
@ -630,13 +640,12 @@ nsresult nsTableRowFrame::RecoverState(RowReflowState& aState,
|
|||
for (nsIFrame* frame = mFirstChild; frame != aKidFrame;) {
|
||||
PRInt32 rowSpan = ((nsTableCellFrame*)frame)->GetRowSpan();
|
||||
if (mMinRowSpan == rowSpan) {
|
||||
// XXX This isn't quite right. We also need to check whether the cell
|
||||
// has a height property that affects the cell...
|
||||
nsSize desiredSize = ((nsTableCellFrame *)frame)->GetPriorDesiredSize();
|
||||
nsRect rect;
|
||||
frame->GetRect(rect);
|
||||
|
||||
// Update maxCellHeight
|
||||
if (desiredSize.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = desiredSize.height;
|
||||
if (rect.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = rect.height;
|
||||
}
|
||||
|
||||
// Update maxCellVertHeight
|
||||
|
@ -644,18 +653,14 @@ nsresult nsTableRowFrame::RecoverState(RowReflowState& aState,
|
|||
|
||||
if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, margin) == NS_OK)
|
||||
{
|
||||
nscoord height = desiredSize.height + margin.top + margin.bottom;
|
||||
nscoord height = rect.height + margin.top + margin.bottom;
|
||||
if (height > aState.maxCellVertSpace) {
|
||||
aState.maxCellVertSpace = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX We also need to recover the max element size if requested by the
|
||||
// caller...
|
||||
//
|
||||
// We should be using GetReflowMetrics() to get information from the
|
||||
// table cell, and that will include the max element size...
|
||||
// XXX We also need to recover the max element size...
|
||||
|
||||
// Remember the frame that precedes aKidFrame
|
||||
prevKidFrame = frame;
|
||||
|
@ -687,20 +692,30 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
// Recover our reflow state
|
||||
RecoverState(aState, kidFrame);
|
||||
|
||||
// Get the frame's margins
|
||||
// Figure out the amount of available space for the child
|
||||
nsMargin kidMargin;
|
||||
aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame,kidMargin);
|
||||
|
||||
// Figure out the amount of available space for the child
|
||||
// XXX Shakey...
|
||||
nsSize kidAvailSize(aState.availSize);
|
||||
nsSize kidAvailSize(aState.availSize); // XXX: top and bottom margins?
|
||||
|
||||
// Compute the x-origin for the child, taking into account straddlers (cells
|
||||
// from prior rows with rowspans > 1)
|
||||
nscoord x = ComputeCellXOffset(aState, kidFrame, kidMargin);
|
||||
// Compute the x-origin for the child, taking into account straddlers (cells from prior
|
||||
// rows with rowspans > 1)
|
||||
nscoord x = kidMargin.left;
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
for (PRInt32 colIndex=0; colIndex<cellColIndex; colIndex++)
|
||||
{
|
||||
x += aState.tableFrame->GetColumnWidth(colIndex);
|
||||
}
|
||||
|
||||
// Compute the cell avail width from the column widths
|
||||
nscoord availWidth = ComputeCellAvailWidth(aState, kidFrame);
|
||||
// at this point, we know the column widths.
|
||||
// so we get the avail width from the known column widths
|
||||
PRInt32 cellStartingCol = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
PRInt32 cellColSpan = ((nsTableCellFrame *)kidFrame)->GetColSpan();
|
||||
nscoord availWidth = 0;
|
||||
for (PRInt32 numColSpan=0; numColSpan<cellColSpan; numColSpan++)
|
||||
availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan);
|
||||
kidAvailSize.width = availWidth;
|
||||
|
||||
// Pass along the reflow command. Reflow the child with an unconstrained
|
||||
|
@ -726,23 +741,16 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
kidReflowState.maxSize.width = NS_UNCONSTRAINEDSIZE;
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState);
|
||||
|
||||
// Update the cell layout data. Note that we need to do this for both
|
||||
// the data the cell maintains AND the data the table maintains...
|
||||
nsCellLayoutData *kidLayoutData = ((nsTableCellFrame *)kidFrame)->GetCellLayoutData();
|
||||
|
||||
kidLayoutData->SetDesiredSize(&desiredSize);
|
||||
kidLayoutData->SetMaxElementSize(&kidMaxElementSize);
|
||||
|
||||
kidLayoutData = aState.tableFrame->GetCellLayoutData((nsTableCellFrame*)kidFrame);
|
||||
kidLayoutData->SetDesiredSize(&desiredSize);
|
||||
kidLayoutData->SetMaxElementSize(&kidMaxElementSize);
|
||||
// Update the cell layout data.
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1DesiredSize(desiredSize);
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
|
||||
// Now reflow the cell again this time constraining the width
|
||||
// XXX Ignore for now the possibility that the column width has changed...
|
||||
kidReflowState.maxSize.width = availWidth;
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState);
|
||||
|
||||
// Place the child after taking into account its margin and attributes
|
||||
// Place the child after taking into account it's margin and attributes
|
||||
nscoord specifiedHeight = 0;
|
||||
nscoord cellHeight = desiredSize.height;
|
||||
nsIStyleContextPtr kidSC;
|
||||
|
@ -767,7 +775,6 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
// begin special Nav4 compatibility code
|
||||
if (0==cellWidth)
|
||||
{
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
|
||||
}
|
||||
// end special Nav4 compatibility code
|
||||
|
@ -781,8 +788,8 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
// Now iterate over the remaining cells, and update our max cell
|
||||
// height and our running x-offset
|
||||
//
|
||||
// We don't have to re-position the x-origin of any of the child frames
|
||||
// that follow, because the column width hasn't changed...
|
||||
// We don't have to re-position any of the child frames that follow, because
|
||||
// the column width hasn't changed...
|
||||
nscoord maxCellTopMargin = 0;
|
||||
nscoord maxCellBottomMargin = 0;
|
||||
kidFrame->GetNextSibling((nsIFrame*&)kidFrame);
|
||||
|
@ -791,11 +798,9 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
nsRect rect;
|
||||
kidFrame->GetRect(rect);
|
||||
if (mMinRowSpan == rowSpan) {
|
||||
nsSize desiredSize = ((nsTableCellFrame *)kidFrame)->GetPriorDesiredSize();
|
||||
|
||||
// Update maxCellHeight
|
||||
if (desiredSize.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = desiredSize.height;
|
||||
if (rect.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = rect.height;
|
||||
}
|
||||
|
||||
// Update maxCellVertHeight
|
||||
|
@ -803,7 +808,7 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
|
||||
if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, margin) == NS_OK)
|
||||
{
|
||||
nscoord height = desiredSize.height + margin.top + margin.bottom;
|
||||
nscoord height = rect.height + margin.top + margin.bottom;
|
||||
if (height > aState.maxCellVertSpace) {
|
||||
aState.maxCellVertSpace = height;
|
||||
}
|
||||
|
@ -899,16 +904,22 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_METHOD
|
||||
nsTableRowFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aStyleContext,
|
||||
nsIFrame*& aContinuingFrame)
|
||||
{
|
||||
// Because rows are always complete we should never be asked to create
|
||||
// a continuing frame
|
||||
NS_ERROR("Unexpected request");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (gsDebug1==PR_TRUE) printf("nsTableRowFrame::CreateContinuingFrame\n");
|
||||
nsTableRowFrame* cf = new nsTableRowFrame(mContent, aParent);
|
||||
if (nsnull == cf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsTableRowFrame::NewFrame( nsIFrame** aInstancePtrResult,
|
||||
|
|
|
@ -29,13 +29,11 @@
|
|||
#include "nsIReflowCommand.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug1 = PR_FALSE;
|
||||
static PRBool gsDebug2 = PR_FALSE;
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
//#define NOISY
|
||||
//#define NOISY_FLOW
|
||||
#else
|
||||
static const PRBool gsDebug1 = PR_FALSE;
|
||||
static const PRBool gsDebug2 = PR_FALSE;
|
||||
static const PRBool gsDebug = PR_FALSE;
|
||||
#endif
|
||||
|
||||
NS_DEF_PTR(nsIStyleContext);
|
||||
|
@ -195,7 +193,7 @@ void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
|
|||
nsSize* aMaxElementSize,
|
||||
nsSize& aKidMaxElementSize)
|
||||
{
|
||||
if (PR_TRUE==gsDebug1)
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf ("rowgroup: placing row at %d, %d, %d, %d\n",
|
||||
aKidRect.x, aKidRect.y, aKidRect.width, aKidRect.height);
|
||||
|
||||
|
@ -256,7 +254,7 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
|||
#endif
|
||||
#endif
|
||||
NS_PRECONDITION(nsnull != mFirstChild, "no children");
|
||||
|
||||
if (gsDebug) printf("\n\nREFLOWMAPPED FOR ROW GROUP FRAME\n");
|
||||
PRInt32 childCount = 0;
|
||||
nsIFrame* prevKidFrame = nsnull;
|
||||
|
||||
|
@ -1039,7 +1037,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
|||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
if (gsDebug1==PR_TRUE)
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf("nsTableRowGroupFrame::Reflow - aMaxSize = %d, %d\n",
|
||||
aReflowState.maxSize.width, aReflowState.maxSize.height);
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -1153,7 +1151,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
|||
PostReflowCheck(aStatus);
|
||||
#endif
|
||||
|
||||
if (gsDebug1==PR_TRUE)
|
||||
if (gsDebug==PR_TRUE)
|
||||
{
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
printf("nsTableRowGroupFrame::RR returning: %s with aDesiredSize=%d,%d, aMES=%d,%d\n",
|
||||
|
@ -1181,7 +1179,7 @@ nsTableRowGroupFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
|
||||
if (PR_TRUE==gsDebug1) printf("nsTableRowGroupFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf);
|
||||
if (PR_TRUE==gsDebug) printf("nsTableRowGroupFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf);
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -19,16 +19,13 @@
|
|||
#include "BasicTableLayoutStrategy.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsColLayoutData.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsTableCol.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
|
||||
NS_DEF_PTR(nsTableCol);
|
||||
NS_DEF_PTR(nsIStyleContext);
|
||||
|
||||
|
||||
|
@ -64,6 +61,23 @@ struct ProportionalColumnLayoutStruct
|
|||
};
|
||||
|
||||
|
||||
/* ---------- ColSpanStruct ---------- */
|
||||
struct ColSpanStruct
|
||||
{
|
||||
PRInt32 colIndex;
|
||||
PRInt32 colSpan;
|
||||
nscoord width;
|
||||
|
||||
ColSpanStruct(PRInt32 aSpan, PRInt32 aIndex, nscoord aWidth)
|
||||
{
|
||||
colSpan = aSpan;
|
||||
colIndex = aIndex;
|
||||
width = aWidth;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* ---------- BasicTableLayoutStrategy ---------- */
|
||||
|
||||
|
@ -228,7 +242,9 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
|
||||
if (gsDebug==PR_TRUE) printf (" AssignFixedColumnWidths\n");
|
||||
nsVoidArray *spanList=nsnull;
|
||||
|
||||
nsVoidArray *colSpanList=nsnull;
|
||||
nscoord * effectiveColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
|
||||
PRBool hasColsAttribute = (PRBool)(NS_STYLE_TABLE_COLS_NONE!=mCols);
|
||||
|
||||
|
@ -240,26 +256,24 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
maxColWidthArray = new PRInt32[mNumCols];
|
||||
}
|
||||
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
|
||||
// for every column, determine it's min and max width, and keep track of the table width
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
NS_ASSERTION(nsnull != colData, "bad column data");
|
||||
nsTableColFrame *colFrame = colData->GetColFrame();
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
|
||||
// need to track min/max column width for setting min/max table widths
|
||||
// QQQ: Eventually, this will be cached in col frame
|
||||
// We'll just ask the column frame to compute this, and it'll use cached info if available
|
||||
PRInt32 minColWidth = 0;
|
||||
PRInt32 maxColWidth = 0;
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 numCells = cells->Count();
|
||||
if (gsDebug==PR_TRUE) printf (" for column %d numCells = %d\n", colIndex, numCells);
|
||||
|
||||
// Get column information
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
|
||||
// Get the columns's style
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
const nsStylePosition* colPosition = (const nsStylePosition*) colSC->GetStyleData(eStyleStruct_Position);
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
|
||||
// Get column width if it has one
|
||||
PRBool haveColWidth = PR_FALSE;
|
||||
|
@ -268,7 +282,7 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
case eStyleUnit_Coord:
|
||||
haveColWidth = PR_TRUE;
|
||||
specifiedFixedColWidth = colPosition->mWidth.GetCoordValue();
|
||||
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth); //QQQ add in margins?
|
||||
mTableFrame->SetColumnWidth(colIndex, specifiedFixedColWidth);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -303,38 +317,49 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
}
|
||||
}
|
||||
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
PRInt32 firstRowIndex = -1;
|
||||
for (PRInt32 rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull == data) {
|
||||
// For cells that span rows there's only cell layout data for the first row
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
if (-1==firstRowIndex)
|
||||
firstRowIndex = rowIndex;
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
if (colIndex!=cellFrame->GetColIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetColSpan(), "col index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
nsMargin margin;
|
||||
nsresult result = data->GetMargin(margin);
|
||||
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
nsReflowMetrics * cellDesiredSize = data->GetDesiredSize();
|
||||
NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize");
|
||||
PRInt32 colSpan = data->GetCellFrame()->GetColSpan();
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d, margins %d %d\n",
|
||||
cellIndex, colSpan, cellMinSize->width, cellMinSize->height,
|
||||
cellDesiredSize->width, cellDesiredSize->height,
|
||||
margin.left, margin.right);
|
||||
printf (" for cell %d with colspan=%d, min = %d,%d and des = %d,%d\n",
|
||||
rowIndex, colSpan, cellMinSize.width, cellMinSize.height,
|
||||
cellDesiredSize.width, cellDesiredSize.height);
|
||||
|
||||
switch (colPosition->mWidth.GetUnit()) {
|
||||
switch (colPosition->mWidth.GetUnit())
|
||||
{
|
||||
case eStyleUnit_Coord:
|
||||
{
|
||||
// This col has a fixed width, so set the cell's width to the
|
||||
// larger of (specified width, largest max_element_size of the
|
||||
// cells in the column)
|
||||
PRInt32 widthForThisCell = PR_MAX(cellMinSize->width, colPosition->mWidth.GetCoordValue());
|
||||
if (mTableFrame->GetColumnWidth(colIndex) < widthForThisCell)
|
||||
nscoord widthForThisCell = PR_MAX(cellMinSize.width, colPosition->mWidth.GetCoordValue());
|
||||
widthForThisCell = widthForThisCell/colSpan;
|
||||
nscoord widthFromCol = mTableFrame->GetColumnWidth(colIndex);
|
||||
if (widthFromCol < widthForThisCell)
|
||||
{
|
||||
if (gsDebug) printf (" setting fixed width to %d\n",widthForThisCell);
|
||||
mTableFrame->SetColumnWidth(colIndex, widthForThisCell); //QQQ add in margins?
|
||||
mTableFrame->SetColumnWidth(colIndex, widthForThisCell);
|
||||
maxColWidth = widthForThisCell;
|
||||
}
|
||||
}
|
||||
|
@ -347,24 +372,24 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
|
||||
// regardless of the width specification, keep track of the
|
||||
// min/max column widths
|
||||
nscoord cellMinWidth = cellMinSize->width/colSpan;
|
||||
nscoord cellDesiredWidth = cellDesiredSize->width/colSpan;
|
||||
|
||||
if (aMaxWidth!=cellDesiredSize->width)
|
||||
{
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellMinWidth)
|
||||
cellMinWidth += margin.left + margin.right;
|
||||
if (NS_UNCONSTRAINEDSIZE!=cellDesiredWidth)
|
||||
cellDesiredWidth += margin.left + margin.right;
|
||||
}
|
||||
|
||||
nscoord cellMinWidth = cellMinSize.width/colSpan;
|
||||
nscoord cellDesiredWidth = cellDesiredSize.width/colSpan;
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
if (maxColWidth < cellDesiredWidth)
|
||||
maxColWidth = cellDesiredWidth;
|
||||
// effectiveColumnWidth is the width as if no cells with colspans existed
|
||||
if ((1==colSpan) && (effectiveColumnWidths[colIndex] < maxColWidth))
|
||||
effectiveColumnWidths[colIndex] = cellDesiredWidth;
|
||||
if (1<colSpan)
|
||||
{
|
||||
// add the cell to our list of spanners
|
||||
// add the column to our list of post-process columns
|
||||
ColSpanStruct *colSpanInfo = new ColSpanStruct(colSpan, colIndex, cellDesiredSize.width);
|
||||
if (nsnull==colSpanList)
|
||||
colSpanList = new nsVoidArray();
|
||||
colSpanList->AppendElement(colSpanInfo);
|
||||
|
||||
// add the cell to our list of spanning cells
|
||||
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
|
||||
if (nsnull==spanList)
|
||||
spanList = new nsVoidArray();
|
||||
|
@ -372,26 +397,30 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
}
|
||||
if (gsDebug) {
|
||||
printf (" after cell %d, minColWidth = %d and maxColWidth = %d\n",
|
||||
cellIndex, minColWidth, maxColWidth);
|
||||
rowIndex, minColWidth, maxColWidth);
|
||||
}
|
||||
}
|
||||
|
||||
// do all the global bookkeeping, factoring in margins
|
||||
nsTableCellFrame * firstCellInColumn = mTableFrame->GetCellAt(firstRowIndex, colIndex);
|
||||
nsMargin colMargin;
|
||||
firstCellInColumn->GetMargin(colMargin);
|
||||
nscoord colInset = colMargin.left + colMargin.right;
|
||||
// keep a running total of the amount of space taken up by all fixed-width columns
|
||||
if (PR_TRUE==haveColWidth)
|
||||
aTotalFixedWidth += mTableFrame->GetColumnWidth(colIndex);
|
||||
aTotalFixedWidth += mTableFrame->GetColumnWidth(colIndex) + colInset;
|
||||
|
||||
if (gsDebug) {
|
||||
printf (" after col %d, aTotalFixedWidth = %d\n",
|
||||
colIndex, aTotalFixedWidth);
|
||||
}
|
||||
|
||||
// add col[i] metrics to the running totals for the table min/max width
|
||||
if (NS_UNCONSTRAINEDSIZE!=aMinTableWidth)
|
||||
aMinTableWidth += minColWidth; // SEC: insets!
|
||||
aMinTableWidth += minColWidth + colInset;
|
||||
if (aMinTableWidth<=0)
|
||||
aMinTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
|
||||
if (NS_UNCONSTRAINEDSIZE!=aMaxTableWidth)
|
||||
aMaxTableWidth += maxColWidth; // SEC: insets!
|
||||
aMaxTableWidth += maxColWidth + colInset;
|
||||
if (aMaxTableWidth<=0)
|
||||
aMaxTableWidth = NS_UNCONSTRAINEDSIZE; // handle overflow
|
||||
if (PR_TRUE==hasColsAttribute)
|
||||
|
@ -441,15 +470,59 @@ PRBool BasicTableLayoutStrategy::AssignFixedColumnWidths(nsIPresContext* aPresCo
|
|||
delete [] minColWidthArray;
|
||||
delete [] maxColWidthArray;
|
||||
}
|
||||
if (nsnull!=colSpanList)
|
||||
DistributeFixedSpace(colSpanList, effectiveColumnWidths);
|
||||
// today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in
|
||||
if (nsnull!=effectiveColumnWidths)
|
||||
delete [] effectiveColumnWidths;
|
||||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf ("%p: aMinTW=%d, aMaxTW=%d\n", mTableFrame, aMinTableWidth, aMaxTableWidth);
|
||||
|
||||
if (nsnull!=spanList)
|
||||
delete spanList;
|
||||
if (nsnull!=colSpanList)
|
||||
delete colSpanList;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// take the fixed space spanned by the columns in aColSpanList
|
||||
// and distribute it proportionately (based on desired width)
|
||||
void BasicTableLayoutStrategy::DistributeFixedSpace(nsVoidArray *aColSpanList, nscoord *aColWidths)
|
||||
{
|
||||
nscoord excess = 0;
|
||||
if (PR_TRUE==gsDebug) printf ("DistributeFixedSpace:\n");
|
||||
// for all fixed-width columns, determine the amount of the specified width each column spanned recieves
|
||||
PRInt32 numSpanningCells = aColSpanList->Count();
|
||||
for (PRInt32 nextSpanningCell=0; nextSpanningCell<numSpanningCells; nextSpanningCell++)
|
||||
{ // proportionately distributed extra space, based on the column's fixed width
|
||||
ColSpanStruct * colInfo = (ColSpanStruct *)aColSpanList->ElementAt(nextSpanningCell);
|
||||
PRInt32 colIndex = colInfo->colIndex;
|
||||
PRInt32 colSpan = colInfo->colSpan;
|
||||
nscoord totalColWidth = colInfo->width;
|
||||
|
||||
// 1. get the sum of the effective widths of the columns in the span
|
||||
nscoord totalEffectiveWidth=0;
|
||||
PRInt32 i;
|
||||
for (i = 0; i<colSpan; i++)
|
||||
{
|
||||
totalEffectiveWidth += aColWidths[colIndex+i];
|
||||
}
|
||||
|
||||
// 2. next, compute the proportion to be added to each column, and add it
|
||||
for (i = 0; i<colSpan; i++)
|
||||
{
|
||||
float percent;
|
||||
percent = ((float)(aColWidths[colIndex+i]))/((float)totalEffectiveWidth);
|
||||
nscoord colWidth = (nscoord)(totalColWidth*percent);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" assigning fixed col width for spanning cells: column %d set to %d\n",
|
||||
colIndex+i, colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex+i, colWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool BasicTableLayoutStrategy::BalanceProportionalColumns(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nscoord aAvailWidth,
|
||||
|
@ -529,35 +602,37 @@ PRBool BasicTableLayoutStrategy::SetColumnsToMinWidth(nsIPresContext* aPresConte
|
|||
minColWidthArray = new PRInt32[mNumCols];
|
||||
}
|
||||
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 minColWidth = 0;
|
||||
PRInt32 maxColWidth = 0;
|
||||
PRInt32 numCells = cells->Count();
|
||||
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
|
||||
|
||||
// XXX need column frame to ask this question
|
||||
const nsStylePosition* colPosition = nsnull;
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
|
||||
// Get the columns's style
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
{ // this col has proportional width, so determine its width requirements
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull==data)
|
||||
{ // For cells that span rows there's only cell layout data for the first row
|
||||
for (PRInt32 rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{ // this col has non-fixed width, so determine its width requirements
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
nsMargin margin;
|
||||
data->GetMargin(margin);
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize");
|
||||
nscoord cellMinWidth = cellMinSize->width; // do we need to take into account colSpan here?
|
||||
cellMinWidth += margin.left + margin.right;
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
nscoord cellMinWidth = cellMinSize.width/colSpan;
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
}
|
||||
|
@ -624,32 +699,42 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
|
||||
PRBool result = PR_TRUE;
|
||||
nscoord tableWidth=0; // the width of the table as a result of setting column widths
|
||||
nscoord widthOfFixedTableColumns=0; // the sum of the width of all fixed-width columns
|
||||
// tableWidth - widthOfFixedTableColumns is the width of columns computed in this method
|
||||
PRInt32 totalSlices=0; // the total number of slices the proportional-width columns request
|
||||
nsVoidArray *proportionalColumnsList=nsnull; // a list of the columns that are proportional-width
|
||||
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
nscoord * effectiveColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveColumnWidths, 0, numCols*sizeof(PRInt32));
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
nscoord * effectiveColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
|
||||
PRInt32 minColWidth = 0;
|
||||
PRInt32 maxColWidth = 0;
|
||||
// Get column information
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 numCells = cells->Count();
|
||||
|
||||
// Get the columns's style
|
||||
nsTableColFrame *colFrame = colData->GetColFrame();
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
const nsStylePosition* colPosition = (const nsStylePosition*) colSC->GetStyleData(eStyleStruct_Position);
|
||||
if (gsDebug) printf("col %d has frame %p with style %p and pos %p\n",
|
||||
colIndex, colFrame, (nsIStyleContext *)colSC, colPosition);
|
||||
PRInt32 rowIndex;
|
||||
PRInt32 firstRowIndex = -1;
|
||||
nsTableCellFrame * firstCellInColumn;
|
||||
for (rowIndex=0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
firstCellInColumn = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull!=firstCellInColumn)
|
||||
break;
|
||||
}
|
||||
nsMargin colMargin;
|
||||
nscoord colInset = 0;
|
||||
if (nsnull!=firstCellInColumn)
|
||||
{
|
||||
firstCellInColumn->GetMargin(colMargin);
|
||||
colInset = colMargin.left + colMargin.right;
|
||||
}
|
||||
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
// first, deal with any cells that span into this column from a pervious column
|
||||
|
@ -676,33 +761,33 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
}
|
||||
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
for (rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{ // this col has proportional width, so determine its width requirements
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull == data) {
|
||||
// For cells that span columns there's only cell layout data for the first column
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
if (-1==firstRowIndex)
|
||||
firstRowIndex = rowIndex;
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
PRInt32 colSpan = data->GetCellFrame()->GetColSpan();
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
// distribute a portion of the spanning cell's min and max width to this column
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize");
|
||||
nsReflowMetrics * cellDesiredSize = data->GetDesiredSize();
|
||||
NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize");
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
|
||||
|
||||
nsMargin margin;
|
||||
nsresult result = data->GetMargin(margin);
|
||||
nscoord marginWidth = margin.left + margin.right;
|
||||
PRInt32 cellMinWidth = cellMinSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellMinWidth = cellMinSize.width/colSpan;
|
||||
// first get the desired size info from reflow pass 1
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize.width/colSpan;
|
||||
// then get the desired size info factoring in the cell style attributes
|
||||
nscoord specifiedCellWidth=-1;
|
||||
nsIStyleContextPtr cellSC;
|
||||
data->GetCellFrame()->GetStyleContext(aPresContext, cellSC.AssignRef());
|
||||
const nsStylePosition* cellPosition = (const nsStylePosition*)
|
||||
cellSC->GetStyleData(eStyleStruct_Position);
|
||||
const nsStylePosition* cellPosition;
|
||||
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
|
||||
switch (cellPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedCellWidth = cellPosition->mWidth.GetCoordValue();
|
||||
|
@ -730,17 +815,17 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
if (-1!=specifiedCellWidth)
|
||||
{
|
||||
if (specifiedCellWidth>cellMinWidth)
|
||||
if (specifiedCellWidth/colSpan>cellMinWidth)
|
||||
{
|
||||
if (gsDebug) printf("setting cellDesiredWidth from %d to %d\n",
|
||||
cellDesiredWidth, specifiedCellWidth);
|
||||
cellDesiredWidth = specifiedCellWidth; // TODO: some math needed here for colspans
|
||||
cellDesiredWidth, specifiedCellWidth/colSpan);
|
||||
cellDesiredWidth = specifiedCellWidth/colSpan; // TODO: some math needed here for colspans
|
||||
}
|
||||
}
|
||||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
|
||||
cellIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
rowIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
if (maxColWidth < cellDesiredWidth)
|
||||
|
@ -750,10 +835,10 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
effectiveColumnWidths[colIndex] = cellDesiredWidth;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d\n",
|
||||
cellIndex, minColWidth, maxColWidth,
|
||||
rowIndex, minColWidth, maxColWidth,
|
||||
colIndex, effectiveColumnWidths[colIndex]);
|
||||
if (1<colSpan)
|
||||
{ // add the cell to our list of spanners
|
||||
if ((1<colSpan) && (cellFrame->GetColIndex()==colIndex))
|
||||
{ // add this cell to span list iff we are currently processing the column the cell starts in
|
||||
SpanInfo *spanInfo = new SpanInfo(colSpan-1, cellMinWidth, cellDesiredWidth);
|
||||
if (nsnull==spanList)
|
||||
spanList = new nsVoidArray();
|
||||
|
@ -863,7 +948,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
if (-1==percentage)
|
||||
{
|
||||
percentage = 100/numCols;
|
||||
percentage = 100/mNumCols;
|
||||
// base the % on the remaining available width
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
|
||||
if (gsDebug==PR_TRUE)
|
||||
|
@ -879,7 +964,11 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
}
|
||||
}
|
||||
}
|
||||
tableWidth += mTableFrame->GetColumnWidth(colIndex);
|
||||
else
|
||||
{ // need to maintain this so we know how much we have left over at the end
|
||||
widthOfFixedTableColumns += mTableFrame->GetColumnWidth(colIndex) + colInset;
|
||||
}
|
||||
tableWidth += mTableFrame->GetColumnWidth(colIndex) + colInset;
|
||||
}
|
||||
|
||||
/* --- post-process if necessary --- */
|
||||
|
@ -938,9 +1027,9 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
// next, if the specified width of the table is greater than the table's computed width, expand the
|
||||
// table's computed width to match the specified width, giving the extra space to proportionately-sized
|
||||
// columns if possible.
|
||||
if ((PR_FALSE==aTableIsAutoWidth) && (aAvailWidth > tableWidth))
|
||||
if ((PR_FALSE==aTableIsAutoWidth) && (aAvailWidth > (tableWidth-widthOfFixedTableColumns)))
|
||||
{
|
||||
DistributeExcessSpace(aAvailWidth, tableWidth, effectiveColumnWidths);
|
||||
DistributeExcessSpace(aAvailWidth, tableWidth, widthOfFixedTableColumns, effectiveColumnWidths);
|
||||
}
|
||||
// today we always allocate effectiveColumnWidths, but tomorrow we might be smarter, so leave the check in
|
||||
if (nsnull!=effectiveColumnWidths)
|
||||
|
@ -952,24 +1041,27 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(nsIPresContext* aPresCo
|
|||
|
||||
// take the extra space in the table and distribute it proportionately (based on desired width)
|
||||
// give extra space to auto-width cells first, or if there are none to all cells
|
||||
void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth,
|
||||
nscoord aComputedTableWidth,
|
||||
void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aAvailWidth,
|
||||
nscoord aTableWidth,
|
||||
nscoord aWidthOfFixedTableColumns,
|
||||
nscoord *aColWidths)
|
||||
{
|
||||
nscoord excess = 0;
|
||||
if (PR_TRUE==gsDebug) printf ("DistributeExcessSpace: fixed width %d > computed table width %d\n",
|
||||
aTableFixedWidth, aComputedTableWidth);
|
||||
if (PR_TRUE==gsDebug) printf ("DistributeExcessSpace: fixed width %d > computed table width %d, woftc=%d\n",
|
||||
aAvailWidth, aTableWidth, aWidthOfFixedTableColumns);
|
||||
// if there are auto-sized columns, give them the extra space
|
||||
// the trick here is to do the math excluding non-auto width columns
|
||||
PRInt32 numAutoColumns=0;
|
||||
PRInt32 *autoColumns=nsnull;
|
||||
mTableFrame->GetColumnsByType(eStyleUnit_Auto, numAutoColumns, autoColumns);
|
||||
if (0!=numAutoColumns)
|
||||
{
|
||||
nscoord computedTableWidth = aTableWidth - aWidthOfFixedTableColumns;
|
||||
// there's at least one auto-width column, so give it (them) the extra space
|
||||
// proportionately distributed extra space, based on the column's desired size
|
||||
nscoord totalEffectiveWidthOfAutoColumns = 0;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
printf(" aAvailWidth specified as %d, expanding columns by excess = %d\n", aAvailWidth, excess);
|
||||
// 1. first, get the total width of the auto columns
|
||||
PRInt32 i;
|
||||
for (i = 0; i<numAutoColumns; i++)
|
||||
|
@ -979,12 +1071,12 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth,
|
|||
else
|
||||
totalEffectiveWidthOfAutoColumns += mTableFrame->GetColumnWidth(autoColumns[i]);
|
||||
}
|
||||
excess = aTableFixedWidth - aComputedTableWidth;
|
||||
excess = aAvailWidth - computedTableWidth;
|
||||
// 2. next, compute the proportion to be added to each column, and add it
|
||||
for (i = 0; i<numAutoColumns; i++)
|
||||
{
|
||||
PRInt32 colIndex = autoColumns[i];
|
||||
nscoord oldColWidth = aColWidths[colIndex];
|
||||
nscoord oldColWidth = mTableFrame->GetColumnWidth(colIndex);//aColWidths[colIndex];
|
||||
float percent;
|
||||
if (0!=totalEffectiveWidthOfAutoColumns)
|
||||
percent = ((float)(aColWidths[colIndex]))/((float)totalEffectiveWidthOfAutoColumns);
|
||||
|
@ -1002,25 +1094,25 @@ void BasicTableLayoutStrategy::DistributeExcessSpace(nscoord aTableFixedWidth,
|
|||
// (they must be all fixed and percentage-width columns, or we would have gone into the block above)
|
||||
else
|
||||
{
|
||||
excess = aTableFixedWidth - aComputedTableWidth;
|
||||
nscoord excessPerColumn = excess/mNumCols;
|
||||
excess = aAvailWidth - (aTableWidth-aWidthOfFixedTableColumns);
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" aTableFixedWidth specified as %d, expanding columns by excess = %d\n", aTableFixedWidth, excess);
|
||||
printf(" aAvailWidth specified as %d, expanding columns by excess = %d\n",
|
||||
aAvailWidth, excess);
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nscoord oldColWidth = aColWidths[colIndex];
|
||||
nscoord oldColWidth=0;// = aColWidths[colIndex];
|
||||
if (0==oldColWidth)
|
||||
oldColWidth = mTableFrame->GetColumnWidth(colIndex);
|
||||
float percent;
|
||||
if (0!=aComputedTableWidth)
|
||||
percent = (float)oldColWidth/(float)aComputedTableWidth;
|
||||
if (0!=aTableWidth)
|
||||
percent = (float)oldColWidth/(float)aTableWidth;
|
||||
else
|
||||
percent = (float)1/(float)mNumCols;
|
||||
nscoord excessForThisColumn = (nscoord)(excess*percent);
|
||||
nscoord colWidth = excessForThisColumn+oldColWidth;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" distribute excess to all columns: column %d was %d, now set to %d\n",
|
||||
colIndex, aColWidths[colIndex], colWidth);
|
||||
printf(" distribute excess to all columns: column %d was %d, now set to %d from % = %f\n",
|
||||
colIndex, oldColWidth, colWidth, percent);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
}
|
||||
|
@ -1051,29 +1143,40 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
// proportional-width columns are equal (if any are anything other than 1)
|
||||
PRBool atLeastOneAutoWidthColumn = PR_FALSE; // true if at least one column is auto-width, requiring us to post-process
|
||||
nsVoidArray *spanList=nsnull; // a list of the cells that span columns
|
||||
nsVoidArray *columnLayoutData = mTableFrame->GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
nscoord * effectiveMaxColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMaxColumnWidths, 0, numCols*sizeof(PRInt32));
|
||||
nscoord * effectiveMinColumnWidths = new nscoord[numCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMinColumnWidths, 0, numCols*sizeof(PRInt32));
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
nscoord * effectiveMaxColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMaxColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
nscoord * effectiveMinColumnWidths = new nscoord[mNumCols]; // used for Nav4 compatible table fluffing
|
||||
nsCRT::memset (effectiveMinColumnWidths, 0, mNumCols*sizeof(PRInt32));
|
||||
PRInt32 numRows = mTableFrame->GetRowCount();
|
||||
|
||||
for (PRInt32 colIndex = 0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
if (gsDebug==PR_TRUE) printf (" for col %d\n", colIndex);
|
||||
nscoord minColWidth = 0;
|
||||
nscoord maxColWidth = 0;
|
||||
|
||||
// Get column information
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsVoidArray *cells = colData->GetCells();
|
||||
PRInt32 numCells = cells->Count();
|
||||
|
||||
// Get the columns's style
|
||||
nsTableColFrame *colFrame = colData->GetColFrame();
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(colIndex);
|
||||
NS_ASSERTION(nsnull!=colFrame, "bad col frame");
|
||||
nsIStyleContextPtr colSC;
|
||||
colFrame->GetStyleContext(aPresContext, colSC.AssignRef());
|
||||
const nsStylePosition* colPosition = (const nsStylePosition*) colSC->GetStyleData(eStyleStruct_Position);
|
||||
// Get the columns's style and margins
|
||||
PRInt32 rowIndex;
|
||||
PRInt32 firstRowIndex = -1;
|
||||
nsTableCellFrame * firstCellInColumn;
|
||||
for (rowIndex=0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
firstCellInColumn = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull!=firstCellInColumn)
|
||||
break;
|
||||
}
|
||||
nsMargin colMargin;
|
||||
nscoord colInset = 0;
|
||||
if (nsnull!=firstCellInColumn)
|
||||
{
|
||||
firstCellInColumn->GetMargin(colMargin);
|
||||
colInset = colMargin.left + colMargin.right;
|
||||
}
|
||||
const nsStylePosition* colPosition;
|
||||
colFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)colPosition);
|
||||
|
||||
if (PR_FALSE==IsFixedWidth(colPosition))
|
||||
{
|
||||
|
@ -1100,33 +1203,30 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
}
|
||||
}
|
||||
}
|
||||
for (PRInt32 cellIndex = 0; cellIndex<numCells; cellIndex++)
|
||||
{ // this col has proportional width, so determine its width requirements
|
||||
nsCellLayoutData * data = (nsCellLayoutData *)(cells->ElementAt(cellIndex));
|
||||
if (nsnull == data) {
|
||||
// For cells that span rows there's only cell layout data for the first row
|
||||
for (rowIndex = 0; rowIndex<numRows; rowIndex++)
|
||||
{
|
||||
nsTableCellFrame * cellFrame = mTableFrame->GetCellAt(rowIndex, colIndex);
|
||||
if (nsnull==cellFrame)
|
||||
{ // there is no cell in this row that corresponds to this column
|
||||
continue;
|
||||
}
|
||||
if (rowIndex!=cellFrame->GetRowIndex()) {
|
||||
// For cells that span rows, we only figure it in once
|
||||
NS_ASSERTION(1 != cellFrame->GetRowSpan(), "row index does not match row span"); // sanity check
|
||||
continue;
|
||||
}
|
||||
|
||||
PRInt32 colSpan = data->GetCellFrame()->GetColSpan();
|
||||
nsSize * cellMinSize = data->GetMaxElementSize();
|
||||
NS_ASSERTION(nsnull != cellMinSize, "bad cellMinSize");
|
||||
nsReflowMetrics * cellDesiredSize = data->GetDesiredSize();
|
||||
NS_ASSERTION(nsnull != cellDesiredSize, "bad cellDesiredSize");
|
||||
PRInt32 colSpan = cellFrame->GetColSpan();
|
||||
nsSize cellMinSize = cellFrame->GetPass1MaxElementSize();
|
||||
nsSize cellDesiredSize = cellFrame->GetPass1DesiredSize();
|
||||
|
||||
nsMargin margin;
|
||||
nsresult result = data->GetMargin(margin);
|
||||
nscoord marginWidth = margin.left + margin.right;
|
||||
|
||||
PRInt32 cellMinWidth = cellMinSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellMinWidth = cellMinSize.width/colSpan;
|
||||
// first get the desired size info from reflow pass 1
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize->width/colSpan + marginWidth;
|
||||
PRInt32 cellDesiredWidth = cellDesiredSize.width/colSpan;
|
||||
// then get the desired size info factoring in the cell style attributes
|
||||
nscoord specifiedCellWidth=-1;
|
||||
nsIStyleContextPtr cellSC;
|
||||
data->GetCellFrame()->GetStyleContext(aPresContext, cellSC.AssignRef());
|
||||
const nsStylePosition* cellPosition = (const nsStylePosition*)
|
||||
cellSC->GetStyleData(eStyleStruct_Position);
|
||||
const nsStylePosition* cellPosition;
|
||||
cellFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)cellPosition);
|
||||
switch (cellPosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedCellWidth = cellPosition->mWidth.GetCoordValue();
|
||||
|
@ -1164,7 +1264,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf("factoring in cell %d with colSpan=%d\n factoring in min=%d and desired=%d\n",
|
||||
cellIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
rowIndex, colSpan, cellMinWidth, cellDesiredWidth);
|
||||
// remember the widest min cell width
|
||||
if (minColWidth < cellMinWidth)
|
||||
minColWidth = cellMinWidth;
|
||||
|
@ -1179,7 +1279,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
effectiveMaxColumnWidths[colIndex] = cellDesiredWidth;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d,%d\n",
|
||||
cellIndex, minColWidth, maxColWidth,
|
||||
rowIndex, minColWidth, maxColWidth,
|
||||
colIndex, effectiveMaxColumnWidths[colIndex], effectiveMaxColumnWidths[colIndex]);
|
||||
if (1<colSpan)
|
||||
{
|
||||
|
@ -1236,7 +1336,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
printf (" 4 (0): col %d set to min width = %d because style set proportionalWidth=0\n",
|
||||
colIndex, mTableFrame->GetColumnWidth(colIndex));
|
||||
}
|
||||
else if (1==numCols)
|
||||
else if (1==mNumCols)
|
||||
{ // there is only one column, and we know that it's desired width doesn't fit
|
||||
// so the column should be as wide as the available space allows it to be
|
||||
if (gsDebug==PR_TRUE) printf (" 4 one-column: col %d set to width = %d\n", colIndex, aAvailWidth);
|
||||
|
@ -1300,7 +1400,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( nsIPresContext* aPre
|
|||
}
|
||||
if (-1==percentage)
|
||||
{
|
||||
percentage = 100/numCols;
|
||||
percentage = 100/mNumCols;
|
||||
// base the % on the remaining available width
|
||||
mTableFrame->SetColumnWidth(colIndex, (percentage*aAvailWidth)/100);
|
||||
if (gsDebug==PR_TRUE)
|
||||
|
@ -1417,16 +1517,52 @@ void BasicTableLayoutStrategy::DistributeRemainingSpace(nscoord aTableFixedWidt
|
|||
else
|
||||
percent = ((float)1)/((float)numAutoColumns);
|
||||
nscoord colWidth = (nscoord)(availWidth*percent);
|
||||
if (colWidth<aMinColWidths[colIndex])
|
||||
{
|
||||
availWidth -= (aMinColWidths[colIndex]-colWidth);
|
||||
colWidth=aMinColWidths[colIndex];
|
||||
}
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf(" distribute width to auto columns: column %d was %d, now set to %d\n",
|
||||
colIndex, aMaxColWidths[colIndex], colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth);
|
||||
}
|
||||
EnsureCellMinWidths(aMinColWidths);
|
||||
}
|
||||
}
|
||||
|
||||
void BasicTableLayoutStrategy::EnsureCellMinWidths(nscoord *aMinColWidths)
|
||||
{
|
||||
PRBool atLeastOne = PR_TRUE;
|
||||
while (PR_TRUE==atLeastOne)
|
||||
{
|
||||
atLeastOne=PR_FALSE;
|
||||
PRInt32 colIndex;
|
||||
nscoord addedWidth = 0;
|
||||
// first, bump up cells that are below their min to their min width
|
||||
for (colIndex=0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nscoord colWidth = mTableFrame->GetColumnWidth(colIndex);
|
||||
if (colWidth<aMinColWidths[colIndex])
|
||||
{
|
||||
addedWidth += (aMinColWidths[colIndex]-colWidth);
|
||||
mTableFrame->SetColumnWidth(colIndex, aMinColWidths[colIndex]);
|
||||
atLeastOne=PR_TRUE;
|
||||
}
|
||||
}
|
||||
// second, remove the added space from cells that can afford to slim down
|
||||
//QQQ boy is this slow! there has to be a faster way that is still guaranteed to be accurate...
|
||||
while ((addedWidth>0))
|
||||
{ // while we still have some extra space, and last time we were able to take some off...
|
||||
for (colIndex=0; colIndex<mNumCols; colIndex++)
|
||||
{
|
||||
nscoord colWidth = mTableFrame->GetColumnWidth(colIndex);
|
||||
if (colWidth>aMinColWidths[colIndex])
|
||||
{
|
||||
mTableFrame->SetColumnWidth(colIndex, colWidth-1);
|
||||
addedWidth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0<addedWidth)
|
||||
{ // all our cells are at their min width, so no use doing anything else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "nsITableLayoutStrategy.h"
|
||||
#include "nsCoord.h"
|
||||
|
||||
class nsVoidArray;
|
||||
class nsTableFrame;
|
||||
struct nsStylePosition;
|
||||
|
||||
|
@ -164,18 +165,31 @@ public:
|
|||
nscoord aMinTableWidth,
|
||||
nscoord aMaxTableWidth);
|
||||
|
||||
/** post-process to AssignFixedColumnWidths
|
||||
*
|
||||
* @param aColSpanList a list of fixed-width columns that have colspans
|
||||
* @param aColWidths the effective column widths (ignoring col span cells)
|
||||
*
|
||||
* NOTE: does not yet properly handle overlapping col spans
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
virtual void DistributeFixedSpace(nsVoidArray *aColSpanList, nscoord *aColWidths);
|
||||
|
||||
/** starting with a partially balanced table, compute the amount
|
||||
* of space to pad each column by to completely balance the table.
|
||||
* set the column widths in mTableFrame based on these computations.
|
||||
*
|
||||
* @param aTableFixedWidth the specified width of the table. If there is none,
|
||||
* this param is 0
|
||||
* @param aComputedTableWidth the width of the table before this final step.
|
||||
* @param aAvailWidth the space still to be allocated within the table
|
||||
* @param aTableWidth the sum of all columns widths
|
||||
* @param aWidthOfFixedTableColumns the sum of the widths of fixed-width columns
|
||||
* @param aColWidths the effective column widths (ignoring col span cells)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
virtual void DistributeExcessSpace(nscoord aTableFixedWidth,
|
||||
nscoord aComputedTableWidth,
|
||||
virtual void DistributeExcessSpace(nscoord aAvailWidth,
|
||||
nscoord aTableWidth,
|
||||
nscoord aWidthOfFixedTableColumns,
|
||||
nscoord *aColWidths);
|
||||
|
||||
/** starting with a partially balanced table, compute the amount
|
||||
|
@ -193,6 +207,11 @@ public:
|
|||
nscoord *aMinColWidths,
|
||||
nscoord *aMaxColWidths);
|
||||
|
||||
/** force all cells to be at least their minimum width, removing any excess space
|
||||
* created in the process from fat cells that can afford to lose a little tonnage.
|
||||
*/
|
||||
virtual void EnsureCellMinWidths(nscoord *aMinColWidths);
|
||||
|
||||
/** return true if the style indicates that the width is a specific width
|
||||
* for the purposes of column width determination.
|
||||
* return false if the width changes based on content, parent size, etc.
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCellMap.h"
|
||||
#include "nsTableFrame.h"
|
||||
|
||||
|
@ -25,17 +27,20 @@ static PRBool gsDebug1 = PR_FALSE;
|
|||
static const PRBool gsDebug1 = PR_FALSE;
|
||||
#endif
|
||||
|
||||
static PRInt32 gBytesPerPointer = sizeof(PRInt32);
|
||||
static const PRInt32 gBytesPerPointer = sizeof(PRInt32);
|
||||
|
||||
nsCellMap::nsCellMap(int aRows, int aColumns)
|
||||
: mRowCount(aRows),
|
||||
mColCount(aColumns)
|
||||
{
|
||||
mCells = nsnull;
|
||||
mColFrames = nsnull;
|
||||
Reset(aRows, aColumns);
|
||||
}
|
||||
|
||||
nsCellMap::~nsCellMap()
|
||||
{
|
||||
if (nsnull!=mCells)
|
||||
{
|
||||
for (int i=0;i<mRowCount;i++)
|
||||
{
|
||||
|
@ -51,12 +56,21 @@ nsCellMap::~nsCellMap()
|
|||
}
|
||||
}
|
||||
delete [] mCells;
|
||||
}
|
||||
if (nsnull!= mColFrames)
|
||||
delete mColFrames;
|
||||
mCells = nsnull;
|
||||
mColFrames = nsnull;
|
||||
};
|
||||
|
||||
|
||||
void nsCellMap::Reset(int aRows, int aColumns)
|
||||
{
|
||||
if (nsnull==mColFrames)
|
||||
{
|
||||
mColFrames = new nsVoidArray();
|
||||
}
|
||||
|
||||
// needs to be more efficient, to reuse space if possible
|
||||
if (nsnull!=mCells)
|
||||
{
|
||||
|
@ -67,6 +81,7 @@ void nsCellMap::Reset(int aRows, int aColumns)
|
|||
mColCount = aColumns;
|
||||
mCells = new PRInt32 [mRowCount*mColCount*gBytesPerPointer];
|
||||
nsCRT::memset (mCells, 0, (mRowCount*mColCount)*gBytesPerPointer);
|
||||
|
||||
}
|
||||
|
||||
void nsCellMap::GrowTo(int aColCount)
|
||||
|
@ -110,4 +125,9 @@ void nsCellMap::SetCellAt(CellData *aCell, int aRow, int aColumn)
|
|||
mCells[index] = (PRInt32)aCell;
|
||||
}
|
||||
|
||||
nsTableColFrame* nsCellMap::GetColumnFrame(PRInt32 aColIndex)
|
||||
{
|
||||
return (nsTableColFrame *)(mColFrames->ElementAt(aColIndex));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
#define nsCellMap_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "CellData.h"
|
||||
|
||||
class CellData;
|
||||
class nsVoidArray;
|
||||
class nsTableColFrame;
|
||||
class nsTableCellFrame;
|
||||
|
||||
/** nsCellMap is a support class for nsTablePart.
|
||||
* It maintains an Rows x Columns grid onto which the cells of the table are mapped.
|
||||
|
@ -40,55 +43,94 @@ protected:
|
|||
/** storage for CellData pointers */
|
||||
PRInt32 *mCells; ///XXX CellData *?
|
||||
|
||||
/** a cache of the column frames, by col index */
|
||||
nsVoidArray * mColFrames;
|
||||
|
||||
/** the number of rows */
|
||||
int mRowCount; // in java, we could just do fCellMap.length;
|
||||
PRInt32 mRowCount; // in java, we could just do fCellMap.length;
|
||||
|
||||
/** the number of columns (the max of all row lengths) */
|
||||
int mColCount; // in java, we could just do fCellMap[i].length
|
||||
PRInt32 mColCount;
|
||||
|
||||
public:
|
||||
nsCellMap(int aRows, int aColumns);
|
||||
nsCellMap(PRInt32 aRows, PRInt32 aColumns);
|
||||
|
||||
// NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
|
||||
~nsCellMap();
|
||||
|
||||
/** initialize the CellMap to (aRows x aColumns) */
|
||||
void Reset(int aRows, int aColumns);
|
||||
void Reset(PRInt32 aRows, PRInt32 aColumns);
|
||||
|
||||
/** return the CellData for the cell at (aRow,aColumn) */
|
||||
CellData * GetCellAt(int aRow, int aColumn) const;
|
||||
/** return the CellData for the cell at (aRowIndex,aColIndex) */
|
||||
CellData * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) const;
|
||||
|
||||
/** return the nsTableCellFrame for the cell at (aRowIndex, aColIndex) */
|
||||
nsTableCellFrame * GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex) const;
|
||||
|
||||
/** assign aCellData to the cell at (aRow,aColumn) */
|
||||
void SetCellAt(CellData *aCellData, int aRow, int aColumn);
|
||||
void SetCellAt(CellData *aCellData, PRInt32 aRow, PRInt32 aColumn);
|
||||
|
||||
/** expand the CellMap to have aColCount columns. The number of rows remains the same */
|
||||
void GrowTo(int aColCount);
|
||||
void GrowTo(PRInt32 aColCount);
|
||||
|
||||
/** return the total number of columns in the table represented by this CellMap */
|
||||
int GetColCount() const;
|
||||
PRInt32 GetColCount() const;
|
||||
|
||||
/** return the total number of rows in the table represented by this CellMap */
|
||||
int GetRowCount() const;
|
||||
PRInt32 GetRowCount() const;
|
||||
|
||||
/** for debugging, print out this CellMap */
|
||||
nsTableColFrame * GetColumnFrame(PRInt32 aColIndex);
|
||||
|
||||
void AppendColumnFrame(nsTableColFrame *aColFrame);
|
||||
|
||||
PRBool RowImpactedBySpanningCell(PRInt32 aRowIndex);
|
||||
|
||||
PRBool ColumnImpactedBySpanningCell(PRInt32 aColIndex);
|
||||
|
||||
/** for debugging */
|
||||
void DumpCellMap() const;
|
||||
|
||||
};
|
||||
|
||||
inline CellData * nsCellMap::GetCellAt(int aRow, int aColumn) const
|
||||
/* ----- inline methods ----- */
|
||||
|
||||
inline CellData * nsCellMap::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) const
|
||||
{
|
||||
int index = (aRow*mColCount)+aColumn;
|
||||
NS_PRECONDITION(0<=aRowIndex && aRowIndex < mRowCount, "bad aRowIndex arg");
|
||||
NS_PRECONDITION(0<=aColIndex && aColIndex < mColCount, "bad aColIndex arg");
|
||||
|
||||
PRInt32 index = (aRowIndex*mColCount)+aColIndex;
|
||||
return (CellData *)mCells[index];
|
||||
}
|
||||
|
||||
inline int nsCellMap::GetColCount() const
|
||||
inline nsTableCellFrame * nsCellMap::GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex) const
|
||||
{
|
||||
NS_PRECONDITION(0<=aRowIndex && aRowIndex < mRowCount, "bad aRowIndex arg");
|
||||
NS_PRECONDITION(0<=aColIndex && aColIndex < mColCount, "bad aColIndex arg");
|
||||
|
||||
nsTableCellFrame *result = nsnull;
|
||||
CellData * cellData = GetCellAt(aRowIndex, aColIndex);
|
||||
if (nsnull!=cellData)
|
||||
result = cellData->mCell;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline PRInt32 nsCellMap::GetColCount() const
|
||||
{
|
||||
return mColCount;
|
||||
}
|
||||
|
||||
inline int nsCellMap::GetRowCount() const
|
||||
inline PRInt32 nsCellMap::GetRowCount() const
|
||||
{
|
||||
return mRowCount;
|
||||
}
|
||||
|
||||
inline void nsCellMap::AppendColumnFrame(nsTableColFrame *aColFrame)
|
||||
{
|
||||
mColFrames->AppendElement(aColFrame);
|
||||
// sanity check
|
||||
NS_ASSERTION(mColFrames->Count()<=mColCount, "too many columns appended to CellMap");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* Reserved.
|
||||
*/
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsBodyFrame.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
#include "nsIStyleContext.h"
|
||||
|
@ -53,21 +52,24 @@ static const PRBool gsDebugNT = PR_FALSE;
|
|||
*/
|
||||
nsTableCellFrame::nsTableCellFrame(nsIContent* aContent,
|
||||
nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aParentFrame),
|
||||
mCellLayoutData(nsnull)
|
||||
: nsContainerFrame(aContent, aParentFrame)
|
||||
{
|
||||
mRowSpan=1;
|
||||
mColSpan=1;
|
||||
mColIndex=0;
|
||||
mPriorAvailWidth=0;
|
||||
mPriorDesiredSize.width=0;
|
||||
mPriorDesiredSize.height=0;
|
||||
mDesiredSize.width=0;
|
||||
mDesiredSize.height=0;
|
||||
mMaxElementSize.width=0;
|
||||
mMaxElementSize.height=0;
|
||||
mPass1DesiredSize.width=0;
|
||||
mPass1DesiredSize.height=0;
|
||||
mPass1MaxElementSize.width=0;
|
||||
mPass1MaxElementSize.height=0;
|
||||
}
|
||||
|
||||
nsTableCellFrame::~nsTableCellFrame()
|
||||
{
|
||||
if (nsnull!=mCellLayoutData)
|
||||
delete mCellLayoutData;
|
||||
}
|
||||
|
||||
NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
|
||||
|
@ -291,7 +293,6 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
|||
mFirstChild->WillReflow(*aPresContext);
|
||||
mFirstChild->MoveTo(leftInset, topInset);
|
||||
aStatus = ReflowChild(mFirstChild, aPresContext, kidSize, kidReflowState);
|
||||
SetPriorDesiredSize(kidSize);
|
||||
|
||||
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
||||
{
|
||||
|
@ -325,10 +326,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
|||
// first, compute the height
|
||||
// the height can be set w/o being restricted by aMaxSize.height
|
||||
nscoord cellHeight = kidSize.height;
|
||||
if (NS_UNCONSTRAINEDSIZE!=aReflowState.maxSize.height)
|
||||
{
|
||||
cellHeight += topInset + bottomInset;
|
||||
}
|
||||
if (PR_TRUE==gsDebugNT)
|
||||
printf(" %p cellFrame height set to %d from kidSize=%d and insets %d,%d\n",
|
||||
this, cellHeight, kidSize.height, topInset, bottomInset);
|
||||
|
@ -369,6 +367,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
|||
aDesiredSize.maxElementSize->height += topInset + bottomInset;
|
||||
aDesiredSize.maxElementSize->width += leftInset + rightInset;
|
||||
}
|
||||
SetDesiredSize(aDesiredSize);
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
SetMaxElementSize(*(aDesiredSize.maxElementSize));
|
||||
|
||||
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
||||
printf(" %p cellFrame returning aDesiredSize=%d,%d\n",
|
||||
|
@ -590,6 +591,505 @@ nsresult nsTableCellFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* ----- methods from CellLayoutData ----- */
|
||||
|
||||
/**
|
||||
* Given a frame and an edge, find the margin
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::GetMargin(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin margin;
|
||||
spacing->CalcMarginFor(aFrame, margin);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = margin.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = margin.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = margin.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = margin.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a style context and an edge, find the border width
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::GetBorderWidth(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin border;
|
||||
spacing->CalcBorderFor(aFrame, border);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = border.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = border.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = border.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = border.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a style context and an edge, find the padding
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::GetPadding(nsIFrame* aFrame, PRUint8 aEdge) const
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (aFrame)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
aFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
nsMargin padding;
|
||||
spacing->CalcPaddingFor(aFrame, padding);
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_TOP:
|
||||
result = padding.top;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = padding.right;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = padding.bottom;
|
||||
break;
|
||||
|
||||
case NS_SIDE_LEFT:
|
||||
result = padding.left;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Given an Edge, find the opposing edge (top<-->bottom, left<-->right)
|
||||
*
|
||||
**/
|
||||
PRUint8 nsTableCellFrame::GetOpposingEdge(PRUint8 aEdge)
|
||||
{
|
||||
PRUint8 result;
|
||||
|
||||
switch (aEdge)
|
||||
{
|
||||
case NS_SIDE_LEFT:
|
||||
result = NS_SIDE_RIGHT;
|
||||
break;
|
||||
|
||||
case NS_SIDE_RIGHT:
|
||||
result = NS_SIDE_LEFT;
|
||||
break;
|
||||
|
||||
case NS_SIDE_TOP:
|
||||
result = NS_SIDE_BOTTOM;
|
||||
break;
|
||||
|
||||
case NS_SIDE_BOTTOM:
|
||||
result = NS_SIDE_TOP;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = NS_SIDE_TOP;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Determine border style for two cells.
|
||||
*
|
||||
1.If the adjacent elements are of the same type, the wider of the two borders is used.
|
||||
"Wider" takes into account the border-style of 'none', so a "1px solid" border
|
||||
will take precedence over a "20px none" border.
|
||||
|
||||
2.If there are two or more with the same width, but different style,
|
||||
then the one with a style near the start of the following list will be drawn:
|
||||
|
||||
'blank', 'double', 'solid', 'dashed', 'dotted', 'ridge', 'groove', 'none'
|
||||
|
||||
3.If the borders are of the same width, the border on the element occurring first is used.
|
||||
|
||||
First is defined as aStyle for this method.
|
||||
|
||||
NOTE: This assumes left-to-right, top-to-bottom bias. -- gpk
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
nsIFrame* nsTableCellFrame::CompareCellBorders(nsIFrame* aFrame1,
|
||||
PRUint8 aEdge1,
|
||||
nsIFrame* aFrame2,
|
||||
PRUint8 aEdge2)
|
||||
{
|
||||
PRInt32 width1 = GetBorderWidth(aFrame1,aEdge1);
|
||||
PRInt32 width2 = GetBorderWidth(aFrame2,aEdge2);
|
||||
|
||||
nsIFrame* result = nsnull;
|
||||
|
||||
if (width1 > width2)
|
||||
result = aFrame1;
|
||||
else if (width1 < width2)
|
||||
result = aFrame2;
|
||||
else // width1 == width2
|
||||
{
|
||||
const nsStyleSpacing* border1;
|
||||
const nsStyleSpacing* border2;
|
||||
aFrame1->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)border1);
|
||||
aFrame2->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)border2);
|
||||
if (border1->mBorderStyle[aEdge1] >= border2->mBorderStyle[aEdge2])
|
||||
result = aFrame1;
|
||||
else
|
||||
result = aFrame2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a List of cell layout data, compare the edges to see which has the
|
||||
* border with the highest precidence.
|
||||
*
|
||||
**/
|
||||
|
||||
nsIFrame* nsTableCellFrame::FindHighestPrecedentBorder(nsVoidArray* aList,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* result = nsnull;
|
||||
PRInt32 index = 0;
|
||||
PRInt32 count = 0;
|
||||
|
||||
|
||||
NS_ASSERTION(aList,"a List must be valid");
|
||||
count = aList->Count();
|
||||
if (count)
|
||||
{
|
||||
nsIFrame* frame1;
|
||||
nsIFrame* frame2;
|
||||
|
||||
frame1 = (nsIFrame*)(aList->ElementAt(index++));
|
||||
while (index < count)
|
||||
{
|
||||
frame2 = (nsIFrame*)(aList->ElementAt(index++));
|
||||
if (GetMargin(frame2,aEdge) == 0) {
|
||||
frame1 = CompareCellBorders(frame1, aEdge, frame2, aEdge);
|
||||
}
|
||||
}
|
||||
if ((nsnull != frame1) && (GetMargin(frame1, aEdge) != 0))
|
||||
result = frame1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nsIFrame* nsTableCellFrame::FindInnerBorder(nsVoidArray* aList, PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* result = nsnull;
|
||||
PRUint8 opposite = GetOpposingEdge(aEdge);
|
||||
|
||||
if (GetMargin(this, aEdge) == 0)
|
||||
{
|
||||
nsIFrame* altFrame = FindHighestPrecedentBorder(aList,opposite);
|
||||
if (nsnull != altFrame)
|
||||
result = CompareCellBorders(this, aEdge, altFrame, opposite);
|
||||
else
|
||||
result = this;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* FindRelevantBorder recursively searches up the frame hierarchy for the border
|
||||
* style that is applicable to the cell. If at any point the frame has a margin
|
||||
* or the parent frame has padding, then the outer frame for this object takes
|
||||
* presendence over the inner frame.
|
||||
|
||||
1.Borders on 'table' elements take precedence over borders on any other table elements.
|
||||
2.Borders on 'row-groups' take precedence over borders on 'rows',
|
||||
and likewise borders on 'column-groups' take precedence over borders on 'columns'.
|
||||
3.Borders on any other type of table element take precedence over 'table-cell' elements.
|
||||
|
||||
*
|
||||
* NOTE: This method assumes that the table cell potentially shares a border.
|
||||
* It should not be called for internal cells
|
||||
*
|
||||
* NOTE: COLUMNS AND COLGROUPS NEED TO BE FIGURED INTO THE ALGORITHM -- GPK!!!
|
||||
*
|
||||
*
|
||||
*/
|
||||
nsIFrame* nsTableCellFrame::FindOuterBorder( nsTableFrame* aTableFrame,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* frame = this; // By default, return our frame
|
||||
PRBool done = PR_FALSE;
|
||||
|
||||
|
||||
// The table frame is the outer most frame we test against
|
||||
while (done == PR_FALSE)
|
||||
{
|
||||
done = PR_TRUE; // where done unless the frame's margin is zero
|
||||
// and the parent's padding is zero
|
||||
|
||||
nscoord margin = GetMargin(frame,aEdge);
|
||||
|
||||
// if the margin for this style is zero then check to see if the paddding
|
||||
// for the parent frame is also zero
|
||||
if (margin == 0)
|
||||
{
|
||||
nsIFrame* parentFrame;
|
||||
|
||||
frame->GetGeometricParent(parentFrame);
|
||||
|
||||
// if the padding for the parent style is zero just
|
||||
// recursively call this routine
|
||||
PRInt32 padding = GetPadding(parentFrame,aEdge);
|
||||
if ((nsnull != parentFrame) && (padding == 0))
|
||||
{
|
||||
frame = parentFrame;
|
||||
// If this frame represents the table frame then
|
||||
// the table style is used
|
||||
done = PRBool(frame != (nsIFrame*)aTableFrame);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Border Resolution
|
||||
1.Borders on 'table' elements take precedence over borders on any other table elements.
|
||||
2.Borders on 'row-groups' take precedence over borders on 'rows', and likewise borders on 'column-groups' take
|
||||
precedence over borders on 'columns'.
|
||||
3.Borders on any other type of table element take precedence over 'table-cell' elements.
|
||||
4.If the adjacent elements are of the same type, the wider of the two borders is used. "Wider" takes into account
|
||||
the border-style of 'none', so a "1px solid" border will take precedence over a "20px none" border.
|
||||
5.If the borders are of the same width, the border on the element occurring first is used.
|
||||
|
||||
|
||||
How to compare
|
||||
1.Those of the one or two cells that have an edge here.
|
||||
Less than two can occur at the edge of the table, but also
|
||||
at the edges of "holes" (unoccupied grid cells).
|
||||
2.Those of the columns that have an edge here.
|
||||
3.Those of the column groups that have an edge here.
|
||||
4.Those of the rows that have an edge here.
|
||||
5.Those of the row groups that have an edge here.
|
||||
6.Those of the table, if this is the edge of the table.
|
||||
|
||||
*
|
||||
* @param aIsFirst -- TRUE if this is the first cell in the row
|
||||
* @param aIsLast -- TRUE if this is the last cell in the row
|
||||
* @param aIsTop -- TRUE if this is the top cell in the column
|
||||
* @param aIsBottom -- TRUE if this is the last cell in the column
|
||||
*/
|
||||
|
||||
nsIFrame* nsTableCellFrame::FindBorderFrame(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aList,
|
||||
PRUint8 aEdge)
|
||||
{
|
||||
nsIFrame* frame = nsnull;
|
||||
|
||||
if (aList && aList->Count() == 0)
|
||||
frame = FindOuterBorder(aTableFrame, aEdge);
|
||||
else
|
||||
frame = FindInnerBorder(aList, aEdge);
|
||||
|
||||
if (! frame)
|
||||
frame = this;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a List of cell layout data, compare the edges to see which has the
|
||||
* border with the highest precidence.
|
||||
*
|
||||
**/
|
||||
nscoord nsTableCellFrame::FindLargestMargin(nsVoidArray* aList,PRUint8 aEdge)
|
||||
{
|
||||
nscoord result = 0;
|
||||
PRInt32 index = 0;
|
||||
PRInt32 count = 0;
|
||||
|
||||
|
||||
NS_ASSERTION(aList,"a List must be valid");
|
||||
count = aList->Count();
|
||||
if (count)
|
||||
{
|
||||
nsIFrame* frame;
|
||||
|
||||
nscoord value = 0;
|
||||
while (index < count)
|
||||
{
|
||||
frame = (nsIFrame*)(aList->ElementAt(index++));
|
||||
value = GetMargin(frame, aEdge);
|
||||
if (value > result)
|
||||
result = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nsTableCellFrame::CalculateMargins(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
{
|
||||
// By default the margin is just the margin found in the
|
||||
// table cells style
|
||||
const nsStyleSpacing* spacing;
|
||||
GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
|
||||
spacing->CalcMarginFor(this, mMargin);
|
||||
|
||||
// Left and Top Margins are collapsed with their neightbors
|
||||
// Right and Bottom Margins are simple left as they are
|
||||
nscoord value;
|
||||
|
||||
// The left and top sides margins are the difference between
|
||||
// their inherint value and the value of the margin of the
|
||||
// object to the left or right of them.
|
||||
|
||||
value = FindLargestMargin(aBoundaryCells[NS_SIDE_LEFT],NS_SIDE_RIGHT);
|
||||
if (value > mMargin.left)
|
||||
mMargin.left = 0;
|
||||
else
|
||||
mMargin.left -= value;
|
||||
|
||||
value = FindLargestMargin(aBoundaryCells[NS_SIDE_TOP],NS_SIDE_BOTTOM);
|
||||
if (value > mMargin.top)
|
||||
mMargin.top = 0;
|
||||
else
|
||||
mMargin.top -= value;
|
||||
}
|
||||
|
||||
|
||||
void nsTableCellFrame::RecalcLayoutData(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
|
||||
{
|
||||
CalculateBorders(aTableFrame, aBoundaryCells);
|
||||
CalculateMargins(aTableFrame, aBoundaryCells);
|
||||
mCalculated = NS_OK;
|
||||
}
|
||||
|
||||
#if 0 //QQQ
|
||||
void nsTableCellFrame::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
PRInt32 indent;
|
||||
|
||||
nsIContent* cell;
|
||||
|
||||
this->GetContent(cell);
|
||||
if (cell != nsnull)
|
||||
{
|
||||
/*
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"RowSpan = %d ColSpan = %d \n",cell->GetRowSpan(),cell->GetColSpan());
|
||||
*/
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Margin -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.top),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.left),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(mMargin.right));
|
||||
|
||||
|
||||
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
|
||||
nscoord top,left,bottom,right;
|
||||
|
||||
top = (mBorderFrame[NS_SIDE_TOP] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_TOP], NS_SIDE_TOP) : 0);
|
||||
left = (mBorderFrame[NS_SIDE_LEFT] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_LEFT], NS_SIDE_LEFT) : 0);
|
||||
bottom = (mBorderFrame[NS_SIDE_BOTTOM] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_BOTTOM], NS_SIDE_BOTTOM) : 0);
|
||||
right = (mBorderFrame[NS_SIDE_RIGHT] ? GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_RIGHT], NS_SIDE_RIGHT) : 0);
|
||||
|
||||
|
||||
fprintf(out,"Border -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(top),
|
||||
NS_TWIPS_TO_POINTS_INT(left),
|
||||
NS_TWIPS_TO_POINTS_INT(bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(right));
|
||||
|
||||
|
||||
|
||||
cell->List(out,aIndent);
|
||||
NS_RELEASE(cell);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ----- debug only methods, to be removed ----- */
|
||||
|
||||
|
||||
// For Debugging ONLY
|
||||
NS_METHOD nsTableCellFrame::MoveTo(nscoord aX, nscoord aY)
|
||||
{
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "nscore.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsTableFrame.h"
|
||||
#include "nsTableRowFrame.h" // need to actually include this here to inline GetRowIndex
|
||||
|
||||
class nsCellLayoutData;
|
||||
struct nsStyleSpacing;
|
||||
|
||||
/* eb42f7b0-079e-11d2-8f37-006008159b0c */
|
||||
|
@ -72,34 +72,124 @@ public:
|
|||
/** return the mapped cell's row span. Always >= 1. */
|
||||
virtual PRInt32 GetRowSpan();
|
||||
|
||||
// there is no set row index because row index depends on the cell's parent row only
|
||||
|
||||
/** return the mapped cell's row index (starting at 0 for the first row) */
|
||||
virtual PRInt32 GetRowIndex();
|
||||
|
||||
/** return the mapped cell's col span. Always >= 1. */
|
||||
virtual PRInt32 GetColSpan();
|
||||
|
||||
/** return the mapped cell's column index (starting at 0 for the first column) */
|
||||
virtual PRInt32 GetColIndex();
|
||||
|
||||
/** set the index of the column belonging to this cell */
|
||||
// XXX should be removed, use cell map?
|
||||
virtual void SetColIndex (int aColIndex);
|
||||
|
||||
/** return the available width given to this frame during its last reflow */
|
||||
virtual nscoord GetPriorAvailWidth();
|
||||
|
||||
/** set the available width given to this frame during its last reflow */
|
||||
virtual void SetPriorAvailWidth(nscoord aPriorAvailWidth);
|
||||
|
||||
virtual nsSize GetPriorDesiredSize();
|
||||
/** return the desired size returned by this frame during its last reflow */
|
||||
virtual nsSize GetDesiredSize();
|
||||
|
||||
virtual void SetPriorDesiredSize(const nsReflowMetrics & aDesiredSize);
|
||||
/** set the desired size returned by this frame during its last reflow */
|
||||
virtual void SetDesiredSize(const nsReflowMetrics & aDesiredSize);
|
||||
|
||||
virtual ~nsTableCellFrame();
|
||||
/** return the MaxElement size returned by this frame during its last reflow
|
||||
* not counting reflows where MaxElementSize is not requested.
|
||||
* That is, the cell frame will always remember the last non-null MaxElementSize
|
||||
*/
|
||||
virtual nsSize GetMaxElementSize();
|
||||
|
||||
// Get the TableFrame that contains this cell frame
|
||||
/** set the MaxElement size returned by this frame during its last reflow.
|
||||
* should never be called with a null MaxElementSize
|
||||
*/
|
||||
virtual void SetMaxElementSize(const nsSize & aMaxElementSize);
|
||||
|
||||
/** return the desired size returned by this frame during its last reflow */
|
||||
virtual nsSize GetPass1DesiredSize();
|
||||
|
||||
/** set the desired size returned by this frame during its last reflow */
|
||||
virtual void SetPass1DesiredSize(const nsReflowMetrics & aDesiredSize);
|
||||
|
||||
/** return the MaxElement size returned by this frame during its last reflow
|
||||
* not counting reflows where MaxElementSize is not requested.
|
||||
* That is, the cell frame will always remember the last non-null MaxElementSize
|
||||
*/
|
||||
virtual nsSize GetPass1MaxElementSize();
|
||||
|
||||
/** set the MaxElement size returned by this frame during its last reflow.
|
||||
* should never be called with a null MaxElementSize
|
||||
*/
|
||||
virtual void SetPass1MaxElementSize(const nsSize & aMaxElementSize);
|
||||
|
||||
|
||||
|
||||
/** Get the TableFrame that contains this cell frame */
|
||||
virtual nsTableFrame* GetTableFrame();
|
||||
|
||||
nsCellLayoutData * GetCellLayoutData();
|
||||
void SetCellLayoutData(nsCellLayoutData *aData);
|
||||
void RecalcLayoutData(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
// For DEBUGGING Purposes Only
|
||||
|
||||
NS_IMETHOD GetMargin(nsMargin& aMargin);
|
||||
|
||||
|
||||
/** destructor */
|
||||
virtual ~nsTableCellFrame();
|
||||
|
||||
|
||||
// For DEBUGGING Purposes Only, to be removed
|
||||
NS_IMETHOD MoveTo(nscoord aX, nscoord aY);
|
||||
NS_IMETHOD SizeTo(nscoord aWidth, nscoord aHeight);
|
||||
|
||||
private:
|
||||
|
||||
// All these methods are support methods for RecalcLayoutData
|
||||
nsIFrame* GetFrameAt(nsVoidArray* aList, PRInt32 aIndex);
|
||||
|
||||
nscoord GetMargin(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
nscoord GetBorderWidth(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
nscoord GetPadding(nsIFrame* aFrame, PRUint8 aEdge) const;
|
||||
|
||||
PRUint8 GetOpposingEdge(PRUint8 aEdge);
|
||||
|
||||
nsIFrame* CompareCellBorders(nsIFrame* aFrame1,
|
||||
PRUint8 aEdge1,
|
||||
nsIFrame* aFrame2,
|
||||
PRUint8 aEdge2);
|
||||
|
||||
|
||||
nsIFrame* FindHighestPrecedentBorder(nsVoidArray* aList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
|
||||
|
||||
nsIFrame* FindInnerBorder( nsVoidArray* aList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
nsIFrame* FindOuterBorder( nsTableFrame* aTableFrame,
|
||||
PRUint8 aEdge);
|
||||
|
||||
nsIFrame* FindBorderFrame(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aCellList,
|
||||
PRUint8 aEdge);
|
||||
|
||||
void CalculateBorders(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
nscoord FindLargestMargin(nsVoidArray* aList,PRUint8 aEdge);
|
||||
|
||||
|
||||
void CalculateMargins(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4]);
|
||||
|
||||
protected:
|
||||
|
||||
/** protected constructor.
|
||||
|
@ -132,9 +222,17 @@ protected:
|
|||
/** the available width we were given in our previous reflow */
|
||||
nscoord mPriorAvailWidth;
|
||||
|
||||
nsSize mPriorDesiredSize;
|
||||
/** these are the last computed desired and max element sizes */
|
||||
nsSize mDesiredSize;
|
||||
nsSize mMaxElementSize;
|
||||
|
||||
nsCellLayoutData *mCellLayoutData;
|
||||
/** these are the Pass 1 unconstrained desired and max element sizes */
|
||||
nsSize mPass1DesiredSize;
|
||||
nsSize mPass1MaxElementSize;
|
||||
|
||||
nsresult mCalculated;
|
||||
nsMargin mMargin;
|
||||
nsIFrame* mBorderFrame[4]; // the frame whose border is used
|
||||
|
||||
};
|
||||
|
||||
|
@ -151,6 +249,16 @@ inline void nsTableCellFrame::Init(PRInt32 aRowSpan, PRInt32 aColSpan, PRInt32 a
|
|||
inline PRInt32 nsTableCellFrame::GetRowSpan()
|
||||
{ return mRowSpan;}
|
||||
|
||||
inline PRInt32 nsTableCellFrame::GetRowIndex()
|
||||
{
|
||||
nsTableRowFrame * row;
|
||||
GetContentParent((nsIFrame *&)row);
|
||||
if (nsnull!=row)
|
||||
return row->GetRowIndex();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline PRInt32 nsTableCellFrame::GetColSpan()
|
||||
{ return mColSpan;}
|
||||
|
||||
|
@ -163,25 +271,64 @@ inline void nsTableCellFrame::SetColIndex (int aColIndex)
|
|||
mColIndex = aColIndex;
|
||||
}
|
||||
|
||||
inline nsCellLayoutData * nsTableCellFrame::GetCellLayoutData()
|
||||
{ return mCellLayoutData;}
|
||||
|
||||
inline void nsTableCellFrame::SetCellLayoutData(nsCellLayoutData *aData)
|
||||
{ mCellLayoutData = aData;}
|
||||
|
||||
inline nscoord nsTableCellFrame::GetPriorAvailWidth()
|
||||
{ return mPriorAvailWidth;}
|
||||
|
||||
inline void nsTableCellFrame::SetPriorAvailWidth(nscoord aPriorAvailWidth)
|
||||
{ mPriorAvailWidth = aPriorAvailWidth;}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetPriorDesiredSize()
|
||||
{ return mPriorDesiredSize; }
|
||||
inline nsSize nsTableCellFrame::GetDesiredSize()
|
||||
{ return mDesiredSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetPriorDesiredSize(const nsReflowMetrics & aDesiredSize)
|
||||
inline void nsTableCellFrame::SetDesiredSize(const nsReflowMetrics & aDesiredSize)
|
||||
{
|
||||
mPriorDesiredSize.width = aDesiredSize.width;
|
||||
mPriorDesiredSize.height = aDesiredSize.height;
|
||||
mDesiredSize.width = aDesiredSize.width;
|
||||
mDesiredSize.height = aDesiredSize.height;
|
||||
}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetMaxElementSize()
|
||||
{ return mMaxElementSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetMaxElementSize(const nsSize & aMaxElementSize)
|
||||
{
|
||||
mMaxElementSize.width = aMaxElementSize.width;
|
||||
mMaxElementSize.height = aMaxElementSize.height;
|
||||
}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetPass1DesiredSize()
|
||||
{ return mPass1DesiredSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetPass1DesiredSize(const nsReflowMetrics & aDesiredSize)
|
||||
{
|
||||
mPass1DesiredSize.width = aDesiredSize.width;
|
||||
mPass1DesiredSize.height = aDesiredSize.height;
|
||||
}
|
||||
|
||||
inline nsSize nsTableCellFrame::GetPass1MaxElementSize()
|
||||
{ return mPass1MaxElementSize; }
|
||||
|
||||
inline void nsTableCellFrame::SetPass1MaxElementSize(const nsSize & aMaxElementSize)
|
||||
{
|
||||
mPass1MaxElementSize.width = aMaxElementSize.width;
|
||||
mPass1MaxElementSize.height = aMaxElementSize.height;
|
||||
}
|
||||
|
||||
inline void nsTableCellFrame::CalculateBorders(nsTableFrame* aTableFrame,
|
||||
nsVoidArray* aBoundaryCells[4])
|
||||
{
|
||||
for (PRInt32 edge = 0; edge < 4; edge++)
|
||||
mBorderFrame[edge] = FindBorderFrame(aTableFrame, aBoundaryCells[edge], edge);
|
||||
}
|
||||
|
||||
inline NS_METHOD nsTableCellFrame::GetMargin(nsMargin& aMargin)
|
||||
{
|
||||
if (mCalculated == NS_OK)
|
||||
{
|
||||
aMargin = mMargin;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
static PRBool gsNoisyRefs = PR_FALSE;
|
||||
#else
|
||||
static const PRBool gsDebug = PR_FALSE;
|
||||
static const PRBool gsNoisyRefs = PR_FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
nsTableColFrame::nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsFrame(aContent, aParentFrame)
|
||||
{
|
||||
mColIndex = 0;
|
||||
mRepeat = 0;
|
||||
}
|
||||
|
||||
|
||||
nsTableColFrame::~nsTableColFrame()
|
||||
{
|
||||
}
|
||||
|
||||
NS_METHOD nsTableColFrame::Paint(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf("nsTableColFrame::Paint\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_METHOD nsTableColFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
NS_ASSERTION(nsnull!=aPresContext, "bad arg");
|
||||
aDesiredSize.width=0;
|
||||
aDesiredSize.height=0;
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
{
|
||||
aDesiredSize.maxElementSize->width=0;
|
||||
aDesiredSize.maxElementSize->height=0;
|
||||
}
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ----- static methods ------ */
|
||||
|
||||
nsresult nsTableColFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
||||
if (nsnull == aInstancePtrResult) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsIFrame* it = new nsTableColFrame(aContent, aParent);
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aInstancePtrResult = it;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -48,6 +48,12 @@ public:
|
|||
/** set the index of the column this content object represents. must be >= 0 */
|
||||
virtual void SetColumnIndex (int aColIndex);
|
||||
|
||||
/** convenience method, calls into cellmap */
|
||||
nsVoidArray * GetCells();
|
||||
|
||||
/** convenience method, calls into cellmap */
|
||||
PRInt32 Count() const;
|
||||
|
||||
protected:
|
||||
|
||||
nsTableColFrame(nsIContent* aContent, nsIFrame* aParentFrame);
|
||||
|
@ -60,6 +66,12 @@ protected:
|
|||
/** the number of columns that the attributes of this column extend to */
|
||||
PRInt32 mRepeat;
|
||||
|
||||
nscoord mMaxWidth;
|
||||
nscoord mMinWidth;
|
||||
|
||||
nscoord mMaxEffectiveWidth;
|
||||
nscoord mMinEffectiveWidth;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -29,14 +29,12 @@
|
|||
#include "nsTableColGroupFrame.h"
|
||||
#include "nsTableRowFrame.h"
|
||||
#include "nsTableRowGroupFrame.h"
|
||||
#include "nsColLayoutData.h"
|
||||
|
||||
#include "BasicTableLayoutStrategy.h"
|
||||
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIView.h"
|
||||
|
@ -269,7 +267,6 @@ void ColumnInfoCache::GetColumnsByType(const nsStyleUnit aType,
|
|||
nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
||||
: nsContainerFrame(aContent, aParentFrame),
|
||||
mCellMap(nsnull),
|
||||
mColumnLayoutData(nsnull),
|
||||
mColCache(nsnull),
|
||||
mColumnWidths(nsnull),
|
||||
mTableLayoutStrategy(nsnull),
|
||||
|
@ -279,32 +276,11 @@ nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to delete all owned objects assoicated
|
||||
* with the ColumnLayoutObject instance variable
|
||||
*/
|
||||
void nsTableFrame::DeleteColumnLayoutData()
|
||||
{
|
||||
if (nsnull!=mColumnLayoutData)
|
||||
{
|
||||
PRInt32 numCols = mColumnLayoutData->Count();
|
||||
for (PRInt32 i = 0; i<numCols; i++)
|
||||
{
|
||||
nsColLayoutData *colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(i));
|
||||
delete colData;
|
||||
}
|
||||
delete mColumnLayoutData;
|
||||
mColumnLayoutData = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsTableFrame::~nsTableFrame()
|
||||
{
|
||||
if (nsnull!=mCellMap)
|
||||
delete mCellMap;
|
||||
|
||||
DeleteColumnLayoutData();
|
||||
|
||||
if (nsnull!=mColumnWidths)
|
||||
delete [] mColumnWidths;
|
||||
|
||||
|
@ -351,8 +327,7 @@ nsTableRowGroupFrame* nsTableFrame::NextRowGroupFrame(nsTableRowGroupFrame* aRow
|
|||
PRInt32 nsTableFrame::GetSpecifiedColumnCount ()
|
||||
{
|
||||
mColCount=0;
|
||||
nsIFrame * colGroup;
|
||||
ChildAt (0, (nsIFrame *&)colGroup);
|
||||
nsIFrame * colGroup = mFirstChild;
|
||||
while (nsnull!=colGroup)
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
|
@ -379,8 +354,7 @@ PRInt32 nsTableFrame::GetRowCount ()
|
|||
if (nsnull != mCellMap)
|
||||
return mCellMap->GetRowCount();
|
||||
|
||||
nsIFrame *child=nsnull;
|
||||
ChildAt(0, child);
|
||||
nsIFrame *child=mFirstChild;
|
||||
while (nsnull!=child)
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
|
@ -393,6 +367,35 @@ PRInt32 nsTableFrame::GetRowCount ()
|
|||
}
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
nsTableColFrame * nsTableFrame::GetColFrame(PRInt32 aColIndex)
|
||||
{
|
||||
nsTableColFrame *result = nsnull;
|
||||
if (nsnull!=mCellMap)
|
||||
{
|
||||
result = mCellMap->GetColumnFrame(aColIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// can return nsnull
|
||||
nsTableCellFrame * nsTableFrame::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex)
|
||||
{
|
||||
nsTableCellFrame *result = nsnull;
|
||||
if (nsnull!=mCellMap)
|
||||
{
|
||||
CellData * cellData = mCellMap->GetCellAt(aRowIndex, aColIndex);
|
||||
if (nsnull!=cellData)
|
||||
{
|
||||
result = cellData->mCell;
|
||||
if (nsnull==result)
|
||||
result = cellData->mRealCell->mCell;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// return the rows spanned by aCell starting at aRowIndex
|
||||
// note that this is different from just the rowspan of aCell
|
||||
// (that would be GetEffectiveRowSpan (indexOfRowThatContains_aCell, aCell)
|
||||
|
@ -413,13 +416,6 @@ PRInt32 nsTableFrame::GetEffectiveRowSpan (PRInt32 aRowIndex, nsTableCellFrame *
|
|||
return rowSpan;
|
||||
}
|
||||
|
||||
|
||||
// returns the actual cell map, not a copy, so don't mess with it!
|
||||
nsCellMap* nsTableFrame::GetCellMap() const
|
||||
{
|
||||
return mCellMap;
|
||||
}
|
||||
|
||||
/* call when the cell structure has changed. mCellMap will be rebuilt on demand. */
|
||||
void nsTableFrame::ResetCellMap ()
|
||||
{
|
||||
|
@ -449,10 +445,9 @@ void nsTableFrame::EnsureColumns(nsIPresContext* aPresContext,
|
|||
|
||||
PRInt32 actualColumns = 0;
|
||||
nsTableColGroupFrame *lastColGroupFrame = nsnull;
|
||||
nsIFrame * childFrame=nsnull;
|
||||
nsIFrame * firstRowGroupFrame=nsnull;
|
||||
nsIFrame * prevSibFrame=nsnull;
|
||||
ChildAt (0, (nsIFrame *&)childFrame);
|
||||
nsIFrame * childFrame=mFirstChild;
|
||||
while (nsnull!=childFrame)
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
|
@ -795,35 +790,67 @@ void nsTableFrame::GrowCellMap (PRInt32 aColCount)
|
|||
*/
|
||||
void nsTableFrame::ListColumnLayoutData(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
// if this is a continuing frame, there will be no output
|
||||
if (nsnull!=mColumnLayoutData)
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
if (this!=firstInFlow)
|
||||
{
|
||||
firstInFlow->ListColumnLayoutData(out, aIndent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsnull!=mCellMap)
|
||||
{
|
||||
fprintf(out,"Column Layout Data \n");
|
||||
|
||||
PRInt32 numCols = mColumnLayoutData->Count();
|
||||
for (PRInt32 i = 0; i<numCols; i++)
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
PRInt32 numRows = mCellMap->GetRowCount();
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
nsColLayoutData *colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(i));
|
||||
for (PRInt32 indent = aIndent; --indent >= 0; )
|
||||
fputs(" ", out);
|
||||
fprintf(out,"Column Data [%d] \n",colIndex);
|
||||
for (PRInt32 rowIndex = 0; rowIndex < numRows; rowIndex++)
|
||||
{
|
||||
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(rowIndex, colIndex);
|
||||
PRInt32 rowIndent;
|
||||
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Cell Data [%d] \n",rowIndex);
|
||||
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
||||
nsMargin margin;
|
||||
cellFrame->GetMargin(margin);
|
||||
fprintf(out,"Margin -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(margin.top),
|
||||
NS_TWIPS_TO_POINTS_INT(margin.left),
|
||||
NS_TWIPS_TO_POINTS_INT(margin.bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(margin.right));
|
||||
|
||||
for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
||||
fprintf(out,"Column Data [%d] \n",i);
|
||||
colData->List(out,aIndent+2);
|
||||
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
||||
|
||||
nscoord top,left,bottom,right;
|
||||
/*
|
||||
top = (mBorderFrame[NS_SIDE_TOP] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_TOP], NS_SIDE_TOP) : 0);
|
||||
left = (mBorderFrame[NS_SIDE_LEFT] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_LEFT], NS_SIDE_LEFT) : 0);
|
||||
bottom = (mBorderFrame[NS_SIDE_BOTTOM] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_BOTTOM], NS_SIDE_BOTTOM) : 0);
|
||||
right = (mBorderFrame[NS_SIDE_RIGHT] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_RIGHT], NS_SIDE_RIGHT) : 0);
|
||||
*/
|
||||
|
||||
fprintf(out,"Border -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
||||
NS_TWIPS_TO_POINTS_INT(top),
|
||||
NS_TWIPS_TO_POINTS_INT(left),
|
||||
NS_TWIPS_TO_POINTS_INT(bottom),
|
||||
NS_TWIPS_TO_POINTS_INT(right));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For the TableCell in CellData, find the CellLayoutData assocated
|
||||
* and add it to the list
|
||||
**/
|
||||
* For the TableCell in CellData, add it to the list
|
||||
*/
|
||||
void nsTableFrame::AppendLayoutData(nsVoidArray* aList, nsTableCellFrame* aTableCell)
|
||||
{
|
||||
|
||||
if (aTableCell != nsnull)
|
||||
{
|
||||
nsCellLayoutData* layoutData = GetCellLayoutData(aTableCell);
|
||||
if (layoutData != nsnull)
|
||||
aList->AppendElement((void*)layoutData);
|
||||
aList->AppendElement((void*)aTableCell);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -996,9 +1023,7 @@ void nsTableFrame::RecalcLayoutData()
|
|||
r++;
|
||||
}
|
||||
|
||||
nsCellLayoutData* cellLayoutData = GetCellLayoutData(cell);
|
||||
if (cellLayoutData != nsnull)
|
||||
cellLayoutData->RecalcLayoutData(this,boundaryCells);
|
||||
cell->RecalcLayoutData(this,boundaryCells);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1310,7 +1335,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
|
|||
if (nsnull!=prevKidFrame)
|
||||
prevKidFrame->GetNextSibling(kidFrame); // no need to check for an error, just see if it returned null...
|
||||
else
|
||||
ChildAt(0, kidFrame);
|
||||
kidFrame=mFirstChild;
|
||||
|
||||
// if this is the first time, allocate the frame
|
||||
if (nsnull==kidFrame)
|
||||
|
@ -2210,11 +2235,10 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext,
|
|||
if (gsDebug)
|
||||
printf ("BalanceColumnWidths...\n");
|
||||
|
||||
nsVoidArray *columnLayoutData = GetColumnLayoutData();
|
||||
if (nsnull==columnLayoutData)
|
||||
if (nsnull==mCellMap)
|
||||
return; // we don't have any information yet, so we can't do any useful work
|
||||
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
if (nsnull==mColumnWidths)
|
||||
{
|
||||
mColumnWidths = new PRInt32[numCols];
|
||||
|
@ -2233,9 +2257,22 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext,
|
|||
|
||||
// need to figure out the overall table width constraint
|
||||
// default case, get 100% of available space
|
||||
|
||||
// begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
|
||||
nsIFrame * outerTableFrame = nsnull;
|
||||
const nsStylePosition* position;
|
||||
GetGeometricParent(outerTableFrame);
|
||||
outerTableFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)position));
|
||||
// end REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED
|
||||
|
||||
|
||||
|
||||
PRInt32 maxWidth;
|
||||
/*
|
||||
const nsStylePosition* position =
|
||||
(const nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
|
||||
use this line when tableFrame contains its own position style info
|
||||
*/
|
||||
switch (position->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
maxWidth = position->mWidth.GetCoordValue();
|
||||
|
@ -2251,7 +2288,6 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext* aPresContext,
|
|||
// XXX for now these fall through
|
||||
|
||||
default:
|
||||
|
||||
maxWidth = aMaxSize.width;
|
||||
break;
|
||||
}
|
||||
|
@ -2293,16 +2329,20 @@ void nsTableFrame::SetTableWidth(nsIPresContext* aPresContext)
|
|||
|
||||
if (gsDebug==PR_TRUE) printf ("SetTableWidth...");
|
||||
PRInt32 tableWidth = 0;
|
||||
nsVoidArray *columnLayoutData = GetColumnLayoutData();
|
||||
if (nsnull==columnLayoutData)
|
||||
if (nsnull==mCellMap)
|
||||
return; // no info, so nothing to do
|
||||
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
for (PRInt32 i = 0; i<numCols; i++)
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
tableWidth += mColumnWidths[i];
|
||||
nscoord totalColWidth = mColumnWidths[colIndex];
|
||||
nsTableCellFrame * cellFrame = GetCellAt(0, colIndex);
|
||||
nsMargin colMargin;
|
||||
GetCellMarginData(cellFrame,colMargin);
|
||||
totalColWidth += colMargin.left + colMargin.right;
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf (" += %d ", mColumnWidths[i]);
|
||||
printf (" += %d ", totalColWidth);
|
||||
tableWidth += totalColWidth;
|
||||
}
|
||||
|
||||
// Compute the insets (sum of border and padding)
|
||||
|
@ -2384,12 +2424,9 @@ NS_METHOD nsTableFrame::GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aCol
|
|||
{
|
||||
aColFrame = nsnull; // initialize out parameter
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
if (nsnull!=firstInFlow->mColumnLayoutData)
|
||||
if (nsnull!=firstInFlow->mCellMap)
|
||||
{ // hooray, we get to do this the easy way because the info is cached
|
||||
nsColLayoutData * colData = (nsColLayoutData *)
|
||||
(firstInFlow->mColumnLayoutData->ElementAt(aColIndex));
|
||||
NS_ASSERTION(nsnull != colData, "bad column data");
|
||||
aColFrame = colData->GetColFrame();
|
||||
aColFrame = firstInFlow->mCellMap->GetColumnFrame(aColIndex);
|
||||
NS_ASSERTION(nsnull!=aColFrame, "bad col frame");
|
||||
}
|
||||
else
|
||||
|
@ -2443,18 +2480,30 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
mColCache = new ColumnInfoCache(mColCount);
|
||||
nsIFrame * childFrame = mFirstChild;
|
||||
while (nsnull!=childFrame)
|
||||
{ // for every child, if it's a col group then get the columns
|
||||
{ // in this loop, we cache column info and set column style info from cells in first row
|
||||
const nsStyleDisplay *childDisplay;
|
||||
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{ // if it's a col group then get the columns and cache them in the CellMap
|
||||
nsTableColFrame *colFrame=nsnull;
|
||||
childFrame->FirstChild((nsIFrame *&)colFrame);
|
||||
while (nsnull!=colFrame)
|
||||
{
|
||||
mCellMap->AppendColumnFrame(colFrame);
|
||||
colFrame->GetNextSibling((nsIFrame *&)colFrame);
|
||||
}
|
||||
}
|
||||
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
|
||||
{ // for every cell in every row, call SetCellLayoutData with the cached info
|
||||
// QQQ we can probably just leave the info in the table cell frame, not cache it here
|
||||
{ // if it's a row group, get the cells and set the column style if appropriate
|
||||
nsIFrame *rowFrame;
|
||||
childFrame->ChildAt(0, rowFrame);
|
||||
childFrame->FirstChild(rowFrame);
|
||||
if (nsnull!=rowFrame)
|
||||
{
|
||||
nsIFrame *cellFrame;
|
||||
rowFrame->ChildAt(0, cellFrame);
|
||||
rowFrame->FirstChild(cellFrame);
|
||||
while (nsnull!=cellFrame)
|
||||
{
|
||||
/* this is the first time we are guaranteed to have both the cell frames
|
||||
|
@ -2465,9 +2514,12 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
cellFrame->GetNextSibling(cellFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
|
||||
// second time through, set column cache info for each column
|
||||
// we can't do this until the loop above has set the column style info from the cells in the first row
|
||||
childFrame = mFirstChild;
|
||||
while (nsnull!=childFrame)
|
||||
{ // for every child, if it's a col group then get the columns
|
||||
|
@ -2476,7 +2528,7 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
nsTableColFrame *colFrame=nsnull;
|
||||
childFrame->ChildAt(0, (nsIFrame *&)colFrame);
|
||||
childFrame->FirstChild((nsIFrame *&)colFrame);
|
||||
while (nsnull!=colFrame)
|
||||
{ // for every column, create an entry in the column cache
|
||||
// assumes that the col style has been twiddled to account for first cell width attribute
|
||||
|
@ -2489,176 +2541,14 @@ void nsTableFrame::BuildColumnCache( nsIPresContext* aPresContext,
|
|||
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
|
||||
{ // for every cell in every row, call SetCellLayoutData with the cached info
|
||||
// QQQ we can probably just leave the info in the table cell frame, not cache it here
|
||||
nsIFrame *rowFrame;
|
||||
childFrame->ChildAt(0, rowFrame);
|
||||
while (nsnull!=rowFrame)
|
||||
{
|
||||
nsIFrame *cellFrame;
|
||||
rowFrame->ChildAt(0, cellFrame);
|
||||
while (nsnull!=cellFrame)
|
||||
{
|
||||
nsCellLayoutData *cld = ((nsTableCellFrame*)cellFrame)->GetCellLayoutData();
|
||||
SetCellLayoutData(aPresContext, cld, (nsTableCellFrame*)cellFrame);
|
||||
cellFrame->GetNextSibling(cellFrame);
|
||||
}
|
||||
rowFrame->GetNextSibling(rowFrame);
|
||||
}
|
||||
break; // once we hit a row group, we're done
|
||||
}
|
||||
childFrame->GetNextSibling(childFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nsnull is a valid return value. This is for empty tables.
|
||||
nsVoidArray * nsTableFrame::GetColumnLayoutData()
|
||||
{
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
return firstInFlow->mColumnLayoutData;
|
||||
}
|
||||
|
||||
/** Associate aData with the cell at (aRow,aCol)
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
PRBool nsTableFrame::SetCellLayoutData(nsIPresContext* aPresContext,
|
||||
nsCellLayoutData * aData, nsTableCellFrame *aCell)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aPresContext, "bad arg aPresContext");
|
||||
NS_ASSERTION(nsnull != aData, "bad arg aData");
|
||||
NS_ASSERTION(nsnull != aCell, "bad arg aCell");
|
||||
|
||||
PRBool result = PR_TRUE;
|
||||
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
if (this!=firstInFlow)
|
||||
result = firstInFlow->SetCellLayoutData(aPresContext, aData, aCell);
|
||||
else
|
||||
{
|
||||
if ((kPASS_FIRST==GetReflowPass()) || (kPASS_INCREMENTAL==GetReflowPass()))
|
||||
{
|
||||
if (nsnull==mColumnLayoutData)
|
||||
{
|
||||
PRInt32 rows = GetRowCount();
|
||||
mColumnLayoutData = new nsVoidArray();
|
||||
NS_ASSERTION(nsnull != mColumnLayoutData, "bad alloc");
|
||||
PRInt32 tableKidCount = mContent->ChildCount();
|
||||
nsIFrame * colGroupFrame = mFirstChild;
|
||||
for (PRInt32 i=0; i<tableKidCount; ) // notice increment of i is done just before ChildAt call
|
||||
{
|
||||
const nsStyleDisplay *childDisplay;
|
||||
colGroupFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
||||
{
|
||||
nsTableColFrame *colFrame=nsnull;
|
||||
colGroupFrame->ChildAt(0, (nsIFrame *&)colFrame);
|
||||
while (nsnull!=colFrame)
|
||||
{
|
||||
// TODO: unify these 2 kinds of column data
|
||||
// TODO: cache more column data, like the mWidth.GetUnit and what its value
|
||||
nsColLayoutData *colData = new nsColLayoutData(colFrame, rows);
|
||||
mColumnLayoutData->AppendElement((void *)colData);
|
||||
colFrame->GetNextSibling((nsIFrame *&)colFrame);
|
||||
}
|
||||
}
|
||||
// can't have col groups after row groups, so stop if you find a row group
|
||||
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
|
||||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
ChildAt(i, colGroupFrame); // can't use colGroupFrame->GetNextSibling because it hasn't been set yet
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 firstColIndex = aCell->GetColIndex();
|
||||
nsTableRowFrame *row;
|
||||
aCell->GetGeometricParent((nsIFrame*&)row);
|
||||
PRInt32 rowIndex = row->GetRowIndex();
|
||||
PRInt32 colSpan = aCell->GetColSpan();
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(firstColIndex));
|
||||
nsVoidArray *col = colData->GetCells();
|
||||
if (gsDebugCLD) printf (" ~ SetCellLayoutData with row = %d, firstCol = %d, colSpan = %d, colData = %ld, col=%ld\n",
|
||||
rowIndex, firstColIndex, colSpan, colData, col);
|
||||
/* this logic looks wrong wrong wrong
|
||||
it seems to add an entries in col (the array of cells for a column) for aCell
|
||||
based on colspan. This is weird, because you would expect one entry in each
|
||||
column spanned for aCell, not multiple entries in the same col.
|
||||
*/
|
||||
for (PRInt32 i=0; i<colSpan; i++)
|
||||
{
|
||||
nsSize * cellSize = aData->GetMaxElementSize();
|
||||
nsSize partialCellSize(*cellSize);
|
||||
partialCellSize.width = (cellSize->width)/colSpan;
|
||||
// This method will copy the nsReflowMetrics pointed at by aData->GetDesiredSize()
|
||||
nsCellLayoutData * kidLayoutData = new nsCellLayoutData(aData->GetCellFrame(),
|
||||
aData->GetDesiredSize(),
|
||||
&partialCellSize);
|
||||
NS_ASSERTION(col->Count() > rowIndex, "unexpected count");
|
||||
if (gsDebugCLD) printf (" ~ replacing rowIndex = %d\n", rowIndex);
|
||||
nsCellLayoutData* data = (nsCellLayoutData*)col->ElementAt(rowIndex);
|
||||
col->ReplaceElementAt((void *)kidLayoutData, rowIndex);
|
||||
if (data != nsnull) {
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
result = PR_FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Get the layout data associated with the cell at (aRow,aCol)
|
||||
* @return nsnull if there was an error, such as aRow or aCol being invalid
|
||||
* otherwise, the data is returned.
|
||||
*/
|
||||
nsCellLayoutData * nsTableFrame::GetCellLayoutData(nsTableCellFrame *aCell)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aCell, "bad arg");
|
||||
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
||||
nsCellLayoutData *result = nsnull;
|
||||
if (this!=firstInFlow)
|
||||
result = firstInFlow->GetCellLayoutData(aCell);
|
||||
else
|
||||
{
|
||||
if (nsnull!=mColumnLayoutData)
|
||||
{
|
||||
PRInt32 firstColIndex = aCell->GetColIndex();
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(mColumnLayoutData->ElementAt(firstColIndex));
|
||||
nsTableRowFrame *rowFrame;
|
||||
aCell->GetGeometricParent((nsIFrame *&)rowFrame);
|
||||
PRInt32 rowIndex = rowFrame->GetRowIndex();
|
||||
result = colData->ElementAt(rowIndex);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
// Do some sanity checking
|
||||
if (nsnull != result) {
|
||||
nsIContent* inputContent;
|
||||
nsIContent* resultContent;
|
||||
result->GetCellFrame()->GetContent(resultContent);
|
||||
aCell->GetContent(inputContent);
|
||||
NS_ASSERTION(resultContent == inputContent, "unexpected cell");
|
||||
NS_IF_RELEASE(inputContent);
|
||||
NS_IF_RELEASE(resultContent);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRInt32 nsTableFrame::GetReflowPass() const
|
||||
{
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
|
@ -2698,7 +2588,7 @@ nsTableFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
|||
// add headers and footers to cf
|
||||
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
||||
nsIFrame * rg = nsnull;
|
||||
firstInFlow->ChildAt(0, rg);
|
||||
firstInFlow->FirstChild(rg);
|
||||
NS_ASSERTION (nsnull!=rg, "previous frame has no children");
|
||||
nsIAtom * tHeadTag = NS_NewAtom(nsTablePart::kRowGroupHeadTagString); // tHeadTag: REFCNT++
|
||||
nsIAtom * tFootTag = NS_NewAtom(nsTablePart::kRowGroupFootTagString); // tFootTag: REFCNT++
|
||||
|
@ -2758,9 +2648,8 @@ PRInt32 nsTableFrame::GetColumnWidth(PRInt32 aColIndex)
|
|||
{
|
||||
NS_ASSERTION(nsnull!=mColumnWidths, "illegal state");
|
||||
#ifdef DEBUG
|
||||
nsVoidArray *cld = GetColumnLayoutData();
|
||||
NS_ASSERTION(nsnull!=cld, "no column layout data");
|
||||
PRInt32 numCols = cld->Count();
|
||||
NS_ASSERTION(nsnull!=mCellMap, "no column layout data");
|
||||
PRInt32 numCols = mCellMap->GetColCount();
|
||||
NS_ASSERTION (numCols > aColIndex, "bad arg, col index out of bounds");
|
||||
#endif
|
||||
if (nsnull!=mColumnWidths)
|
||||
|
@ -2770,11 +2659,6 @@ PRInt32 nsTableFrame::GetColumnWidth(PRInt32 aColIndex)
|
|||
//printf("GET_COL_WIDTH: %p, FIF=%p getting col %d and returning %d\n", this, firstInFlow, aColIndex, result);
|
||||
|
||||
// XXX hack
|
||||
#if 0
|
||||
if (result <= 0) {
|
||||
result = 100;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2936,9 +2820,7 @@ NS_METHOD nsTableFrame::GetCellMarginData(nsTableCellFrame* aKidFrame, nsMargin&
|
|||
|
||||
if (nsnull != aKidFrame)
|
||||
{
|
||||
nsCellLayoutData* layoutData = GetCellLayoutData(aKidFrame);
|
||||
if (layoutData)
|
||||
result = layoutData->GetMargin(aMargin);
|
||||
result = aKidFrame->GetMargin(aMargin);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -3218,37 +3100,6 @@ PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* valuable code not yet used anywhere
|
||||
|
||||
// since the table is a specified width, we need to expand the columns to fill the table
|
||||
nsVoidArray *columnLayoutData = GetColumnLayoutData();
|
||||
PRInt32 numCols = columnLayoutData->Count();
|
||||
PRInt32 spaceUsed = 0;
|
||||
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
||||
spaceUsed += mColumnWidths[colIndex];
|
||||
PRInt32 spaceRemaining = spaceUsed - aMaxWidth;
|
||||
PRInt32 additionalSpaceAdded = 0;
|
||||
if (0<spaceRemaining)
|
||||
{
|
||||
for (colIndex = 0; colIndex<numCols; colIndex++)
|
||||
{
|
||||
nsColLayoutData * colData = (nsColLayoutData *)(columnLayoutData->ElementAt(colIndex));
|
||||
nsTableColPtr col = colData->GetCol(); // col: ADDREF++
|
||||
nsStyleMolecule* colStyle =
|
||||
(nsStyleMolecule*)mStyleContext->GetData(eStyleStruct_Molecule);
|
||||
if (PR_TRUE==IsProportionalWidth(colStyle))
|
||||
{
|
||||
PRInt32 percentage = (100*mColumnWidths[colIndex]) / aMaxWidth;
|
||||
PRInt32 additionalSpace = (spaceRemaining*percentage)/100;
|
||||
mColumnWidths[colIndex] += additionalSpace;
|
||||
additionalSpaceAdded += additionalSpace;
|
||||
}
|
||||
}
|
||||
if (spaceUsed+additionalSpaceAdded < aMaxTableWidth)
|
||||
mColumnWidths[numCols-1] += (aMaxTableWidth - (spaceUsed+additionalSpaceAdded));
|
||||
}
|
||||
*/
|
||||
|
||||
// For Debugging ONLY
|
||||
NS_METHOD nsTableFrame::MoveTo(nscoord aX, nscoord aY)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "nsStyleCoord.h"
|
||||
|
||||
class nsCellMap;
|
||||
class nsCellLayoutData;
|
||||
class nsVoidArray;
|
||||
class nsTableCellFrame;
|
||||
class nsTableColFrame;
|
||||
|
@ -42,29 +41,6 @@ struct nsStyleSpacing;
|
|||
|
||||
extern const nsIID kTableFrameCID;
|
||||
|
||||
/** Data stored by nsCellMap to rationalize rowspan and colspan cells.
|
||||
* if mCell is null then mRealCell will be the rowspan/colspan source
|
||||
* in addition, if fOverlap is non-null then it will point to the
|
||||
* other cell that overlaps this position
|
||||
* @see nsCellMap
|
||||
* @see nsTableFrame::BuildCellMap
|
||||
* @see nsTableFrame::GrowCellMap
|
||||
* @see nsTableFrame::BuildCellIntoMap
|
||||
*
|
||||
*/
|
||||
class CellData
|
||||
{
|
||||
public:
|
||||
nsTableCellFrame *mCell;
|
||||
CellData *mRealCell;
|
||||
CellData *mOverlap;
|
||||
|
||||
CellData();
|
||||
|
||||
~CellData();
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================================ */
|
||||
|
||||
/** nsTableFrame maps the inner portion of a table (everything except captions.)
|
||||
|
@ -153,36 +129,12 @@ public:
|
|||
*/
|
||||
NS_METHOD GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame);
|
||||
|
||||
/** return the column layout data for this inner table frame.
|
||||
* if this is a continuing frame, return the first-in-flow's column layout data.
|
||||
* @return the column layout data array, or null if there is no info yet.
|
||||
*/
|
||||
virtual nsVoidArray *GetColumnLayoutData();
|
||||
|
||||
/** Associate aData with the cell at (aRow,aCol)
|
||||
*
|
||||
* @param aPresContext -- used to resolve style when initializing caches
|
||||
* @param aData -- the info to cache
|
||||
* @param aCell -- the content object for which layout info is being cached
|
||||
*
|
||||
* @return PR_TRUE if the data was successfully associated with a Cell
|
||||
* PR_FALSE if there was an error, such as aRow or aCol being invalid
|
||||
*/
|
||||
virtual PRBool SetCellLayoutData(nsIPresContext * aPresContext,
|
||||
nsCellLayoutData * aData,
|
||||
nsTableCellFrame * aCell);
|
||||
|
||||
/** Get the layout data associated with the cell at (aRow,aCol)
|
||||
* @return PR_NULL if there was an error, such as aRow or aCol being invalid
|
||||
* otherwise, the data is returned.
|
||||
*/
|
||||
virtual nsCellLayoutData * GetCellLayoutData(nsTableCellFrame *aCell);
|
||||
|
||||
/**
|
||||
* DEBUG METHOD
|
||||
*
|
||||
*/
|
||||
virtual void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
//virtual void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
|
||||
|
||||
/** return the width of the column at aColIndex */
|
||||
|
@ -236,11 +188,6 @@ protected:
|
|||
/** destructor, responsible for mColumnLayoutData and mColumnWidths */
|
||||
virtual ~nsTableFrame();
|
||||
|
||||
/** helper method to delete contents of mColumnLayoutData
|
||||
* should be called with care (ie, only by destructor)
|
||||
*/
|
||||
virtual void DeleteColumnLayoutData();
|
||||
|
||||
/** first pass of ResizeReflow.
|
||||
* lays out all table content with aMaxSize(NS_UNCONSTRAINEDSIZE,NS_UNCONSTRAINEDSIZE) and
|
||||
* a non-null aMaxElementSize so we get all the metrics we need to do column balancing.
|
||||
|
@ -380,6 +327,16 @@ protected:
|
|||
*/
|
||||
virtual void ResetCellMap ();
|
||||
|
||||
/** for debugging only
|
||||
* prints out information about the cell map
|
||||
*/
|
||||
void DumpCellMap() const;
|
||||
|
||||
/** for debugging only
|
||||
* prints out info about the table layout state, printing columns and their cells
|
||||
*/
|
||||
void ListColumnLayoutData(FILE* out, PRInt32 aIndent) const;
|
||||
|
||||
/** ResetColumns is called when the column structure of the table is changed.
|
||||
* Call with caution, only when adding or removing columns, changing
|
||||
* column attributes, changing the rowspan or colspan attribute of a cell, etc.
|
||||
|
@ -418,13 +375,6 @@ protected:
|
|||
*/
|
||||
virtual nsTableRowGroupFrame* NextRowGroupFrame (nsTableRowGroupFrame*);
|
||||
|
||||
/** returns the number of rows in this table.
|
||||
* if mCellMap has been created, it is asked for the number of rows.<br>
|
||||
* otherwise, the content is enumerated and the rows are counted.
|
||||
*/
|
||||
virtual PRInt32 GetRowCount();
|
||||
|
||||
|
||||
/** return the number of columns as specified by the input.
|
||||
* has 2 side effects:<br>
|
||||
* calls SetStartColumnIndex on each nsTableColumn<br>
|
||||
|
@ -432,9 +382,18 @@ protected:
|
|||
*/
|
||||
virtual PRInt32 GetSpecifiedColumnCount ();
|
||||
|
||||
public:
|
||||
virtual void DumpCellMap() const;
|
||||
virtual nsCellMap* GetCellMap() const;
|
||||
public: /* ----- Cell Map public methods ----- */
|
||||
|
||||
/** returns the number of rows in this table.
|
||||
* if mCellMap has been created, it is asked for the number of rows.<br>
|
||||
* otherwise, the content is enumerated and the rows are counted.
|
||||
*/
|
||||
virtual PRInt32 GetRowCount();
|
||||
|
||||
nsTableColFrame * GetColFrame(PRInt32 aColIndex);
|
||||
|
||||
nsTableCellFrame * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
@ -446,9 +405,7 @@ private:
|
|||
*/
|
||||
enum {kPASS_UNDEFINED=0, kPASS_FIRST=1, kPASS_SECOND=2, kPASS_THIRD=3, kPASS_INCREMENTAL=4};
|
||||
|
||||
nsVoidArray *mColumnLayoutData; // array of array of cellLayoutData's
|
||||
PRInt32 *mColumnWidths; // widths of each column
|
||||
//TODO: move all column info into this object
|
||||
ColumnInfoCache *mColCache; // cached information about the table columns
|
||||
PRBool mFirstPassValid; // PR_TRUE if first pass data is still legit
|
||||
PRInt32 mPass; // which Reflow pass are we currently in?
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include "nsTableFrame.h"
|
||||
#include "nsTableColFrame.h"
|
||||
#include "nsTableCellFrame.h"
|
||||
#include "nsCellLayoutData.h"
|
||||
#include "nsColLayoutData.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIReflowCommand.h"
|
||||
|
@ -37,6 +35,7 @@ NS_DEF_PTR(nsIStyleContext);
|
|||
static PRBool gsDebug1 = PR_FALSE;
|
||||
static PRBool gsDebug2 = PR_FALSE;
|
||||
//#define NOISY
|
||||
//#define NOISY_FLOW
|
||||
#else
|
||||
static const PRBool gsDebug1 = PR_FALSE;
|
||||
static const PRBool gsDebug2 = PR_FALSE;
|
||||
|
@ -51,6 +50,9 @@ struct RowReflowState {
|
|||
// The body's available size (computed from the body's parent)
|
||||
nsSize availSize;
|
||||
|
||||
// the running x-offset
|
||||
nscoord x;
|
||||
|
||||
// Height of tallest cell (excluding cells with rowspan > 1)
|
||||
nscoord maxCellHeight; // just the height of the cell frame
|
||||
nscoord maxCellVertSpace; // the maximum MAX(cellheight + topMargin + bottomMargin)
|
||||
|
@ -68,6 +70,7 @@ struct RowReflowState {
|
|||
maxCellHeight = 0;
|
||||
maxCellVertSpace = 0;
|
||||
tableFrame = aTableFrame;
|
||||
x=0;
|
||||
}
|
||||
|
||||
~RowReflowState() {
|
||||
|
@ -111,12 +114,12 @@ nsTableRowFrame::DidReflow(nsIPresContext& aPresContext,
|
|||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(mRowIndex, cellFrame);
|
||||
if (1==rowSpan)
|
||||
{
|
||||
// Resize the cell's height
|
||||
// resize the cell's height
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
cellFrame->SizeTo(cellFrameSize.width, cellHeight);
|
||||
|
||||
// Realign cell content based on the new height
|
||||
// realign cell content based on the new height
|
||||
cellFrame->VerticallyAlignChild(&aPresContext);
|
||||
}
|
||||
|
||||
|
@ -287,6 +290,9 @@ void nsTableRowFrame::PlaceChild(nsIPresContext* aPresContext,
|
|||
// Place and size the child
|
||||
aKidFrame->SetRect(aKidRect);
|
||||
|
||||
// update the running total for the row width
|
||||
aState.x += aKidRect.width;
|
||||
|
||||
// Update the maximum element size
|
||||
PRInt32 rowSpan = ((nsTableCellFrame*)aKidFrame)->GetRowSpan();
|
||||
if (nsnull != aMaxElementSize)
|
||||
|
@ -328,6 +334,8 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
NS_PRECONDITION(nsnull != mFirstChild, "no children");
|
||||
|
||||
nsSize kidMaxElementSize;
|
||||
PRBool result = PR_TRUE;
|
||||
PRInt32 prevColIndex = -1; // remember the col index of the previous cell to handle rowspans into this row
|
||||
nsSize* pKidMaxElementSize = (nsnull != aDesiredSize.maxElementSize) ?
|
||||
&kidMaxElementSize : nsnull;
|
||||
nscoord maxCellTopMargin = 0;
|
||||
|
@ -335,6 +343,13 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
|
||||
// Reflow each of our existing cell frames
|
||||
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
|
||||
nsSize kidAvailSize(aState.availSize);
|
||||
if (0>=kidAvailSize.height)
|
||||
kidAvailSize.height = 1; // XXX: HaCk - we don't handle negative heights yet
|
||||
|
||||
nsReflowMetrics desiredSize(pKidMaxElementSize);
|
||||
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
|
||||
|
||||
// Get the frame's margins, and compare the top and bottom margin
|
||||
// against our current max values
|
||||
nsMargin kidMargin;
|
||||
|
@ -344,15 +359,49 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
if (kidMargin.bottom > maxCellBottomMargin)
|
||||
maxCellBottomMargin = kidMargin.bottom;
|
||||
|
||||
// Figure out the amount of available size for the child (subtract
|
||||
// off the top margin we are going to apply to it)
|
||||
|
||||
//XXX TROY??? unconstrainedHeight was removed from aState, what should happen here?
|
||||
/*
|
||||
if (PR_FALSE == aState.unconstrainedHeight)
|
||||
{
|
||||
kidAvailSize.height -= kidMargin.top + kidMargin.bottom;
|
||||
}
|
||||
*/
|
||||
|
||||
// left and right margins already taken into account by table layout strategy
|
||||
|
||||
// Compute the x-origin for the child
|
||||
//
|
||||
// XXX Having to re-compute the value each time from scratch is very inefficent...
|
||||
nscoord x = ComputeCellXOffset(aState, kidFrame, kidMargin);
|
||||
// Compute the x-origin for the child, taking into account straddlers (cells from prior
|
||||
// rows with rowspans > 1)
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
if (prevColIndex != (cellColIndex-1))
|
||||
{ // if this cell is not immediately adjacent to the previous cell, factor in missing col info
|
||||
for (PRInt32 colIndex=prevColIndex+1; colIndex<cellColIndex; colIndex++)
|
||||
{
|
||||
aState.x += aState.tableFrame->GetColumnWidth(colIndex);
|
||||
aState.x += kidMargin.left + kidMargin.right;
|
||||
}
|
||||
}
|
||||
aState.x += kidMargin.left;
|
||||
|
||||
// at this point, we know the column widths.
|
||||
// so we get the avail width from the known column widths
|
||||
PRInt32 cellColSpan = ((nsTableCellFrame *)kidFrame)->GetColSpan();
|
||||
nscoord availWidth = 0;
|
||||
for (PRInt32 numColSpan=0; numColSpan<cellColSpan; numColSpan++)
|
||||
{
|
||||
availWidth += aState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
|
||||
if (0<numColSpan)
|
||||
{
|
||||
availWidth += kidMargin.right;
|
||||
if (0!=cellColIndex)
|
||||
availWidth += kidMargin.left;
|
||||
}
|
||||
}
|
||||
|
||||
prevColIndex = cellColIndex + (cellColSpan-1); // remember the rightmost column this cell spans into
|
||||
|
||||
// Compute the cell available width from the column widths
|
||||
nscoord availWidth = ComputeCellAvailWidth(aState, kidFrame);
|
||||
|
||||
// If the available width is the same as last time we reflowed the cell,
|
||||
// then just use the previous desired size
|
||||
|
@ -360,7 +409,6 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
// XXX Wouldn't it be cleaner (but slightly less efficient) for the row to
|
||||
// just reflow the cell, and have the cell decide whether it could use the
|
||||
// cached value rather than having the row make that determination?
|
||||
nsReflowMetrics desiredSize(pKidMaxElementSize);
|
||||
if (availWidth != ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth())
|
||||
{
|
||||
// Always let the cell be as high as it wants. We ignore the height that's
|
||||
|
@ -370,7 +418,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
|
||||
// Reflow the child
|
||||
kidFrame->WillReflow(*aPresContext);
|
||||
kidFrame->MoveTo(x, kidMargin.top);
|
||||
kidFrame->MoveTo(aState.x, kidMargin.top);
|
||||
kidAvailSize.width = availWidth;
|
||||
nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize,
|
||||
eReflowReason_Resize);
|
||||
|
@ -393,12 +441,12 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
}
|
||||
else
|
||||
{
|
||||
nsSize priorSize = ((nsTableCellFrame *)kidFrame)->GetPriorDesiredSize();
|
||||
nsSize priorSize = ((nsTableCellFrame *)kidFrame)->GetDesiredSize();
|
||||
desiredSize.width = priorSize.width;
|
||||
desiredSize.height = priorSize.height;
|
||||
}
|
||||
|
||||
// Place the child after taking into account its margin and attributes
|
||||
// Place the child after taking into account it's margin and attributes
|
||||
nscoord specifiedHeight = 0;
|
||||
nscoord cellHeight = desiredSize.height;
|
||||
nsIStyleContextPtr kidSC;
|
||||
|
@ -423,19 +471,20 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
// begin special Nav4 compatibility code
|
||||
if (0==cellWidth)
|
||||
{
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
|
||||
}
|
||||
// end special Nav4 compatibility code
|
||||
|
||||
// Place the child
|
||||
nsRect kidRect (x, kidMargin.top, cellWidth, cellHeight);
|
||||
nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight);
|
||||
|
||||
PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
|
||||
pKidMaxElementSize);
|
||||
aState.x += kidMargin.right; // add in right margin only after cell has been placed
|
||||
|
||||
// Get the next child
|
||||
kidFrame->GetNextSibling(kidFrame);
|
||||
|
||||
}
|
||||
|
||||
SetMaxChildHeight(aState.maxCellHeight,maxCellTopMargin, maxCellBottomMargin); // remember height of tallest child who doesn't have a row span
|
||||
|
@ -448,42 +497,6 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compute the x-origin for the child by summing up the width of each
|
||||
// prior column. This correctly handles cells from prior rows with rowspans
|
||||
// > 1
|
||||
nscoord nsTableRowFrame::ComputeCellXOffset(const RowReflowState& aState,
|
||||
nsIFrame* aKidFrame,
|
||||
const nsMargin& aKidMargin) const
|
||||
{
|
||||
nscoord x = aKidMargin.left;
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)aKidFrame)->GetColIndex();
|
||||
|
||||
for (PRInt32 colIndex = 0; colIndex < cellColIndex; colIndex++)
|
||||
{
|
||||
x += aState.tableFrame->GetColumnWidth(colIndex);
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// Computes the avail width for the cell. Takes into account column
|
||||
// spans
|
||||
nscoord nsTableRowFrame::ComputeCellAvailWidth(const RowReflowState& aState,
|
||||
nsIFrame* aKidFrame) const
|
||||
{
|
||||
nscoord availWidth = 0;
|
||||
nsCellLayoutData *cellData = aState.tableFrame->GetCellLayoutData((nsTableCellFrame *)aKidFrame);
|
||||
PRInt32 cellStartingCol = ((nsTableCellFrame *)aKidFrame)->GetColIndex();
|
||||
PRInt32 cellColSpan = ((nsTableCellFrame *)aKidFrame)->GetColSpan();
|
||||
|
||||
for (PRInt32 numColSpan = 0; numColSpan < cellColSpan; numColSpan++)
|
||||
{
|
||||
availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol + numColSpan);
|
||||
}
|
||||
|
||||
return availWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called for the initial reflow. Creates each table cell frame, and
|
||||
* reflows it to gets its minimum and maximum sizes
|
||||
|
@ -570,13 +583,10 @@ nsTableRowFrame::InitialReflow(nsIPresContext* aPresContext,
|
|||
|
||||
kidFrame->WillReflow(*aPresContext);
|
||||
status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState);
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1DesiredSize(kidSize);
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "unexpected child reflow status");
|
||||
|
||||
// Allocate and set the cell layout data
|
||||
nsCellLayoutData *kidLayoutData = new nsCellLayoutData((nsTableCellFrame *)kidFrame,
|
||||
&kidSize, &kidMaxElementSize);
|
||||
((nsTableCellFrame *)kidFrame)->SetCellLayoutData(kidLayoutData);
|
||||
|
||||
if (gsDebug1)
|
||||
{
|
||||
printf("reflow of cell returned result = %s with desired=%d,%d, min = %d,%d\n",
|
||||
|
@ -630,13 +640,12 @@ nsresult nsTableRowFrame::RecoverState(RowReflowState& aState,
|
|||
for (nsIFrame* frame = mFirstChild; frame != aKidFrame;) {
|
||||
PRInt32 rowSpan = ((nsTableCellFrame*)frame)->GetRowSpan();
|
||||
if (mMinRowSpan == rowSpan) {
|
||||
// XXX This isn't quite right. We also need to check whether the cell
|
||||
// has a height property that affects the cell...
|
||||
nsSize desiredSize = ((nsTableCellFrame *)frame)->GetPriorDesiredSize();
|
||||
nsRect rect;
|
||||
frame->GetRect(rect);
|
||||
|
||||
// Update maxCellHeight
|
||||
if (desiredSize.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = desiredSize.height;
|
||||
if (rect.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = rect.height;
|
||||
}
|
||||
|
||||
// Update maxCellVertHeight
|
||||
|
@ -644,18 +653,14 @@ nsresult nsTableRowFrame::RecoverState(RowReflowState& aState,
|
|||
|
||||
if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, margin) == NS_OK)
|
||||
{
|
||||
nscoord height = desiredSize.height + margin.top + margin.bottom;
|
||||
nscoord height = rect.height + margin.top + margin.bottom;
|
||||
if (height > aState.maxCellVertSpace) {
|
||||
aState.maxCellVertSpace = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX We also need to recover the max element size if requested by the
|
||||
// caller...
|
||||
//
|
||||
// We should be using GetReflowMetrics() to get information from the
|
||||
// table cell, and that will include the max element size...
|
||||
// XXX We also need to recover the max element size...
|
||||
|
||||
// Remember the frame that precedes aKidFrame
|
||||
prevKidFrame = frame;
|
||||
|
@ -687,20 +692,30 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
// Recover our reflow state
|
||||
RecoverState(aState, kidFrame);
|
||||
|
||||
// Get the frame's margins
|
||||
// Figure out the amount of available space for the child
|
||||
nsMargin kidMargin;
|
||||
aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame,kidMargin);
|
||||
|
||||
// Figure out the amount of available space for the child
|
||||
// XXX Shakey...
|
||||
nsSize kidAvailSize(aState.availSize);
|
||||
nsSize kidAvailSize(aState.availSize); // XXX: top and bottom margins?
|
||||
|
||||
// Compute the x-origin for the child, taking into account straddlers (cells
|
||||
// from prior rows with rowspans > 1)
|
||||
nscoord x = ComputeCellXOffset(aState, kidFrame, kidMargin);
|
||||
// Compute the x-origin for the child, taking into account straddlers (cells from prior
|
||||
// rows with rowspans > 1)
|
||||
nscoord x = kidMargin.left;
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
for (PRInt32 colIndex=0; colIndex<cellColIndex; colIndex++)
|
||||
{
|
||||
x += aState.tableFrame->GetColumnWidth(colIndex);
|
||||
}
|
||||
|
||||
// Compute the cell avail width from the column widths
|
||||
nscoord availWidth = ComputeCellAvailWidth(aState, kidFrame);
|
||||
// at this point, we know the column widths.
|
||||
// so we get the avail width from the known column widths
|
||||
PRInt32 cellStartingCol = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
PRInt32 cellColSpan = ((nsTableCellFrame *)kidFrame)->GetColSpan();
|
||||
nscoord availWidth = 0;
|
||||
for (PRInt32 numColSpan=0; numColSpan<cellColSpan; numColSpan++)
|
||||
availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan);
|
||||
kidAvailSize.width = availWidth;
|
||||
|
||||
// Pass along the reflow command. Reflow the child with an unconstrained
|
||||
|
@ -726,23 +741,16 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
kidReflowState.maxSize.width = NS_UNCONSTRAINEDSIZE;
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState);
|
||||
|
||||
// Update the cell layout data. Note that we need to do this for both
|
||||
// the data the cell maintains AND the data the table maintains...
|
||||
nsCellLayoutData *kidLayoutData = ((nsTableCellFrame *)kidFrame)->GetCellLayoutData();
|
||||
|
||||
kidLayoutData->SetDesiredSize(&desiredSize);
|
||||
kidLayoutData->SetMaxElementSize(&kidMaxElementSize);
|
||||
|
||||
kidLayoutData = aState.tableFrame->GetCellLayoutData((nsTableCellFrame*)kidFrame);
|
||||
kidLayoutData->SetDesiredSize(&desiredSize);
|
||||
kidLayoutData->SetMaxElementSize(&kidMaxElementSize);
|
||||
// Update the cell layout data.
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1DesiredSize(desiredSize);
|
||||
((nsTableCellFrame *)kidFrame)->SetPass1MaxElementSize(kidMaxElementSize);
|
||||
|
||||
// Now reflow the cell again this time constraining the width
|
||||
// XXX Ignore for now the possibility that the column width has changed...
|
||||
kidReflowState.maxSize.width = availWidth;
|
||||
status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState);
|
||||
|
||||
// Place the child after taking into account its margin and attributes
|
||||
// Place the child after taking into account it's margin and attributes
|
||||
nscoord specifiedHeight = 0;
|
||||
nscoord cellHeight = desiredSize.height;
|
||||
nsIStyleContextPtr kidSC;
|
||||
|
@ -767,7 +775,6 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
// begin special Nav4 compatibility code
|
||||
if (0==cellWidth)
|
||||
{
|
||||
PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
|
||||
cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
|
||||
}
|
||||
// end special Nav4 compatibility code
|
||||
|
@ -781,8 +788,8 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
// Now iterate over the remaining cells, and update our max cell
|
||||
// height and our running x-offset
|
||||
//
|
||||
// We don't have to re-position the x-origin of any of the child frames
|
||||
// that follow, because the column width hasn't changed...
|
||||
// We don't have to re-position any of the child frames that follow, because
|
||||
// the column width hasn't changed...
|
||||
nscoord maxCellTopMargin = 0;
|
||||
nscoord maxCellBottomMargin = 0;
|
||||
kidFrame->GetNextSibling((nsIFrame*&)kidFrame);
|
||||
|
@ -791,11 +798,9 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
nsRect rect;
|
||||
kidFrame->GetRect(rect);
|
||||
if (mMinRowSpan == rowSpan) {
|
||||
nsSize desiredSize = ((nsTableCellFrame *)kidFrame)->GetPriorDesiredSize();
|
||||
|
||||
// Update maxCellHeight
|
||||
if (desiredSize.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = desiredSize.height;
|
||||
if (rect.height > aState.maxCellHeight) {
|
||||
aState.maxCellHeight = rect.height;
|
||||
}
|
||||
|
||||
// Update maxCellVertHeight
|
||||
|
@ -803,7 +808,7 @@ nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresContext,
|
|||
|
||||
if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, margin) == NS_OK)
|
||||
{
|
||||
nscoord height = desiredSize.height + margin.top + margin.bottom;
|
||||
nscoord height = rect.height + margin.top + margin.bottom;
|
||||
if (height > aState.maxCellVertSpace) {
|
||||
aState.maxCellVertSpace = height;
|
||||
}
|
||||
|
@ -899,16 +904,22 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_METHOD
|
||||
nsTableRowFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aStyleContext,
|
||||
nsIFrame*& aContinuingFrame)
|
||||
{
|
||||
// Because rows are always complete we should never be asked to create
|
||||
// a continuing frame
|
||||
NS_ERROR("Unexpected request");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (gsDebug1==PR_TRUE) printf("nsTableRowFrame::CreateContinuingFrame\n");
|
||||
nsTableRowFrame* cf = new nsTableRowFrame(mContent, aParent);
|
||||
if (nsnull == cf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsTableRowFrame::NewFrame( nsIFrame** aInstancePtrResult,
|
||||
|
|
|
@ -29,13 +29,11 @@
|
|||
#include "nsIReflowCommand.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gsDebug1 = PR_FALSE;
|
||||
static PRBool gsDebug2 = PR_FALSE;
|
||||
static PRBool gsDebug = PR_FALSE;
|
||||
//#define NOISY
|
||||
//#define NOISY_FLOW
|
||||
#else
|
||||
static const PRBool gsDebug1 = PR_FALSE;
|
||||
static const PRBool gsDebug2 = PR_FALSE;
|
||||
static const PRBool gsDebug = PR_FALSE;
|
||||
#endif
|
||||
|
||||
NS_DEF_PTR(nsIStyleContext);
|
||||
|
@ -195,7 +193,7 @@ void nsTableRowGroupFrame::PlaceChild( nsIPresContext* aPresContext,
|
|||
nsSize* aMaxElementSize,
|
||||
nsSize& aKidMaxElementSize)
|
||||
{
|
||||
if (PR_TRUE==gsDebug1)
|
||||
if (PR_TRUE==gsDebug)
|
||||
printf ("rowgroup: placing row at %d, %d, %d, %d\n",
|
||||
aKidRect.x, aKidRect.y, aKidRect.width, aKidRect.height);
|
||||
|
||||
|
@ -256,7 +254,7 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon
|
|||
#endif
|
||||
#endif
|
||||
NS_PRECONDITION(nsnull != mFirstChild, "no children");
|
||||
|
||||
if (gsDebug) printf("\n\nREFLOWMAPPED FOR ROW GROUP FRAME\n");
|
||||
PRInt32 childCount = 0;
|
||||
nsIFrame* prevKidFrame = nsnull;
|
||||
|
||||
|
@ -1039,7 +1037,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
|||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
if (gsDebug1==PR_TRUE)
|
||||
if (gsDebug==PR_TRUE)
|
||||
printf("nsTableRowGroupFrame::Reflow - aMaxSize = %d, %d\n",
|
||||
aReflowState.maxSize.width, aReflowState.maxSize.height);
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -1153,7 +1151,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
|||
PostReflowCheck(aStatus);
|
||||
#endif
|
||||
|
||||
if (gsDebug1==PR_TRUE)
|
||||
if (gsDebug==PR_TRUE)
|
||||
{
|
||||
if (nsnull!=aDesiredSize.maxElementSize)
|
||||
printf("nsTableRowGroupFrame::RR returning: %s with aDesiredSize=%d,%d, aMES=%d,%d\n",
|
||||
|
@ -1181,7 +1179,7 @@ nsTableRowGroupFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
|
||||
if (PR_TRUE==gsDebug1) printf("nsTableRowGroupFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf);
|
||||
if (PR_TRUE==gsDebug) printf("nsTableRowGroupFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf);
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче