Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Protected Attributes
BasicTableLayoutStrategy Class Reference

Implementation of Nav4 compatible HTML browser table layout. More...

#include <BasicTableLayoutStrategy.h>

Inheritance diagram for BasicTableLayoutStrategy:
Inheritance graph
[legend]
Collaboration diagram for BasicTableLayoutStrategy:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 BasicTableLayoutStrategy (nsTableFrame *aFrame, PRBool aIsNavQuirksMode=PR_TRUE)
 Public constructor.
virtual ~BasicTableLayoutStrategy ()
 destructor
virtual PRBool Initialize (const nsHTMLReflowState &aReflowState)
 call every time any table thing changes that might effect the width of any column in the table (content, structure, or style)
virtual PRBool BalanceColumnWidths (const nsHTMLReflowState &aReflowState)
 Called during resize reflow to determine the new column widths.
virtual nscoord CalcPctAdjTableWidth (const nsHTMLReflowState &aReflowState, nscoord aAvailWidth)
 Calculate the basis for percent width calculations of the table elements.
void Dump (PRInt32 aIndent)

Protected Member Functions

virtual PRBool AssignNonPctColumnWidths (nscoord aComputedWidth, const nsHTMLReflowState &aReflowState)
 assign widths for each column.
void ComputeNonPctColspanWidths (const nsHTMLReflowState &aReflowState, PRBool aConsiderPct, float aPixelToTwips, PRBool *aHasPctCol)
 Calculate the adjusted widths (min, desired, fixed, or pct) for a cell spanning multiple columns.
PRBool ComputeNonPctColspanWidths (PRInt32 aWidthIndex, const nsTableCellFrame *aCellFrame, PRInt32 aCellWidth, PRInt32 aColIndex, PRInt32 aColSpan, PRInt32 &aLimitType, float aPixelToTwips)
 main helper for above.
nscoord AssignPctColumnWidths (const nsHTMLReflowState &aReflowState, nscoord aBasis, PRBool aTableIsAutoWidth, float aPixelToTwips)
 Determine percentage col widths for each col frame.
void ReduceOverSpecifiedPctCols (nscoord aExcess)
 Reduce the percent columns by the amount specified in aExcess as the percent width's can accumulate to be over 100%.
void CalculateTotals (PRInt32 *aTotalCounts, PRInt32 *aTotalWidths, PRInt32 *aDupedWidths, PRInt32 &a0ProportionalCount)
 calculate totals by width type.
void AllocateFully (nscoord &aTotalAllocated, PRInt32 *aAllocTypes, PRInt32 aWidthType)
 Allocate aWidthType values to the corresponding columns.
void AllocateConstrained (PRInt32 aAvailWidth, PRInt32 aWidthType, PRBool aStartAtMin, PRInt32 *aAllocTypes, float aPixelToTwips)
 Allocate aWidthType values to the corresponding columns up to the aAvailWidth.
void AllocateUnconstrained (PRInt32 aAllocAmount, PRInt32 *aAllocTypes, PRBool aExcludePct, PRBool aExcludeFix, PRBool aExcludePro, PRBool aExclude0Pro, float aPixelToTwips)
 Give the remaining space and exclude the selected columns.
void ContinuingFrameCheck ()
 Check in debug mode whether the routine is called on a continuing frame.

Protected Attributes

nsTableFramemTableFrame
PRInt32 mCols
nscoord mCellSpacingTotal
float mMinToDesProportionRatio
PRPackedBool mIsNavQuirksMode

Detailed Description

Implementation of Nav4 compatible HTML browser table layout.

The input to this class is the results from pass1 table layout. The output from this class is to set the column widths in mTableFrame.

Definition at line 60 of file BasicTableLayoutStrategy.h.


Constructor & Destructor Documentation

Public constructor.

aFrame - the table frame for which this delegate will do layout

Parameters:
aIsNavQuirksMode- honor NN4x table quirks

Definition at line 112 of file BasicTableLayoutStrategy.cpp.

{
  MOZ_COUNT_CTOR(BasicTableLayoutStrategy);
  NS_ASSERTION(nsnull != aFrame, "bad frame arg");

  mTableFrame            = aFrame;
  mCellSpacingTotal      = 0;
  mIsNavQuirksMode       = aIsNavQuirks;
}

destructor

Definition at line 122 of file BasicTableLayoutStrategy.cpp.


Member Function Documentation

void BasicTableLayoutStrategy::AllocateConstrained ( PRInt32  aAvailWidth,
PRInt32  aWidthType,
PRBool  aStartAtMin,
PRInt32 aAllocTypes,
float  aPixelToTwips 
) [protected]

Allocate aWidthType values to the corresponding columns up to the aAvailWidth.

Parameters:
aAvailWidth- width that can distributed to the selected columns
aWidthType- width type selecting the columns for width allocation
aStartAtMin- allocation should start at min. content width
aAllocTypes- width type that has determined col width
aPixelToTwips- the number of twips in a pixel.

Definition at line 1828 of file BasicTableLayoutStrategy.cpp.

{
  if ((0 == aAvailWidth) || (aWidthType < 0) || (aWidthType >= NUM_WIDTHS)) {
    NS_ASSERTION(PR_TRUE, "invalid args to AllocateConstrained");
    return;
  }

  PRInt32 numCols = mTableFrame->GetColCount();
  PRInt32 numConstrainedCols = 0;
  nscoord sumMaxConstraints  = 0;
  nscoord sumMinConstraints  = 0;
  PRInt32 colX;
  // find out how many constrained cols there are
  for (colX = 0; colX < numCols; colX++) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
      continue;
    }
    numConstrainedCols++;
  }

  // allocate storage for the constrained cols. Only they get adjusted.
  ColInfo** colInfo = new ColInfo*[numConstrainedCols];
  if (!colInfo) return;
  memset(colInfo, 0, numConstrainedCols * sizeof(ColInfo *));

  PRInt32 maxMinDiff = 0;
  PRInt32 constrColX = 0;
  // set the col info entries for each constrained col
  for (colX = 0; colX < numCols; colX++) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
      continue;
    }
    nscoord minWidth = mTableFrame->GetColumnWidth(colX);
    nscoord maxWidth = GetColWidth(colFrame, aWidthType);
    // proportional and desired widths are handled together
    PRBool haveProWidth = PR_FALSE;
    if (DES_CON == aWidthType) {
      // Take into acount MIN_adj width as it has been included in totals before
      maxWidth = PR_MAX(maxWidth, colFrame->GetWidth(MIN_ADJ));
      nscoord proWidth = colFrame->GetWidth(MIN_PRO);
      if (proWidth >= 0) {
        haveProWidth = PR_TRUE;
        maxWidth = proWidth;
      }
    }

    if (maxWidth <= 0) continue;

    sumMaxConstraints += maxWidth;
    sumMinConstraints += minWidth;

    maxWidth = PR_MAX(maxWidth, minWidth);
    maxMinDiff += maxWidth - minWidth;
    nscoord startWidth = (aStartAtMin) ? minWidth : maxWidth;
    colInfo[constrColX] = new ColInfo(colFrame, colX, minWidth, startWidth, maxWidth);
    if (!colInfo[constrColX]) {
      AC_Wrapup(mTableFrame, numConstrainedCols, colInfo, PR_TRUE);
      return;
    }
    aAllocTypes[colX] = (haveProWidth) ? MIN_PRO : aWidthType;
    constrColX++;
  }

  if (constrColX < numConstrainedCols) {
    // some of the constrainted cols might have been 0 and skipped
    numConstrainedCols = constrColX;
  }

  PRInt32 i;
  if (aStartAtMin) { // allocate extra space 
    nscoord availWidth = aAvailWidth; 
    for (i = 0; i < numConstrainedCols; i++) {
      // the weight here is a relative metric for determining when cols reach their max constraint. 
      // A col with a larger weight will reach its max before one with a smaller value.
      nscoord delta = colInfo[i]->mMaxWidth - colInfo[i]->mWidth;
      colInfo[i]->mWeight = (delta <= 0) 
        ? 1000000 // cols which have already reached their max get a large value
        : ((float)colInfo[i]->mMaxWidth) / ((float)delta);
    }
      
    // sort the cols based on the weight so that in one pass cols with higher 
    // weights will get their max earlier than ones with lower weights
    // This is an innefficient bubble sort, but unless there are an unlikely 
    // large number of cols, it is not an issue.
    AC_Sort(colInfo, numConstrainedCols);
   
    // compute the proportion to be added to each column, don't go beyond the col's
    // max. This algorithm assumes that the Weight works as stated above
    AC_Increase(numConstrainedCols, colInfo, sumMaxConstraints - sumMinConstraints, 
                availWidth, aPixelToTwips);
  }
  else { // reduce each col width 
    nscoord reduceWidth = maxMinDiff - aAvailWidth;
    if (reduceWidth < 0) {
      NS_ASSERTION(PR_TRUE, "AllocateConstrained called incorrectly");
      AC_Wrapup(mTableFrame, numConstrainedCols, colInfo);
      return;
    }
    for (i = 0; i < numConstrainedCols; i++) {
      // the weight here is a relative metric for determining when cols reach their min. 
      // A col with a larger weight will reach its min before one with a smaller value.
      nscoord delta = colInfo[i]->mWidth - colInfo[i]->mMinWidth;
      colInfo[i]->mWeight = (delta <= 0) 
        ? 1000000 // cols which have already reached their min get a large value
        : ((float)colInfo[i]->mWidth) / ((float)delta);
    }
      
    // sort the cols based on the Weight 
    AC_Sort(colInfo, numConstrainedCols);
   
    // compute the proportion to be subtracted from each column, don't go beyond 
    // the col's min. This algorithm assumes that the Weight works as stated above
    AC_Decrease(numConstrainedCols, colInfo, sumMaxConstraints, reduceWidth, aPixelToTwips);
  }
  AC_Wrapup(mTableFrame, numConstrainedCols, colInfo);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::AllocateFully ( nscoord aTotalAllocated,
PRInt32 aAllocTypes,
PRInt32  aWidthType 
) [protected]

Allocate aWidthType values to the corresponding columns.

Parameters:
aTotalAllocated- width that has been allocated in this routine
aAllocTypes- width type that has determined col width
aWidthType- width type selecting the columns for full width allocation

Definition at line 411 of file BasicTableLayoutStrategy.cpp.

{
  PRInt32 numCols = mTableFrame->GetColCount(); 
  for (PRInt32 colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    if (!CanAllocate(aWidthType, aAllocTypes[colX], colFrame)) {
      continue;
    }
    nscoord oldWidth = mTableFrame->GetColumnWidth(colX);
    nscoord newWidth = GetColWidth(colFrame, aWidthType);
    // proportional and desired widths are handled together
    PRBool haveProWidth = PR_FALSE;
    if (DES_CON == aWidthType) {
      nscoord proWidth = colFrame->GetWidth(MIN_PRO);
      if (proWidth >= 0) {
        haveProWidth = PR_TRUE;
        newWidth = proWidth;
      }
    }

    if (WIDTH_NOT_SET == newWidth) continue;
   
    if (newWidth > oldWidth) {
      mTableFrame->SetColumnWidth(colX, newWidth);
      aTotalAllocated += newWidth - oldWidth;
    }
    aAllocTypes[colX] = (haveProWidth) ? MIN_PRO : aWidthType;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::AllocateUnconstrained ( PRInt32  aAllocAmount,
PRInt32 aAllocTypes,
PRBool  aExcludePct,
PRBool  aExcludeFix,
PRBool  aExcludePro,
PRBool  aExclude0Pro,
float  aPixelToTwips 
) [protected]

Give the remaining space and exclude the selected columns.

Parameters:
aAllocAmount- space that can be distributed
aAllocTypes- width type that has determined col width
aExcludePct- dont give space to percent columns
aExcludeFix- dont give space to fixed width columns
aExcludePro- dont give space to proportional columns
aExclude0Pro- dont give space to proportional columns with 0*
aPixelToTwips- the number of twips in a pixel.

Definition at line 447 of file BasicTableLayoutStrategy.cpp.

{
  // set up allocTypes to exclude anything but auto cols if possible
  PRInt32 colX;
  PRInt32 numCols = mTableFrame->GetColCount();
  for (colX = 0; colX < numCols; colX++) {
    if (aExcludePct && (PCT == aAllocTypes[colX])) {
      aAllocTypes[colX] = FINISHED;
    }
    else if (aExcludeFix && ((FIX == aAllocTypes[colX]) || (FIX_ADJ == aAllocTypes[colX]))) {
      aAllocTypes[colX] = FINISHED;
    }
    else if (MIN_PRO == aAllocTypes[colX]) {
      if (aExcludePro) {
        aAllocTypes[colX] = FINISHED;
      }
      else {
        if (aExclude0Pro) {
          nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
          if (!colFrame) continue;
          if (colFrame->GetConstraint() == e0ProportionConstraint) {
            aAllocTypes[colX] = FINISHED;
          }
        }
      }
    }
  }
    
  nscoord divisor          = 0;
  PRInt32 numColsAllocated = 0; 
  PRInt32 totalAllocated   = 0;
  for (colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue; 
    PRBool skipColumn = aExclude0Pro && (e0ProportionConstraint == colFrame->GetConstraint());
    if (FINISHED != aAllocTypes[colX] && !skipColumn ) {
      divisor += mTableFrame->GetColumnWidth(colX);
      numColsAllocated++;
    }
  }
  if (!numColsAllocated) {
    // redistribute the space to all columns and prevent a division by zero
    numColsAllocated = numCols;
  }
  for (colX = 0; colX < numCols; colX++) { 
    if (FINISHED != aAllocTypes[colX]) {
      if (aExclude0Pro) {
        nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
        if (!colFrame) continue;
        if (e0ProportionConstraint == colFrame->GetConstraint()) {
          continue;
        }
      }
      nscoord oldWidth = mTableFrame->GetColumnWidth(colX);
      float percent = (divisor == 0) 
        ? (1.0f / ((float)numColsAllocated))
        : ((float)oldWidth) / ((float)divisor);
      nscoord addition = nsTableFrame::RoundToPixel(NSToCoordRound(((float)aAllocAmount) * percent), aPixelToTwips);
      if (addition > (aAllocAmount - totalAllocated)) {
        addition = nsTableFrame::RoundToPixel(aAllocAmount - totalAllocated, aPixelToTwips);
        mTableFrame->SetColumnWidth(colX, oldWidth + addition);
        break;
      }
      mTableFrame->SetColumnWidth(colX, oldWidth + addition);
      totalAllocated += addition;
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool BasicTableLayoutStrategy::AssignNonPctColumnWidths ( nscoord  aComputedWidth,
const nsHTMLReflowState aReflowState 
) [protected, virtual]

assign widths for each column.

if the column has a fixed coord width, use it. if the column includes col spanning cells, then distribute the fixed space between cells proportionately. Computes the minimum and maximum table widths. Set column width information in each column frame and in the table frame.

Returns:
PR_TRUE has a pct cell or col, PR_FALSE otherwise

Reimplemented in FixedTableLayoutStrategy.

Definition at line 987 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eNonPctCols, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
#ifdef DEBUG_TABLE_STRATEGY
  printf("AssignNonPctColWidths en max=%d count=%d \n", aMaxWidth, gsDebugCount++); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);
#endif
  PRInt32 numRows = mTableFrame->GetRowCount();
  PRInt32 numCols = mTableFrame->GetColCount();
  nscoord spacingX = mTableFrame->GetCellSpacingX();
  PRInt32 colX, rowX; 
  mCellSpacingTotal = 0;
  PRBool hasPctCol = PR_FALSE; // return value
  float pixelToTwips = mTableFrame->GetPresContext()->ScaledPixelsToTwips();

  PRInt32 rawPropTotal = -1; // total of numbers of the type 1*, 2*, etc 
  PRInt32 numColsForColsAttr = 0; // Nav Quirks cols attribute for equal width cols
  if (NS_STYLE_TABLE_COLS_NONE != mCols) {
    numColsForColsAttr = (NS_STYLE_TABLE_COLS_ALL == mCols) ? numCols : mCols;
  }

  // For every column, determine it's min and desired width based on cell style
  // base on cells which do not span cols. Also, determine mCellSpacingTotal
  for (colX = 0; colX < numCols; colX++) { 
    nscoord minWidth = 0;
    nscoord desWidth = 0;
    nscoord fixWidth = WIDTH_NOT_SET;
    
    // Get column frame and reset it
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    NS_ASSERTION(nsnull != colFrame, "bad col frame");
    colFrame->ResetSizingInfo();

    if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) {
      mCellSpacingTotal += spacingX;
    }

    // Scan the cells in the col that have colspan = 1 and find the maximum
    // min, desired, and fixed cells.
    nsTableCellFrame* fixContributor = nsnull;
    nsTableCellFrame* desContributor = nsnull;
    for (rowX = 0; rowX < numRows; rowX++) {
      PRBool originates;
      PRInt32 colSpan;
      nsTableCellFrame* cellFrame = mTableFrame->GetCellInfoAt(rowX, colX, &originates, &colSpan);
      // skip cells that don't originate at (rowX, colX); colspans are handled in the
      // next pass, row spans don't need to be handled
      if (!cellFrame || !originates || (colSpan > 1)) { 
        continue;
      }
      // these values include borders and padding
      minWidth = PR_MAX(minWidth, cellFrame->GetPass1MaxElementWidth());
      nscoord cellDesWidth = cellFrame->GetMaximumWidth();
      if (cellDesWidth > desWidth) {
        desContributor = cellFrame;
        desWidth = cellDesWidth;
      }
      // see if the cell has a style width specified
      const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
      if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) {
        nscoord coordValue = cellPosition->mWidth.GetCoordValue();
        if (coordValue > 0) { // ignore if width == 0
          // need to add border and padding into fixed width
          nsSize percentBase(aReflowState.mComputedWidth, 0);
          nsMargin borderPadding = nsTableFrame::GetBorderPadding(percentBase, pixelToTwips, cellFrame);
          nscoord newFixWidth = coordValue + borderPadding.left + borderPadding.right;
          // 2nd part of condition is Nav/IE Quirk like below
          if ((newFixWidth > fixWidth) || ((newFixWidth == fixWidth) && (desContributor == cellFrame))) {
            fixWidth = newFixWidth;
            fixContributor = cellFrame;
          }
        }
      }
      if (!hasPctCol && HasPctValue(cellFrame)) { // see if there is a pct cell
        hasPctCol = PR_TRUE;
      }
    }

    // Nav/IE Quirk like above
    if (fixWidth > 0) {
      if (mIsNavQuirksMode && (desWidth > fixWidth) && (fixContributor != desContributor)) {
        fixWidth = WIDTH_NOT_SET;
        fixContributor = nsnull;
      }
    }
    desWidth = PR_MAX(desWidth, minWidth);

    // cache the computed column info
    colFrame->SetWidth(MIN_CON, minWidth);
    colFrame->SetWidth(DES_CON, desWidth);
    if (fixWidth > 0) {
      colFrame->SetWidth(FIX, fixWidth);
    }

    nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
    // determine if there is a proportional column either from html4 
    // proportional width on a col or Nav Quirks cols attr
    if (fixWidth <= 0) {
      nscoord proportion = WIDTH_NOT_SET;
      if (eStyleUnit_Proportional == colStyleWidth.GetUnit()) {
        proportion = colStyleWidth.GetIntValue();
      }
      else if (colX < numColsForColsAttr) {
        proportion = 1;
        if ((eStyleUnit_Percent == colStyleWidth.GetUnit()) &&
            (colStyleWidth.GetPercentValue() > 0.0f)) {
          proportion = WIDTH_NOT_SET;
        }
      }
      if (proportion >= 0) {
        rawPropTotal = PR_MAX(rawPropTotal, 0); // it was initialized to -1
        colFrame->SetWidth(MIN_PRO, proportion);
        nsColConstraint colConstraint = (0 == proportion) 
          ? e0ProportionConstraint : eProportionConstraint;
        rawPropTotal += proportion;
        colFrame->SetConstraint(colConstraint);
      }
    }
    if (!hasPctCol) { // see if there is a pct col
      if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
        float percent = colStyleWidth.GetPercentValue();
        if (percent > 0.0f) {
          hasPctCol = PR_TRUE;
        }
      }
    }
  }
  if (mCellSpacingTotal > 0) {
    mCellSpacingTotal += spacingX; // add last cell spacing on right
  }
//set the table col fixed width if present
  for (colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord fixColWidth = colFrame->GetWidth(FIX);
    // use the style width of a col only if the col hasn't gotten a fixed width from any cell
    if (fixColWidth <= 0) {
      nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
      if (eStyleUnit_Coord == colStyleWidth.GetUnit()) {
        fixColWidth = colStyleWidth.GetCoordValue();
        if (fixColWidth > 0) {
          colFrame->SetWidth(FIX, fixColWidth);
        }
      }
    }
  }
  PRBool* pctRequest = (hasPctCol) ? nsnull : &hasPctCol;
  ComputeNonPctColspanWidths(aReflowState, PR_FALSE, pixelToTwips, pctRequest);
  PRInt32 numEffCols = mTableFrame->GetEffectiveColCount();
  // figure the proportional widths for porportional cols
  if (rawPropTotal > 0)  {
    // find the largest combined prop size considering each prop col and
    // its desired size
    nscoord maxPropTotal = 0;
    for (colX = 0; colX < numEffCols; colX++) { 
      nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
      nscoord rawProp = colFrame->GetWidth(MIN_PRO);
      if (rawProp > 0) {
        nscoord desWidth = colFrame->GetDesWidth();
        nscoord propTotal = NSToCoordRound( ((float)desWidth) * ((float)rawPropTotal) / (float)rawProp );
        propTotal = nsTableFrame::RoundToPixel(propTotal, pixelToTwips);
        maxPropTotal = PR_MAX(maxPropTotal, propTotal);
      }
    }
    // set MIN_PRO widths based on the maxPropTotal
    for (colX = 0; colX < numEffCols; colX++) { 
      nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
      if (!colFrame) continue;
      nscoord rawProp = colFrame->GetWidth(MIN_PRO);
      if (0 == rawProp) {
        // a 0* col gets only the min width
        colFrame->SetWidth(MIN_PRO, colFrame->GetMinWidth());
      }
      else if ((rawProp > 0) && (rawPropTotal > 0)) {
        nscoord propWidth = NSToCoordRound( ((float)maxPropTotal) * ((float)rawProp) / (float)rawPropTotal ) ;
        propWidth = nsTableFrame::RoundToPixel(propWidth, pixelToTwips);
        colFrame->SetWidth(MIN_PRO, PR_MAX(propWidth, colFrame->GetMinWidth()));
      }
    }
  }

  // Set the table col width for each col to the content min. 
  for (colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord minWidth = colFrame->GetMinWidth();
    mTableFrame->SetColumnWidth(colX, minWidth);
  }

#ifdef DEBUG_TABLE_STRATEGY
  printf("AssignNonPctColWidths ex\n"); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);
#endif
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eNonPctCols, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
#endif
  return hasPctCol;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nscoord BasicTableLayoutStrategy::AssignPctColumnWidths ( const nsHTMLReflowState aReflowState,
nscoord  aBasis,
PRBool  aTableIsAutoWidth,
float  aPixelToTwips 
) [protected]

Determine percentage col widths for each col frame.

Parameters:
aReflowState- the reflow state of the table
aBasis- the basis for percent width as computed by CalcPctAdjTableWidth
aTableIsAutoWidth- true if no width specification for the table is available
aPixelToTwips- the number of twips in a pixel.
Returns:
- the adjusted basis including table border, padding and cell spacing

Definition at line 1361 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::ePctCols, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
  mTableFrame->SetHasCellSpanningPctCol(PR_FALSE); // this gets refigured below
  PRInt32 numRows = mTableFrame->GetRowCount();
  PRInt32 numCols = mTableFrame->GetColCount(); // consider cols at end without orig cells 
  PRInt32 numEffCols = mTableFrame->GetEffectiveColCount();
  nscoord spacingX = mTableFrame->GetCellSpacingX();
  PRInt32 colX, rowX; 

  NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aAvailWidth, "AssignPctColumnWidths has unconstrained avail width");  
  // For an auto table, determine the potentially new percent adjusted width based 
  // on percent cells/cols. This probably should only be a NavQuirks thing, since
  // a percentage based cell or column on an auto table should force the column to auto
  nscoord basis = (aTableIsAutoWidth) 
                  ? CalcPctAdjTableWidth(aReflowState, aAvailWidth)
                  : aAvailWidth;

  // adjust the basis to exclude table border, padding and cell spacing
  nsMargin borderPadding = mTableFrame->GetContentAreaOffset(&aReflowState);
  basis -= borderPadding.left + borderPadding.right + mCellSpacingTotal;

  nscoord colPctTotal = 0;

  struct nsSpannedEle {
    nsSpannedEle *next, *prev;
    PRInt32 col, colSpan;
    nsTableCellFrame *cellFrame;
  };

  nsSpannedEle *spanList = 0;
  nsSpannedEle *spanTail = 0;
  PLArenaPool   spanArena;
  
  PL_INIT_ARENA_POOL(&spanArena, "AssignPctColumnWidths", 512);
  // Determine the percentage contribution for cols and for cells with colspan = 1
  // Iterate backwards, similarly to the reasoning in AssignNonPctColumnWidths
  for (colX = numCols - 1; colX >= 0; colX--) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord maxColPctWidth = WIDTH_NOT_SET;
    float maxColPct = 0.0f;

    nsTableCellFrame* percentContributor = nsnull;
    // Scan the cells in the col that have colspan = 1; assign PER widths
    for (rowX = 0; rowX < numRows; rowX++) {
      PRBool originates;
      PRInt32 colSpan;
      nsTableCellFrame* cellFrame = mTableFrame->GetCellInfoAt(rowX, colX, &originates, &colSpan);
      // skip cells that don't originate at (rowX, colX)
      if (!cellFrame || !originates) { 
        continue;
      }

      // colspans are handled in the next pass, but we record them here so we dont have to
      // search for the again.  row spans do not need to be handled.
      if(colSpan>1) {
        nsSpannedEle *spanned;
        ARENA_ALLOCATE(spanned, &spanArena, 1, nsSpannedEle);
        if(spanned) {
          spanned->col = colX;
          spanned->colSpan = colSpan;
          spanned->cellFrame = cellFrame;
          spanned->next = spanList;
          spanned->prev = nsnull;
          if(spanList) {
            spanList->prev = spanned;
          } else {
            spanTail = spanned;
          }
          spanList = spanned;
        }
        continue;
      }
      // see if the cell has a style percent width specified
      const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
      if (eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) {
        float percent = cellPosition->mWidth.GetPercentValue();
        if (percent > maxColPct) {
          maxColPct = percent;
          maxColPctWidth = nsTableFrame::RoundToPixel(NSToCoordRound( ((float)basis) * maxColPct ), aPixelToTwips);
          percentContributor = cellFrame;
          if (!mIsNavQuirksMode) { 
            // need to add border and padding
            nsMargin cellBorderPadding = nsTableFrame::GetBorderPadding(nsSize(basis, 0), aPixelToTwips, cellFrame);
            maxColPctWidth += cellBorderPadding.left + cellBorderPadding.right;
          }
        }
      }
    }
    if (WIDTH_NOT_SET == maxColPctWidth) {
      // see if the col has a style percent width specified
      nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
      if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
        maxColPct = colStyleWidth.GetPercentValue();
        maxColPctWidth = nsTableFrame::RoundToPixel(NSToCoordRound( ((float)basis) * maxColPct ), aPixelToTwips);
      }
    }
    // conflicting pct/fixed widths are recorded. Nav 4.x may be changing the
    // fixed width value if it exceeds the pct value and not recording the pct
    // value. This is not being done and IE5 doesn't do it either.
    if (maxColPctWidth > 0) {
      maxColPctWidth = PR_MAX(maxColPctWidth, colFrame->GetWidth(MIN_CON));
      colFrame->SetWidth(PCT, maxColPctWidth);
      colPctTotal += NSToCoordRound(100.0f * (float)maxColPct);
    }
  }

  // if the percent total went over 100%, adjustments need to be made to right most cols
  if (colPctTotal > 100) {
    ReduceOverSpecifiedPctCols(nsTableFrame::RoundToPixel(NSToCoordRound(((float)(colPctTotal - 100)) * 0.01f * (float)basis), aPixelToTwips));
    colPctTotal = 100;
  }

  // check to see if a cell spans a percentage col. This will cause the MIN_ADJ,
  // FIX_ADJ, and DES_ADJ values to be recomputed 
  PRBool done = PR_FALSE;
  nsSpannedEle *spannedCell;
  for(spannedCell=spanList; !done && spannedCell; spannedCell=spannedCell->next)
  {
    colX = spannedCell->col;
    PRInt32 colSpan = spannedCell->colSpan;
    // determine if the cell spans cols which have a pct value
    for (PRInt32 spanX = 0; spanX < colSpan; spanX++) {
      nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); 
      if (!colFrame) continue;
      if (colFrame->GetWidth(PCT) > 0) {
        mTableFrame->SetHasCellSpanningPctCol(PR_TRUE);
        // recompute the MIN_ADJ, FIX_ADJ, and DES_ADJ values
        ComputeNonPctColspanWidths(aReflowState, PR_TRUE, aPixelToTwips, nsnull);
        done = PR_TRUE;
        break;
      }
    }
  }

  // For each col, consider the cells originating in it with colspans > 1.
  // Adjust the cols that each cell spans if necessary.
  // if more than one  colspan originate in one column, resort the access to 
  // the rows so that the inner colspans are handled first

  CellInfo* cellInfo = nsnull;

  if(spanTail)
    ARENA_ALLOCATE(cellInfo, &spanArena, numRows, CellInfo);

  if(cellInfo) for(spannedCell=spanTail; spannedCell;) {
    PRInt32 spannedRows = 0;
    colX = spannedCell->col;
    do {
      cellInfo[spannedRows].cellFrame = spannedCell->cellFrame;
      cellInfo[spannedRows].colSpan   = spannedCell->colSpan;
      ++spannedRows;
    } while((spannedCell=spannedCell->prev) && (spannedCell->col==colX));
    if(spannedRows>1) {
      NS_QuickSort(cellInfo, spannedRows, sizeof(cellInfo[0]), RowSortCB, 0);
    }

    for (PRInt32 i = 0; i < spannedRows; i++) {
      const CellInfo *inf = &cellInfo[i];
      const nsTableCellFrame* cellFrame = inf->cellFrame;

      const PRInt32 colSpan = PR_MIN(inf->colSpan, numEffCols - colX);
      nscoord cellPctWidth = WIDTH_NOT_SET;
      // see if the cell has a style percentage width specified
      const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
      float cellPct = 0.0f;
      if (eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) {
        cellPct = cellPosition->mWidth.GetPercentValue();
        if (colSpan == numEffCols)
          cellPct = 1.0f; // overwrite spurious percent colspan width's - bug 46944
        cellPctWidth = nsTableFrame::RoundToPixel(NSToCoordRound( ((float)basis) * cellPct ), aPixelToTwips);
        if (!mIsNavQuirksMode) { 
          // need to add border and padding 
          nsMargin cellBorderPadding = nsTableFrame::GetBorderPadding(nsSize(basis, 0), aPixelToTwips, cellFrame);
          cellPctWidth += cellBorderPadding.left + cellBorderPadding.right;
        }
      }
      if (cellPctWidth > 0) {
        nscoord spanCellSpacing = 0;
        nscoord spanTotal = 0;
        nscoord spanTotalNoPctAdj = 0;
        nscoord colPctWidthTotal = 0; // accumulate the PCT width 
        nscoord colPctAdjTotal = 0;   // accumulate the PCT_ADJ width or  the max of PCT_ADJ and PCT width if a 
                                      // PCT width is specified
        PRBool canSkipPctAdj = PR_FALSE;
        // accumulate the spanTotal as the max of MIN, DES, FIX, PCT
        PRInt32 spanX;
        for (spanX = 0; spanX < colSpan; spanX++) {
          nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); 
          if (!colFrame) continue;
          nscoord colPctWidth = colFrame->GetWidth(PCT);
          if (colPctWidth > 0) { // skip pct cols
            colPctWidthTotal += colPctWidth;
            colPctAdjTotal += PR_MAX(colFrame->GetWidth(PCT_ADJ), colPctWidth);
            continue;
          }
          colPctAdjTotal += PR_MAX(colFrame->GetWidth(PCT_ADJ), 0);
          nscoord colWidth = PR_MAX(colFrame->GetMinWidth(), colFrame->GetFixWidth());
          colWidth = PR_MAX(colWidth, colFrame->GetDesWidth()); // XXX check this
          //colWidth = PR_MAX(colWidth, colFrame->GetPctWidth());
          spanTotal += colWidth;
          if (colFrame->GetWidth(PCT_ADJ) <= 0) { // if we have a cell that is neither PCT or PCT_ADJ we have
                                                  // other places where we can drop the width
            canSkipPctAdj = PR_TRUE; 
            spanTotalNoPctAdj += colWidth;
          }
          if ((spanX > 0) && (mTableFrame->GetNumCellsOriginatingInCol(colX + spanX) > 0)) {
            spanCellSpacing += spacingX;
          }
        }
        cellPctWidth += spanCellSpacing; // add it back in since it was subtracted from aBasisIn
        if (cellPctWidth <= 0) {
          continue;
        }
        spanTotal = canSkipPctAdj ? spanTotalNoPctAdj: spanTotal; // if we can skip the PCT_ADJ ignore theire width
      
        colPctWidthTotal = canSkipPctAdj ? colPctAdjTotal: colPctWidthTotal; 
        
        if ((PR_MAX(colPctWidthTotal, colPctAdjTotal)+ spanCellSpacing) < cellPctWidth) { 
          // we have something to distribute ...
          // record the percent contributions for the spanned cols
          PRInt32 usedColumns = colSpan;
          for (spanX = colSpan-1; spanX >= 0; spanX--) {
            nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX + spanX); 
            if (!colFrame) continue;
            if ((colFrame->GetWidth(PCT) > 0) || (canSkipPctAdj && (colFrame->GetWidth(PCT_ADJ) > 0))) {
              // dont use pct cols or if we can skip the pct adj event do not take the PCT_ADJ cols
              usedColumns--;
              continue;
            } // count the pieces 
            if (usedColumns == 0)
              usedColumns = 1; // avoid division by 0 later
            nscoord minWidth = colFrame->GetMinWidth();
            nscoord colWidth = PR_MAX(minWidth, colFrame->GetFixWidth());
            colWidth = PR_MAX(colWidth, colFrame->GetDesWidth()); // XXX check this
            float avail = (float)PR_MAX(cellPctWidth - colPctWidthTotal, 0);
            float colPctAdj = (0 == spanTotal) 
                              ? avail / ((float) usedColumns) / ((float)basis)
                              : (avail / (float)basis) * (((float)colWidth) / (float)spanTotal);
            if (colPctAdj > 0) {
              nscoord colPctAdjWidth = colFrame->GetWidth(PCT_ADJ);
              nscoord newColPctAdjWidth = nsTableFrame::RoundToPixel(NSToCoordRound(colPctAdj * (float)basis), aPixelToTwips);
              if (newColPctAdjWidth > colPctAdjWidth) {
                newColPctAdjWidth = PR_MAX(newColPctAdjWidth, minWidth); 
                if (newColPctAdjWidth > colFrame->GetWidth(PCT)) {
                  colFrame->SetWidth(PCT_ADJ, newColPctAdjWidth);
                  if(0 != basis) { // I am paranoid
                    colPctTotal += NSToCoordRound(100.0f *(newColPctAdjWidth-colPctAdjWidth) / (float)basis); 
                    // accumulate the new distributed percents
                  }
                }
              }
              else {
                usedColumns--;
                colPctWidthTotal += colPctAdjWidth; // accumulate the already distributed percents
              }
            }
          }
        }
      }
    } // end for (index ..
  } // end for (colX ..

  // We are done with our spanlist, get rid of it now
  PL_FinishArenaPool(&spanArena);

  // if the percent total went over 100%, adjustments need to be made to right most cols
  if (colPctTotal > 100) {
    ReduceOverSpecifiedPctCols(nsTableFrame::RoundToPixel(NSToCoordRound(((float)(colPctTotal - 100)) * 0.01f * (float)basis), aPixelToTwips));
  }

  // adjust the basis to include table border, padding and cell spacing
  basis += borderPadding.left + borderPadding.right + mCellSpacingTotal;
  return WrapupAssignPctColumnWidths(mTableFrame, aReflowState, basis); 
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called during resize reflow to determine the new column widths.

Parameters:
aReflowState- the reflow state for mTableFrame

Implements nsITableLayoutStrategy.

Reimplemented in FixedTableLayoutStrategy.

Definition at line 209 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_STRATEGY
  printf("BalanceColumnWidths en count=%d \n", gsDebugCount++); mTableFrame->Dump(PR_FALSE, PR_TRUE, PR_FALSE);
#endif
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eBalanceCols, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
  float p2t = mTableFrame->GetPresContext()->ScaledPixelsToTwips();

  ContinuingFrameCheck();

  PRInt32 numCols = mTableFrame->GetColCount();
  PRBool tableIsAutoWidth = mTableFrame->IsAutoWidth();

  nscoord horOffset; 
  // get the reduction in available horizontal space due to borders and padding
  nsMargin offset = mTableFrame->GetChildAreaOffset(&aReflowState);
  horOffset = offset.left + offset.right;

  // determine if the table is auto/fixed and get the fixed width if available
  nscoord maxWidth = mTableFrame->CalcBorderBoxWidth(aReflowState);
  if (NS_UNCONSTRAINEDSIZE == maxWidth) {
    maxWidth = PR_MIN(maxWidth, aReflowState.availableWidth);
    if (NS_UNCONSTRAINEDSIZE == maxWidth) {
      NS_ASSERTION(NS_UNCONSTRAINEDSIZE != maxWidth, "cannot balance with an unconstrained width");
      return PR_FALSE;
    }
  }
  // initialize the col percent and cell percent values to 0.
  ResetPctValues(mTableFrame, numCols);

  // An auto table returns a new table width based on percent cells/cols if they exist
  nscoord perAdjTableWidth = 0;
  if (mTableFrame->HasPctCol()) {
    perAdjTableWidth = AssignPctColumnWidths(aReflowState, maxWidth, tableIsAutoWidth, p2t);
    if (perAdjTableWidth > 0) {
      // if an auto table has a pct col or cell, set the preferred table width 
      // here so that CalcPctAdjTableWidth wont't need to be called by the table
      mTableFrame->SetPreferredWidth(perAdjTableWidth);
    }
    perAdjTableWidth = PR_MIN(perAdjTableWidth, maxWidth);
    perAdjTableWidth -= horOffset;
    perAdjTableWidth = PR_MAX(perAdjTableWidth, 0);
  }

  // reduce the maxWidth by border and padding, since we will be dealing with content width
  maxWidth -= horOffset;
  maxWidth = PR_MAX(0, maxWidth);

  // we will re-calc mCellSpacingTotal in case longer rows were added after Initialize was called
  mCellSpacingTotal = 0;
  nscoord spacingX = mTableFrame->GetCellSpacingX();

  PRInt32 numNonZeroWidthCols = 0;
  // set the table's columns to the min width
  nscoord minTableWidth = 0;
  PRInt32 colX;
  for (colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord colMinWidth = colFrame->GetMinWidth();
    mTableFrame->SetColumnWidth(colX, colMinWidth);
    minTableWidth += colMinWidth;
    if ((colFrame->GetMinWidth() > 0) || (colFrame->GetDesWidth() > 0) ||
        (colFrame->GetFixWidth() > 0) || (colFrame->GetPctWidth() > 0) || 
        (colFrame->GetWidth(MIN_PRO) > 0)) {
      numNonZeroWidthCols++;
    }
    if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) {
      mCellSpacingTotal += spacingX;
    }
  }
  if (mCellSpacingTotal > 0) {
    mCellSpacingTotal += spacingX; // add last cell spacing on right
  }
  minTableWidth += mCellSpacingTotal;

  // if the max width available is less than the min content width for fixed table, we're done
  if (!tableIsAutoWidth && (maxWidth < minTableWidth)) {
    return BCW_Wrapup(aReflowState, this, mTableFrame, nsnull);
  }

  // if the max width available is less than the min content width for auto table
  // that had no % cells/cols, we're done
  if (tableIsAutoWidth && (maxWidth < minTableWidth) && (0 == perAdjTableWidth)) {
    return BCW_Wrapup(aReflowState, this, mTableFrame, nsnull);
  }

  // the following are of size NUM_WIDTHS, but only MIN_CON, DES_CON, FIX, FIX_ADJ, PCT
  // are used and they account for colspan ADJusted values
  PRInt32 totalWidths[NUM_WIDTHS]; // sum of col widths of a particular type 
  PRInt32 totalCounts[NUM_WIDTHS]; // num of cols of a particular type
  PRInt32 dupedWidths[NUM_WIDTHS];
  PRInt32 num0Proportional;

  CalculateTotals(totalCounts, totalWidths, dupedWidths, num0Proportional);
  // auto width table's adjusted width needs cell spacing
  if (tableIsAutoWidth && perAdjTableWidth > 0) { 
    maxWidth = perAdjTableWidth;
  }
  nscoord totalAllocated = totalWidths[MIN_CON] + mCellSpacingTotal;
  
  // allocate and initialize arrays indicating what col gets set
  PRInt32* allocTypes = new PRInt32[numCols];
  if (!allocTypes) return PR_FALSE;
 
  for (colX = 0; colX < numCols; colX++) {
    allocTypes[colX] = -1;
  }

  // allocate PCT/PCT_ADJ cols
  if (totalCounts[PCT] > 0) {
    if (totalAllocated + totalWidths[PCT] - dupedWidths[PCT] <= maxWidth) {
      AllocateFully(totalAllocated, allocTypes, PCT);
      //NS_WARN_IF_FALSE(totalAllocated <= maxWidth, "over allocated");
    }
    else {
      AllocateConstrained(maxWidth - totalAllocated, PCT, PR_FALSE, allocTypes, p2t);
      return BCW_Wrapup(aReflowState, this, mTableFrame, allocTypes);
    }
  }
  // allocate FIX cols
  if ((totalAllocated < maxWidth) && (totalCounts[FIX] > 0)) {
    if (totalAllocated + totalWidths[FIX] - dupedWidths[FIX] <= maxWidth) { 
      AllocateFully(totalAllocated, allocTypes, FIX);
      //NS_WARN_IF_FALSE(totalAllocated <= maxWidth, "over allocated");
    }
    else {
      AllocateConstrained(maxWidth - totalAllocated, FIX, PR_TRUE, allocTypes, p2t);
      return BCW_Wrapup(aReflowState, this, mTableFrame, allocTypes);
    }
  }
  // allocate fixed adjusted cols
  if ((totalAllocated < maxWidth) && (totalCounts[FIX_ADJ] > 0)) {
    if (totalAllocated + totalWidths[FIX_ADJ] - dupedWidths[FIX_ADJ] <= maxWidth) { 
      AllocateFully(totalAllocated, allocTypes, FIX_ADJ);
      //NS_WARN_IF_FALSE(totalAllocated <= maxWidth, "over allocated");
    }
    else {
      AllocateConstrained(maxWidth - totalAllocated, FIX_ADJ, PR_TRUE, allocTypes, p2t);
      return BCW_Wrapup(aReflowState, this, mTableFrame, allocTypes);
    }
  }

  // allocate proportional and auto cols together
  if ((totalAllocated < maxWidth) && (totalCounts[MIN_PRO] + totalCounts[DES_CON] > 0)) {
    if (totalAllocated + totalWidths[MIN_PRO] - dupedWidths[MIN_PRO] +
        totalWidths[DES_CON] - dupedWidths[DES_CON] <= maxWidth) { 
      AllocateFully(totalAllocated, allocTypes, DES_CON);
      //NS_WARN_IF_FALSE(totalAllocated <= maxWidth, "over allocated");
    }
    else {
      AllocateConstrained(maxWidth - totalAllocated, DES_CON, PR_TRUE, allocTypes, p2t);
      return BCW_Wrapup(aReflowState, this, mTableFrame, allocTypes);
    }
  }

  // if this is a nested non auto table and pass1 reflow, we are done
  if ((maxWidth == NS_UNCONSTRAINEDSIZE) && (!tableIsAutoWidth))  {
    return BCW_Wrapup(aReflowState, this, mTableFrame, allocTypes);
  }

  // allocate the rest to auto columns, with some exceptions
  if ( (tableIsAutoWidth && (perAdjTableWidth - totalAllocated > 0)) ||
       (!tableIsAutoWidth && (totalAllocated < maxWidth)) ) {
    // determine how many cols have width either because of a min, fixed, des, or pct value
    PRBool excludePct  = (totalCounts[PCT] != numNonZeroWidthCols);
    PRBool excludeFix  = (totalCounts[PCT] + totalCounts[FIX] + totalCounts[FIX_ADJ] < numNonZeroWidthCols);
    PRBool excludePro  = (totalCounts[DES_CON] > 0);
    PRBool exclude0Pro = (totalCounts[MIN_PRO] != num0Proportional);
    if (tableIsAutoWidth) {
      AllocateUnconstrained(perAdjTableWidth - totalAllocated, allocTypes, excludePct,
                            excludeFix, excludePro, exclude0Pro, p2t);
    }
    else {
      AllocateUnconstrained(maxWidth - totalAllocated, allocTypes, excludePct,
                            excludeFix, excludePro, exclude0Pro, p2t);
    }
  }

  return BCW_Wrapup(aReflowState, this, mTableFrame, allocTypes);
}

Here is the call graph for this function:

Calculate the basis for percent width calculations of the table elements.

Parameters:
aReflowState- the reflow state of the table
aAvailWidth- the available width for the table
Returns:
- the basis for percent calculations

Implements nsITableLayoutStrategy.

Reimplemented in FixedTableLayoutStrategy.

Definition at line 1232 of file BasicTableLayoutStrategy.cpp.

{
  NS_ASSERTION(mTableFrame->IsAutoWidth() && mTableFrame->HasPctCol(), "invalid call");

  PRInt32 numRows  = mTableFrame->GetRowCount();
  PRInt32 numCols  = mTableFrame->GetColCount(); // consider cols at end without orig cells 
  PRInt32 colX, rowX; 
  float pixelToTwips = mTableFrame->GetPresContext()->ScaledPixelsToTwips();

  // For an auto table, determine the potentially new percent adjusted width based 
  // on percent cells/cols. This probably should only be a NavQuirks thing, since
  // a percentage based cell or column on an auto table should force the column to auto
  nscoord basis = 0;                 
  float* rawPctValues = new float[numCols]; // store the raw pct values, allow for spans past the effective numCols
  if (!rawPctValues) return NS_ERROR_OUT_OF_MEMORY;
  for (colX = 0; colX < numCols; colX++) {
    rawPctValues[colX] = 0.0f;
  }

  nsMargin borderPadding = mTableFrame->GetContentAreaOffset(&aReflowState);
  nscoord availWidth = aAvailWidthIn;
  if (NS_UNCONSTRAINEDSIZE != availWidth) {
    // adjust the avail width to exclude table border, padding and cell spacing
    availWidth -= borderPadding.left + borderPadding.right + mCellSpacingTotal;
  }

  for (colX = 0; colX < numCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord maxColBasis = -1;
    // Scan the cells in the col 
    for (rowX = 0; rowX < numRows; rowX++) {
      PRBool originates;
      PRInt32 colSpan;
      nsTableCellFrame* cellFrame = mTableFrame->GetCellInfoAt(rowX, colX, &originates, &colSpan);
      if (!originates) continue; // skip  cells that don't originate in the col
      // see if the cell has a style percent width specified
      const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
      if (eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) {
        float percent = cellPosition->mWidth.GetPercentValue();
        if (percent > 0.0f) {
          // calculate the preferred width of the cell based on fix, des, widths of the cols it spans
          nscoord cellDesWidth  = 0;
          float spanPct = percent / float(colSpan);
          for (PRInt32 spanX = 0; spanX < colSpan; spanX++) {
            nsTableColFrame* spanFrame = mTableFrame->GetColFrame(colX + spanX);
            if (!spanFrame) continue;
            cellDesWidth += spanFrame->GetWidth(DES_CON); // don't consider DES_ADJ
            // crudely allocate pct values to the spanning cols so that we can check if they exceed 100 pct below
            rawPctValues[colX + spanX] = PR_MAX(rawPctValues[colX + spanX], spanPct);
          }
          // consider the cell's preferred width 
          cellDesWidth = PR_MAX(cellDesWidth, cellFrame->GetMaximumWidth());
          nscoord colBasis = nsTableFrame::RoundToPixel(NSToCoordRound((float)cellDesWidth / percent), pixelToTwips);
          maxColBasis = PR_MAX(maxColBasis, colBasis);
        }
      }
    }
    if (-1 == maxColBasis) {
      // see if the col has a style percent width specified
      nsStyleCoord colStyleWidth = colFrame->GetStyleWidth();
      if (eStyleUnit_Percent == colStyleWidth.GetUnit()) {
        float percent = colStyleWidth.GetPercentValue();
        maxColBasis = 0;
        if (percent > 0.0f) {
          rawPctValues[colX] = PR_MAX(rawPctValues[colX], percent);
          nscoord desWidth = colFrame->GetWidth(DES_CON); // don't consider DES_ADJ
          maxColBasis = nsTableFrame::RoundToPixel(NSToCoordRound((float)desWidth / percent), pixelToTwips);
        }
      }
    }
    basis = PR_MAX(basis, maxColBasis);
  } // end for (colX ..

  float   perTotal         = 0.0f; // total of percentage constrained cols and/or cells in cols
  PRInt32 numPerCols       = 0;    // number of colums that have percentage constraints
  nscoord fixDesTotal      = 0;    // total of fix or des widths of cols 
  nscoord fixDesTotalNoPct = 0;    // total of fix or des widths of cols without pct

  for (colX = 0; colX < numCols; colX++) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord fixWidth = colFrame->GetFixWidth();
    nscoord fixDesWidth = (fixWidth > 0) ? fixWidth : colFrame->GetDesWidth();
    fixDesTotal += fixDesWidth;
    if (rawPctValues[colX] + perTotal > 1.0f) {
      rawPctValues[colX] = PR_MAX(1.0f - perTotal, 0.0f);
    }
    if (rawPctValues[colX] > 0.0f) {
      numPerCols++;
      perTotal += rawPctValues[colX];
    }
    else {
      fixDesTotalNoPct += fixDesWidth;
    }
  }
  delete [] rawPctValues; // destroy the raw pct values
  // If there are no pct cells or cols, there is nothing to do.
  if ((0 == numPerCols) || (0.0f == perTotal)) {
    NS_ASSERTION(PR_FALSE, "invalid call");
    return basis; 
  }
  // If there is only one col and it is % based, it won't affect anything
  if ((1 == numCols) && (numCols == numPerCols)) {
    return basis + borderPadding.left + borderPadding.right + mCellSpacingTotal;
  }

  // compute a basis considering total percentages and the desired width of everything else
  if ((perTotal > 0.0f) && (perTotal < 1.0f)) {
    nscoord otherBasis = nsTableFrame::RoundToPixel(NSToCoordRound((float)fixDesTotalNoPct / (1.0f - perTotal)), pixelToTwips);
    basis = PR_MAX(basis, otherBasis);
  }
  else if ((fixDesTotalNoPct > 0) && (NS_UNCONSTRAINEDSIZE != availWidth)) { // make the basis as big as possible 
    basis = availWidth; // the 100% cols force as big a width as possible
  }
  basis = PR_MAX(basis, fixDesTotal);
  basis = PR_MIN(basis, availWidth); // don't exceed the max we were given

  if (NS_UNCONSTRAINEDSIZE != availWidth) {
    // add back the table border, padding and cell spacing
    basis += borderPadding.left + borderPadding.right + mCellSpacingTotal;
  }

  return basis;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::CalculateTotals ( PRInt32 aTotalCounts,
PRInt32 aTotalWidths,
PRInt32 aDupedWidths,
PRInt32 a0ProportionalCount 
) [protected]

calculate totals by width type.

The logic here is kept in synch with that in CanAllocate

Parameters:
aTotalCounts- array with counts for each width type that has determined the aTotalWidths sum
aTotalWidths- array with accumulated widths for each width type
aDupedWidths- (duplicatd) are widths that will be allocated in BalanceColumnWidths before aTotalsWidths
a0ProportionalCount- number of columns with col="0*" constraint

Definition at line 1649 of file BasicTableLayoutStrategy.cpp.

{
  //mTableFrame->Dump(PR_TRUE, PR_FALSE);
  for (PRInt32 widthX = 0; widthX < NUM_WIDTHS; widthX++) {
    aTotalCounts[widthX]      = 0;
    aTotalWidths[widthX]      = 0;
    aDupedWidths[widthX]      = 0;
  }
  a0ProportionalCount = 0;

  PRInt32 numEffCols = mTableFrame->GetEffectiveColCount();
  PRInt32 colX;

  for (colX = 0; colX < numEffCols; colX++) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord minCol = colFrame->GetMinWidth();
    aTotalCounts[MIN_CON]++;
    aTotalWidths[MIN_CON] += minCol;

    if (e0ProportionConstraint == colFrame->GetConstraint()) {
      a0ProportionalCount++;
    }

    nscoord pct    = colFrame->GetPctWidth();
    nscoord fix    = colFrame->GetWidth(FIX);
    nscoord fixAdj = colFrame->GetWidth(FIX_ADJ);
    // if there is a pct width then no others are considered
    if (pct > 0) {
      aTotalCounts[PCT]++;
      aTotalWidths[PCT] += PR_MAX(pct, minCol);
      aDupedWidths[PCT] += minCol;
    }
    else if ((fix > 0) || (fixAdj > 0)) {
      if (fix > 0) {
        aTotalCounts[FIX]++;
        aTotalWidths[FIX] += PR_MAX(fix, minCol);
        aDupedWidths[FIX] += minCol;
      }
      if (fixAdj > 0) {
        if (fixAdj > fix) {
          aTotalCounts[FIX_ADJ]++;
          aTotalWidths[FIX_ADJ] += PR_MAX(fixAdj, minCol);
          if (fix > 0) {
            aDupedWidths[FIX_ADJ] += fix;
          }
          else { // there was no fix
            aDupedWidths[FIX_ADJ] += minCol;
          }
        }
      }
    }
    else if ((eProportionConstraint == colFrame->GetConstraint()) ||
             (e0ProportionConstraint == colFrame->GetConstraint())) {
      aTotalCounts[MIN_PRO]++;
      aTotalWidths[MIN_PRO] += PR_MAX(colFrame->GetWidth(MIN_PRO), minCol);
      aDupedWidths[MIN_PRO] += minCol;
    }
    else {
      // desired alone is lowest priority
      aTotalCounts[DES_CON]++;
      aTotalWidths[DES_CON] += PR_MAX(colFrame->GetDesWidth(), minCol);
      aDupedWidths[DES_CON] += minCol;
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void BasicTableLayoutStrategy::ComputeNonPctColspanWidths ( const nsHTMLReflowState aReflowState,
PRBool  aConsiderPct,
float  aPixelToTwips,
PRBool aHasPctCol 
) [protected]

Calculate the adjusted widths (min, desired, fixed, or pct) for a cell spanning multiple columns.

Parameters:
aReflowState- the reflow state of the table
aConsiderPct- if true, consider columns that have pct widths and are spanned by the cell
aPixelToTwips-the number of twips in a pixel.
aHasPctCol- if not null, then set *aHasPctCol to true if there is a pct cell or col

Definition at line 587 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eNonPctColspans, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
  PRInt32 numCols = mTableFrame->GetColCount();
  PRInt32 numEffCols = mTableFrame->GetEffectiveColCount();
  // zero out prior ADJ values 

  PRInt32 colX;
  for (colX = numCols - 1; colX >= 0; colX--) { 
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    colFrame->SetWidth(MIN_ADJ, WIDTH_NOT_SET);
    colFrame->SetWidth(FIX_ADJ, WIDTH_NOT_SET);
    colFrame->SetWidth(DES_ADJ, WIDTH_NOT_SET);
  }

  // For each col, consider the cells originating in it with colspans > 1.
  // Adjust the cols that each cell spans if necessary. Iterate backwards 
  // so that nested and/or overlaping col spans handle the inner ones first, 
  // ensuring more accurated calculations.
  // if more than one  colspan originate in one column, resort the access to 
  // the rows so that the inner colspans are handled first
  PRInt32 numRows = mTableFrame->GetRowCount();

  CellInfo* cellInfo = new CellInfo[numRows];

  if(!cellInfo) {
    return;
  }

  for (colX = numEffCols - 1; colX >= 0; colX--) { // loop only over effective columns
    PRInt32 spannedRows = GetSortedFrames(mTableFrame, colX, numRows, cellInfo);

    for (PRInt32 i = 0; i < spannedRows; i++) {
      const CellInfo *inf = &cellInfo[i];
      const nsTableCellFrame* cellFrame = inf->cellFrame;

      const PRInt32 colSpan = PR_MIN(inf->colSpan, numEffCols - colX);
      // set MIN_ADJ, DES_ADJ, FIX_ADJ
      for (PRInt32 widthX = 0; widthX < NUM_MAJOR_WIDTHS; widthX++) {
        nscoord cellWidth = 0;
        if (MIN_CON == widthX) {
          cellWidth = cellFrame->GetPass1MaxElementWidth();
        }
        else if (DES_CON == widthX) {
          cellWidth = cellFrame->GetMaximumWidth();
        }
        else { // FIX width
          // see if the cell has a style width specified
          const nsStylePosition* cellPosition = cellFrame->GetStylePosition();
          if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) {
            // need to add borde and padding into fixed width
            nsMargin borderPadding = nsTableFrame::GetBorderPadding(nsSize(aReflowState.mComputedWidth, 0),
                                                                    aPixelToTwips, cellFrame);
            cellWidth = cellPosition->mWidth.GetCoordValue() + borderPadding.left + borderPadding.right;
            cellWidth = PR_MAX(cellWidth, cellFrame->GetPass1MaxElementWidth());
          }
        }

        if (0 >= cellWidth) continue;

        // first allocate pct cells up to their value if aConsiderPct, then
        // allocate fixed cells up to their value, then allocate auto cells 
        // up to their value, then allocate auto cells proportionally.
        PRInt32 limit = (aConsiderPct) ? LIMIT_PCT : LIMIT_FIX;
        if (MIN_CON != widthX) { // FIX and DES only need to allocate NONE
          limit = LIMIT_NONE;
        }
        while (limit <= LIMIT_NONE) {
          if (ComputeNonPctColspanWidths(widthX, cellFrame, cellWidth, colX, colSpan, 
                                         limit, aPixelToTwips)) {
            break;
          }
          limit++;
        }
      }
      // determine if there is a pct col if we are requested to do so
      if (aHasPctCol && !*aHasPctCol) {
        *aHasPctCol = HasPctValue(cellFrame);
      }
    }
  }
  delete [] cellInfo;
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eNonPctColspans, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool BasicTableLayoutStrategy::ComputeNonPctColspanWidths ( PRInt32  aWidthIndex,
const nsTableCellFrame aCellFrame,
PRInt32  aCellWidth,
PRInt32  aColIndex,
PRInt32  aColSpan,
PRInt32 aLimitType,
float  aPixelToTwips 
) [protected]

main helper for above.

For min width calculations, it can get called up to 3 times, 1st to let constrained pct cols reach their limit, 2nd to let fix cols reach their limit and 3rd to spread any remainder among auto cols. If there are no auto cols then only constrained cols are considered.

Parameters:
aWidthIndex- the width to calculate (see nsTableColFrame.h for enums)
aCellFrame- the frame of the cell with a colspan
aCellWidth- the width of the cell with a colspan
aColIndex- the column index of the cell in the table
aColSpan- the colspan of the cell
aLimitType- the type of limit (ie. pct, fix, none).
aPixelToTwips-the number of twips in a pixel.
Returns:
- true if all of aCellWidth was allocated, false otherwise

Definition at line 714 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_STRATEGY
  DumpColWidths(*mTableFrame, "enter ComputeNonPctColspanWidths", aCellFrame, aColIndex, aWidthIndex, aLimitType);
#endif  
  PRBool result = PR_TRUE;

  nscoord spanCellSpacing   = 0; // total cell spacing cells being spanned
  nscoord minTotal          = 0; // the sum of min widths of spanned cells. 
  nscoord autoMinTotal      = 0; // the sum of min widths of spanned auto cells. 
  nscoord fixMinTotal       = 0; // the sum of min widths of spanned fix cells. 
  nscoord pctMinTotal       = 0; // the sum of min widths of spanned pct cells. 
  nscoord pctTotal          = 0; // the sum of pct widths of spanned cells. 
  nscoord fixTotal          = 0; // the sum of fix widths of spanned cells
  nscoord autoDesTotal      = 0; // the sum of desired widths of spanned cells which are auto
  nscoord pctLimitTotal     = 0; // the sum of pct widths not exceeding aCellWidth
  nscoord fixLimitTotal     = 0; // the sum of fix widths not exceeding aCellWidth
  nscoord desLimitTotal     = 0; // the sum of des widths not exceeding aCellWidth
  PRInt32 numAutoCols       = 0;

  nscoord spacingX = mTableFrame->GetCellSpacingX();
  PRInt32 spanX;
  // accumulate the various divisors to be used later
  for (spanX = 0; spanX < aColSpan; spanX++) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); 
    if (!colFrame) continue;
    nscoord minWidth = PR_MAX(colFrame->GetMinWidth(), 0);
    nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
    nscoord fixWidth = PR_MAX(colFrame->GetFixWidth(), 0);
    nscoord desWidth = PR_MAX(colFrame->GetDesWidth(), minWidth);

    minTotal += minWidth;

    if (pctWidth > 0) {
      pctTotal += pctWidth;
      pctMinTotal += minWidth;
    }
    else if (fixWidth > 0) {
      fixTotal += fixWidth;
      fixMinTotal += minWidth;
    }
    if (colFrame->GetWidth(PCT) + colFrame->GetWidth(FIX) <= 0) {
      autoDesTotal += desWidth;
      autoMinTotal += minWidth;
      numAutoCols++;
    }
    if ((spanX > 0) && (mTableFrame->GetNumCellsOriginatingInCol(aColIndex + spanX) > 0)) {
      spanCellSpacing += spacingX;
    }
  }
  nscoord availWidth = aCellWidth - spanCellSpacing;
  if (MIN_CON == aWidthIndex) {
    // MIN widths (unlike the others) are added to existing values, so subtract out the min total
    availWidth -= minTotal;

    pctLimitTotal = ((pctTotal - pctMinTotal) < availWidth) ? pctTotal - pctMinTotal : availWidth;
    fixLimitTotal = ((fixTotal - fixMinTotal) < availWidth) ? fixTotal - fixMinTotal : availWidth;
    desLimitTotal = ((autoDesTotal - autoMinTotal) < availWidth) ? autoDesTotal - autoMinTotal : availWidth;
  }
  else { // FIX or DES_CON with LIMIT_NONE
    if (FIX == aWidthIndex) {
      if (autoDesTotal > 0) {
        availWidth -= pctTotal + fixTotal;
      }
      else if (fixTotal > 0) {
        availWidth -= pctTotal;
      }
    }
    else if (DES_CON == aWidthIndex) {
      availWidth -= pctTotal + fixTotal; 
    }
  }

  // Below are some optimizations which can skip steps.
  if (LIMIT_PCT == aLimitType) {
    NS_ASSERTION(MIN_CON == aWidthIndex, "invalid call to ComputeNonPctColspanWidths");
    // if there are no pct cols, limit fix cols
    if (0 == pctTotal) {
      aLimitType = LIMIT_FIX;
    }
  }
  if (LIMIT_FIX == aLimitType) {
    NS_ASSERTION(MIN_CON == aWidthIndex, "invalid call to ComputeNonPctColspanWidths");
    // if there are no fix cols, limit des
    if (0 == fixTotal) {
      aLimitType = LIMIT_DES;
    }
  }
  if (LIMIT_DES == aLimitType) {
    NS_ASSERTION(MIN_CON == aWidthIndex, "invalid call to ComputeNonPctColspanWidths");
    // if there are no auto cols, limit none
    if (0 == autoDesTotal) {
      aLimitType = LIMIT_NONE;
    }
  }

  // there are some cases where allocating up to aCellWidth will not be satisfied
  switch (aLimitType) {
  case LIMIT_PCT:
    if (pctLimitTotal < availWidth) {
      // the pct cols won't satisfy the request alone
      availWidth = pctLimitTotal;
      result = PR_FALSE;
    }
    break;
  case LIMIT_FIX:
    if (fixLimitTotal < availWidth) {
      // the fix cols won't satisfy the request alone
      availWidth = fixLimitTotal;
      result = PR_FALSE;
    }
    break;
  case LIMIT_DES:
    if (desLimitTotal < availWidth) {
      // the auto cols won't satisfy the request alone
      availWidth = desLimitTotal;
      result = PR_FALSE;
    }
    break;
  default: // LIMIT_NONE
    break;
  }

  if (availWidth > 0) {
    nscoord usedWidth = 0;
    // get the correct numerator in a similar fashion to getting the divisor
    for (spanX = 0; spanX < aColSpan; spanX++) {
      if (usedWidth >= availWidth) break;
      nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex + spanX); 
      if (!colFrame) continue;
      nscoord minWidth = colFrame->GetMinWidth();
      nscoord pctWidth = PR_MAX(colFrame->GetPctWidth(), 0);
      nscoord fixWidth = PR_MAX(colFrame->GetFixWidth(), 0);
      nscoord desWidth = PR_MAX(colFrame->GetDesWidth(), minWidth);

      nscoord colWidth = PR_MAX(colFrame->GetWidth(aWidthIndex), 
                                colFrame->GetWidth(aWidthIndex + NUM_MAJOR_WIDTHS));
      colWidth = PR_MAX(colWidth, minWidth);

      nscoord numeratorPct     = 0;
      nscoord numeratorFix     = 0;
      nscoord numeratorAutoDes = 0;

      if (pctWidth > 0) {
        numeratorPct = pctWidth;
      }
      else if (fixWidth > 0) {
        numeratorFix = fixWidth;
      }
      if (colFrame->GetWidth(PCT) + colFrame->GetWidth(FIX) <= 0) {
        numeratorAutoDes = desWidth;
      }

      nscoord divisor = 0;
      nscoord numerator = 0;

      // let pct cols reach their target 
      if (LIMIT_PCT == aLimitType) {
        if (pctLimitTotal > 0) {
          divisor   = pctTotal - pctMinTotal;
          numerator = PR_MAX(numeratorPct - minWidth, 0);
        }
      }
      // let fix cols reach their target 
      else if (LIMIT_FIX == aLimitType) {
        if (fixLimitTotal > 0) {
          divisor   = fixTotal - fixMinTotal;
          numerator = PR_MAX(numeratorFix - minWidth, 0);
        }
      }
      // let auto cols reach their target 
      else if (LIMIT_DES == aLimitType) {
        if (desLimitTotal > 0) {
          if (autoDesTotal > 0) { // there were auto cols
            divisor   = autoDesTotal - autoMinTotal;
            numerator = PR_MAX(numeratorAutoDes - minWidth, 0);
          }
          else if (fixTotal > 0) {  // there were fix cols but no auto
            divisor   = fixTotal - fixMinTotal;
            numerator = PR_MAX(numeratorFix - minWidth, 0);
          }
          else if (pctTotal > 0) {  // there were only pct cols
            divisor   = pctTotal - pctMinTotal;
            numerator = PR_MAX(numeratorPct - minWidth, 0);
          }
          else continue;
        }
      }
      else if (LIMIT_NONE == aLimitType) { 
        if ((MIN_CON == aWidthIndex) && (0 == minTotal)) {
          // divide evenly among the spanned cols
          divisor = aColSpan;
          numerator = 1;
        }
        else {
          if (autoDesTotal > 0) { // there were auto cols
            divisor   = autoDesTotal;
            numerator = numeratorAutoDes;
          }
          else if (fixTotal > 0) {  // there were fix cols but no auto
            divisor   = fixTotal;
            numerator = numeratorFix;
          }
          else if (pctTotal > 0) {  // there were only pct cols
            divisor   = pctTotal;
            numerator = numeratorPct;
          }
          else continue;

        }
      }
      // calculate the adj col width
      nscoord newColAdjWidth = (0 >= divisor) 
        ? NSToCoordRound( ((float)availWidth) / ((float)aColSpan) )
        : NSToCoordRound( (((float)numerator) / ((float)divisor)) * availWidth);
      newColAdjWidth = nsTableFrame::RoundToPixel(newColAdjWidth, aPixelToTwips);
      // don't let the new allocation exceed the avail total
      newColAdjWidth = PR_MIN(newColAdjWidth, availWidth - usedWidth);
      // put the remainder of the avail total in the last spanned col
      if (spanX == aColSpan - 1) {
        newColAdjWidth = availWidth - usedWidth;
      }
      usedWidth += newColAdjWidth;
      // MIN_CON gets added to what is there, the others don't
      if (MIN_CON == aWidthIndex) {
        newColAdjWidth += colWidth;
      }
      if (newColAdjWidth > colWidth) { 
        if (FIX == aWidthIndex) {
          // a colspan cannot fix a column below what a cell desires on its own
          nscoord desCon = colFrame->GetWidth(DES_CON); // do not consider DES_ADJ
          if (desCon > newColAdjWidth) {
            newColAdjWidth = desCon;
          }
        }
        colFrame->SetWidth(aWidthIndex + NUM_MAJOR_WIDTHS, newColAdjWidth);
      }
      else {        
        if((newColAdjWidth > 0) && (FIX == aWidthIndex)) {
          if(colFrame->GetWidth(FIX) < 0) {
            nscoord desCon = colFrame->GetWidth(DES_CON);
            if (desCon > newColAdjWidth) {
              newColAdjWidth = desCon;
            }
          }
          if(colFrame->GetWidth(FIX_ADJ) < newColAdjWidth) {
            colFrame->SetWidth(FIX_ADJ, PR_MAX(colWidth,newColAdjWidth));
          }
        }
      }
    }
  }
#ifdef DEBUG_TABLE_STRATEGY
  DumpColWidths(*mTableFrame, "exit ComputeNonPctColspanWidths", aCellFrame, aColIndex, aWidthIndex, aLimitType);
#endif
  return result;
}

Here is the call graph for this function:

Check in debug mode whether the routine is called on a continuing frame.

Definition at line 171 of file BasicTableLayoutStrategy.cpp.

{
  NS_ASSERTION(!mTableFrame->GetPrevInFlow(),
               "never ever call me on a continuing frame!");
}

Here is the call graph for this function:

Here is the caller graph for this function:

call every time any table thing changes that might effect the width of any column in the table (content, structure, or style)

Parameters:
aReflowState- the reflow state for mTableFrame

Implements nsITableLayoutStrategy.

Definition at line 127 of file BasicTableLayoutStrategy.cpp.

{
#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eInit, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_TRUE);
#endif
  ContinuingFrameCheck();

  PRBool result = PR_TRUE;

  // re-init instance variables
  mCellSpacingTotal = 0;
  mCols             = mTableFrame->GetEffectiveCOLSAttribute();

  mTableFrame->SetHasPctCol(PR_FALSE);

  nscoord boxWidth = mTableFrame->CalcBorderBoxWidth(aReflowState);
  PRBool hasPctCol = AssignNonPctColumnWidths(boxWidth, aReflowState);

  mTableFrame->SetHasPctCol(hasPctCol);

  // calc the min, desired, preferred widths from what we know so far
  nscoord minWidth, prefWidth;
  mTableFrame->CalcMinAndPreferredWidths(aReflowState, PR_FALSE, minWidth, prefWidth);
  if (hasPctCol && mTableFrame->IsAutoWidth()) {
    prefWidth = CalcPctAdjTableWidth(aReflowState, boxWidth);
  }
  // calc the desired width, considering if there is a specified width. 
  // don't use nsTableFrame::CalcDesiredWidth because it is based on table column widths.
  nscoord desWidth = (mTableFrame->IsAutoWidth()) ? PR_MIN(prefWidth, aReflowState.availableWidth)
                                                  : prefWidth;
  desWidth = PR_MAX(desWidth, minWidth);

  mTableFrame->SetMinWidth(minWidth);
  mTableFrame->SetDesiredWidth(desWidth);
  mTableFrame->SetPreferredWidth(prefWidth);

  mTableFrame->SetNeedStrategyInit(PR_FALSE);

#ifdef DEBUG_TABLE_REFLOW_TIMING
  nsTableFrame::DebugTimeMethod(nsTableFrame::eInit, *mTableFrame, (nsHTMLReflowState&)aReflowState, PR_FALSE);
#endif
  return result;
}

Here is the call graph for this function:

Reduce the percent columns by the amount specified in aExcess as the percent width's can accumulate to be over 100%.

Parameters:
aExcess- reduction amount

Definition at line 1189 of file BasicTableLayoutStrategy.cpp.

{
  nscoord numCols = mTableFrame->GetColCount();
  for (PRInt32 colX = numCols - 1; (colX >= 0) && (aExcess > 0); colX--) {
    nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); 
    if (!colFrame) continue;
    nscoord pctWidth = colFrame->GetWidth(PCT);
    nscoord reduction = 0;
    if (pctWidth > 0) {
      reduction = (aExcess > pctWidth) ? pctWidth : aExcess;
      nscoord newPctWidth = (reduction == pctWidth) ? WIDTH_NOT_SET : pctWidth - reduction;
      colFrame->SetWidth(PCT, PR_MAX(newPctWidth, colFrame->GetMinWidth()));
    }
    else {
      nscoord pctAdjWidth = colFrame->GetWidth(PCT_ADJ);
      if (pctAdjWidth > 0) {
        reduction = (aExcess > pctAdjWidth) ? pctAdjWidth : aExcess;
        nscoord newPctAdjWidth = (reduction == pctAdjWidth) ? WIDTH_NOT_SET : pctAdjWidth - reduction;
        colFrame->SetWidth(PCT_ADJ, PR_MAX(newPctAdjWidth, colFrame->GetMinWidth()));
      }
    }
    aExcess -= reduction;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 229 of file BasicTableLayoutStrategy.h.

Definition at line 227 of file BasicTableLayoutStrategy.h.

Definition at line 231 of file BasicTableLayoutStrategy.h.

Definition at line 230 of file BasicTableLayoutStrategy.h.

Definition at line 226 of file BasicTableLayoutStrategy.h.


The documentation for this class was generated from the following files: