1998-04-30 21:57:09 +04:00
/* -*- 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 "BasicTableLayoutStrategy.h"
# include "nsTableFrame.h"
1998-05-30 02:08:19 +04:00
# include "nsTableColFrame.h"
1998-04-30 21:57:09 +04:00
# include "nsTableCellFrame.h"
# include "nsIStyleContext.h"
# include "nsStyleConsts.h"
1998-07-11 04:00:31 +04:00
# include "nsVoidArray.h"
1998-05-31 01:21:51 +04:00
# include "nsHTMLIIDs.h"
1998-04-30 21:57:09 +04:00
static const PRBool gsDebug = PR_FALSE ;
1999-01-07 05:16:10 +03:00
const nscoord gBigSpace = 100000 ; // a fudge constant used when the table is laid out with unconstrained width
1998-08-18 03:37:04 +04:00
1999-04-04 03:02:43 +04:00
// these macros are defined to improve the readability of the main code
# define TDBG_S(str) \
if ( gsDebug ) { \
printf ( ( str ) ) ; \
}
# define TDBG_SP(str,ptr) \
if ( gsDebug ) { \
printf ( ( str ) , ( ptr ) ) ; \
}
# define TDBG_SPD(str,ptr,dec) \
if ( gsDebug ) { \
printf ( ( str ) , ( ptr ) , ( dec ) ) ; \
}
# define TDBG_SPDD(str,ptr,dec1,dec2) \
if ( gsDebug ) { \
printf ( ( str ) , ( ptr ) , ( dec1 ) , ( dec2 ) ) ; \
}
# define TDBG_SFDD(str,flt,dec1,dec2) \
if ( gsDebug ) { \
printf ( ( str ) , ( flt ) , ( dec1 ) , ( dec2 ) ) ; \
}
# define TDBG_SDF(str,dec,flt) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec ) , ( flt ) ) ; \
}
# define TDBG_SDFDDD(str,dec1,flt,dec2,dec3,dec4) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( flt ) , ( dec2 ) , ( dec3 ) , ( dec4 ) ) ; \
}
# define TDBG_SD(str,dec) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec ) ) ; \
}
# define TDBG_SDD(str,dec1,dec2) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( dec2 ) ) ; \
}
# define TDBG_SDDD(str,dec1,dec2,dec3) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( dec2 ) , ( dec3 ) ) ; \
}
# define TDBG_SDFD(str,dec1,flt,dec2) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( flt ) , ( dec2 ) ) ; \
}
# define TDBG_SDDF(str,dec1,dec2,flt) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( dec2 ) , ( flt ) ) ; \
}
# define TDBG_SDDDD(str,dec1,dec2,dec3,dec4) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( dec2 ) , ( dec3 ) , ( dec4 ) ) ; \
}
# define TDBG_SDDDF(str,dec1,dec2,dec3,flt) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( dec2 ) , ( dec3 ) , ( flt ) ) ; \
}
# define TDBG_SDDDDD(str,dec1,dec2,dec3,dec4,dec5) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( dec2 ) , ( dec3 ) , ( dec4 ) , ( dec5 ) ) ; \
}
# define TDBG_SDDDDDD(str,dec1,dec2,dec3,dec4,dec5,dec6) \
if ( gsDebug ) { \
printf ( ( str ) , ( dec1 ) , ( dec2 ) , ( dec3 ) , ( dec4 ) , ( dec5 ) , ( dec6 ) ) ; \
}
# define TDBG_SDD_SDD(str1,dec1a,dec1b,str2,dec2a,dec2b) \
if ( gsDebug ) { \
printf ( ( str1 ) , ( dec1a ) , ( dec1b ) ) ; \
printf ( ( str2 ) , ( dec2a ) , ( dec2b ) ) ; \
}
# define TDBG_SDS_SDD_SD(str1a,dec1,str1b,str2,dec2a,dec2b,str3,dec3) \
if ( gsDebug ) { \
printf ( ( str1a ) , ( dec1 ) , ( str1b ) ) ; \
printf ( ( str2 ) , ( dec2a ) , ( dec2b ) ) ; \
printf ( ( str3 ) , ( dec3 ) ) ; \
}
# define TDBG_SDS_SD(str1a,dec1,str1b,str2,dec2) \
if ( gsDebug ) { \
printf ( ( str1a ) , ( dec1 ) , ( str1b ) ) ; \
printf ( ( str2 ) , ( dec2 ) ) ; \
}
# define TDBG_WIDTHS1() \
if ( PR_TRUE = = gsDebug ) { \
printf ( " BalanceColumnWidths with aMaxWidth = %d, availWidth = %d \n " , aMaxWidth , availWidth ) ; \
printf ( " \t \t specifiedTW = %d, min/maxTW = %d %d \n " , specifiedTableWidth , mMinTableWidth , mMaxTableWidth ) ; \
printf ( " \t \t reflow reason = %d \n " , aReflowState . reason ) ; \
}
# define TDBG_WIDTHS2(string) \
if ( PR_TRUE = = gsDebug ) { \
printf ( " \n %p: %s \n " , ( string ) , mTableFrame ) ; \
for ( PRInt32 i = 0 ; i < mNumCols ; i + + ) { \
printf ( " col %d assigned width %d \n " , i , mTableFrame - > GetColumnWidth ( i ) ) ; \
} \
printf ( " \n " ) ; \
}
# define TDBG_WIDTHS4(string,haveShrinkFit,shrinkFit) \
if ( PR_TRUE = = gsDebug ) { \
nscoord tableWidth = 0 ; \
printf ( ( string ) ) ; \
for ( PRInt32 i = 0 ; i < mNumCols ; i + + ) { \
tableWidth + = mTableFrame - > GetColumnWidth ( i ) ; \
printf ( " %d " , mTableFrame - > GetColumnWidth ( i ) ) ; \
} \
printf ( " \n computed table width is %d " , tableWidth ) ; \
if ( ( haveShrinkFit ) ) { \
printf ( " with aShrinkFixedCols = %s " , shrinkFit ? " TRUE " : " FALSE " ) ; \
} \
printf ( " \n " ) ; \
}
1998-05-30 02:08:19 +04:00
/* ---------- ProportionalColumnLayoutStruct ---------- */
// TODO: make public so other subclasses can use it
1999-01-07 05:16:10 +03:00
/** useful info about a column for layout of tables with colspans */
1998-05-30 02:08:19 +04:00
struct ProportionalColumnLayoutStruct
{
ProportionalColumnLayoutStruct ( PRInt32 aColIndex ,
nscoord aMinColWidth ,
nscoord aMaxColWidth ,
PRInt32 aProportion )
{
1999-04-04 03:02:43 +04:00
mColIndex = aColIndex ;
1998-05-30 02:08:19 +04:00
mMinColWidth = aMinColWidth ;
mMaxColWidth = aMaxColWidth ;
1999-04-04 03:02:43 +04:00
mProportion = aProportion ;
1998-05-30 02:08:19 +04:00
} ;
PRInt32 mColIndex ;
nscoord mMinColWidth ;
nscoord mMaxColWidth ;
PRInt32 mProportion ;
} ;
1998-07-11 04:00:31 +04:00
/* ---------- ColSpanStruct ---------- */
1999-01-07 05:16:10 +03:00
/** useful info about a column for layout of tables with colspans */
1998-07-11 04:00:31 +04:00
struct ColSpanStruct
{
PRInt32 colIndex ;
PRInt32 colSpan ;
nscoord width ;
ColSpanStruct ( PRInt32 aSpan , PRInt32 aIndex , nscoord aWidth )
{
1999-04-04 03:02:43 +04:00
colSpan = aSpan ;
1998-07-11 04:00:31 +04:00
colIndex = aIndex ;
1999-04-04 03:02:43 +04:00
width = aWidth ;
1998-07-11 04:00:31 +04:00
}
} ;
1998-05-30 02:08:19 +04:00
/* ---------- BasicTableLayoutStrategy ---------- */
1998-11-16 09:46:00 +03:00
/* return true if the style indicates that the width is fixed
1998-05-27 02:03:16 +04:00
* for the purposes of column width determination
*/
1998-11-16 09:46:00 +03:00
inline
PRBool BasicTableLayoutStrategy : : IsFixedWidth ( const nsStylePosition * aStylePosition ,
1999-04-04 03:02:43 +04:00
const nsStyleTable * aStyleTable )
1998-05-27 02:03:16 +04:00
{
1998-11-16 09:46:00 +03:00
return PRBool ( ( eStyleUnit_Coord = = aStylePosition - > mWidth . GetUnit ( ) ) | |
( eStyleUnit_Coord = = aStyleTable - > mSpanWidth . GetUnit ( ) ) ) ;
1998-05-27 02:03:16 +04:00
}
1998-10-20 03:43:06 +04:00
BasicTableLayoutStrategy : : BasicTableLayoutStrategy ( nsTableFrame * aFrame )
1998-04-30 21:57:09 +04:00
{
1999-04-04 03:02:43 +04:00
NS_ASSERTION ( nsnull ! = aFrame , " bad frame arg " ) ;
1998-06-24 03:23:21 +04:00
1999-04-04 03:02:43 +04:00
mTableFrame = aFrame ;
mMinTableWidth = 0 ;
mMaxTableWidth = 0 ;
mFixedTableWidth = 0 ;
1998-04-30 21:57:09 +04:00
}
BasicTableLayoutStrategy : : ~ BasicTableLayoutStrategy ( )
{
}
1999-04-04 03:02:43 +04:00
PRBool BasicTableLayoutStrategy : : Initialize ( nsSize * aMaxElementSize ,
PRInt32 aNumCols )
1998-04-30 21:57:09 +04:00
{
1999-04-04 03:02:43 +04:00
# ifdef NS_DEBUG
nsIFrame * tablePIF = nsnull ;
mTableFrame - > GetPrevInFlow ( & tablePIF ) ;
NS_ASSERTION ( nsnull = = tablePIF , " never ever call me on a continuing frame! " ) ;
1998-07-17 03:23:31 +04:00
# endif
1998-04-30 21:57:09 +04:00
PRBool result = PR_TRUE ;
1998-05-27 02:03:16 +04:00
1998-07-22 22:22:12 +04:00
// re-init instance variables
1999-04-04 03:02:43 +04:00
mNumCols = aNumCols ;
mMinTableWidth = 0 ;
mMaxTableWidth = 0 ;
mFixedTableWidth = 0 ;
mCols = mTableFrame - > GetEffectiveCOLSAttribute ( ) ;
1998-07-22 22:22:12 +04:00
1998-04-30 21:57:09 +04:00
// Step 1 - assign the width of all fixed-width columns
1998-07-17 03:23:31 +04:00
AssignPreliminaryColumnWidths ( ) ;
1998-04-30 21:57:09 +04:00
1998-07-17 03:23:31 +04:00
// set aMaxElementSize here because we compute mMinTableWidth in AssignPreliminaryColumnWidths
1999-04-04 03:02:43 +04:00
if ( nsnull ! = aMaxElementSize ) {
1998-10-09 23:59:45 +04:00
SetMaxElementSize ( aMaxElementSize ) ;
}
return result ;
}
void BasicTableLayoutStrategy : : SetMaxElementSize ( nsSize * aMaxElementSize )
{
1999-04-04 03:02:43 +04:00
if ( nsnull ! = aMaxElementSize ) {
1998-07-17 03:23:31 +04:00
aMaxElementSize - > height = 0 ;
1998-08-07 06:11:51 +04:00
nsMargin borderPadding ;
const nsStylePosition * tablePosition ;
const nsStyleSpacing * tableSpacing ;
1998-11-20 12:29:58 +03:00
mTableFrame - > GetStyleData ( eStyleStruct_Position , ( ( const nsStyleStruct * & ) tablePosition ) ) ;
mTableFrame - > GetStyleData ( eStyleStruct_Spacing , ( ( const nsStyleStruct * & ) tableSpacing ) ) ;
1998-12-23 18:47:43 +03:00
mTableFrame - > GetTableBorder ( borderPadding ) ;
nsMargin padding ;
tableSpacing - > GetPadding ( padding ) ;
borderPadding + = padding ;
1999-04-04 03:02:43 +04:00
if ( tablePosition - > mWidth . GetUnit ( ) = = eStyleUnit_Coord ) {
1998-08-04 00:27:59 +04:00
aMaxElementSize - > width = tablePosition - > mWidth . GetCoordValue ( ) ;
1998-08-04 04:56:57 +04:00
aMaxElementSize - > width = PR_MAX ( aMaxElementSize - > width , mMinTableWidth ) ;
1998-08-07 06:11:51 +04:00
//XXX: need to factor in borderpadding here!
1998-08-04 04:56:57 +04:00
}
1999-04-04 03:02:43 +04:00
else {
1998-08-07 06:11:51 +04:00
aMaxElementSize - > width = mMinTableWidth + borderPadding . left + borderPadding . right ;
}
1999-04-04 03:02:43 +04:00
TDBG_SPD ( " %p BTLS::Init setting aMaxElementSize->width = %d \n " , mTableFrame , aMaxElementSize - > width ) ;
1998-04-30 21:57:09 +04:00
}
}
1999-04-04 03:02:43 +04:00
PRBool BasicTableLayoutStrategy : : BalanceColumnWidths ( nsIStyleContext * aTableStyle ,
1998-10-02 08:10:00 +04:00
const nsHTMLReflowState & aReflowState ,
1999-04-04 03:02:43 +04:00
nscoord aMaxWidth )
1998-04-30 21:57:09 +04:00
{
1998-09-23 03:36:06 +04:00
# ifdef NS_DEBUG
1999-04-04 03:02:43 +04:00
nsIFrame * tablePIF = nsnull ;
1999-02-24 07:48:08 +03:00
mTableFrame - > GetPrevInFlow ( & tablePIF ) ;
1998-04-30 21:57:09 +04:00
NS_ASSERTION ( nsnull = = tablePIF , " never ever call me on a continuing frame! " ) ;
# endif
1998-07-17 03:23:31 +04:00
PRBool result ;
1999-04-04 03:02:43 +04:00
NS_ASSERTION ( nsnull ! = aTableStyle , " bad arg " ) ;
if ( nsnull = = aTableStyle ) {
1998-07-17 03:23:31 +04:00
return PR_FALSE ;
1999-04-04 03:02:43 +04:00
}
1998-07-17 03:23:31 +04:00
nscoord specifiedTableWidth = 0 ; // not cached as a data member because it can vary depending on aMaxWidth
PRBool tableIsAutoWidth = nsTableFrame : : TableIsAutoWidth ( mTableFrame , aTableStyle , aReflowState , specifiedTableWidth ) ;
1998-11-30 18:10:20 +03:00
// HACK! Fix TableIsAutoWidth to return the right width
1999-04-04 03:02:43 +04:00
specifiedTableWidth = PR_MIN ( specifiedTableWidth , aMaxWidth ) ;
if ( NS_UNCONSTRAINEDSIZE = = specifiedTableWidth ) {
specifiedTableWidth = 0 ;
tableIsAutoWidth = PR_TRUE ;
1998-07-18 01:02:28 +04:00
}
1998-07-17 03:23:31 +04:00
// Step 2 - determine how much space is really available
1998-08-14 20:16:43 +04:00
nscoord availWidth = aMaxWidth ; // start with the max width I've been given
1999-04-04 03:02:43 +04:00
if ( NS_UNCONSTRAINEDSIZE ! = availWidth ) { // if that's not infinite, subtract the fixed columns
availWidth - = mFixedTableWidth ;
} // that have already been accounted for
if ( PR_FALSE = = tableIsAutoWidth ) { // if the table has a specified width
1998-07-31 04:31:09 +04:00
availWidth = specifiedTableWidth - mFixedTableWidth ; // use it, minus the fixed columns already accounted for
1999-04-04 03:02:43 +04:00
}
//if (0!=mMinTableWidth && mMinTableWidth>availWidth) // if the computed available size is too small
//availWidth = mMinTableWidth; // bump it up to the min
availWidth = PR_MAX ( 0 , availWidth ) ; // avail width can never be negative
1998-07-31 04:31:09 +04:00
1998-07-17 03:23:31 +04:00
// Step 3 - assign the width of all proportional-width columns in the remaining space
1999-04-04 03:02:43 +04:00
TDBG_WIDTHS1 ( ) ;
TDBG_WIDTHS2 ( " BEGIN BALANCE COLUMN WIDTHS \n " ) ;
1998-07-17 03:23:31 +04:00
result = BalanceProportionalColumns ( aReflowState , availWidth , aMaxWidth ,
specifiedTableWidth , tableIsAutoWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_WIDTHS2 ( " END BALANCE COLUMN WIDTHS \n " ) ;
1998-07-27 06:15:37 +04:00
# ifdef NS_DEBUG // sanity check for table column widths
1999-04-04 03:02:43 +04:00
for ( PRInt32 i = 0 ; i < mNumCols ; i + + ) {
1998-07-27 06:15:37 +04:00
nsTableColFrame * colFrame ;
mTableFrame - > GetColumnFrame ( i , colFrame ) ;
nscoord minColWidth = colFrame - > GetMinColWidth ( ) ;
nscoord assignedColWidth = mTableFrame - > GetColumnWidth ( i ) ;
NS_ASSERTION ( assignedColWidth > = minColWidth , " illegal width assignment " ) ;
}
# endif
1998-07-17 03:23:31 +04:00
return result ;
}
// Step 1 - assign the width of all fixed-width columns, all other columns get there max,
// and calculate min/max table width
PRBool BasicTableLayoutStrategy : : AssignPreliminaryColumnWidths ( )
{
1999-04-04 03:02:43 +04:00
TDBG_SP ( " ** %p: AssignPreliminaryColumnWidths ** \n " , mTableFrame ) ;
nsVoidArray * spanList = nsnull ;
nsVoidArray * colSpanList = nsnull ;
1998-06-24 03:23:21 +04:00
1999-04-04 03:02:43 +04:00
PRBool hasColsAttribute = ( PRBool ) ( NS_STYLE_TABLE_COLS_NONE ! = mCols ) ;
1998-06-24 03:23:21 +04:00
1998-07-17 03:23:31 +04:00
PRInt32 * minColWidthArray = nsnull ; // used for computing the effect of COLS attribute
PRInt32 * maxColWidthArray = nsnull ; // used for computing the effect of COLS attribute
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = hasColsAttribute ) {
1998-06-24 03:23:21 +04:00
minColWidthArray = new PRInt32 [ mNumCols ] ;
maxColWidthArray = new PRInt32 [ mNumCols ] ;
}
1999-04-04 03:02:43 +04:00
nscoord cellPadding = mTableFrame - > GetCellPadding ( ) ;
TDBG_SD ( " table cell padding = %d \n " , cellPadding ) ;
1998-11-25 21:43:56 +03:00
1998-07-11 04:00:31 +04:00
PRInt32 numRows = mTableFrame - > GetRowCount ( ) ;
1998-08-01 06:31:55 +04:00
PRInt32 colIndex , rowIndex ;
1998-07-11 04:00:31 +04:00
1998-06-24 03:23:21 +04:00
// for every column, determine it's min and max width, and keep track of the table width
1999-04-04 03:02:43 +04:00
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
nscoord minColWidth = 0 ; // min col width factoring in table attributes
nscoord minColContentWidth = 0 ; // min width of the col's contents, does not take into account table attributes
nscoord maxColWidth = 0 ; // max col width factoring in table attributes
1998-07-17 03:23:31 +04:00
nscoord effectiveMinColumnWidth = 0 ; // min col width ignoring cells with colspans
nscoord effectiveMaxColumnWidth = 0 ; // max col width ignoring cells with colspans
1999-04-04 03:02:43 +04:00
nscoord specifiedFixedColWidth = 0 ; // the width of the column if given stylistically (or via cell Width attribute)
// only applicable if haveColWidth==PR_TRUE
PRBool haveColWidth = PR_FALSE ; // if true, the column has a width either from HTML width attribute,
// from a style rule on the column,
// or from a width attr/style on a cell that has colspan==1
1998-07-11 04:00:31 +04:00
// Get column information
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
TDBG_SDD ( " BTLS::APCW - got colFrame %p for colIndex %d \n " , colFrame , colIndex ) ;
NS_ASSERTION ( nsnull ! = colFrame , " bad col frame " ) ;
1998-04-30 21:57:09 +04:00
// Get the columns's style
1998-07-11 04:00:31 +04:00
const nsStylePosition * colPosition ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
1998-11-16 09:46:00 +03:00
const nsStyleTable * colTableStyle ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Table , ( const nsStyleStruct * & ) colTableStyle ) ;
1998-04-30 21:57:09 +04:00
1998-07-17 03:23:31 +04:00
// Get fixed column width if it has one
1999-04-04 03:02:43 +04:00
if ( eStyleUnit_Coord = = colPosition - > mWidth . GetUnit ( ) ) {
1998-07-17 03:23:31 +04:00
haveColWidth = PR_TRUE ;
specifiedFixedColWidth = colPosition - > mWidth . GetCoordValue ( ) ;
1998-11-25 21:43:56 +03:00
specifiedFixedColWidth + = ( cellPadding * 2 ) ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " BTLS::APCW - got specified col width = %d \n " , specifiedFixedColWidth ) ;
1998-04-30 21:57:09 +04:00
}
1998-07-17 03:23:31 +04:00
/* Scan the column, simulatneously assigning column widths
1998-04-30 21:57:09 +04:00
* and computing the min / max column widths
*/
1998-07-11 04:00:31 +04:00
PRInt32 firstRowIndex = - 1 ;
1998-07-17 03:23:31 +04:00
PRInt32 maxColSpan = 1 ;
1999-04-04 03:02:43 +04:00
PRBool cellGrantingWidth = PR_TRUE ;
for ( rowIndex = 0 ; rowIndex < numRows ; rowIndex + + ) {
nsTableCellFrame * cellFrame = mTableFrame - > GetCellFrameAt ( rowIndex , colIndex ) ;
if ( nsnull = = cellFrame ) { // there is no cell in this row that corresponds to this column
1998-07-11 04:00:31 +04:00
continue ;
}
1999-04-04 03:02:43 +04:00
if ( - 1 = = firstRowIndex ) {
1998-07-11 04:00:31 +04:00
firstRowIndex = rowIndex ;
1999-04-04 03:02:43 +04:00
}
1999-02-11 04:16:28 +03:00
PRInt32 cellRowIndex ;
cellFrame - > GetRowIndex ( cellRowIndex ) ;
1999-04-04 03:02:43 +04:00
if ( rowIndex ! = cellRowIndex ) {
1998-07-11 04:00:31 +04:00
// 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
1998-06-12 02:51:54 +04:00
continue ;
}
1998-07-17 03:23:31 +04:00
PRInt32 colSpan = mTableFrame - > GetEffectiveColSpan ( colIndex , cellFrame ) ;
1999-04-04 03:02:43 +04:00
maxColSpan = PR_MAX ( maxColSpan , colSpan ) ;
1999-02-11 04:16:28 +03:00
PRInt32 cellColIndex ;
cellFrame - > GetColIndex ( cellColIndex ) ;
1999-04-04 03:02:43 +04:00
if ( colIndex ! = cellColIndex ) {
1998-07-17 03:23:31 +04:00
// For cells that span cols, we figure in the row using previously-built SpanInfo
1998-09-01 01:23:28 +04:00
NS_ASSERTION ( 1 ! = cellFrame - > GetColSpan ( ) , " col index does not match col span " ) ; // sanity check
1998-07-11 04:00:31 +04:00
continue ;
}
nsSize cellMinSize = cellFrame - > GetPass1MaxElementSize ( ) ;
nsSize cellDesiredSize = cellFrame - > GetPass1DesiredSize ( ) ;
1998-07-22 07:53:43 +04:00
nscoord cellDesiredWidth = cellDesiredSize . width ;
1998-07-26 08:23:01 +04:00
nscoord cellMinWidth = cellMinSize . width ;
1998-08-04 00:27:59 +04:00
1999-04-04 03:02:43 +04:00
if ( 1 = = colSpan ) {
if ( 0 = = minColContentWidth ) {
1998-07-27 06:15:37 +04:00
minColContentWidth = cellMinWidth ;
1999-04-04 03:02:43 +04:00
}
else {
1998-07-27 06:15:37 +04:00
minColContentWidth = PR_MAX ( minColContentWidth , cellMinWidth ) ;
1999-04-04 03:02:43 +04:00
}
1998-07-27 06:15:37 +04:00
}
1999-04-04 03:02:43 +04:00
else {
1998-07-27 06:15:37 +04:00
minColContentWidth = PR_MAX ( minColContentWidth , cellMinWidth / colSpan ) ; // no need to divide this proportionately
1999-04-04 03:02:43 +04:00
}
TDBG_SDDDDDD ( " for cell %d with colspan=%d, min = %d,%d and des = %d,%d \n " ,
rowIndex , colSpan , cellMinSize . width , cellMinSize . height ,
cellDesiredSize . width , cellDesiredSize . height ) ;
if ( PR_TRUE = = haveColWidth ) {
// This col has a specified coord fixed width, so set the min and max width to the larger of
// (specified width, largest max_element_size of the cells in the column)
// factoring in the min width of the prior cells (stored in minColWidth)
1998-07-26 08:23:01 +04:00
nscoord widthForThisCell = specifiedFixedColWidth ;
1999-04-04 03:02:43 +04:00
if ( 0 = = specifiedFixedColWidth ) { // set to min
1998-07-26 08:23:01 +04:00
specifiedFixedColWidth = cellMinWidth ;
1999-04-04 03:02:43 +04:00
}
1998-07-27 11:20:03 +04:00
widthForThisCell = PR_MAX ( widthForThisCell , effectiveMinColumnWidth ) ;
1999-04-04 03:02:43 +04:00
if ( 1 = = colSpan ) {
1998-07-27 11:20:03 +04:00
widthForThisCell = PR_MAX ( widthForThisCell , cellMinWidth ) ;
1999-04-04 03:02:43 +04:00
}
1998-07-17 03:23:31 +04:00
mTableFrame - > SetColumnWidth ( colIndex , widthForThisCell ) ;
maxColWidth = widthForThisCell ;
1998-07-27 06:15:37 +04:00
minColWidth = PR_MAX ( minColWidth , cellMinWidth ) ;
1999-04-04 03:02:43 +04:00
if ( 1 = = colSpan ) {
1998-07-26 08:23:01 +04:00
effectiveMaxColumnWidth = PR_MAX ( effectiveMaxColumnWidth , widthForThisCell ) ;
1999-04-04 03:02:43 +04:00
if ( 0 = = effectiveMinColumnWidth ) {
1998-07-27 06:15:37 +04:00
effectiveMinColumnWidth = cellMinWidth ; //widthForThisCell;
1999-04-04 03:02:43 +04:00
}
else {
1998-07-27 06:15:37 +04:00
//effectiveMinColumnWidth = PR_MIN(effectiveMinColumnWidth, widthForThisCell);
1999-04-04 03:02:43 +04:00
//above line works for most tables, but it can't be right
effectiveMinColumnWidth = PR_MAX ( effectiveMinColumnWidth , cellMinWidth ) ;
//above line seems right and works for xT1, but breaks lots of other tables.
}
1998-07-26 08:23:01 +04:00
}
1998-07-17 03:23:31 +04:00
}
1999-04-04 03:02:43 +04:00
else {
if ( maxColWidth < cellDesiredWidth ) {
1998-07-17 03:23:31 +04:00
maxColWidth = cellDesiredWidth ;
1999-04-04 03:02:43 +04:00
}
if ( ( 1 = = colSpan ) & & ( effectiveMaxColumnWidth < cellDesiredWidth ) ) {
1998-07-17 03:23:31 +04:00
effectiveMaxColumnWidth = cellDesiredWidth ;
1999-04-04 03:02:43 +04:00
}
if ( minColWidth < cellMinWidth ) {
1998-07-26 08:23:01 +04:00
minColWidth = cellMinWidth ;
1999-04-04 03:02:43 +04:00
}
1998-07-26 08:23:01 +04:00
// effectiveMinColumnWidth is the min width as if no cells with colspans existed
1999-04-04 03:02:43 +04:00
if ( ( 1 = = colSpan ) & & ( effectiveMinColumnWidth < cellMinWidth ) ) {
1998-07-26 08:23:01 +04:00
effectiveMinColumnWidth = cellMinWidth ;
1999-04-04 03:02:43 +04:00
}
1998-04-30 21:57:09 +04:00
}
1999-04-04 03:02:43 +04:00
if ( 1 < colSpan ) {
1998-07-22 07:53:43 +04:00
// add the column to our list of post-process columns, if all of the intersected columns are auto
PRBool okToAdd = PR_TRUE ;
1999-04-04 03:02:43 +04:00
if ( numRows = = 1 | | ( PR_FALSE = = IsFixedWidth ( colPosition , colTableStyle ) ) ) {
1998-07-22 07:53:43 +04:00
okToAdd = PR_FALSE ;
1999-04-04 03:02:43 +04:00
}
else {
for ( PRInt32 i = 1 ; i < colSpan ; i + + ) {
nsTableColFrame * cf ;
1998-07-22 07:53:43 +04:00
mTableFrame - > GetColumnFrame ( i + colIndex , cf ) ;
const nsStylePosition * colPos ;
1998-11-20 12:29:58 +03:00
cf - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPos ) ;
1998-08-19 19:43:51 +04:00
if ( colPos - > mWidth . GetUnit ( ) ! = eStyleUnit_Auto & &
1999-04-04 03:02:43 +04:00
( nsTableColFrame : : eWIDTH_SOURCE_CELL_WITH_SPAN ! = cf - > GetWidthSource ( ) ) ) {
1998-07-22 07:53:43 +04:00
okToAdd = PR_FALSE ;
break ;
}
}
}
1998-08-19 19:43:51 +04:00
nscoord width = cellDesiredSize . width ; // used below as the cell's "natural" width
1999-04-04 03:02:43 +04:00
if ( eStyleUnit_Coord = = colTableStyle - > mSpanWidth . GetUnit ( ) ) {
width = colSpan * colTableStyle - > mSpanWidth . GetCoordValue ( ) ; // "colSpan*" because table frame divided per column spanned
}
if ( PR_TRUE = = okToAdd ) {
nscoord colwidth = PR_MAX ( width , cellMinWidth ) ;
ColSpanStruct * colSpanInfo = new ColSpanStruct ( colSpan , colIndex , colwidth ) ;
if ( nsnull = = colSpanList ) {
1998-07-22 07:53:43 +04:00
colSpanList = new nsVoidArray ( ) ;
1999-04-04 03:02:43 +04:00
}
1998-07-22 07:53:43 +04:00
colSpanList - > AppendElement ( colSpanInfo ) ;
}
1998-07-11 04:00:31 +04:00
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = cellGrantingWidth ) {
1998-08-19 19:43:51 +04:00
// add the cell to our list of spanning cells
1999-04-04 03:02:43 +04:00
SpanInfo * spanInfo = new SpanInfo ( colIndex , colSpan , cellMinWidth , width ) ;
if ( nsnull = = spanList ) {
1998-08-19 19:43:51 +04:00
spanList = new nsVoidArray ( ) ;
1999-04-04 03:02:43 +04:00
}
1998-08-19 19:43:51 +04:00
spanList - > AppendElement ( spanInfo ) ;
}
1998-04-30 21:57:09 +04:00
}
1998-08-19 19:43:51 +04:00
1999-04-04 03:02:43 +04:00
// bookkeeping: is this the cell that gave the column it's fixed width attribute?
1998-08-19 19:43:51 +04:00
// must be done after "haveColWidth && cellGrantingWidth" used above
1999-04-04 03:02:43 +04:00
// since we want the biggest, I don't think this is valid anymore
// it made sense when the rule was to grab the first cell that contributed a width
//if (PR_TRUE==cellGrantingWidth)
//{
// const nsStylePosition* cellPosition;
// cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
// if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
// cellGrantingWidth=PR_FALSE; //I've found the cell that gave the col it's width
//}
1998-08-19 19:43:51 +04:00
// book 'em, Danno
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " after cell %d, minColWidth = %d and maxColWidth = %d \n " ,
1998-07-11 04:00:31 +04:00
rowIndex , minColWidth , maxColWidth ) ;
1999-04-04 03:02:43 +04:00
} // end for (rowIndex = 0; rowIndex < numRows; rowIndex++)
1998-04-30 21:57:09 +04:00
1998-07-24 07:53:59 +04:00
// adjust the "fixed" width for content that is too wide
1999-04-04 03:02:43 +04:00
if ( effectiveMinColumnWidth > specifiedFixedColWidth ) {
specifiedFixedColWidth = effectiveMinColumnWidth ;
}
1998-07-11 04:00:31 +04:00
// do all the global bookkeeping, factoring in margins
1998-12-09 09:37:18 +03:00
nscoord colInset = mTableFrame - > GetCellSpacingX ( ) ;
1998-06-02 00:21:05 +04:00
// keep a running total of the amount of space taken up by all fixed-width columns
1999-04-04 03:02:43 +04:00
if ( ( PR_TRUE = = haveColWidth ) & &
( nsTableColFrame : : eWIDTH_SOURCE_CELL = = colFrame - > GetWidthSource ( ) ) ) {
1998-07-23 00:06:31 +04:00
mFixedTableWidth + = specifiedFixedColWidth + colInset ;
1999-04-04 03:02:43 +04:00
if ( 0 = = colIndex ) {
1998-07-22 07:53:43 +04:00
mFixedTableWidth + = colInset ;
1999-04-04 03:02:43 +04:00
}
TDBG_SD ( " setting mFixedTableWidth=%d \n " , mFixedTableWidth ) ;
1998-07-22 07:53:43 +04:00
}
1998-07-17 03:23:31 +04:00
// cache the computed column info
1998-07-22 07:53:43 +04:00
colFrame - > SetMinColWidth ( effectiveMinColumnWidth ) ;
colFrame - > SetMaxColWidth ( effectiveMaxColumnWidth ) ;
1998-07-17 03:23:31 +04:00
colFrame - > SetEffectiveMinColWidth ( effectiveMinColumnWidth ) ;
colFrame - > SetEffectiveMaxColWidth ( effectiveMaxColumnWidth ) ;
1998-08-01 06:31:55 +04:00
// this is the default, the real adjustment happens below where we deal with colspans
colFrame - > SetAdjustedMinColWidth ( effectiveMinColumnWidth ) ;
1999-04-04 03:02:43 +04:00
if ( ( PR_TRUE = = haveColWidth ) & &
( nsTableColFrame : : eWIDTH_SOURCE_CELL_WITH_SPAN ! = colFrame - > GetWidthSource ( ) ) ) {
1998-07-23 00:06:31 +04:00
mTableFrame - > SetColumnWidth ( colIndex , specifiedFixedColWidth ) ;
1999-04-04 03:02:43 +04:00
}
else {
1998-07-23 00:06:31 +04:00
mTableFrame - > SetColumnWidth ( colIndex , effectiveMaxColumnWidth ) ;
1999-04-04 03:02:43 +04:00
}
TDBG_SDD ( " col %d, set col width to = %d \n " , colIndex , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-07-17 03:23:31 +04:00
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = hasColsAttribute ) {
1998-06-24 03:23:21 +04:00
minColWidthArray [ colIndex ] = minColWidth ;
maxColWidthArray [ colIndex ] = maxColWidth ;
}
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " after col %d, minColWidth=%d effectiveMinColumnWidth=%d \n \t effectiveMaxColumnWidth = %d \n " ,
colIndex , minColWidth , effectiveMinColumnWidth , effectiveMaxColumnWidth ) ;
1998-07-17 03:23:31 +04:00
}
1998-06-24 03:23:21 +04:00
// now, post-process the computed values based on the table attributes
1998-07-22 07:53:43 +04:00
1998-07-31 04:31:09 +04:00
// first, factor in max values of spanning cells proportionately.
1998-07-22 07:53:43 +04:00
// We can't do this above in the first loop, because we don't have enough information
// to determine the proportion each column gets from spanners.
1999-04-04 03:02:43 +04:00
if ( nsnull ! = spanList ) {
1998-08-07 06:11:51 +04:00
// we only want to do this if there are auto-cells involved
1998-08-19 19:43:51 +04:00
// or if we have columns that are provisionally fixed-width with colspans
1998-08-07 06:11:51 +04:00
PRInt32 numAutoColumns = 0 ;
1999-04-04 03:02:43 +04:00
PRInt32 * autoColumns = nsnull ;
1998-08-07 06:11:51 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Auto , numAutoColumns , autoColumns ) ;
1998-11-16 09:46:00 +03:00
// for every column, handle spanning cells that impact that column
1999-04-04 03:02:43 +04:00
for ( PRInt32 colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
TDBG_SD ( " handling span for %d \n " , colIndex ) ;
1998-07-22 07:53:43 +04:00
PRInt32 spanCount = spanList - > Count ( ) ;
// go through the list backwards so we can delete easily
1999-04-04 03:02:43 +04:00
for ( PRInt32 spanIndex = spanCount - 1 ; 0 < = spanIndex ; spanIndex - - ) {
// get each spanInfo struct and see if it impacts this column
1998-07-22 07:53:43 +04:00
SpanInfo * spanInfo = ( SpanInfo * ) ( spanList - > ElementAt ( spanIndex ) ) ;
1998-11-16 09:46:00 +03:00
// if the spanInfo is about a column before the current column, it effects
// the current column (otherwise it would have already been deleted.)
1999-04-04 03:02:43 +04:00
if ( spanInfo - > initialColIndex < = colIndex ) {
if ( - 1 = = spanInfo - > effectiveMaxWidthOfSpannedCols ) {
// if we have not yet computed effectiveMaxWidthOfSpannedCols, do it now
1998-11-16 09:46:00 +03:00
// first, initialize the sums
1999-04-04 03:02:43 +04:00
spanInfo - > effectiveMaxWidthOfSpannedCols = 0 ;
spanInfo - > effectiveMinWidthOfSpannedCols = 0 ;
1998-11-16 09:46:00 +03:00
// then compute the sums
1999-04-04 03:02:43 +04:00
for ( PRInt32 span = 0 ; span < spanInfo - > initialColSpan ; span + + ) {
nsTableColFrame * nextColFrame = mTableFrame - > GetColFrame ( colIndex + span ) ;
if ( nsnull = = nextColFrame ) {
1998-11-16 09:46:00 +03:00
break ;
1999-04-04 03:02:43 +04:00
}
1998-11-16 09:46:00 +03:00
spanInfo - > effectiveMaxWidthOfSpannedCols + = nextColFrame - > GetEffectiveMaxColWidth ( ) ;
spanInfo - > effectiveMinWidthOfSpannedCols + = nextColFrame - > GetEffectiveMinColWidth ( ) ;
1998-10-23 23:56:11 +04:00
}
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " effective min total = %d, max total = %d \n " ,
spanInfo - > effectiveMinWidthOfSpannedCols , spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
1998-11-16 09:46:00 +03:00
}
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
1998-11-16 09:46:00 +03:00
nscoord colMinWidth = colFrame - > GetMinColWidth ( ) ;
// compute the spanning cell's contribution to the column min width
// this is the "adjusted" column width, used in SetTableToMinWidth
nscoord spanCellMinWidth ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = spanInfo - > effectiveMinWidthOfSpannedCols ) {
1998-11-16 09:46:00 +03:00
float percent = ( ( float ) ( colFrame - > GetEffectiveMinColWidth ( ) ) ) /
1999-04-04 03:02:43 +04:00
( ( float ) ( spanInfo - > effectiveMinWidthOfSpannedCols ) ) ;
1998-11-16 09:46:00 +03:00
spanCellMinWidth = NSToCoordRound ( ( ( float ) ( spanInfo - > cellMinWidth ) ) * percent ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDFDDD ( " spanCellMinWidth portion = %d from percent=%f, cellMW=%d, effMinColW=%d, sum=%d \n " ,
spanCellMinWidth , percent , spanInfo - > cellMinWidth , colFrame - > GetEffectiveMinColWidth ( ) ,
spanInfo - > effectiveMinWidthOfSpannedCols ) ;
if ( colMinWidth < spanCellMinWidth ) {
colFrame - > SetAdjustedMinColWidth ( spanCellMinWidth ) ; // set the new min width for the col
}
1998-11-16 09:46:00 +03:00
}
1999-04-04 03:02:43 +04:00
else {
spanCellMinWidth = spanInfo - > cellMinWidth / spanInfo - > initialColSpan ;
if ( colMinWidth < spanCellMinWidth ) {
1998-11-16 09:46:00 +03:00
colFrame - > SetAdjustedMinColWidth ( spanCellMinWidth ) ;
1998-10-23 23:56:11 +04:00
}
1998-11-16 09:46:00 +03:00
}
1998-08-01 06:31:55 +04:00
1998-11-16 09:46:00 +03:00
// compute the spanning cell's contribution to the column max width
nscoord colMaxWidth = colFrame - > GetMaxColWidth ( ) ;
nscoord spanCellMaxWidth ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = spanInfo - > effectiveMaxWidthOfSpannedCols ) {
1998-11-16 09:46:00 +03:00
float percent = ( ( float ) ( colFrame - > GetEffectiveMaxColWidth ( ) ) ) /
1999-04-04 03:02:43 +04:00
( ( float ) ( spanInfo - > effectiveMaxWidthOfSpannedCols ) ) ;
1998-11-16 09:46:00 +03:00
spanCellMaxWidth = NSToCoordRound ( ( ( float ) ( spanInfo - > cellDesiredWidth ) ) * percent ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDFDDD ( " spanCellMaxWidth portion = %d with percent = %f from cellDW = %d, effMaxColW=%d and sum=%d \n " ,
spanCellMaxWidth , percent , spanInfo - > cellDesiredWidth , colFrame - > GetEffectiveMaxColWidth ( ) ,
spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
if ( colMaxWidth < spanCellMaxWidth ) {
1998-11-16 09:46:00 +03:00
// make sure we're at least as big as our min
spanCellMaxWidth = PR_MAX ( spanCellMaxWidth , colMinWidth ) ;
colFrame - > SetMaxColWidth ( spanCellMaxWidth ) ; // set the new max width for the col
mTableFrame - > SetColumnWidth ( colIndex , spanCellMaxWidth ) ; // set the column to the new desired max width
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " for spanning cell into col %d with remaining span=%d, old max = %d, new max = %d \n " ,
colIndex , spanInfo - > span , colMaxWidth , spanCellMaxWidth ) ;
1998-08-07 06:11:51 +04:00
}
1998-11-16 09:46:00 +03:00
}
1999-04-04 03:02:43 +04:00
else {
spanCellMaxWidth = spanInfo - > cellDesiredWidth / spanInfo - > initialColSpan ;
1998-11-16 09:46:00 +03:00
nscoord minColWidth = colFrame - > GetMinColWidth ( ) ;
spanCellMaxWidth = PR_MAX ( spanCellMaxWidth , minColWidth ) ;
colFrame - > SetMaxColWidth ( spanCellMaxWidth ) ;
mTableFrame - > SetColumnWidth ( colIndex , spanCellMaxWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " for spanning cell into col %d with remaining span=%d, old max = %d, new max = %d \n " ,
colIndex , spanInfo - > span , colMaxWidth , spanCellMaxWidth ) ;
1998-11-16 09:46:00 +03:00
}
1998-07-22 07:53:43 +04:00
1998-11-16 09:46:00 +03:00
spanInfo - > span - - ;
1999-04-04 03:02:43 +04:00
if ( 0 = = spanInfo - > span ) {
1998-11-16 09:46:00 +03:00
spanList - > RemoveElementAt ( spanIndex ) ;
delete spanInfo ;
1998-07-22 07:53:43 +04:00
}
1998-11-30 22:06:33 +03:00
// begin code that respects column width attribute
/* the code below checks to see if the column has a width attribute (either it's own or a cell's)
* if so , if it fits within the constraints we computed above , we use it .
* why go through all that pain above , then ? because the given width attribute might not
* be rational . So we need to act as if it doesn ' t exist and then fit it in if it makes sense .
* a shortcut that checks for a column width attribute and skips the above computations
* would not work without lots of extra computation that would lead you down the same path anyway .
*/
const nsStylePosition * colPosition ;
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
// Get fixed column width if it has one
1999-04-04 03:02:43 +04:00
if ( eStyleUnit_Coord = = colPosition - > mWidth . GetUnit ( ) ) {
if ( nsTableColFrame : : eWIDTH_SOURCE_CELL_WITH_SPAN ! = colFrame - > GetWidthSource ( ) ) {
1998-11-30 22:06:33 +03:00
nscoord specifiedFixedColWidth = colPosition - > mWidth . GetCoordValue ( ) ;
specifiedFixedColWidth + = ( cellPadding * 2 ) ;
1999-04-04 03:02:43 +04:00
if ( specifiedFixedColWidth > = colFrame - > GetEffectiveMinColWidth ( ) ) {
1998-11-30 22:06:33 +03:00
mTableFrame - > SetColumnWidth ( colIndex , specifiedFixedColWidth ) ;
colFrame - > SetMaxColWidth ( specifiedFixedColWidth ) ;
}
}
}
// end code that respects column width attribute
1998-07-22 07:53:43 +04:00
}
}
}
}
1998-08-01 06:31:55 +04:00
// now set the min and max table widths
SetMinAndMaxTableWidths ( ) ;
1998-07-22 07:53:43 +04:00
1998-08-01 06:31:55 +04:00
// then, handle the COLS attribute (equal column widths)
1998-07-17 03:23:31 +04:00
// if there is a COLS attribute, fix up mMinTableWidth and mMaxTableWidth
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = hasColsAttribute ) {
TDBG_SD ( " has COLS attribute = %d \n " , mCols ) ;
1998-06-24 03:23:21 +04:00
// for every effected column, subtract out its prior contribution and add back in the new value
PRInt32 numColsEffected = mNumCols ;
1999-04-04 03:02:43 +04:00
if ( NS_STYLE_TABLE_COLS_ALL ! = mCols ) {
1998-06-24 03:23:21 +04:00
numColsEffected = mCols ;
1999-04-04 03:02:43 +04:00
}
PRInt32 maxOfMinColWidths = 0 ;
PRInt32 maxOfMaxColWidths = 0 ;
1998-06-27 06:49:36 +04:00
PRInt32 effectedColIndex ;
1999-04-04 03:02:43 +04:00
for ( effectedColIndex = 0 ; effectedColIndex < numColsEffected ; effectedColIndex + + ) {
maxOfMinColWidths = PR_MAX ( maxOfMinColWidths , minColWidthArray [ effectedColIndex ] ) ;
maxOfMaxColWidths = PR_MAX ( maxOfMaxColWidths , maxColWidthArray [ effectedColIndex ] ) ;
1998-06-24 03:23:21 +04:00
}
1999-04-04 03:02:43 +04:00
for ( effectedColIndex = 0 ; effectedColIndex < numColsEffected ; effectedColIndex + + ) {
1998-06-24 03:23:21 +04:00
// subtract out the prior contributions of this column
// and add back in the adjusted value
1999-04-04 03:02:43 +04:00
if ( NS_UNCONSTRAINEDSIZE ! = mMinTableWidth ) {
1998-07-17 03:23:31 +04:00
mMinTableWidth - = minColWidthArray [ effectedColIndex ] ;
mMinTableWidth + = maxOfMinColWidths ;
1998-06-24 03:23:21 +04:00
}
1999-04-04 03:02:43 +04:00
if ( NS_UNCONSTRAINEDSIZE ! = mMaxTableWidth ) {
1998-07-17 03:23:31 +04:00
mMaxTableWidth - = maxColWidthArray [ effectedColIndex ] ;
mMaxTableWidth + = maxOfMaxColWidths ;
1998-06-24 03:23:21 +04:00
}
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
1998-07-17 03:23:31 +04:00
mTableFrame - > GetColumnFrame ( effectedColIndex , colFrame ) ;
colFrame - > SetMaxColWidth ( maxOfMaxColWidths ) ; // cache the new column max width (min width is uneffected)
colFrame - > SetEffectiveMaxColWidth ( maxOfMaxColWidths ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " col %d now has max col width %d \n " , effectedColIndex , maxOfMaxColWidths ) ;
1998-06-24 03:23:21 +04:00
}
delete [ ] minColWidthArray ;
delete [ ] maxColWidthArray ;
}
1999-04-04 03:02:43 +04:00
if ( nsnull ! = colSpanList ) {
1998-07-17 03:23:31 +04:00
DistributeFixedSpace ( colSpanList ) ;
1999-04-04 03:02:43 +04:00
}
1998-06-24 03:23:21 +04:00
1999-04-04 03:02:43 +04:00
TDBG_SPDD ( " %p: aMinTW=%d, aMaxTW=%d \n " , mTableFrame , mMinTableWidth , mMaxTableWidth ) ;
1998-07-17 03:23:31 +04:00
// clean up
1999-04-04 03:02:43 +04:00
if ( nsnull ! = spanList ) {
TDBG_S ( " BTLS::APCW...space leak, span list not empty \n " ) ;
1998-04-30 21:57:09 +04:00
delete spanList ;
1998-07-18 01:02:28 +04:00
}
1999-04-04 03:02:43 +04:00
if ( nsnull ! = colSpanList ) {
1998-07-13 22:11:12 +04:00
PRInt32 colSpanListCount = colSpanList - > Count ( ) ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 i = 0 ; i < colSpanListCount ; i + + ) {
1998-07-13 22:11:12 +04:00
ColSpanStruct * colSpanInfo = ( ColSpanStruct * ) ( colSpanList - > ElementAt ( i ) ) ;
1999-04-04 03:02:43 +04:00
if ( nsnull ! = colSpanInfo ) {
1998-07-13 22:11:12 +04:00
delete colSpanInfo ;
1999-04-04 03:02:43 +04:00
}
1998-07-13 22:11:12 +04:00
}
1998-07-11 04:00:31 +04:00
delete colSpanList ;
1998-07-13 22:11:12 +04:00
}
1998-04-30 21:57:09 +04:00
return PR_TRUE ;
}
1998-08-01 06:31:55 +04:00
void BasicTableLayoutStrategy : : SetMinAndMaxTableWidths ( )
{
1999-04-04 03:02:43 +04:00
TDBG_S ( " SetMinAndMaxTableWidths \n " ) ;
1998-08-01 06:31:55 +04:00
PRInt32 colIndex , rowIndex ;
PRInt32 numRows = mTableFrame - > GetRowCount ( ) ;
1998-12-09 09:37:18 +03:00
nscoord colInset = mTableFrame - > GetCellSpacingX ( ) ;
1999-04-04 03:02:43 +04:00
for ( rowIndex = 0 ; rowIndex < numRows ; rowIndex + + ) {
TDBG_SD ( " row %d \n " , rowIndex ) ;
1998-08-01 06:31:55 +04:00
nscoord rowMinWidth = colInset ;
nscoord rowMaxWidth = colInset ;
1999-04-04 03:02:43 +04:00
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
TDBG_SD ( " col %d \n " , colIndex ) ;
nsTableCellFrame * cellFrame = mTableFrame - > GetCellFrameAt ( rowIndex , colIndex ) ;
1998-08-01 06:31:55 +04:00
rowMinWidth + = colInset ;
rowMaxWidth + = colInset ;
1999-04-04 03:02:43 +04:00
if ( nsnull = = cellFrame ) { // there is no cell in this row that corresponds to this column
TDBG_SD ( " col %d skipped because there is no cell \n " , colIndex ) ;
1998-08-01 06:31:55 +04:00
continue ;
}
1999-02-11 04:16:28 +03:00
PRInt32 cellColIndex ;
cellFrame - > GetColIndex ( cellColIndex ) ;
1999-04-04 03:02:43 +04:00
if ( colIndex ! = cellColIndex ) {
1998-08-01 06:31:55 +04:00
// For cells that span cols, we figured in the cell the first time we saw it
1999-04-04 03:02:43 +04:00
TDBG_SD ( " col %d skipped because it has colspan so we've already added it in \n " , colIndex ) ;
1998-08-01 06:31:55 +04:00
continue ;
}
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
1998-08-01 06:31:55 +04:00
nsSize cellMinSize = cellFrame - > GetPass1MaxElementSize ( ) ;
1998-09-10 00:00:40 +04:00
nscoord cellMinWidth = PR_MAX ( cellMinSize . width , colFrame - > GetEffectiveMinColWidth ( ) ) ;
1998-08-01 06:31:55 +04:00
nsSize cellMaxSize = cellFrame - > GetPass1DesiredSize ( ) ;
1998-09-10 00:00:40 +04:00
nscoord cellMaxWidth = PR_MAX ( cellMaxSize . width , colFrame - > GetEffectiveMaxColWidth ( ) ) ;
PRInt32 colSpan = mTableFrame - > GetEffectiveColSpan ( colIndex , cellFrame ) ;
nscoord spanningCellMinWidth = ( colSpan - 1 ) * colInset ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " cellMin=%d, cellMax=%d, spanningCellMin=%d \n " ,
cellMinWidth , cellMaxWidth , spanningCellMinWidth ) ;
1998-09-10 00:00:40 +04:00
// spanning cells must be at least as wide as the columns they span, including the cell spacing spanned.
1999-04-04 03:02:43 +04:00
if ( NS_UNCONSTRAINEDSIZE ! = rowMinWidth ) {
1998-09-10 00:00:40 +04:00
rowMinWidth + = PR_MAX ( cellMinWidth , spanningCellMinWidth ) ;
1999-04-04 03:02:43 +04:00
}
if ( NS_UNCONSTRAINEDSIZE ! = rowMaxWidth ) {
1998-09-10 00:00:40 +04:00
rowMaxWidth + = PR_MAX ( cellMaxWidth , spanningCellMinWidth ) ;
1999-04-04 03:02:43 +04:00
}
TDBG_SDD ( " rowMinWidth=%d, rowMaxWidth=%d \n " , rowMinWidth , rowMaxWidth ) ;
1998-08-01 06:31:55 +04:00
}
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " rowMinWidth=%d, rowMaxWidth=%d \n " , rowMinWidth , rowMaxWidth ) ;
1998-08-01 06:31:55 +04:00
// the largest row widths are the table widths
mMinTableWidth = PR_MAX ( mMinTableWidth , rowMinWidth ) ;
mMaxTableWidth = PR_MAX ( mMaxTableWidth , rowMaxWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " mMinTableWidth=%d, mMaxTableWidth=%d \n " , mMinTableWidth , mMaxTableWidth ) ;
1998-08-01 06:31:55 +04:00
}
// verify max of min row widths vs. sum of adjusted column min widths. bigger one wins
1999-04-04 03:02:43 +04:00
nscoord sumOfAdjustedColMinWidths = colInset ;
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
nsTableColFrame * colFrame ;
1998-08-01 06:31:55 +04:00
mTableFrame - > GetColumnFrame ( colIndex , colFrame ) ;
sumOfAdjustedColMinWidths + = colFrame - > GetAdjustedMinColWidth ( ) + colInset ;
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " col %d has amcw=%d, cellspacing=%d, sum=%d \n " ,
colIndex , colFrame - > GetAdjustedMinColWidth ( ) , colInset , sumOfAdjustedColMinWidths ) ;
1998-08-01 06:31:55 +04:00
}
1999-04-04 03:02:43 +04:00
TDBG_SD ( " sumOfAdjustedColMinWidths=%d \n " , sumOfAdjustedColMinWidths ) ;
1998-09-10 00:00:40 +04:00
/*
1998-08-01 06:31:55 +04:00
mMinTableWidth = PR_MAX ( mMinTableWidth , sumOfAdjustedColMinWidths ) ;
1998-09-10 00:00:40 +04:00
mMaxTableWidth = PR_MAX ( mMinTableWidth , mMaxTableWidth ) ;
*/
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " end SetMinAndMaxTW: minTW=%d, maxTW=%d with DMCW=%d \n " , mMinTableWidth , mMaxTableWidth , sumOfAdjustedColMinWidths ) ;
1998-08-01 06:31:55 +04:00
}
1998-07-11 04:00:31 +04:00
// take the fixed space spanned by the columns in aColSpanList
// and distribute it proportionately (based on desired width)
1998-07-17 03:23:31 +04:00
void BasicTableLayoutStrategy : : DistributeFixedSpace ( nsVoidArray * aColSpanList )
1998-07-11 04:00:31 +04:00
{
nscoord excess = 0 ;
1999-04-04 03:02:43 +04:00
TDBG_S ( " ** DistributeFixedSpace: \n " ) ;
1998-07-11 04:00:31 +04:00
// for all fixed-width columns, determine the amount of the specified width each column spanned recieves
PRInt32 numSpanningCells = aColSpanList - > Count ( ) ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 nextSpanningCell = 0 ; nextSpanningCell < numSpanningCells ; nextSpanningCell + + ) { // proportionately distributed extra space, based on the column's fixed width
ColSpanStruct * colInfo = ( ColSpanStruct * ) aColSpanList - > ElementAt ( nextSpanningCell ) ;
1998-07-11 04:00:31 +04:00
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 ;
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
1998-07-11 04:00:31 +04:00
PRInt32 i ;
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < colSpan ; i + + ) {
1998-07-17 03:23:31 +04:00
mTableFrame - > GetColumnFrame ( colIndex + i , colFrame ) ;
1998-11-16 09:46:00 +03:00
totalEffectiveWidth + = colFrame - > GetColWidthForComputation ( ) ;
1998-07-11 04:00:31 +04:00
}
// 2. next, compute the proportion to be added to each column, and add it
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < colSpan ; i + + ) {
1998-07-17 03:23:31 +04:00
mTableFrame - > GetColumnFrame ( colIndex + i , colFrame ) ;
1998-07-11 04:00:31 +04:00
float percent ;
1999-04-04 03:02:43 +04:00
percent = ( ( float ) ( colFrame - > GetColWidthForComputation ( ) ) ) / ( ( float ) totalEffectiveWidth ) ;
1998-11-03 01:19:17 +03:00
nscoord newColWidth = NSToCoordRound ( ( ( float ) totalColWidth ) * percent ) ;
1998-07-28 04:23:01 +04:00
nscoord minColWidth = colFrame - > GetEffectiveMinColWidth ( ) ;
nscoord oldColWidth = mTableFrame - > GetColumnWidth ( colIndex + i ) ;
1999-04-04 03:02:43 +04:00
if ( newColWidth > minColWidth ) {
TDBG_SDD_SDD ( " assigning fixed col width for spanning cells: column %d set to %d \n " ,
colIndex + i , newColWidth ,
" minCW = %d oldCW = %d \n " , minColWidth , oldColWidth ) ;
1998-07-28 04:23:01 +04:00
mTableFrame - > SetColumnWidth ( colIndex + i , newColWidth ) ;
colFrame - > SetEffectiveMaxColWidth ( newColWidth ) ;
}
1998-07-11 04:00:31 +04:00
}
}
}
1998-07-17 03:23:31 +04:00
/* assign column widths to all non-fixed-width columns (adjusting fixed-width columns if absolutely necessary)
aAvailWidth is the amount of space left in the table to distribute after fixed - width columns are accounted for
aMaxWidth is the space the parent gave us ( minus border & padding ) to fit ourselves into
aTableIsAutoWidth is true if the table is auto - width , false if it is anything else ( percent , fixed , etc )
*/
1999-04-04 03:02:43 +04:00
PRBool BasicTableLayoutStrategy : :
BalanceProportionalColumns ( const nsHTMLReflowState & aReflowState ,
nscoord aAvailWidth ,
nscoord aMaxWidth ,
nscoord aTableSpecifiedWidth ,
PRBool aTableIsAutoWidth )
1998-04-30 21:57:09 +04:00
{
PRBool result = PR_TRUE ;
1998-07-17 03:23:31 +04:00
nscoord actualMaxWidth ; // the real target width, depends on if we're auto or specified width
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = aTableIsAutoWidth ) {
1998-07-17 03:23:31 +04:00
actualMaxWidth = aMaxWidth ;
1999-04-04 03:02:43 +04:00
} else {
1998-09-08 23:11:14 +04:00
actualMaxWidth = PR_MIN ( aMaxWidth , aTableSpecifiedWidth ) ;
1999-04-04 03:02:43 +04:00
}
if ( NS_UNCONSTRAINEDSIZE = = aMaxWidth | | NS_UNCONSTRAINEDSIZE = = mMinTableWidth ) {
// the max width of the table fits comfortably in the available space
TDBG_S ( " * table laying out in NS_UNCONSTRAINEDSIZE, calling BalanceColumnsTableFits \n " ) ;
1999-01-07 05:16:10 +03:00
// nested tables are laid out with unconstrained width. But the underlying algorithms require a
// real width. So we pick a really big width here. It doesn't really matter, of course, because
// eventually the table will be laid out with a constrained width.
1998-08-18 03:37:04 +04:00
nscoord bigSpace = gBigSpace ;
1998-08-14 20:16:43 +04:00
bigSpace = PR_MAX ( bigSpace , mMaxTableWidth ) ;
1999-04-04 03:02:43 +04:00
result = BalanceColumnsTableFits ( aReflowState , bigSpace , bigSpace ,
aTableSpecifiedWidth , aTableIsAutoWidth ) ;
1998-07-17 03:23:31 +04:00
}
1999-04-04 03:02:43 +04:00
else if ( mMinTableWidth > actualMaxWidth ) {
// the table doesn't fit in the available space
TDBG_S ( " * table minTW does not fit, calling BalanceColumnsTableDoesNotFit \n " ) ;
1998-10-23 23:56:11 +04:00
result = BalanceColumnsTableDoesNotFit ( ) ;
1998-07-17 03:23:31 +04:00
}
1999-04-04 03:02:43 +04:00
else if ( mMaxTableWidth < = actualMaxWidth ) {
// the max width of the table fits comfortably in the available space
TDBG_S ( " * table desired size fits, calling BalanceColumnsTableFits \n " ) ;
result = BalanceColumnsTableFits ( aReflowState , aAvailWidth , aMaxWidth ,
aTableSpecifiedWidth , aTableIsAutoWidth ) ;
1998-04-30 21:57:09 +04:00
}
1999-04-04 03:02:43 +04:00
else {
// the table fits somewhere between its min and desired size
TDBG_S ( " * table desired size does not fit, calling BalanceColumnsConstrained \n " ) ;
1998-07-17 03:23:31 +04:00
result = BalanceColumnsConstrained ( aReflowState , aAvailWidth ,
1998-08-02 00:31:40 +04:00
actualMaxWidth , aTableIsAutoWidth ) ;
1998-04-30 21:57:09 +04:00
}
1998-07-17 03:23:31 +04:00
1998-04-30 21:57:09 +04:00
return result ;
}
1998-07-17 03:23:31 +04:00
// the table doesn't fit, so squeeze every column down to its minimum
1998-10-23 23:56:11 +04:00
PRBool BasicTableLayoutStrategy : : BalanceColumnsTableDoesNotFit ( )
1998-04-30 21:57:09 +04:00
{
PRBool result = PR_TRUE ;
1998-06-24 03:23:21 +04:00
PRBool hasColsAttribute = ( PRBool ) ( NS_STYLE_TABLE_COLS_NONE ! = mCols ) ;
1999-04-04 03:02:43 +04:00
PRInt32 * minColWidthArray = nsnull ;
if ( PR_TRUE = = hasColsAttribute ) {
1998-06-24 03:23:21 +04:00
minColWidthArray = new PRInt32 [ mNumCols ] ;
}
1998-07-11 04:00:31 +04:00
PRInt32 numRows = mTableFrame - > GetRowCount ( ) ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
1998-08-01 06:31:55 +04:00
nscoord minAdjustedColWidth = 0 ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " for col %d \n " , colIndex ) ;
1998-04-30 21:57:09 +04:00
1998-07-11 04:00:31 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
1999-04-04 03:02:43 +04:00
NS_ASSERTION ( nsnull ! = colFrame , " bad col frame " ) ;
1998-04-30 21:57:09 +04:00
1998-07-11 04:00:31 +04:00
// Get the columns's style
const nsStylePosition * colPosition ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
1998-11-16 09:46:00 +03:00
const nsStyleTable * colTableStyle ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Table , ( const nsStyleStruct * & ) colTableStyle ) ;
1998-11-16 09:46:00 +03:00
//if (PR_FALSE==IsFixedWidth(colPosition, colTableStyle))
1998-04-30 21:57:09 +04:00
{
1998-08-01 06:31:55 +04:00
minAdjustedColWidth = colFrame - > GetAdjustedMinColWidth ( ) ;
mTableFrame - > SetColumnWidth ( colIndex , minAdjustedColWidth ) ;
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = hasColsAttribute ) {
1998-08-01 06:31:55 +04:00
minColWidthArray [ colIndex ] = minAdjustedColWidth ;
1998-04-30 21:57:09 +04:00
}
}
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " 2: col %d, set to width = %d \n " , colIndex , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-04-30 21:57:09 +04:00
}
1998-06-24 03:23:21 +04:00
// now, post-process the computed values based on the table attributes
1998-07-17 03:23:31 +04:00
// if there is a COLS attribute, fix up mMinTableWidth and mMaxTableWidth
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = hasColsAttribute ) { // for every effected column, subtract out its prior contribution and add back in the new value
1998-06-24 03:23:21 +04:00
PRInt32 numColsEffected = mNumCols ;
1999-04-04 03:02:43 +04:00
if ( NS_STYLE_TABLE_COLS_ALL ! = mCols ) {
1998-06-24 03:23:21 +04:00
numColsEffected = mCols ;
1999-04-04 03:02:43 +04:00
}
nscoord maxOfEffectedColWidths = 0 ;
1998-06-27 06:49:36 +04:00
PRInt32 effectedColIndex ;
1998-06-24 03:23:21 +04:00
// XXX need to fix this and all similar code if any fixed-width columns intersect COLS
1999-04-04 03:02:43 +04:00
for ( effectedColIndex = 0 ; effectedColIndex < numColsEffected ; effectedColIndex + + ) {
maxOfEffectedColWidths = PR_MAX ( maxOfEffectedColWidths , minColWidthArray [ effectedColIndex ] ) ;
1998-06-24 03:23:21 +04:00
}
1999-04-04 03:02:43 +04:00
for ( effectedColIndex = 0 ; effectedColIndex < numColsEffected ; effectedColIndex + + ) {
1998-06-24 03:23:21 +04:00
// set each effected column to the size of the largest column in the group
mTableFrame - > SetColumnWidth ( effectedColIndex , maxOfEffectedColWidths ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " 2 (cols): setting %d to %d \n " , effectedColIndex , maxOfEffectedColWidths ) ;
1998-06-24 03:23:21 +04:00
}
1998-07-17 03:23:31 +04:00
// we're guaranteed here that minColWidthArray has been allocated, and that
// if we don't get here, it was never allocated
1998-06-24 03:23:21 +04:00
delete [ ] minColWidthArray ;
}
1998-04-30 21:57:09 +04:00
return result ;
}
1998-07-17 03:23:31 +04:00
/* the table fits in the given space. Set all columns to their desired width,
* and if we are not an auto - width table add extra space to fluff out the total width
*/
1999-04-04 03:02:43 +04:00
PRBool BasicTableLayoutStrategy : :
BalanceColumnsTableFits ( const nsHTMLReflowState & aReflowState ,
nscoord aAvailWidth ,
nscoord aMaxWidth ,
nscoord aTableSpecifiedWidth ,
PRBool aTableIsAutoWidth )
1998-04-30 21:57:09 +04:00
{
1998-07-07 01:00:11 +04:00
PRBool result = PR_TRUE ;
1999-04-04 03:02:43 +04:00
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 plus margins
// 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
1998-07-11 04:00:31 +04:00
PRInt32 numRows = mTableFrame - > GetRowCount ( ) ;
1998-12-09 09:37:18 +03:00
nscoord colInset = mTableFrame - > GetCellSpacingX ( ) ;
1998-08-11 22:42:10 +04:00
PRInt32 colIndex ;
1998-07-11 04:00:31 +04:00
1999-04-04 03:02:43 +04:00
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
TDBG_SD ( " for col %d \n " , colIndex ) ;
1998-05-30 02:08:19 +04:00
// Get column information
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
NS_ASSERTION ( nsnull ! = colFrame , " bad col frame " ) ;
1998-07-22 07:53:43 +04:00
PRInt32 minColWidth = colFrame - > GetMinColWidth ( ) ;
PRInt32 maxColWidth = 0 ;
1998-07-11 04:00:31 +04:00
PRInt32 rowIndex ;
PRInt32 firstRowIndex = - 1 ;
1998-04-30 21:57:09 +04:00
1998-07-11 04:00:31 +04:00
const nsStylePosition * colPosition ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
1998-11-16 09:46:00 +03:00
const nsStyleTable * colTableStyle ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Table , ( const nsStyleStruct * & ) colTableStyle ) ;
1998-07-18 01:02:28 +04:00
// first, deal with any cells that span into this column from a pervious column
1998-07-22 07:53:43 +04:00
// go through the list backwards so we can delete easily
1999-04-04 03:02:43 +04:00
if ( nsnull ! = spanList ) {
1998-07-18 01:02:28 +04:00
PRInt32 spanCount = spanList - > Count ( ) ;
// go through the list backwards so we can delete easily
1999-04-04 03:02:43 +04:00
for ( PRInt32 spanIndex = spanCount - 1 ; 0 < = spanIndex ; spanIndex - - ) {
SpanInfo * spanInfo = ( SpanInfo * ) ( spanList - > ElementAt ( spanIndex ) ) ;
if ( PR_FALSE = = IsFixedWidth ( colPosition , colTableStyle ) ) {
1998-07-22 07:53:43 +04:00
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth ;
1998-08-01 06:31:55 +04:00
PRBool needsExtraMinWidth = PR_FALSE ;
1999-04-04 03:02:43 +04:00
//if (spanInfo->effectiveMinWidthOfSpannedCols<spanInfo->cellMinWidth)
// needsExtraMinWidth = PR_TRUE;
if ( PR_TRUE = = needsExtraMinWidth ) {
if ( 0 ! = spanInfo - > effectiveMinWidthOfSpannedCols ) {
1998-08-01 06:31:55 +04:00
spanCellMinWidth = ( spanInfo - > cellMinWidth * colFrame - > GetEffectiveMinColWidth ( ) ) /
( spanInfo - > effectiveMinWidthOfSpannedCols ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " spanlist min: %d of %d \n " , spanCellMinWidth , spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
if ( minColWidth < spanCellMinWidth ) {
1998-08-01 06:31:55 +04:00
minColWidth = spanCellMinWidth ; // set the new min width for the col
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new min = %d \n " ,
1998-07-27 09:32:50 +04:00
colIndex , spanInfo - > span , minColWidth ) ;
1998-08-01 06:31:55 +04:00
// if the new min width is greater than the desired width, bump up the desired width
maxColWidth = PR_MAX ( maxColWidth , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " and maxColWidth = %d \n " , maxColWidth ) ;
1998-08-01 06:31:55 +04:00
}
}
1999-04-04 03:02:43 +04:00
else {
spanCellMinWidth = spanInfo - > cellMinWidth / spanInfo - > initialColSpan ;
if ( minColWidth < spanCellMinWidth ) {
1998-08-01 06:31:55 +04:00
minColWidth = spanCellMinWidth ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new min = %d \n " ,
colIndex , spanInfo - > span , minColWidth ) ;
1998-08-01 06:31:55 +04:00
// if the new min width is greater than the desired width, bump up the desired width
maxColWidth = PR_MAX ( maxColWidth , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " and maxColWidth = %d \n " , maxColWidth ) ;
1998-08-01 06:31:55 +04:00
}
1998-07-27 09:32:50 +04:00
}
1998-07-22 07:53:43 +04:00
}
// compute the spanning cell's contribution to the column max width
nscoord spanCellMaxWidth ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = spanInfo - > effectiveMaxWidthOfSpannedCols ) {
1998-09-30 03:15:01 +04:00
spanCellMaxWidth = ( spanInfo - > cellDesiredWidth * colFrame - > GetEffectiveMaxColWidth ( ) ) /
1998-07-22 07:53:43 +04:00
( spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " spanlist max: %d of %d \n " , spanCellMaxWidth , spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
if ( maxColWidth < spanCellMaxWidth ) {
1998-07-27 06:15:37 +04:00
spanCellMaxWidth = PR_MAX ( spanCellMaxWidth , minColWidth ) ;
1998-07-22 07:53:43 +04:00
maxColWidth = spanCellMaxWidth ; // set the new max width for the col
mTableFrame - > SetColumnWidth ( colIndex , spanCellMaxWidth ) ; // set the column to the new desired max width
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new max = %d \n " ,
colIndex , spanInfo - > span , maxColWidth ) ;
1998-07-22 07:53:43 +04:00
}
}
1999-04-04 03:02:43 +04:00
else {
spanCellMaxWidth = spanInfo - > cellDesiredWidth / spanInfo - > initialColSpan ;
1998-07-22 07:53:43 +04:00
maxColWidth = spanCellMaxWidth ;
mTableFrame - > SetColumnWidth ( colIndex , spanCellMaxWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new max = %d \n " ,
1998-07-22 07:53:43 +04:00
colIndex , spanInfo - > span , maxColWidth ) ;
}
1998-07-18 01:02:28 +04:00
}
spanInfo - > span - - ;
1999-04-04 03:02:43 +04:00
if ( 0 = = spanInfo - > span ) {
1998-07-18 01:02:28 +04:00
spanList - > RemoveElementAt ( spanIndex ) ;
delete spanInfo ;
1998-04-30 21:57:09 +04:00
}
}
1998-07-18 01:02:28 +04:00
}
1998-04-30 21:57:09 +04:00
1998-07-18 01:02:28 +04:00
// second, process non-fixed-width columns
1999-04-04 03:02:43 +04:00
if ( PR_FALSE = = IsFixedWidth ( colPosition , colTableStyle ) ) {
for ( rowIndex = 0 ; rowIndex < numRows ; rowIndex + + ) {
// this col has proportional width, so determine its width requirements
nsTableCellFrame * cellFrame = mTableFrame - > GetCellFrameAt ( rowIndex , colIndex ) ;
if ( nsnull = = cellFrame ) {
// there is no cell in this row that corresponds to this column
1998-07-11 04:00:31 +04:00
continue ;
}
1999-04-04 03:02:43 +04:00
if ( - 1 = = firstRowIndex ) {
1998-07-11 04:00:31 +04:00
firstRowIndex = rowIndex ;
1999-04-04 03:02:43 +04:00
}
1999-02-11 04:16:28 +03:00
PRInt32 cellRowIndex ;
cellFrame - > GetRowIndex ( cellRowIndex ) ;
1999-04-04 03:02:43 +04:00
if ( rowIndex ! = cellRowIndex ) {
1998-07-11 04:00:31 +04:00
// 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
1998-06-12 02:51:54 +04:00
continue ;
}
1999-02-11 04:16:28 +03:00
PRInt32 cellColIndex ;
cellFrame - > GetColIndex ( cellColIndex ) ;
1999-04-04 03:02:43 +04:00
if ( colIndex ! = cellColIndex ) {
1998-07-17 03:23:31 +04:00
// For cells that span cols, we figure in the row using previously-built SpanInfo
NS_ASSERTION ( 1 ! = cellFrame - > GetColSpan ( ) , " col index does not match row span " ) ; // sanity check
continue ;
}
1998-05-22 03:43:18 +04:00
1998-07-17 03:23:31 +04:00
PRInt32 colSpan = mTableFrame - > GetEffectiveColSpan ( colIndex , cellFrame ) ;
1998-07-11 04:00:31 +04:00
nsSize cellMinSize = cellFrame - > GetPass1MaxElementSize ( ) ;
nsSize cellDesiredSize = cellFrame - > GetPass1DesiredSize ( ) ;
1998-07-22 07:53:43 +04:00
nscoord cellMinWidth = colFrame - > GetMinColWidth ( ) ;
nscoord cellDesiredWidth = colFrame - > GetMaxColWidth ( ) ;
1998-06-05 06:36:25 +04:00
// then get the desired size info factoring in the cell style attributes
1999-04-04 03:02:43 +04:00
if ( 1 = = colSpan ) {
1998-07-22 07:53:43 +04:00
cellMinWidth = cellMinSize . width ;
cellDesiredWidth = cellDesiredSize . width ;
1999-04-04 03:02:43 +04:00
nscoord specifiedCellWidth = - 1 ;
1998-07-22 07:53:43 +04:00
const nsStylePosition * cellPosition ;
cellFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) cellPosition ) ;
1999-04-04 03:02:43 +04:00
if ( eStyleUnit_Percent = = cellPosition - > mWidth . GetUnit ( ) ) {
if ( PR_FALSE = = aTableIsAutoWidth ) {
1998-08-11 22:42:10 +04:00
float percent = cellPosition - > mWidth . GetPercentValue ( ) ;
1999-04-04 03:02:43 +04:00
specifiedCellWidth = ( PRInt32 ) ( aTableSpecifiedWidth * percent ) ;
TDBG_SFDD ( " specified percent width %f of %d = %d \n " ,
percent , aTableSpecifiedWidth , specifiedCellWidth ) ;
1998-08-11 22:42:10 +04:00
}
// otherwise we need to post-process, set to max for now
// do we want to set specifiedCellWidth off of aAvailWidth? aMaxWidth? XXX
1998-07-22 07:53:43 +04:00
}
1999-04-04 03:02:43 +04:00
if ( - 1 ! = specifiedCellWidth ) {
if ( specifiedCellWidth > cellMinWidth ) {
TDBG_SDD ( " setting cellDesiredWidth from %d to %d \n " , cellDesiredWidth , specifiedCellWidth ) ;
1998-07-22 07:53:43 +04:00
cellDesiredWidth = specifiedCellWidth ;
}
}
}
1999-04-04 03:02:43 +04:00
else {
// colSpan>1, get the proportion for this column
1998-07-22 07:53:43 +04:00
// then get the desired size info factoring in the cell style attributes
nscoord effectiveMaxWidthOfSpannedCols = colFrame - > GetEffectiveMaxColWidth ( ) ;
nscoord effectiveMinWidthOfSpannedCols = colFrame - > GetEffectiveMinColWidth ( ) ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 span = 1 ; span < colSpan ; span + + ) {
nsTableColFrame * nextColFrame = mTableFrame - > GetColFrame ( colIndex + span ) ;
if ( nsnull = = nextColFrame ) {
1998-07-22 07:53:43 +04:00
break ;
1999-04-04 03:02:43 +04:00
}
1998-07-22 07:53:43 +04:00
effectiveMaxWidthOfSpannedCols + = nextColFrame - > GetEffectiveMaxColWidth ( ) ;
effectiveMinWidthOfSpannedCols + = nextColFrame - > GetEffectiveMinColWidth ( ) ;
}
1999-04-04 03:02:43 +04:00
nscoord specifiedCellWidth = - 1 ;
1998-07-22 07:53:43 +04:00
const nsStylePosition * cellPosition ;
cellFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) cellPosition ) ;
1999-04-04 03:02:43 +04:00
if ( eStyleUnit_Percent = = cellPosition - > mWidth . GetUnit ( ) ) {
//XXX what if table is auto width?
1998-07-22 07:53:43 +04:00
float percent = cellPosition - > mWidth . GetPercentValue ( ) ;
specifiedCellWidth = ( PRInt32 ) ( aTableSpecifiedWidth * percent ) ;
1999-04-04 03:02:43 +04:00
TDBG_SFDD ( " specified percent width %f of %d = %d \n " ,
percent , aTableSpecifiedWidth , specifiedCellWidth ) ;
1998-07-22 07:53:43 +04:00
}
1999-04-04 03:02:43 +04:00
if ( - 1 ! = specifiedCellWidth ) {
1998-07-22 07:53:43 +04:00
float percentForThisCol = ( float ) ( cellDesiredSize . width * colFrame - > GetEffectiveMaxColWidth ( ) ) /
( float ) effectiveMaxWidthOfSpannedCols ;
nscoord cellWidthForThisCol = ( nscoord ) ( specifiedCellWidth * percentForThisCol ) ;
1999-04-04 03:02:43 +04:00
if ( cellWidthForThisCol > cellMinWidth ) {
TDBG_SDD ( " setting cellDesiredWidth from %d to %d \n " , cellDesiredWidth , cellWidthForThisCol ) ;
1998-07-22 07:53:43 +04:00
cellDesiredWidth = cellWidthForThisCol ;
}
}
// otherwise it's already been factored in.
// now, if this column holds the cell, create a spanInfo struct for the cell
// so subsequent columns can take a proportion of this cell's space into account
1999-02-11 04:16:28 +03:00
PRInt32 cellColIndex ;
cellFrame - > GetColIndex ( cellColIndex ) ;
1999-04-04 03:02:43 +04:00
if ( cellColIndex = = colIndex ) {
// add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo * spanInfo = new SpanInfo ( colIndex , colSpan - 1 , cellMinSize . width , cellDesiredSize . width ) ;
1998-07-22 07:53:43 +04:00
spanInfo - > effectiveMaxWidthOfSpannedCols = effectiveMaxWidthOfSpannedCols ;
spanInfo - > effectiveMinWidthOfSpannedCols = effectiveMinWidthOfSpannedCols ;
1999-04-04 03:02:43 +04:00
if ( nsnull = = spanList ) {
1998-07-22 07:53:43 +04:00
spanList = new nsVoidArray ( ) ;
1999-04-04 03:02:43 +04:00
}
1998-07-22 07:53:43 +04:00
spanList - > AppendElement ( spanInfo ) ;
1998-06-05 06:36:25 +04:00
}
}
1998-05-22 03:43:18 +04:00
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " factoring in cell %d with colSpan=%d \n factoring in min=%d and desired=%d \n " ,
rowIndex , colSpan , cellMinWidth , cellDesiredWidth ) ;
maxColWidth = PR_MAX ( maxColWidth , cellDesiredWidth ) ;
TDBG_SDDDDD ( " after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d \n " ,
rowIndex , minColWidth , maxColWidth ,
colIndex , colFrame - > GetEffectiveMaxColWidth ( ) ) ;
1998-07-17 03:23:31 +04:00
} // end looping through cells in the column
1998-04-30 21:57:09 +04:00
1999-04-04 03:02:43 +04:00
TDBG_SDS_SDD_SD ( " for determining width of col %d %s: \n " ,
colIndex , ! IsFixedWidth ( colPosition , colTableStyle ) ? " (P) " : " (A) " ,
" minColWidth = %d and maxColWidth = %d \n " , minColWidth , maxColWidth ,
" aAvailWidth = %d \n " , aAvailWidth ) ;
1998-04-30 21:57:09 +04:00
1998-05-30 02:08:19 +04:00
// Get column width if it has one
1998-06-05 06:36:25 +04:00
nscoord specifiedProportionColumnWidth = - 1 ;
1998-05-30 02:08:19 +04:00
float specifiedPercentageColWidth = - 1.0f ;
1998-06-05 06:36:25 +04:00
nscoord specifiedFixedColumnWidth = - 1 ;
1998-05-30 02:08:19 +04:00
PRBool isAutoWidth = PR_FALSE ;
switch ( colPosition - > mWidth . GetUnit ( ) ) {
case eStyleUnit_Percent :
specifiedPercentageColWidth = colPosition - > mWidth . GetPercentValue ( ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDF ( " column %d has specified percent width = %f \n " , colIndex , specifiedPercentageColWidth ) ;
1998-05-30 02:08:19 +04:00
break ;
case eStyleUnit_Proportional :
1998-06-05 06:36:25 +04:00
specifiedProportionColumnWidth = colPosition - > mWidth . GetIntValue ( ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " column %d has specified percent width = %d \n " , colIndex , specifiedProportionColumnWidth ) ;
1998-05-30 02:08:19 +04:00
break ;
case eStyleUnit_Auto :
isAutoWidth = PR_TRUE ;
break ;
default :
break ;
}
1998-05-27 02:03:16 +04:00
1999-04-04 03:02:43 +04:00
// set the column width, knowing that the table fits in the available space
if ( 0 = = specifiedProportionColumnWidth | | 0.0 = = specifiedPercentageColWidth ) {
// col width is specified to be the minimum
1998-05-27 02:03:16 +04:00
mTableFrame - > SetColumnWidth ( colIndex , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " 3 min: col %d set to min width = %d because style set proportionalWidth=0 \n " ,
colIndex , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-05-27 02:03:16 +04:00
}
1999-04-04 03:02:43 +04:00
else if ( ( PR_TRUE = = isAutoWidth ) | |
( ( PR_TRUE = = aTableIsAutoWidth ) & & ( - 1 = = specifiedProportionColumnWidth ) ) ) {
// col width is determined by the cells' content,
1998-05-30 02:08:19 +04:00
// so give each remaining column it's desired width (because we know we fit.)
1998-05-27 02:03:16 +04:00
// if there is width left over, we'll factor that in after this loop is complete
1998-08-11 22:42:10 +04:00
// the OR clause is because we fix up percentage widths as a post-process
// in auto-width tables
1998-05-27 02:03:16 +04:00
mTableFrame - > SetColumnWidth ( colIndex , maxColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " 3 auto: col %d with availWidth %d, set to width = %d \n " ,
1998-05-27 02:03:16 +04:00
colIndex , aAvailWidth , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
}
1999-04-04 03:02:43 +04:00
else if ( - 1 ! = specifiedProportionColumnWidth )
1998-05-30 02:08:19 +04:00
{ // we need to save these and do them after all other columns have been calculated
1999-04-04 03:02:43 +04:00
// the calculation will be:
// sum up n, the total number of slices for the columns with proportional width
// compute the table "required" width, fixed-width + percentage-width +
// the sum of the proportional column's max widths (especially because in this routine I know the table fits)
// compute the remaining width: the required width - the used width (fixed + percentage)
// compute the width per slice
// set the width of each proportional-width column to it's number of slices * width per slice
1998-05-30 02:08:19 +04:00
mTableFrame - > SetColumnWidth ( colIndex , 0 ) ; // set the column width to 0, since it isn't computed yet
1999-04-04 03:02:43 +04:00
if ( nsnull = = proportionalColumnsList ) {
1998-05-30 02:08:19 +04:00
proportionalColumnsList = new nsVoidArray ( ) ;
1999-04-04 03:02:43 +04:00
}
ProportionalColumnLayoutStruct * info =
1998-06-05 06:36:25 +04:00
new ProportionalColumnLayoutStruct ( colIndex , minColWidth ,
maxColWidth , specifiedProportionColumnWidth ) ;
1998-05-30 02:08:19 +04:00
proportionalColumnsList - > AppendElement ( info ) ;
1998-06-05 06:36:25 +04:00
totalSlices + = specifiedProportionColumnWidth ; // keep track of the total number of proportions
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " 3 proportional: col %d with availWidth %d, gets %d slices with %d slices so far. \n " ,
colIndex , aAvailWidth , specifiedProportionColumnWidth , totalSlices ) ;
1998-06-05 06:36:25 +04:00
}
1999-04-04 03:02:43 +04:00
else { // give the column a percentage of the remaining space
1998-05-27 02:03:16 +04:00
PRInt32 percentage = - 1 ;
1999-04-04 03:02:43 +04:00
if ( NS_UNCONSTRAINEDSIZE = = aAvailWidth ) {
// since the "remaining space" is infinite, give the column it's max requested size
1998-04-30 21:57:09 +04:00
mTableFrame - > SetColumnWidth ( colIndex , maxColWidth ) ;
}
1999-04-04 03:02:43 +04:00
else {
if ( - 1.0f ! = specifiedPercentageColWidth ) {
percentage = ( PRInt32 ) ( specifiedPercentageColWidth * 100.0f ) ; // TODO: rounding errors?
1998-06-05 22:11:20 +04:00
// base the % on the total specified fixed width of the table
1999-04-04 03:02:43 +04:00
mTableFrame - > SetColumnWidth ( colIndex , ( percentage * aTableSpecifiedWidth ) / 100 ) ;
TDBG_SDDDD ( " 3 percent specified: col %d given %d percent of aTableSpecifiedWidth %d, set to width = %d \n " ,
colIndex , percentage , aTableSpecifiedWidth , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-06-05 22:11:20 +04:00
}
1999-04-04 03:02:43 +04:00
if ( - 1 = = percentage ) {
percentage = 100 / mNumCols ;
1998-06-05 22:11:20 +04:00
// base the % on the remaining available width
1999-04-04 03:02:43 +04:00
mTableFrame - > SetColumnWidth ( colIndex , ( percentage * aAvailWidth ) / 100 ) ;
TDBG_SDDDD ( " 3 percent default: col %d given %d percent of aAvailWidth %d, set to width = %d \n " ,
colIndex , percentage , aAvailWidth , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-06-05 22:11:20 +04:00
}
1998-05-27 02:03:16 +04:00
// if the column was computed to be too small, enlarge the column
1999-04-04 03:02:43 +04:00
if ( mTableFrame - > GetColumnWidth ( colIndex ) < = minColWidth ) {
1998-05-27 02:03:16 +04:00
mTableFrame - > SetColumnWidth ( colIndex , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " enlarging column to it's minimum = %d \n " , minColWidth ) ;
1998-06-06 02:50:03 +04:00
}
1998-05-27 02:03:16 +04:00
}
}
}
1999-04-04 03:02:43 +04:00
else { // need to maintain this so we know how much we have left over at the end
1998-11-03 01:19:17 +03:00
nscoord maxEffectiveColWidth = colFrame - > GetEffectiveMaxColWidth ( ) ;
mTableFrame - > SetColumnWidth ( colIndex , maxEffectiveColWidth ) ;
widthOfFixedTableColumns + = maxEffectiveColWidth + colInset ;
1998-07-11 04:00:31 +04:00
}
tableWidth + = mTableFrame - > GetColumnWidth ( colIndex ) + colInset ;
1998-05-27 02:03:16 +04:00
}
1998-09-10 00:00:40 +04:00
tableWidth + = colInset ;
1998-05-27 02:03:16 +04:00
1998-05-30 02:08:19 +04:00
/* --- post-process if necessary --- */
1998-08-11 22:42:10 +04:00
// XXX the following implementation does not account for borders, cell spacing, cell padding
// first, assign column widths in auto-width tables
1999-04-04 03:02:43 +04:00
PRInt32 numPercentColumns = 0 ;
PRInt32 * percentColumns = nsnull ;
1998-08-11 22:42:10 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Percent , numPercentColumns , percentColumns ) ;
1999-04-04 03:02:43 +04:00
if ( ( PR_TRUE = = aTableIsAutoWidth ) & & ( 0 ! = numPercentColumns ) ) {
1998-08-11 22:42:10 +04:00
// variables common to lots of code in this block
nscoord colWidth ;
float percent ;
const nsStylePosition * colPosition ;
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
if ( numPercentColumns ! = mNumCols ) {
TDBG_S ( " assigning widths to percent colums in auto-width table \n " ) ;
nscoord widthOfPercentCells = 0 ; // the total width of those percent-width cells that have been given a width
nscoord widthOfOtherCells = 0 ; // the total width of those non-percent-width cells that have been given a width
float sumOfPercentColumns = 0.0f ; // the total of the percent widths
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
1998-08-11 22:42:10 +04:00
// every column contributes to either widthOfOtherCells or widthOfPercentCells, but not both
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = IsColumnInList ( colIndex , percentColumns , numPercentColumns ) ) {
1998-08-11 22:42:10 +04:00
colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
percent = colPosition - > mWidth . GetPercentValue ( ) ; // we know this will work
sumOfPercentColumns + = percent ;
1999-04-04 03:02:43 +04:00
if ( sumOfPercentColumns > 1.0f ) { // values greater than 100% are meaningless
sumOfPercentColumns = 1.0f ;
}
1998-08-11 22:42:10 +04:00
widthOfPercentCells + = mTableFrame - > GetColumnWidth ( colIndex ) ;
}
1999-04-04 03:02:43 +04:00
else {
1998-08-11 22:42:10 +04:00
widthOfOtherCells + = mTableFrame - > GetColumnWidth ( colIndex ) ;
}
}
1999-04-04 03:02:43 +04:00
if ( 0 = = widthOfOtherCells ) {
widthOfOtherCells = aMaxWidth ;
}
TDBG_SDDF ( " widthOfOtherCells=%d widthOfPercentCells = %d sumOfPercentColumns=%f \n " ,
widthOfOtherCells , widthOfPercentCells , sumOfPercentColumns ) ;
1998-08-11 22:42:10 +04:00
float remainingPercent = 1.0f - sumOfPercentColumns ;
nscoord newTableWidth ; // the table width after all cells have been resized
1999-04-04 03:02:43 +04:00
if ( 1.0f = = sumOfPercentColumns ) { // this definately seems like a QUIRK!
1998-08-11 22:42:10 +04:00
newTableWidth = aMaxWidth ;
1999-04-04 03:02:43 +04:00
}
else { // the newTableWidth is the larger of the calculation from the percent cells and non-percent cells
1998-08-11 22:42:10 +04:00
nscoord percentWidth = ( nscoord ) ( ( 1.0f / sumOfPercentColumns ) * ( ( float ) ( widthOfPercentCells ) ) ) ;
nscoord otherWidth = ( nscoord ) ( ( 1.0f / remainingPercent ) * ( ( float ) ( widthOfOtherCells ) ) ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " percentWidth=%d otherWidth=%d \n " , percentWidth , otherWidth ) ;
1998-08-18 03:37:04 +04:00
newTableWidth = PR_MAX ( percentWidth , otherWidth ) ; // the table width is the larger of the two computations
newTableWidth = PR_MIN ( newTableWidth , aMaxWidth ) ; // an auto-width table can't normally be wider than it's parent
newTableWidth = PR_MIN ( newTableWidth , mMaxTableWidth ) ; // an auto-width table can't normally be wider than it's own computed max width
1998-08-11 22:42:10 +04:00
}
nscoord excess = newTableWidth - mFixedTableWidth ; // the amount of new space that needs to be
// accounted for in the non-fixed columns
1999-04-04 03:02:43 +04:00
TDBG_SD ( " newTableWidth=%d \n " , newTableWidth ) ;
1998-08-11 22:42:10 +04:00
PRInt32 i ; // just a counter
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numPercentColumns ; i + + ) {
1998-08-11 22:42:10 +04:00
colIndex = percentColumns [ i ] ;
colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
percent = colPosition - > mWidth . GetPercentValue ( ) ; // we know this will work
1999-04-04 03:02:43 +04:00
colWidth = ( nscoord ) ( ( percent ) * ( ( float ) newTableWidth ) ) ;
1998-08-11 22:42:10 +04:00
nscoord minColWidth = colFrame - > GetEffectiveMinColWidth ( ) ;
colWidth = PR_MAX ( colWidth , minColWidth ) ;
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDFD ( " col %d with percentwidth=%f set to %d \n " , colIndex , percent , colWidth ) ;
1998-08-11 22:42:10 +04:00
excess - = colWidth ;
}
1999-04-04 03:02:43 +04:00
if ( 0 < excess ) {
1998-08-11 22:42:10 +04:00
PRInt32 numAutoColumns = 0 ;
1999-04-04 03:02:43 +04:00
PRInt32 * autoColumns = nsnull ;
1998-08-11 22:42:10 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Auto , numAutoColumns , autoColumns ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " excess=%d with %d autoColumns \n " , excess , numAutoColumns ) ;
if ( 0 < numAutoColumns ) {
nscoord excessPerColumn = excess / numAutoColumns ;
for ( i = 0 ; i < numAutoColumns ; i + + ) {
1998-08-11 22:42:10 +04:00
colIndex = autoColumns [ i ] ;
nscoord newWidth = PR_MAX ( excessPerColumn , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " col %d was %d set to %d \n " ,
colIndex , mTableFrame - > GetColumnWidth ( colIndex ) , newWidth ) ;
1998-08-11 22:42:10 +04:00
mTableFrame - > SetColumnWidth ( colIndex , newWidth ) ;
excess - = excessPerColumn ;
}
// handle division underflow
1999-04-04 03:02:43 +04:00
if ( 0 < excess ) {
TDBG_SD ( " after first pass through auto-width columns, excess=%d \n " , excess ) ;
for ( i = 0 ; i < numAutoColumns ; i + + ) {
1998-08-11 22:42:10 +04:00
colIndex = autoColumns [ i ] ;
nscoord newWidth = 1 + mTableFrame - > GetColumnWidth ( colIndex ) ;
mTableFrame - > SetColumnWidth ( colIndex , newWidth ) ;
}
}
}
}
}
1999-04-04 03:02:43 +04:00
else {
// all columns have a percent width. Each already has its desired width.
1998-08-11 22:42:10 +04:00
// find the smallest percentage and base the widths of the others off that
PRInt32 indexOfSmallest ;
nscoord colWidthOfSmallest ;
1999-04-04 03:02:43 +04:00
float smallestPercent = 2.0f ; // an illegal large number
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
1998-08-11 22:42:10 +04:00
colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
percent = colPosition - > mWidth . GetPercentValue ( ) ; // we know this will work
1999-04-04 03:02:43 +04:00
if ( percent < smallestPercent ) {
1998-08-11 22:42:10 +04:00
smallestPercent = percent ;
indexOfSmallest = colIndex ;
colWidthOfSmallest = mTableFrame - > GetColumnWidth ( colIndex ) ;
}
1999-04-04 03:02:43 +04:00
else if ( percent = = smallestPercent ) {
// the largest desired size among equal-percent columns wins
1998-08-11 22:42:10 +04:00
nscoord colWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
1999-04-04 03:02:43 +04:00
if ( colWidth > colWidthOfSmallest ) {
1998-08-11 22:42:10 +04:00
indexOfSmallest = colIndex ;
colWidthOfSmallest = colWidth ;
}
}
}
// now that we know which column to base the other columns' widths off of, do it!
1999-04-04 03:02:43 +04:00
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
1998-08-11 22:42:10 +04:00
colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
percent = colPosition - > mWidth . GetPercentValue ( ) ; // we know this will work
1999-04-04 03:02:43 +04:00
if ( percent = = smallestPercent ) { // set col width to the max width of all columns that shared the smallest percent-width
1998-08-11 22:42:10 +04:00
mTableFrame - > SetColumnWidth ( colIndex , colWidthOfSmallest ) ;
}
1999-04-04 03:02:43 +04:00
else {
colWidth = ( nscoord ) ( ( percent / smallestPercent ) * ( ( float ) colWidthOfSmallest ) ) ;
1998-08-11 22:42:10 +04:00
nscoord minColWidth = colFrame - > GetEffectiveMinColWidth ( ) ;
colWidth = PR_MAX ( colWidth , minColWidth ) ;
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
}
1999-04-04 03:02:43 +04:00
TDBG_SDFD ( " col %d with percentwidth=%f set to %d \n " , colIndex , percent , colWidth ) ;
1998-08-11 22:42:10 +04:00
}
}
}
// second, assign column widths to proportional-width columns
1999-04-04 03:02:43 +04:00
if ( nsnull ! = proportionalColumnsList ) {
1998-05-30 02:08:19 +04:00
// first, figure out the amount of space per slice
1999-04-04 03:02:43 +04:00
nscoord maxWidthForTable = ( 0 ! = aTableSpecifiedWidth ) ? aTableSpecifiedWidth : aMaxWidth ;
if ( NS_UNCONSTRAINEDSIZE ! = maxWidthForTable ) {
1998-06-24 03:23:21 +04:00
nscoord widthRemaining = maxWidthForTable - tableWidth ;
nscoord widthPerSlice = widthRemaining / totalSlices ;
PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList - > Count ( ) ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 i = 0 ; i < numSpecifiedProportionalColumns ; i + + ) {
// for every proportionally-sized column, set the col width to the computed width
ProportionalColumnLayoutStruct * info =
1998-06-24 03:23:21 +04:00
( ProportionalColumnLayoutStruct * ) ( proportionalColumnsList - > ElementAt ( i ) ) ;
1998-08-20 21:31:20 +04:00
// verify that the computed width is at least the minimum width
1998-06-24 03:23:21 +04:00
nscoord computedColWidth = info - > mProportion * widthPerSlice ;
1998-08-20 21:31:20 +04:00
// compute the requested proportional width
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
1998-08-20 21:31:20 +04:00
mTableFrame - > GetColumnFrame ( info - > mColIndex , colFrame ) ;
nscoord minColWidth = colFrame - > GetMinColWidth ( ) ;
computedColWidth = PR_MAX ( computedColWidth , minColWidth ) ;
1998-06-24 03:23:21 +04:00
mTableFrame - > SetColumnWidth ( info - > mColIndex , computedColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " 3 proportional step 2: col %d given %d proportion of remaining space %d, set to width = %d \n " ,
info - > mColIndex , info - > mProportion , widthRemaining , computedColWidth ) ;
1998-06-24 03:23:21 +04:00
tableWidth + = computedColWidth ;
delete info ;
}
}
1999-04-04 03:02:43 +04:00
else {
// we're in an unconstrained situation, so give each column the max of the max column widths
1998-06-24 03:23:21 +04:00
PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList - > Count ( ) ;
PRInt32 maxOfMaxColWidths = 0 ;
1998-06-27 06:49:36 +04:00
PRInt32 i ;
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numSpecifiedProportionalColumns ; i + + ) {
ProportionalColumnLayoutStruct * info =
1998-06-24 03:23:21 +04:00
( ProportionalColumnLayoutStruct * ) ( proportionalColumnsList - > ElementAt ( i ) ) ;
1999-04-04 03:02:43 +04:00
maxOfMaxColWidths = PR_MAX ( maxOfMaxColWidths , info - > mMaxColWidth ) ;
1998-06-24 03:23:21 +04:00
}
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numSpecifiedProportionalColumns ; i + + ) {
ProportionalColumnLayoutStruct * info =
1998-06-24 03:23:21 +04:00
( ProportionalColumnLayoutStruct * ) ( proportionalColumnsList - > ElementAt ( i ) ) ;
mTableFrame - > SetColumnWidth ( info - > mColIndex , maxOfMaxColWidths ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " 3 proportional step 2 (unconstrained!): col %d set to width = %d \n " ,
info - > mColIndex , maxOfMaxColWidths ) ;
1998-06-24 03:23:21 +04:00
tableWidth + = maxOfMaxColWidths ;
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
1998-07-17 03:23:31 +04:00
mTableFrame - > GetColumnFrame ( info - > mColIndex , colFrame ) ;
colFrame - > SetEffectiveMaxColWidth ( maxOfMaxColWidths ) ;
1998-06-24 03:23:21 +04:00
delete info ;
}
1998-05-30 02:08:19 +04:00
}
delete proportionalColumnsList ;
}
1998-05-27 02:03:16 +04:00
1998-09-30 03:15:01 +04:00
// next, account for table width constraints
// if the caption min width is wider than than the table, expand the table
1999-04-04 03:02:43 +04:00
nscoord captionMinWidth = mTableFrame - > GetMinCaptionWidth ( ) ;
if ( captionMinWidth > tableWidth ) {
1998-09-30 03:15:01 +04:00
DistributeExcessSpace ( captionMinWidth , tableWidth , widthOfFixedTableColumns ) ;
1998-06-30 04:37:03 +04:00
}
1999-04-04 03:02:43 +04:00
else {
// else, if the caption min width is not an issue...
// 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 - widthOfFixedTableColumns ) ) & &
( gBigSpace ! = aAvailWidth ) ) {
1998-09-30 03:15:01 +04:00
DistributeExcessSpace ( aAvailWidth , tableWidth , widthOfFixedTableColumns ) ;
1998-08-02 00:31:40 +04:00
}
1998-09-30 03:15:01 +04:00
// IFF the table is NOT (auto-width && all columns have fixed width)
PRInt32 numFixedColumns = 0 ;
1999-04-04 03:02:43 +04:00
PRInt32 * fixedColumns = nsnull ;
1998-09-30 03:15:01 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Coord , numFixedColumns , fixedColumns ) ;
1999-04-04 03:02:43 +04:00
if ( ! ( ( PR_TRUE = = aTableIsAutoWidth ) & & ( numFixedColumns = = mNumCols ) ) ) {
nscoord computedWidth = 0 ;
for ( PRInt32 i = 0 ; i < mNumCols ; i + + ) {
1998-09-30 03:15:01 +04:00
computedWidth + = mTableFrame - > GetColumnWidth ( i ) + colInset ;
}
1999-04-04 03:02:43 +04:00
if ( computedWidth > aMaxWidth ) {
1998-09-30 03:15:01 +04:00
AdjustTableThatIsTooWide ( computedWidth , aMaxWidth , PR_FALSE ) ;
}
1998-08-02 00:31:40 +04:00
}
1998-07-24 01:55:45 +04:00
}
1998-08-02 00:31:40 +04:00
// cleanup
1999-04-04 03:02:43 +04:00
if ( nsnull ! = spanList ) {
TDBG_S ( " BTLS::BCTFits...space leak, span list not empty " ) ;
1998-06-30 04:37:03 +04:00
delete spanList ;
1998-07-18 01:02:28 +04:00
}
1998-06-30 04:37:03 +04:00
return result ;
}
1998-07-07 01:00:11 +04:00
// 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
1998-07-11 04:00:31 +04:00
void BasicTableLayoutStrategy : : DistributeExcessSpace ( nscoord aAvailWidth ,
nscoord aTableWidth ,
1998-07-17 03:23:31 +04:00
nscoord aWidthOfFixedTableColumns )
1998-06-30 04:37:03 +04:00
{
1998-07-07 01:00:11 +04:00
nscoord excess = 0 ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " DistributeExcessSpace: fixed width %d > computed table width %d, woftc=%d \n " ,
aAvailWidth , aTableWidth , aWidthOfFixedTableColumns ) ;
1998-07-17 03:23:31 +04:00
nscoord widthMinusFixedColumns = aTableWidth - aWidthOfFixedTableColumns ;
1998-06-30 04:37:03 +04:00
// if there are auto-sized columns, give them the extra space
1998-07-11 04:00:31 +04:00
// the trick here is to do the math excluding non-auto width columns
1998-06-30 04:37:03 +04:00
PRInt32 numAutoColumns = 0 ;
1999-04-04 03:02:43 +04:00
PRInt32 * autoColumns = nsnull ;
1998-10-03 00:34:11 +04:00
GetColumnsThatActLikeAutoWidth ( numAutoColumns , autoColumns ) ; // allocates autoColumns, be sure to delete it
1999-04-04 03:02:43 +04:00
if ( 0 ! = numAutoColumns ) {
1998-06-30 04:37:03 +04:00
// 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
1998-07-02 21:40:56 +04:00
nscoord totalEffectiveWidthOfAutoColumns = 0 ;
1998-06-30 04:37:03 +04:00
// 1. first, get the total width of the auto columns
PRInt32 i ;
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numAutoColumns ; i + + ) {
nsTableColFrame * colFrame ;
1998-07-17 03:23:31 +04:00
mTableFrame - > GetColumnFrame ( autoColumns [ i ] , colFrame ) ;
nscoord effectiveColWidth = colFrame - > GetEffectiveMaxColWidth ( ) ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = effectiveColWidth ) {
1998-07-17 03:23:31 +04:00
totalEffectiveWidthOfAutoColumns + = effectiveColWidth ;
1999-04-04 03:02:43 +04:00
}
else {
1998-07-02 21:40:56 +04:00
totalEffectiveWidthOfAutoColumns + = mTableFrame - > GetColumnWidth ( autoColumns [ i ] ) ;
1999-04-04 03:02:43 +04:00
}
1998-04-30 21:57:09 +04:00
}
1998-07-17 03:23:31 +04:00
// excess is the amount of space that was available minus the computed available width
1998-08-14 20:16:43 +04:00
// XXX shouldn't it just be aMaxWidth - aTableWidth???
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " aAvailWidth specified as %d, expanding columns by excess = %d \n " , aAvailWidth , excess ) ;
1998-07-17 03:23:31 +04:00
excess = aAvailWidth - widthMinusFixedColumns ;
1998-06-30 04:37:03 +04:00
// 2. next, compute the proportion to be added to each column, and add it
1998-09-10 00:00:40 +04:00
nscoord totalAdded = 0 ;
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numAutoColumns ; i + + ) {
1998-06-30 04:37:03 +04:00
PRInt32 colIndex = autoColumns [ i ] ;
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
1998-07-17 03:23:31 +04:00
mTableFrame - > GetColumnFrame ( colIndex , colFrame ) ;
nscoord oldColWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
1998-06-30 04:37:03 +04:00
float percent ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = totalEffectiveWidthOfAutoColumns ) {
percent = ( ( float ) ( colFrame - > GetEffectiveMaxColWidth ( ) ) ) / ( ( float ) totalEffectiveWidthOfAutoColumns ) ;
}
else {
percent = ( ( float ) 1 ) / ( ( float ) numAutoColumns ) ;
}
nscoord excessForThisColumn = ( nscoord ) ( excess * percent ) ;
1998-09-10 00:00:40 +04:00
totalAdded + = excessForThisColumn ;
1998-06-30 04:37:03 +04:00
nscoord colWidth = excessForThisColumn + oldColWidth ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " distribute excess to auto columns: column %d was %d, now set to %d \n " ,
colIndex , oldColWidth , colWidth ) ;
1998-06-30 04:37:03 +04:00
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
}
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " lost a few twips due to rounding errors: excess=%d, totalAdded=%d \n " , excess , totalAdded ) ;
1998-06-30 04:37:03 +04:00
}
// otherwise, distribute the space between all the columns
// (they must be all fixed and percentage-width columns, or we would have gone into the block above)
1999-04-04 03:02:43 +04:00
else {
1998-07-17 03:23:31 +04:00
excess = aAvailWidth - widthMinusFixedColumns ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " aAvailWidth specified as %d, expanding columns by excess = %d \n " , aAvailWidth , excess ) ;
1998-09-10 00:00:40 +04:00
nscoord totalAdded = 0 ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
1998-07-17 03:23:31 +04:00
nscoord oldColWidth = 0 ;
1999-04-04 03:02:43 +04:00
if ( 0 = = oldColWidth ) {
1998-07-01 00:12:45 +04:00
oldColWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
1999-04-04 03:02:43 +04:00
}
1998-07-01 00:12:45 +04:00
float percent ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = aTableWidth ) {
1998-07-11 04:00:31 +04:00
percent = ( float ) oldColWidth / ( float ) aTableWidth ;
1999-04-04 03:02:43 +04:00
}
else {
percent = ( float ) 1 / ( float ) mNumCols ;
}
nscoord excessForThisColumn = ( nscoord ) ( NSToCoordRound ( excess * percent ) ) ;
1998-09-10 00:00:40 +04:00
totalAdded + = excessForThisColumn ;
1999-04-04 03:02:43 +04:00
nscoord colWidth = excessForThisColumn + oldColWidth ;
TDBG_SDDDF ( " distribute excess: column %d was %d, now %d from %=%f \n " ,
colIndex , oldColWidth , colWidth , percent ) ;
1998-06-30 04:37:03 +04:00
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
1998-05-27 02:03:16 +04:00
}
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " lost a few twips due to rounding errors: excess=%d, totalAdded=%d \n " , excess , totalAdded ) ;
1998-04-30 21:57:09 +04:00
}
1999-04-04 03:02:43 +04:00
if ( nsnull ! = autoColumns ) {
1998-10-03 00:34:11 +04:00
delete [ ] autoColumns ;
1999-04-04 03:02:43 +04:00
}
1998-04-30 21:57:09 +04:00
}
1998-07-17 03:23:31 +04:00
/* assign columns widths for a table whose max size doesn't fit in the available space
1998-06-06 02:50:03 +04:00
*/
1999-04-04 03:02:43 +04:00
PRBool BasicTableLayoutStrategy : :
BalanceColumnsConstrained ( const nsHTMLReflowState & aReflowState ,
nscoord aAvailWidth ,
nscoord aMaxWidth ,
PRBool aTableIsAutoWidth )
1998-04-30 21:57:09 +04:00
{
1998-09-23 03:36:06 +04:00
# ifdef NS_DEBUG
1999-04-04 03:02:43 +04:00
nsIFrame * tablePIF = nsnull ;
1999-02-24 07:48:08 +03:00
mTableFrame - > GetPrevInFlow ( & tablePIF ) ;
1998-04-30 21:57:09 +04:00
NS_ASSERTION ( nsnull = = tablePIF , " never ever call me on a continuing frame! " ) ;
# endif
PRBool result = PR_TRUE ;
1998-05-30 02:08:19 +04:00
PRInt32 maxOfAllMinColWidths = 0 ; // for the case where we have equal column widths, this is the smallest a column can be
1999-04-04 03:02:43 +04:00
nscoord tableWidth = 0 ; // the width of the table as a result of setting column widths
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
1998-06-02 00:21:05 +04:00
PRBool equalWidthColumns = PR_TRUE ; // remember if we're in the special case where all
// proportional-width columns are equal (if any are anything other than 1)
1998-07-07 01:00:11 +04:00
PRBool atLeastOneAutoWidthColumn = PR_FALSE ; // true if at least one column is auto-width, requiring us to post-process
1999-04-04 03:02:43 +04:00
nsVoidArray * spanList = nsnull ; // a list of the cells that span columns
1998-07-11 04:00:31 +04:00
PRInt32 numRows = mTableFrame - > GetRowCount ( ) ;
1998-12-09 09:37:18 +03:00
nscoord colInset = mTableFrame - > GetCellSpacingX ( ) ;
1998-07-11 04:00:31 +04:00
1999-04-04 03:02:43 +04:00
for ( PRInt32 colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
TDBG_SD ( " for col %d \n " , colIndex ) ;
1998-07-07 01:00:11 +04:00
nscoord minColWidth = 0 ;
nscoord maxColWidth = 0 ;
1998-05-30 02:08:19 +04:00
// Get column information
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
NS_ASSERTION ( nsnull ! = colFrame , " bad col frame " ) ;
1998-07-11 04:00:31 +04:00
// Get the columns's style and margins
PRInt32 rowIndex ;
PRInt32 firstRowIndex = - 1 ;
const nsStylePosition * colPosition ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
1998-11-16 09:46:00 +03:00
const nsStyleTable * colTableStyle ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Table , ( const nsStyleStruct * & ) colTableStyle ) ;
1998-05-30 02:08:19 +04:00
1998-07-18 01:02:28 +04:00
// first, deal with any cells that span into this column from a pervious column
1998-07-22 07:53:43 +04:00
// go through the list backwards so we can delete easily
1999-04-04 03:02:43 +04:00
if ( nsnull ! = spanList ) {
1998-07-18 01:02:28 +04:00
PRInt32 spanCount = spanList - > Count ( ) ;
// go through the list backwards so we can delete easily
1999-04-04 03:02:43 +04:00
for ( PRInt32 spanIndex = spanCount - 1 ; 0 < = spanIndex ; spanIndex - - ) {
SpanInfo * spanInfo = ( SpanInfo * ) ( spanList - > ElementAt ( spanIndex ) ) ;
if ( PR_FALSE = = IsFixedWidth ( colPosition , colTableStyle ) ) {
1998-07-22 07:53:43 +04:00
// compute the spanning cell's contribution to the column min width
nscoord spanCellMinWidth ;
1998-08-01 06:31:55 +04:00
PRBool needsExtraMinWidth = PR_FALSE ;
1999-04-04 03:02:43 +04:00
//if (spanInfo->effectiveMinWidthOfSpannedCols<spanInfo->cellMinWidth)
// needsExtraMinWidth = PR_TRUE;
if ( PR_TRUE = = needsExtraMinWidth ) {
if ( 0 ! = spanInfo - > effectiveMinWidthOfSpannedCols ) {
1998-08-01 06:31:55 +04:00
spanCellMinWidth = ( spanInfo - > cellMinWidth * colFrame - > GetEffectiveMinColWidth ( ) ) /
( spanInfo - > effectiveMinWidthOfSpannedCols ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " spanlist min: %d of %d \n " , spanCellMinWidth , spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
if ( minColWidth < spanCellMinWidth ) {
1998-08-01 06:31:55 +04:00
minColWidth = spanCellMinWidth ; // set the new min width for the col
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new min = %d \n " ,
1998-08-01 06:31:55 +04:00
colIndex , spanInfo - > span , minColWidth ) ;
maxColWidth = PR_MAX ( maxColWidth , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " maxColWidth = %d \n " , maxColWidth ) ;
1998-08-01 06:31:55 +04:00
}
1998-07-22 07:53:43 +04:00
}
1999-04-04 03:02:43 +04:00
else {
spanCellMinWidth = spanInfo - > cellMinWidth / spanInfo - > initialColSpan ;
if ( minColWidth < spanCellMinWidth ) {
1998-08-01 06:31:55 +04:00
minColWidth = spanCellMinWidth ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new min = %d \n " ,
1998-08-01 06:31:55 +04:00
colIndex , spanInfo - > span , minColWidth ) ;
maxColWidth = PR_MAX ( maxColWidth , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " maxColWidth = %d \n " , maxColWidth ) ;
1998-08-01 06:31:55 +04:00
}
1998-07-27 09:32:50 +04:00
}
1998-07-22 07:53:43 +04:00
}
// compute the spanning cell's contribution to the column max width
nscoord spanCellMaxWidth ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = spanInfo - > effectiveMaxWidthOfSpannedCols ) {
1998-07-22 07:53:43 +04:00
spanCellMaxWidth = ( spanInfo - > cellDesiredWidth * colFrame - > GetEffectiveMinColWidth ( ) ) /
( spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " spanlist max: %d of %d \n " , spanCellMaxWidth , spanInfo - > effectiveMaxWidthOfSpannedCols ) ;
if ( maxColWidth < spanCellMaxWidth ) {
1998-07-22 07:53:43 +04:00
maxColWidth = spanCellMaxWidth ; // set the new max width for the col
mTableFrame - > SetColumnWidth ( colIndex , spanCellMaxWidth ) ; // set the column to the new desired max width
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new max = %d \n " ,
1998-07-22 07:53:43 +04:00
colIndex , spanInfo - > span , maxColWidth ) ;
}
}
1999-04-04 03:02:43 +04:00
else {
1998-07-22 07:53:43 +04:00
spanCellMaxWidth = spanInfo - > cellDesiredWidth / spanInfo - > initialColSpan ;
maxColWidth = spanCellMaxWidth ;
mTableFrame - > SetColumnWidth ( colIndex , spanCellMaxWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " for spanning cell into col %d with remaining span=%d, new max = %d \n " ,
1998-07-22 07:53:43 +04:00
colIndex , spanInfo - > span , maxColWidth ) ;
}
1998-07-18 01:02:28 +04:00
}
spanInfo - > span - - ;
1999-04-04 03:02:43 +04:00
if ( 0 = = spanInfo - > span ) {
1998-07-18 01:02:28 +04:00
spanList - > RemoveElementAt ( spanIndex ) ;
delete spanInfo ;
1998-04-30 21:57:09 +04:00
}
}
1998-07-18 01:02:28 +04:00
}
1998-07-22 07:53:43 +04:00
// second, process non-fixed-width columns
1999-04-04 03:02:43 +04:00
if ( PR_FALSE = = IsFixedWidth ( colPosition , colTableStyle ) ) {
for ( rowIndex = 0 ; rowIndex < numRows ; rowIndex + + ) {
nsTableCellFrame * cellFrame = mTableFrame - > GetCellFrameAt ( rowIndex , colIndex ) ;
if ( nsnull = = cellFrame ) { // there is no cell in this row that corresponds to this column
1998-07-11 04:00:31 +04:00
continue ;
}
1999-02-11 04:16:28 +03:00
PRInt32 cellRowIndex ;
cellFrame - > GetRowIndex ( cellRowIndex ) ;
if ( rowIndex ! = cellRowIndex ) {
1998-07-11 04:00:31 +04:00
// 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
1998-06-12 02:51:54 +04:00
continue ;
}
1999-02-11 04:16:28 +03:00
PRInt32 cellColIndex ;
cellFrame - > GetColIndex ( cellColIndex ) ;
if ( colIndex ! = cellColIndex ) {
1998-07-17 03:23:31 +04:00
// For cells that span cols, we figure in the row using previously-built SpanInfo
NS_ASSERTION ( 1 ! = cellFrame - > GetColSpan ( ) , " col index does not match row span " ) ; // sanity check
continue ;
}
1998-06-06 02:50:03 +04:00
1998-07-17 03:23:31 +04:00
PRInt32 colSpan = mTableFrame - > GetEffectiveColSpan ( colIndex , cellFrame ) ;
1998-07-11 04:00:31 +04:00
nsSize cellMinSize = cellFrame - > GetPass1MaxElementSize ( ) ;
nsSize cellDesiredSize = cellFrame - > GetPass1DesiredSize ( ) ;
1998-05-22 03:43:18 +04:00
1998-12-08 04:00:14 +03:00
nscoord cellMinWidth = colFrame - > GetAdjustedMinColWidth ( ) ;
1998-07-22 07:53:43 +04:00
nscoord cellDesiredWidth = colFrame - > GetMaxColWidth ( ) ;
1999-04-04 03:02:43 +04:00
if ( 1 = = colSpan ) {
1998-07-22 07:53:43 +04:00
cellMinWidth = cellMinSize . width ;
cellDesiredWidth = cellDesiredSize . width ;
1999-04-04 03:02:43 +04:00
nscoord specifiedCellWidth = - 1 ;
1998-07-22 07:53:43 +04:00
const nsStylePosition * cellPosition ;
cellFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) cellPosition ) ;
1999-04-04 03:02:43 +04:00
if ( eStyleUnit_Percent = = cellPosition - > mWidth . GetUnit ( ) ) {
1998-06-06 02:50:03 +04:00
float percent = cellPosition - > mWidth . GetPercentValue ( ) ;
1999-04-04 03:02:43 +04:00
specifiedCellWidth = ( PRInt32 ) ( aMaxWidth * percent ) ;
TDBG_SFDD ( " specified percent width %f of %d = %d \n " , percent , aMaxWidth , specifiedCellWidth ) ;
1998-07-22 07:53:43 +04:00
}
1999-04-04 03:02:43 +04:00
if ( - 1 ! = specifiedCellWidth ) {
if ( specifiedCellWidth > cellMinWidth ) {
TDBG_SDD ( " setting cellDesiredWidth from %d to %d \n " , cellDesiredWidth , specifiedCellWidth ) ;
1998-07-22 07:53:43 +04:00
cellDesiredWidth = specifiedCellWidth ;
}
1998-06-06 02:50:03 +04:00
}
}
1999-04-04 03:02:43 +04:00
else { // colSpan>1, get the proportion for this column
1998-07-22 07:53:43 +04:00
// then get the desired size info factoring in the cell style attributes
nscoord effectiveMaxWidthOfSpannedCols = colFrame - > GetEffectiveMaxColWidth ( ) ;
nscoord effectiveMinWidthOfSpannedCols = colFrame - > GetEffectiveMinColWidth ( ) ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 span = 1 ; span < colSpan ; span + + ) {
nsTableColFrame * nextColFrame = mTableFrame - > GetColFrame ( colIndex + span ) ;
if ( nsnull = = nextColFrame ) {
1998-07-22 07:53:43 +04:00
break ;
1999-04-04 03:02:43 +04:00
}
1998-07-22 07:53:43 +04:00
effectiveMaxWidthOfSpannedCols + = nextColFrame - > GetEffectiveMaxColWidth ( ) ;
effectiveMinWidthOfSpannedCols + = nextColFrame - > GetEffectiveMinColWidth ( ) ;
}
1999-04-04 03:02:43 +04:00
nscoord specifiedCellWidth = - 1 ;
1998-07-22 07:53:43 +04:00
const nsStylePosition * cellPosition ;
cellFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) cellPosition ) ;
1999-04-04 03:02:43 +04:00
if ( eStyleUnit_Percent = = cellPosition - > mWidth . GetUnit ( ) ) {
//XXX what if table is auto width?
1998-07-22 07:53:43 +04:00
float percent = cellPosition - > mWidth . GetPercentValue ( ) ;
1999-04-04 03:02:43 +04:00
specifiedCellWidth = ( PRInt32 ) ( aMaxWidth * percent ) ;
TDBG_SFDD ( " specified percent width %f of %d = %d \n " , percent , aMaxWidth , specifiedCellWidth ) ;
1998-07-22 07:53:43 +04:00
}
1999-04-04 03:02:43 +04:00
if ( - 1 ! = specifiedCellWidth ) {
1998-07-22 07:53:43 +04:00
float percentForThisCol = ( float ) ( cellDesiredSize . width * colFrame - > GetEffectiveMaxColWidth ( ) ) /
( float ) effectiveMaxWidthOfSpannedCols ;
nscoord cellWidthForThisCol = ( nscoord ) ( specifiedCellWidth * percentForThisCol ) ;
1999-04-04 03:02:43 +04:00
if ( cellWidthForThisCol > cellMinWidth ) {
TDBG_SDD ( " setting cellDesiredWidth from %d to %d \n " , cellDesiredWidth , cellWidthForThisCol ) ;
1998-07-22 07:53:43 +04:00
cellDesiredWidth = cellWidthForThisCol ;
}
}
// otherwise it's already been factored in.
// now, if this column holds the cell, create a spanInfo struct for the cell
// so subsequent columns can take a proportion of this cell's space into account
1999-02-11 04:16:28 +03:00
PRInt32 cellColIndex ;
cellFrame - > GetColIndex ( cellColIndex ) ;
1999-04-04 03:02:43 +04:00
if ( cellColIndex = = colIndex ) {
// add this cell to span list iff we are currently processing the column the cell starts in
SpanInfo * spanInfo = new SpanInfo ( colIndex , colSpan - 1 , cellMinSize . width , cellDesiredSize . width ) ;
1998-07-22 07:53:43 +04:00
spanInfo - > effectiveMaxWidthOfSpannedCols = effectiveMaxWidthOfSpannedCols ;
spanInfo - > effectiveMinWidthOfSpannedCols = effectiveMinWidthOfSpannedCols ;
1999-04-04 03:02:43 +04:00
if ( nsnull = = spanList ) {
1998-07-22 07:53:43 +04:00
spanList = new nsVoidArray ( ) ;
1999-04-04 03:02:43 +04:00
}
1998-07-22 07:53:43 +04:00
spanList - > AppendElement ( spanInfo ) ;
1998-06-06 02:50:03 +04:00
}
}
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " factoring in cell %d with colSpan=%d \n factoring in min=%d and desired=%d \n " ,
rowIndex , colSpan , cellMinWidth , cellDesiredWidth ) ;
1998-07-07 01:00:11 +04:00
// remember the widest min cell width
1999-04-04 03:02:43 +04:00
minColWidth = PR_MAX ( minColWidth , cellMinWidth ) ;
1998-07-07 01:00:11 +04:00
// remember the max desired cell width
1999-04-04 03:02:43 +04:00
maxColWidth = PR_MAX ( maxColWidth , cellDesiredWidth ) ;
1998-07-07 01:00:11 +04:00
// effectiveMaxColumnWidth is the width as if no cells with colspans existed
1999-04-04 03:02:43 +04:00
// if ((1==colSpan) && (colFrame->GetEffectiveMaxColWidth() < maxColWidth))
// colFrame->SetEffectiveMaxColWidth(cellDesiredWidth);
TDBG_SDDDDDD ( " after cell %d, minColWidth=%d maxColWidth=%d effColWidth[%d]=%d,%d \n " ,
rowIndex , minColWidth , maxColWidth , colIndex ,
colFrame - > GetEffectiveMinColWidth ( ) , colFrame - > GetEffectiveMaxColWidth ( ) ) ;
1998-04-30 21:57:09 +04:00
}
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = gsDebug ) {
printf ( " for determining width of col %d %s: \n " ,
colIndex , ! IsFixedWidth ( colPosition , colTableStyle ) ? " (P) " : " (A) " ) ;
printf ( " minTableWidth = %d and maxTableWidth = %d \n " ,
mMinTableWidth , mMaxTableWidth ) ;
printf ( " minColWidth = %d, maxColWidth = %d, eff=%d,%d \n " ,
minColWidth , maxColWidth , colFrame - > GetEffectiveMinColWidth ( ) ,
colFrame - > GetEffectiveMaxColWidth ( ) ) ;
printf ( " aAvailWidth = %d \n " , aAvailWidth ) ;
}
1998-04-30 21:57:09 +04:00
1998-05-30 02:08:19 +04:00
// Get column width if it has one
1998-06-06 02:50:03 +04:00
nscoord specifiedProportionColumnWidth = - 1 ;
1998-05-30 02:08:19 +04:00
float specifiedPercentageColWidth = - 1.0f ;
PRBool isAutoWidth = PR_FALSE ;
switch ( colPosition - > mWidth . GetUnit ( ) ) {
case eStyleUnit_Percent :
specifiedPercentageColWidth = colPosition - > mWidth . GetPercentValue ( ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDF ( " column %d has specified percent width = %f \n " , colIndex , specifiedPercentageColWidth ) ;
1998-05-30 02:08:19 +04:00
break ;
case eStyleUnit_Proportional :
1998-06-06 02:50:03 +04:00
specifiedProportionColumnWidth = colPosition - > mWidth . GetIntValue ( ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " column %d has specified percent width = %d \n " , colIndex , specifiedProportionColumnWidth ) ;
1998-05-30 02:08:19 +04:00
break ;
case eStyleUnit_Auto :
isAutoWidth = PR_TRUE ;
break ;
default :
break ;
}
1999-04-04 03:02:43 +04:00
// set the column width, knowing that the table is constrained
if ( 0 = = specifiedProportionColumnWidth | | 0.0 = = specifiedPercentageColWidth ) {
// col width is specified to be the minimum
1998-05-27 02:03:16 +04:00
mTableFrame - > SetColumnWidth ( colIndex , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " 4 (0): col %d set to min width = %d because style set proportionalWidth=0 \n " ,
colIndex , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-05-27 02:03:16 +04:00
}
1999-04-04 03:02:43 +04:00
else if ( 1 = = mNumCols ) { // there is only one column, and we know that it's desired width doesn't fit
1998-09-10 00:00:40 +04:00
// so the column should be as wide as the available space allows it to be minus cell spacing
nscoord colWidth = aAvailWidth - ( 2 * colInset ) ;
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " 4 one-col: col %d set to width = %d from available width %d and cell spacing %d \n " ,
colIndex , mTableFrame - > GetColumnWidth ( colIndex ) , aAvailWidth , colInset ) ;
1998-05-27 02:03:16 +04:00
}
1999-04-04 03:02:43 +04:00
else if ( PR_TRUE = = isAutoWidth ) { // column's width is determined by its content, done in post-processing
1998-10-01 22:39:31 +04:00
mTableFrame - > SetColumnWidth ( colIndex , minColWidth ) ; // reserve the column's min width
1998-07-07 01:00:11 +04:00
atLeastOneAutoWidthColumn = PR_TRUE ;
1998-05-27 02:03:16 +04:00
}
1999-04-04 03:02:43 +04:00
else if ( - 1 ! = specifiedProportionColumnWidth ) {
// we need to save these and do them after all other columns have been calculated
// the calculation will be:
// sum up n, the total number of slices for the columns with proportional width
// compute the table "required" width, fixed-width + percentage-width +
// the sum of the proportional column's max widths (especially because in this routine I know the table fits)
// compute the remaining width: the required width - the used width (fixed + percentage)
// compute the width per slice
// set the width of each proportional-width column to it's number of slices * width per slice
1998-05-30 02:08:19 +04:00
mTableFrame - > SetColumnWidth ( colIndex , 0 ) ; // set the column width to 0, since it isn't computed yet
1999-04-04 03:02:43 +04:00
if ( nsnull = = proportionalColumnsList ) {
1998-05-30 02:08:19 +04:00
proportionalColumnsList = new nsVoidArray ( ) ;
1999-04-04 03:02:43 +04:00
}
ProportionalColumnLayoutStruct * info =
1998-06-06 02:50:03 +04:00
new ProportionalColumnLayoutStruct ( colIndex , minColWidth , maxColWidth , specifiedProportionColumnWidth ) ;
1998-05-30 02:08:19 +04:00
proportionalColumnsList - > AppendElement ( info ) ;
1998-06-06 02:50:03 +04:00
totalSlices + = specifiedProportionColumnWidth ;
1999-04-04 03:02:43 +04:00
if ( 1 ! = specifiedProportionColumnWidth ) {
1998-06-02 00:21:05 +04:00
equalWidthColumns = PR_FALSE ;
1999-04-04 03:02:43 +04:00
}
1998-05-30 02:08:19 +04:00
}
1999-04-04 03:02:43 +04:00
else { // give the column a percentage of the remaining space
1998-05-30 02:08:19 +04:00
PRInt32 percentage = - 1 ;
1999-04-04 03:02:43 +04:00
if ( NS_UNCONSTRAINEDSIZE = = aAvailWidth ) {
// since the "remaining space" is infinite, give the column it's max requested size
1998-05-30 02:08:19 +04:00
mTableFrame - > SetColumnWidth ( colIndex , maxColWidth ) ;
}
1999-04-04 03:02:43 +04:00
else {
if ( - 1.0f ! = specifiedPercentageColWidth ) {
percentage = ( PRInt32 ) ( specifiedPercentageColWidth * 100.0f ) ; // TODO: rounding errors?
1998-06-06 02:50:03 +04:00
// base the % on the total specified fixed width of the table
mTableFrame - > SetColumnWidth ( colIndex , ( percentage * aMaxWidth ) / 100 ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " 4 percent specified: col %d given %d percent of aMaxWidth %d, set to width = %d \n " ,
colIndex , percentage , aMaxWidth , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-06-06 02:50:03 +04:00
}
1999-04-04 03:02:43 +04:00
if ( - 1 = = percentage ) {
percentage = 100 / mNumCols ;
1998-06-06 02:50:03 +04:00
// base the % on the remaining available width
1999-04-04 03:02:43 +04:00
mTableFrame - > SetColumnWidth ( colIndex , ( percentage * aAvailWidth ) / 100 ) ;
TDBG_SDDDD ( " 4 percent default: col %d given %d percent of aAvailWidth %d, set to width = %d \n " ,
colIndex , percentage , aAvailWidth , mTableFrame - > GetColumnWidth ( colIndex ) ) ;
1998-06-06 02:50:03 +04:00
}
1998-05-30 02:08:19 +04:00
// if the column was computed to be too small, enlarge the column
1999-04-04 03:02:43 +04:00
if ( mTableFrame - > GetColumnWidth ( colIndex ) < = minColWidth ) {
1998-05-30 02:08:19 +04:00
mTableFrame - > SetColumnWidth ( colIndex , minColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " enlarging column to it's minimum = %d \n " , minColWidth ) ;
if ( maxOfAllMinColWidths < minColWidth ) {
1998-05-30 02:08:19 +04:00
maxOfAllMinColWidths = minColWidth ;
1999-04-04 03:02:43 +04:00
TDBG_SD ( " and setting maxOfAllMins to %d \n " , maxOfAllMinColWidths ) ;
1998-06-06 02:50:03 +04:00
}
1998-05-30 02:08:19 +04:00
}
1998-05-27 02:03:16 +04:00
}
1998-04-30 21:57:09 +04:00
}
}
1999-04-04 03:02:43 +04:00
else {
1998-08-14 20:16:43 +04:00
mTableFrame - > SetColumnWidth ( colIndex , colFrame - > GetMaxColWidth ( ) ) ;
}
1998-07-22 07:53:43 +04:00
tableWidth + = mTableFrame - > GetColumnWidth ( colIndex ) + colInset ;
1998-04-30 21:57:09 +04:00
}
1998-09-10 00:00:40 +04:00
tableWidth + = colInset ;
1999-04-04 03:02:43 +04:00
// --- post-process if necessary --- /
1998-07-17 03:23:31 +04:00
// first, assign autoWidth columns a width
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = atLeastOneAutoWidthColumn ) {
// proportionately distribute the remaining space to autowidth columns
1998-10-01 22:39:31 +04:00
// "0" for the last param tells DistributeRemainingSpace that this is the top (non-recursive) call
PRInt32 topRecursiveControl = 0 ;
DistributeRemainingSpace ( aMaxWidth , tableWidth , aTableIsAutoWidth , topRecursiveControl ) ;
1998-07-07 01:00:11 +04:00
}
1998-07-17 03:23:31 +04:00
// second, fix up tables where column width attributes give us a table that is too wide or too narrow
1999-04-04 03:02:43 +04:00
nscoord computedWidth = colInset ;
for ( PRInt32 i = 0 ; i < mNumCols ; i + + ) {
1998-11-04 22:33:27 +03:00
computedWidth + = mTableFrame - > GetColumnWidth ( i ) + colInset ;
}
1999-04-04 03:02:43 +04:00
if ( computedWidth < aMaxWidth ) {
// then widen the table because it's too narrow
1998-11-04 22:33:27 +03:00
// do not widen auto-width tables, they shrinkwrap to their content's width
1999-04-04 03:02:43 +04:00
if ( PR_FALSE = = aTableIsAutoWidth ) {
1998-11-04 22:33:27 +03:00
AdjustTableThatIsTooNarrow ( computedWidth , aMaxWidth ) ;
1999-04-04 03:02:43 +04:00
}
1998-11-04 22:33:27 +03:00
}
1999-04-04 03:02:43 +04:00
else if ( computedWidth > aMaxWidth ) {
// then shrink the table width because its too wide
1998-11-04 22:33:27 +03:00
AdjustTableThatIsTooWide ( computedWidth , aMaxWidth , PR_FALSE ) ;
1998-07-17 03:23:31 +04:00
}
// finally, assign a width to proportional-width columns
1999-04-04 03:02:43 +04:00
if ( nsnull ! = proportionalColumnsList ) {
1998-05-30 02:08:19 +04:00
// first, figure out the amount of space per slice
nscoord widthRemaining = aMaxWidth - tableWidth ;
1999-04-04 03:02:43 +04:00
nscoord widthPerSlice = widthRemaining / totalSlices ;
1998-05-30 02:08:19 +04:00
PRInt32 numSpecifiedProportionalColumns = proportionalColumnsList - > Count ( ) ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 i = 0 ; i < numSpecifiedProportionalColumns ; i + + ) {
ProportionalColumnLayoutStruct * info =
1998-05-30 02:08:19 +04:00
( ProportionalColumnLayoutStruct * ) ( proportionalColumnsList - > ElementAt ( i ) ) ;
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = equalWidthColumns & & 0 ! = maxOfAllMinColWidths ) {
TDBG_SDD ( " EqualColWidths specified and some column couldn't fit, so setting col %d width to %d \n " ,
1998-06-02 00:21:05 +04:00
info - > mColIndex , maxOfAllMinColWidths ) ;
mTableFrame - > SetColumnWidth ( info - > mColIndex , maxOfAllMinColWidths ) ;
}
1999-04-04 03:02:43 +04:00
else {
1998-08-20 21:31:20 +04:00
// compute the requested proportional width
1999-04-04 03:02:43 +04:00
nscoord computedColWidth = info - > mProportion * widthPerSlice ;
1998-08-20 21:31:20 +04:00
// verify that the computed width is at least the minimum width
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
1998-08-20 21:31:20 +04:00
mTableFrame - > GetColumnFrame ( info - > mColIndex , colFrame ) ;
nscoord minColWidth = colFrame - > GetMinColWidth ( ) ;
computedColWidth = PR_MAX ( computedColWidth , minColWidth ) ;
1998-06-02 00:21:05 +04:00
mTableFrame - > SetColumnWidth ( info - > mColIndex , computedColWidth ) ;
1999-04-04 03:02:43 +04:00
TDBG_SDDDD ( " 4 proportion: col %d given %d proportion of remaining space %d, set to width = %d \n " ,
info - > mColIndex , info - > mProportion , widthRemaining , computedColWidth ) ;
1998-06-02 00:21:05 +04:00
}
1998-05-30 02:08:19 +04:00
delete info ;
}
delete proportionalColumnsList ;
}
1998-07-07 01:00:11 +04:00
// clean up
1999-04-04 03:02:43 +04:00
if ( nsnull ! = spanList ) {
TDBG_S ( " BTLS::BCTConstrained...space leak, span list not empty " ) ;
1998-04-30 21:57:09 +04:00
delete spanList ;
1998-07-13 22:11:12 +04:00
}
1998-04-30 21:57:09 +04:00
return result ;
}
1999-04-04 03:02:43 +04:00
static const PRInt32 kRecursionLimit = 10 ; // backwards compatible with Nav4
1998-10-01 22:39:31 +04:00
1998-07-07 01:00:11 +04:00
// take the remaining space in the table and distribute it proportionately
// to the auto-width cells in the table (based on desired width)
1998-07-17 03:23:31 +04:00
void BasicTableLayoutStrategy : : DistributeRemainingSpace ( nscoord aTableSpecifiedWidth ,
1999-04-04 03:02:43 +04:00
nscoord & aComputedTableWidth ,
1998-10-01 22:39:31 +04:00
PRBool aTableIsAutoWidth ,
1999-04-04 03:02:43 +04:00
PRInt32 & aRecursionControl )
1998-07-07 01:00:11 +04:00
{
1998-10-01 22:39:31 +04:00
aRecursionControl + + ;
1999-04-04 03:02:43 +04:00
if ( kRecursionLimit < = aRecursionControl ) { // only allow kRecursionLimit iterations, as per Nav4. See laytable.c
1998-10-01 22:39:31 +04:00
return ;
1999-04-04 03:02:43 +04:00
}
1998-10-01 22:39:31 +04:00
nscoord sumOfMinWidths = 0 ; // sum of min widths of each auto column
1998-12-08 04:00:14 +03:00
nscoord startingComputedTableWidth = aComputedTableWidth ; // remember this so we can see if we're making any progress
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " DistributeRemainingSpace: fixed width %d > computed table width %d \n " ,
aTableSpecifiedWidth , aComputedTableWidth ) ;
1998-07-07 01:00:11 +04:00
// if there are auto-sized columns, give them the extra space
1999-04-04 03:02:43 +04:00
PRInt32 numAutoColumns = 0 ;
PRInt32 * autoColumns = nsnull ;
1998-07-07 01:00:11 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Auto , numAutoColumns , autoColumns ) ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = numAutoColumns ) {
PRInt32 numColumnsToBeResized = 0 ;
1998-07-07 01:00:11 +04:00
// 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 ;
// 1. first, get the total width of the auto columns
PRInt32 i ;
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numAutoColumns ; i + + ) {
1998-10-01 22:39:31 +04:00
PRInt32 colIndex = autoColumns [ i ] ;
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( autoColumns [ i ] ) ;
1998-10-01 22:39:31 +04:00
nscoord startingColWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
1998-07-17 03:23:31 +04:00
nscoord maxEffectiveColWidth = colFrame - > GetEffectiveMaxColWidth ( ) ;
1999-04-04 03:02:43 +04:00
if ( ( PR_FALSE = = aTableIsAutoWidth ) | | ( startingColWidth < maxEffectiveColWidth ) ) {
1998-10-01 22:39:31 +04:00
numColumnsToBeResized + + ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = maxEffectiveColWidth ) {
1998-10-01 22:39:31 +04:00
totalEffectiveWidthOfAutoColumns + = maxEffectiveColWidth ;
1999-04-04 03:02:43 +04:00
}
else {
1998-10-01 22:39:31 +04:00
totalEffectiveWidthOfAutoColumns + = mTableFrame - > GetColumnWidth ( autoColumns [ i ] ) ;
1999-04-04 03:02:43 +04:00
}
1998-10-01 22:39:31 +04:00
}
1998-07-07 01:00:11 +04:00
}
1998-08-14 20:16:43 +04:00
// availWidth is the difference between the total available width and the
// amount of space already assigned, assuming auto col widths were assigned 0.
nscoord availWidth ;
availWidth = aTableSpecifiedWidth - aComputedTableWidth ;
1999-04-04 03:02:43 +04:00
TDBG_SDD ( " aTableSpecifiedWidth specified as %d, availWidth is = %d \n " , aTableSpecifiedWidth , availWidth ) ;
1998-07-07 01:00:11 +04:00
// 2. next, compute the proportion to be added to each column, and add it
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numAutoColumns ; i + + ) {
1998-07-07 01:00:11 +04:00
PRInt32 colIndex = autoColumns [ i ] ;
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
1998-10-01 22:39:31 +04:00
nscoord startingColWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
nscoord maxEffectiveColWidth = colFrame - > GetEffectiveMaxColWidth ( ) ;
1998-07-17 03:23:31 +04:00
// if we actually have room to distribute, do it here
1998-10-01 22:39:31 +04:00
// otherwise, the auto columns already are set to their minimum
1999-04-04 03:02:43 +04:00
if ( 0 < availWidth ) {
if ( ( PR_FALSE = = aTableIsAutoWidth ) | | ( startingColWidth < maxEffectiveColWidth ) ) {
1998-10-01 22:39:31 +04:00
float percent ;
1999-04-04 03:02:43 +04:00
if ( 0 ! = aTableSpecifiedWidth ) {
1998-10-01 22:39:31 +04:00
percent = ( ( float ) maxEffectiveColWidth ) / ( ( float ) totalEffectiveWidthOfAutoColumns ) ;
1999-04-04 03:02:43 +04:00
}
else {
percent = ( ( float ) 1 ) / ( ( float ) numColumnsToBeResized ) ;
}
nscoord colWidth = startingColWidth + NSToCoordRound ( ( ( float ) ( availWidth ) ) * percent ) ;
TDBG_SDDDD ( " colWidth = %d from startingColWidth %d plus %d percent of availWidth %d \n " ,
colWidth , startingColWidth , ( nscoord ) ( ( float ) 100 * percent ) , availWidth ) ;
1998-10-01 22:39:31 +04:00
// in an auto width table, the column cannot be wider than its max width
1999-04-04 03:02:43 +04:00
if ( PR_TRUE = = aTableIsAutoWidth ) {
// since the table shrinks to the content width, don't be wider than the content max width
1998-10-06 12:00:07 +04:00
colWidth = PR_MIN ( colWidth , colFrame - > GetMaxColWidth ( ) ) ;
1998-10-01 22:39:31 +04:00
}
1998-10-06 12:00:07 +04:00
aComputedTableWidth + = colWidth - startingColWidth ;
1999-04-04 03:02:43 +04:00
TDBG_SDDD ( " distribute width to auto columns: column %d was %d, now set to %d \n " ,
colIndex , colFrame - > GetEffectiveMaxColWidth ( ) , colWidth ) ;
1998-10-01 22:39:31 +04:00
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
1998-08-14 20:16:43 +04:00
}
1998-07-17 03:23:31 +04:00
}
}
1999-04-04 03:02:43 +04:00
if ( aComputedTableWidth ! = startingComputedTableWidth ) {
// othewise we made no progress and shouldn't continue
if ( aComputedTableWidth < aTableSpecifiedWidth ) {
1998-10-01 22:39:31 +04:00
DistributeRemainingSpace ( aTableSpecifiedWidth , aComputedTableWidth , aTableIsAutoWidth , aRecursionControl ) ;
1998-07-22 07:53:43 +04:00
}
1998-07-07 01:00:11 +04:00
}
1998-07-17 03:23:31 +04:00
}
1999-04-04 03:02:43 +04:00
TDBG_WIDTHS4 ( " at end of DistributeRemainingSpace: " , PR_FALSE , PR_FALSE ) ;
1998-07-11 04:00:31 +04:00
}
1998-07-25 03:26:23 +04:00
1998-07-17 03:23:31 +04:00
void BasicTableLayoutStrategy : : AdjustTableThatIsTooWide ( nscoord aComputedWidth ,
1998-11-24 22:41:33 +03:00
nscoord aTableWidth ,
PRBool aShrinkFixedCols )
1998-07-17 03:23:31 +04:00
{
1999-04-04 03:02:43 +04:00
TDBG_WIDTHS4 ( " before AdjustTableThatIsTooWide: " , PR_FALSE , PR_FALSE ) ;
1998-07-22 07:53:43 +04:00
1999-04-04 03:02:43 +04:00
PRInt32 numFixedColumns = 0 ;
PRInt32 * fixedColumns = nsnull ;
1998-07-25 03:26:23 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Coord , numFixedColumns , fixedColumns ) ;
1999-04-04 03:02:43 +04:00
PRInt32 numAutoColumns = 0 ;
PRInt32 * autoColumns = nsnull ;
1998-11-24 22:41:33 +03:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Auto , numAutoColumns , autoColumns ) ;
1998-07-17 03:23:31 +04:00
nscoord excess = aComputedWidth - aTableWidth ;
1998-07-24 01:55:45 +04:00
nscoord minDiff ; // the smallest non-zero delta between a column's current width and its min width
1999-04-04 03:02:43 +04:00
PRInt32 * colsToShrink = new PRInt32 [ mNumCols ] ;
1998-07-24 01:55:45 +04:00
// while there is still extra computed space in the table
1999-04-04 03:02:43 +04:00
while ( 0 < excess ) {
1998-07-24 01:55:45 +04:00
// reinit state variables
PRInt32 colIndex ;
1999-04-04 03:02:43 +04:00
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
colsToShrink [ colIndex ] = 0 ;
}
minDiff = 0 ;
1998-07-24 01:55:45 +04:00
1998-11-24 22:41:33 +03:00
// determine what columns we can remove width from
1998-07-24 01:55:45 +04:00
PRInt32 numColsToShrink = 0 ;
1999-04-04 03:02:43 +04:00
PRBool shrinkAutoOnly = PR_TRUE ;
PRBool keepLooking = PR_TRUE ;
while ( PR_TRUE = = keepLooking ) {
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
1998-11-24 22:41:33 +03:00
nscoord currentColWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
1999-04-04 03:02:43 +04:00
nsTableColFrame * colFrame ;
1998-11-24 22:41:33 +03:00
mTableFrame - > GetColumnFrame ( colIndex , colFrame ) ;
nscoord minColWidth = colFrame - > GetAdjustedMinColWidth ( ) ;
1999-04-04 03:02:43 +04:00
if ( currentColWidth = = minColWidth ) {
1998-11-24 22:41:33 +03:00
continue ;
1999-04-04 03:02:43 +04:00
}
1998-11-24 22:41:33 +03:00
if ( ( PR_FALSE = = aShrinkFixedCols ) & &
1999-04-04 03:02:43 +04:00
( PR_TRUE = = IsColumnInList ( colIndex , fixedColumns , numFixedColumns ) ) ) {
1998-11-24 22:41:33 +03:00
continue ;
1999-04-04 03:02:43 +04:00
}
1998-11-24 22:41:33 +03:00
if ( ( PR_TRUE = = shrinkAutoOnly ) & &
1999-04-04 03:02:43 +04:00
( PR_FALSE = = IsColumnInList ( colIndex , autoColumns , numAutoColumns ) ) ) {
1998-11-24 22:41:33 +03:00
continue ;
1999-04-04 03:02:43 +04:00
}
1998-11-24 22:41:33 +03:00
colsToShrink [ numColsToShrink ] = colIndex ;
numColsToShrink + + ;
nscoord diff = currentColWidth - minColWidth ;
1999-04-04 03:02:43 +04:00
if ( ( 0 = = minDiff ) | | ( diff < minDiff ) ) {
1998-11-24 22:41:33 +03:00
minDiff = diff ;
1999-04-04 03:02:43 +04:00
}
}
if ( PR_FALSE = = shrinkAutoOnly ) {
keepLooking = PR_FALSE ; // we've looked everywhere, so bail. this breaks us out of the loop
}
if ( 0 ! = numColsToShrink ) {
keepLooking = PR_FALSE ; // we found at least one column to shrink, so bail. this breaks us out of the loop
1998-11-24 22:41:33 +03:00
}
1999-04-04 03:02:43 +04:00
shrinkAutoOnly = PR_FALSE ; // this guarantees we'll go through this loop only one more time
1998-07-24 01:55:45 +04:00
}
// if there are no columns we can remove space from, we're done
1999-04-04 03:02:43 +04:00
if ( 0 = = numColsToShrink ) {
1998-07-24 01:55:45 +04:00
break ;
1999-04-04 03:02:43 +04:00
}
1998-07-24 01:55:45 +04:00
// determine the amount to remove from each column
nscoord excessPerColumn ;
1999-04-04 03:02:43 +04:00
if ( excess < numColsToShrink ) {
excessPerColumn = 1 ;
}
else {
excessPerColumn = excess / numColsToShrink ; // guess we can remove as much as we want
}
if ( excessPerColumn > minDiff ) { // then adjust for minimum col widths
excessPerColumn = minDiff ;
}
1998-07-24 01:55:45 +04:00
// remove excessPerColumn from every column we've determined we can remove width from
1999-04-04 03:02:43 +04:00
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
if ( ( PR_TRUE = = IsColumnInList ( colIndex , colsToShrink , numColsToShrink ) ) ) {
1998-07-17 03:23:31 +04:00
nscoord colWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
colWidth - = excessPerColumn ;
1998-07-24 01:55:45 +04:00
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
excess - = excessPerColumn ;
1999-04-04 03:02:43 +04:00
if ( 0 = = excess ) {
1998-07-24 01:55:45 +04:00
break ;
1999-04-04 03:02:43 +04:00
}
1998-07-17 03:23:31 +04:00
}
}
1999-04-04 03:02:43 +04:00
} // end while (0 < excess)
TDBG_WIDTHS4 ( " after AdjustTableThatIsTooWide: " , PR_TRUE , aShrinkFixedCols ) ;
1998-07-24 01:55:45 +04:00
delete [ ] colsToShrink ;
// deal with any excess left over
1999-04-04 03:02:43 +04:00
if ( ( PR_FALSE = = aShrinkFixedCols ) & & ( 0 ! = excess ) ) {
1998-07-24 01:55:45 +04:00
// if there's any excess left, we know we've shrunk every non-fixed column to its min
// so we have to shrink fixed width columns if possible
AdjustTableThatIsTooWide ( aComputedWidth , aTableWidth , PR_TRUE ) ;
}
// otherwise we've shrunk the table to its min, and that's all we can do
1998-07-17 03:23:31 +04:00
}
1998-07-25 03:26:23 +04:00
1998-07-17 03:23:31 +04:00
void BasicTableLayoutStrategy : : AdjustTableThatIsTooNarrow ( nscoord aComputedWidth ,
nscoord aTableWidth )
{
1999-04-04 03:02:43 +04:00
TDBG_WIDTHS4 ( " before AdjustTableThatIsTooNarrow: " , PR_FALSE , PR_FALSE ) ;
1998-07-22 07:53:43 +04:00
1998-07-17 03:23:31 +04:00
PRInt32 numFixedColumns = 0 ;
1999-04-04 03:02:43 +04:00
PRInt32 * fixedColumns = nsnull ;
1998-07-25 03:26:23 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Coord , numFixedColumns , fixedColumns ) ;
1998-07-17 03:23:31 +04:00
nscoord excess = aTableWidth - aComputedWidth ;
1999-04-04 03:02:43 +04:00
while ( 0 < excess ) {
1998-07-25 03:26:23 +04:00
PRInt32 colIndex ;
1999-04-04 03:02:43 +04:00
PRInt32 * colsToGrow = new PRInt32 [ mNumCols ] ;
1998-07-25 03:26:23 +04:00
// determine what columns we can take add width to
PRInt32 numColsToGrow = 0 ;
1999-04-04 03:02:43 +04:00
PRBool expandFixedCols = PRBool ( mNumCols = = numFixedColumns ) ;
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
if ( ( PR_FALSE = = expandFixedCols ) & &
( PR_TRUE = = IsColumnInList ( colIndex , fixedColumns , numFixedColumns ) ) ) {
1998-08-14 20:16:43 +04:00
// skip fixed-width cells if we're told to
continue ;
1999-04-04 03:02:43 +04:00
}
if ( PR_TRUE = = ColIsSpecifiedAsMinimumWidth ( colIndex ) ) {
1998-08-14 20:16:43 +04:00
// skip columns that are forced by their attributes to be their minimum width
1998-07-25 03:26:23 +04:00
continue ;
1999-04-04 03:02:43 +04:00
}
1998-07-25 03:26:23 +04:00
colsToGrow [ numColsToGrow ] = colIndex ;
numColsToGrow + + ;
}
1999-04-04 03:02:43 +04:00
if ( 0 ! = numColsToGrow ) {
1998-08-14 20:16:43 +04:00
nscoord excessPerColumn ;
1999-04-04 03:02:43 +04:00
if ( excess < numColsToGrow ) {
excessPerColumn = 1 ;
}
else {
excessPerColumn = excess / numColsToGrow ;
}
for ( colIndex = 0 ; colIndex < mNumCols ; colIndex + + ) {
if ( ( PR_TRUE = = IsColumnInList ( colIndex , colsToGrow , numColsToGrow ) ) ) {
nsTableColFrame * colFrame = mTableFrame - > GetColFrame ( colIndex ) ;
1998-08-14 20:16:43 +04:00
nscoord colWidth = mTableFrame - > GetColumnWidth ( colIndex ) ;
colWidth + = excessPerColumn ;
1999-04-04 03:02:43 +04:00
if ( colWidth > colFrame - > GetMinColWidth ( ) ) {
1998-08-14 20:16:43 +04:00
excess - = excessPerColumn ;
mTableFrame - > SetColumnWidth ( colIndex , colWidth ) ;
}
1999-04-04 03:02:43 +04:00
else {
1998-08-14 20:16:43 +04:00
excess - = mTableFrame - > GetColumnWidth ( colIndex ) - colFrame - > GetMinColWidth ( ) ;
mTableFrame - > SetColumnWidth ( colIndex , colFrame - > GetMinColWidth ( ) ) ;
}
1999-04-04 03:02:43 +04:00
if ( 0 > = excess ) {
1998-08-14 20:16:43 +04:00
break ;
1999-04-04 03:02:43 +04:00
}
1998-07-25 03:26:23 +04:00
}
1998-07-17 03:23:31 +04:00
}
}
1998-07-27 09:32:50 +04:00
delete [ ] colsToGrow ;
1999-04-04 03:02:43 +04:00
if ( 0 = = numColsToGrow ) {
1998-08-14 20:16:43 +04:00
break ;
1998-07-22 07:53:43 +04:00
}
1999-04-04 03:02:43 +04:00
} // end while (0 < excess)
TDBG_WIDTHS4 ( " after AdjustTableThatIsTooNarrow: " , PR_FALSE , PR_FALSE ) ;
1998-07-17 03:23:31 +04:00
}
1998-07-24 01:55:45 +04:00
PRBool BasicTableLayoutStrategy : : IsColumnInList ( const PRInt32 colIndex ,
1999-04-04 03:02:43 +04:00
PRInt32 * colIndexes ,
PRInt32 aNumFixedColumns )
1998-07-24 01:55:45 +04:00
{
PRBool result = PR_FALSE ;
1999-04-04 03:02:43 +04:00
for ( PRInt32 i = 0 ; i < aNumFixedColumns ; i + + ) {
if ( colIndex = = colIndexes [ i ] ) {
1998-07-24 01:55:45 +04:00
result = PR_TRUE ;
break ;
}
1999-04-04 03:02:43 +04:00
else if ( colIndex < colIndexes [ i ] ) {
1998-07-24 01:55:45 +04:00
break ;
1999-04-04 03:02:43 +04:00
}
1998-07-24 01:55:45 +04:00
}
return result ;
}
1998-07-17 03:23:31 +04:00
1998-08-14 20:16:43 +04:00
PRBool BasicTableLayoutStrategy : : ColIsSpecifiedAsMinimumWidth ( PRInt32 aColIndex )
{
PRBool result = PR_FALSE ;
nsTableColFrame * colFrame ;
mTableFrame - > GetColumnFrame ( aColIndex , colFrame ) ;
const nsStylePosition * colPosition ;
1998-11-20 12:29:58 +03:00
colFrame - > GetStyleData ( eStyleStruct_Position , ( const nsStyleStruct * & ) colPosition ) ;
1999-04-04 03:02:43 +04:00
switch ( colPosition - > mWidth . GetUnit ( ) ) {
1998-08-14 20:16:43 +04:00
case eStyleUnit_Coord :
1999-04-04 03:02:43 +04:00
if ( 0 = = colPosition - > mWidth . GetCoordValue ( ) ) {
1998-08-14 20:16:43 +04:00
result = PR_TRUE ;
1999-04-04 03:02:43 +04:00
}
1998-08-14 20:16:43 +04:00
break ;
case eStyleUnit_Percent :
{
// total hack for now for 0% and 1% specifications
// should compare percent to available parent width and see that it is below minimum
// for this column
float percent = colPosition - > mWidth . GetPercentValue ( ) ;
1999-04-04 03:02:43 +04:00
if ( 0.0f = = percent | | 0.01f = = percent ) {
1998-08-14 20:16:43 +04:00
result = PR_TRUE ;
1999-04-04 03:02:43 +04:00
}
1998-08-14 20:16:43 +04:00
break ;
}
case eStyleUnit_Proportional :
1999-04-04 03:02:43 +04:00
if ( 0 = = colPosition - > mWidth . GetIntValue ( ) ) {
result = PR_TRUE ;
}
1999-02-12 20:45:58 +03:00
default :
break ;
1998-08-14 20:16:43 +04:00
}
return result ;
}
1998-10-03 00:34:11 +04:00
// returns a list and count of all columns that behave like they have width=auto
// this includes columns with no width specified, and columns whose fixed width comes from a span
1999-04-04 03:02:43 +04:00
void BasicTableLayoutStrategy : : GetColumnsThatActLikeAutoWidth ( PRInt32 & aNumCols ,
PRInt32 * & aColList )
1998-10-03 00:34:11 +04:00
{
// initialize out params
1999-04-04 03:02:43 +04:00
aNumCols = 0 ;
aColList = nsnull ;
1998-10-03 00:34:11 +04:00
// get the auto columns
PRInt32 numAutoCols = 0 ;
1999-04-04 03:02:43 +04:00
PRInt32 * autoColList = nsnull ;
1998-10-03 00:34:11 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Auto , numAutoCols , autoColList ) ;
// XXX: have to do next step for %-width as well?
// get the fixed columns
PRInt32 numFixedCols = 0 ;
1999-04-04 03:02:43 +04:00
PRInt32 * fixedColList = nsnull ;
1998-10-03 00:34:11 +04:00
mTableFrame - > GetColumnsByType ( eStyleUnit_Coord , numFixedCols , fixedColList ) ;
1999-04-04 03:02:43 +04:00
if ( 0 < numAutoCols + numFixedCols ) {
1998-10-03 00:34:11 +04:00
// allocate the out param aColList to the biggest it could be (usually a little wasteful, but it's
// temp space and the numbers here are small, even for very big tables
aColList = new PRInt32 [ numAutoCols + numFixedCols ] ;
// transfer the auto columns to aColList
PRInt32 i ;
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numAutoCols ; i + + ) {
aColList [ i ] = autoColList [ i ] ;
1998-10-03 00:34:11 +04:00
aNumCols + + ;
}
// get the columns whose fixed width is due to a colspan and transfer them to aColList
1999-04-04 03:02:43 +04:00
for ( i = 0 ; i < numFixedCols ; i + + ) {
nsTableColFrame * colFrame ;
1998-10-03 00:34:11 +04:00
mTableFrame - > GetColumnFrame ( fixedColList [ i ] , colFrame ) ;
1999-04-04 03:02:43 +04:00
if ( nsTableColFrame : : eWIDTH_SOURCE_CELL_WITH_SPAN = = colFrame - > GetWidthSource ( ) ) {
1998-10-03 00:34:11 +04:00
aColList [ aNumCols ] = fixedColList [ i ] ;
aNumCols + + ;
}
}
}
return ;
}
1998-08-14 20:16:43 +04:00
1998-04-30 21:57:09 +04:00