1998-09-23 06:32:15 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/NPL/
|
1998-09-23 06:32:15 +04:00
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1998-09-23 06:32:15 +04:00
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1998-09-23 06:32:15 +04:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 06:40:37 +03:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1998-09-23 06:32:15 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "FixedTableLayoutStrategy.h"
|
|
|
|
#include "nsTableFrame.h"
|
|
|
|
#include "nsTableCellFrame.h"
|
|
|
|
#include "nsIStyleContext.h"
|
|
|
|
#include "nsStyleConsts.h"
|
|
|
|
#include "nsVoidArray.h"
|
|
|
|
#include "nsHTMLIIDs.h"
|
|
|
|
|
1998-10-20 03:43:06 +04:00
|
|
|
FixedTableLayoutStrategy::FixedTableLayoutStrategy(nsTableFrame *aFrame)
|
|
|
|
: BasicTableLayoutStrategy(aFrame)
|
1998-09-23 06:32:15 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FixedTableLayoutStrategy::~FixedTableLayoutStrategy()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2000-01-22 04:16:50 +03:00
|
|
|
PRBool FixedTableLayoutStrategy::BalanceColumnWidths(nsIPresContext* aPresContext,
|
|
|
|
nsIStyleContext* aTableStyle,
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
1999-07-28 12:09:02 +04:00
|
|
|
nscoord aMaxWidth)
|
1998-09-23 06:32:15 +04:00
|
|
|
{
|
1999-07-28 12:09:02 +04:00
|
|
|
return PR_TRUE;
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
|
|
|
|
1999-06-03 06:42:33 +04:00
|
|
|
/*
|
|
|
|
* assign the width of all columns
|
1998-09-23 06:32:15 +04:00
|
|
|
* if there is a colframe with a width attribute, use it as the column width
|
|
|
|
* otherwise if there is a cell in the first row and it has a width attribute, use it
|
|
|
|
* if this cell includes a colspan, width is divided equally among spanned columns
|
|
|
|
* otherwise the cell get a proportion of the remaining space
|
|
|
|
* as determined by the table width attribute. If no table width attribute, it gets 0 width
|
|
|
|
*/
|
2000-02-12 04:55:40 +03:00
|
|
|
PRBool
|
2000-09-09 05:46:44 +04:00
|
|
|
FixedTableLayoutStrategy::AssignNonPctColumnWidths(nsIPresContext* aPresContext,
|
|
|
|
nscoord aComputedWidth,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
float aPixelToTwips)
|
1998-09-23 06:32:15 +04:00
|
|
|
{
|
1999-07-24 00:32:18 +04:00
|
|
|
// NS_ASSERTION(aComputedWidth != NS_UNCONSTRAINEDSIZE, "bad computed width");
|
1999-06-03 06:42:33 +04:00
|
|
|
const nsStylePosition* tablePosition;
|
|
|
|
mTableFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)tablePosition);
|
|
|
|
PRBool tableIsFixedWidth = eStyleUnit_Coord == tablePosition->mWidth.GetUnit() ||
|
|
|
|
eStyleUnit_Percent == tablePosition->mWidth.GetUnit();
|
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
PRInt32 numCols = mTableFrame->GetColCount();
|
1999-06-03 06:42:33 +04:00
|
|
|
PRInt32 colX;
|
|
|
|
// availWidth is used as the basis for percentage width columns. It is aComputedWidth
|
|
|
|
// minus table border, padding, & cellspacing
|
2000-02-12 04:55:40 +03:00
|
|
|
nscoord availWidth = (NS_UNCONSTRAINEDSIZE == aComputedWidth)
|
|
|
|
? NS_UNCONSTRAINEDSIZE
|
|
|
|
: aComputedWidth - aReflowState.mComputedBorderPadding.left -
|
|
|
|
aReflowState.mComputedBorderPadding.right -
|
|
|
|
((numCols + 1) * mTableFrame->GetCellSpacingX());
|
1998-09-23 06:32:15 +04:00
|
|
|
|
1999-06-03 06:42:33 +04:00
|
|
|
PRInt32 specifiedCols = 0; // the number of columns whose width is given
|
|
|
|
nscoord totalColWidth = 0; // the sum of the widths of the columns
|
1998-09-23 06:32:15 +04:00
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
nscoord* colWidths = new PRBool[numCols];
|
2000-11-30 18:53:55 +03:00
|
|
|
if (!colWidths) return PR_FALSE;
|
1999-12-14 01:56:31 +03:00
|
|
|
nsCRT::memset(colWidths, WIDTH_NOT_SET, numCols*sizeof(nscoord));
|
1999-08-29 10:00:32 +04:00
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
nscoord* propInfo = new PRBool[numCols];
|
2000-11-30 18:53:55 +03:00
|
|
|
if (!propInfo) {
|
|
|
|
delete [] colWidths;
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
1999-12-14 01:56:31 +03:00
|
|
|
nsCRT::memset(propInfo, 0, numCols*sizeof(nscoord));
|
1999-08-29 10:00:32 +04:00
|
|
|
nscoord propTotal = 0;
|
1998-09-23 06:32:15 +04:00
|
|
|
|
1999-07-24 03:41:05 +04:00
|
|
|
// for every column, determine its specified width
|
1999-12-14 01:56:31 +03:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
1998-09-23 06:32:15 +04:00
|
|
|
// Get column information
|
1999-06-03 06:42:33 +04:00
|
|
|
nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
|
1999-07-28 12:09:02 +04:00
|
|
|
if (!colFrame) {
|
|
|
|
NS_ASSERTION(PR_FALSE, "bad col frame");
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
1998-09-23 06:32:15 +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-09-23 06:32:15 +04:00
|
|
|
|
1999-06-03 06:42:33 +04:00
|
|
|
// get the fixed width if available
|
|
|
|
if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) {
|
|
|
|
colWidths[colX] = colPosition->mWidth.GetCoordValue();
|
|
|
|
} // get the percentage width
|
1999-07-24 00:32:18 +04:00
|
|
|
else if ((eStyleUnit_Percent == colPosition->mWidth.GetUnit()) &&
|
|
|
|
(aComputedWidth != NS_UNCONSTRAINEDSIZE)) {
|
2000-02-12 04:55:40 +03:00
|
|
|
// Only apply percentages if we're constrained.
|
1999-06-03 06:42:33 +04:00
|
|
|
float percent = colPosition->mWidth.GetPercentValue();
|
2000-09-01 05:29:50 +04:00
|
|
|
colWidths[colX] = nsTableFrame::RoundToPixel(NSToCoordRound(percent * (float)availWidth), aPixelToTwips);
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
1999-08-29 10:00:32 +04:00
|
|
|
else if (eStyleUnit_Proportional == colPosition->mWidth.GetUnit() &&
|
|
|
|
colPosition->mWidth.GetIntValue() > 0) {
|
|
|
|
propInfo[colX] = colPosition->mWidth.GetIntValue();
|
|
|
|
propTotal += propInfo[colX];
|
|
|
|
}
|
1999-06-03 06:42:33 +04:00
|
|
|
else { // get width from the cell
|
1999-12-14 01:56:31 +03:00
|
|
|
|
1999-06-03 06:42:33 +04:00
|
|
|
nsTableCellFrame* cellFrame = mTableFrame->GetCellFrameAt(0, colX);
|
|
|
|
if (nsnull != cellFrame) {
|
1998-09-23 06:32:15 +04:00
|
|
|
// Get the cell's style
|
|
|
|
const nsStylePosition* cellPosition;
|
1998-11-20 12:29:58 +03:00
|
|
|
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
|
1998-09-23 06:32:15 +04:00
|
|
|
|
2000-01-15 23:10:00 +03:00
|
|
|
PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(*cellFrame);
|
1999-06-03 06:42:33 +04:00
|
|
|
// Get fixed cell width if available
|
|
|
|
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) {
|
|
|
|
colWidths[colX] = cellPosition->mWidth.GetCoordValue() / colSpan;
|
|
|
|
}
|
1999-07-24 00:32:18 +04:00
|
|
|
else if ((eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) &&
|
|
|
|
(aComputedWidth != NS_UNCONSTRAINEDSIZE)) {
|
1999-06-03 06:42:33 +04:00
|
|
|
float percent = cellPosition->mWidth.GetPercentValue();
|
2000-09-01 05:29:50 +04:00
|
|
|
colWidths[colX] = nsTableFrame::RoundToPixel(NSToCoordRound(percent * (float)availWidth / (float)colSpan), aPixelToTwips);
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:42:33 +04:00
|
|
|
if (colWidths[colX] >= 0) {
|
|
|
|
totalColWidth += colWidths[colX];
|
|
|
|
specifiedCols++;
|
|
|
|
}
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
1999-06-03 06:42:33 +04:00
|
|
|
|
|
|
|
nscoord lastColAllocated = -1;
|
|
|
|
nscoord remainingWidth = availWidth - totalColWidth;
|
1999-07-24 04:32:21 +04:00
|
|
|
if (remainingWidth >= 500000) {
|
1999-07-24 03:41:05 +04:00
|
|
|
// let's put a cap on the width so that it doesn't become insane.
|
|
|
|
remainingWidth = 100;
|
|
|
|
}
|
|
|
|
|
1999-08-29 10:00:32 +04:00
|
|
|
if (0 < remainingWidth) {
|
|
|
|
if (propTotal > 0) {
|
1999-12-14 01:56:31 +03:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
1999-08-29 10:00:32 +04:00
|
|
|
if (propInfo[colX] > 0) {
|
|
|
|
// We're proportional
|
|
|
|
float percent = ((float)propInfo[colX])/((float)propTotal);
|
2000-09-01 05:29:50 +04:00
|
|
|
colWidths[colX] = nsTableFrame::RoundToPixel(NSToCoordRound(percent * (float)remainingWidth), aPixelToTwips);
|
1999-08-29 10:00:32 +04:00
|
|
|
totalColWidth += colWidths[colX];
|
1999-06-03 06:42:33 +04:00
|
|
|
lastColAllocated = colX;
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
1999-08-29 10:00:32 +04:00
|
|
|
}
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
1999-08-29 10:00:32 +04:00
|
|
|
else if (tableIsFixedWidth) {
|
1999-12-14 01:56:31 +03:00
|
|
|
if (numCols > specifiedCols) {
|
1999-08-29 10:00:32 +04:00
|
|
|
// allocate the extra space to the columns which have no width specified
|
2000-09-01 05:29:50 +04:00
|
|
|
nscoord colAlloc = nsTableFrame::RoundToPixel( NSToCoordRound(((float)remainingWidth) / (((float)numCols) - ((float)specifiedCols))), aPixelToTwips);
|
1999-12-14 01:56:31 +03:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
1999-08-29 10:00:32 +04:00
|
|
|
if (-1 == colWidths[colX]) {
|
|
|
|
colWidths[colX] = colAlloc;
|
|
|
|
totalColWidth += colAlloc;
|
|
|
|
lastColAllocated = colX;
|
|
|
|
}
|
1999-06-03 06:42:33 +04:00
|
|
|
}
|
|
|
|
}
|
1999-08-29 10:00:32 +04:00
|
|
|
else { // allocate the extra space to the columns which have width specified
|
|
|
|
float divisor = (float)totalColWidth;
|
1999-12-14 01:56:31 +03:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
1999-08-29 10:00:32 +04:00
|
|
|
if (colWidths[colX] > 0) {
|
2000-09-01 05:29:50 +04:00
|
|
|
nscoord colAlloc = nsTableFrame::RoundToPixel(NSToCoordRound(remainingWidth * colWidths[colX] / divisor), aPixelToTwips);
|
1999-08-29 10:00:32 +04:00
|
|
|
colWidths[colX] += colAlloc;
|
|
|
|
totalColWidth += colAlloc;
|
|
|
|
lastColAllocated = colX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
1999-06-03 06:42:33 +04:00
|
|
|
|
|
|
|
nscoord overAllocation = (availWidth >= 0)
|
|
|
|
? totalColWidth - availWidth : 0;
|
|
|
|
// set the column widths
|
1999-12-14 01:56:31 +03:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
1999-06-03 06:42:33 +04:00
|
|
|
if (colWidths[colX] < 0)
|
|
|
|
colWidths[colX] = 0;
|
|
|
|
// if there was too much allocated due to rounding, remove it from the last col
|
|
|
|
if ((colX == lastColAllocated) && (overAllocation != 0)) {
|
|
|
|
colWidths[colX] += overAllocation;
|
|
|
|
colWidths[colX] = PR_MAX(0, colWidths[colX]);
|
|
|
|
}
|
|
|
|
mTableFrame->SetColumnWidth(colX, colWidths[colX]);
|
|
|
|
}
|
|
|
|
|
1998-09-23 06:32:15 +04:00
|
|
|
// clean up
|
1999-06-03 06:42:33 +04:00
|
|
|
if (nsnull != colWidths) {
|
|
|
|
delete [] colWidths;
|
1998-09-23 06:32:15 +04:00
|
|
|
}
|
1999-08-29 10:00:32 +04:00
|
|
|
|
|
|
|
if (nsnull != propInfo) {
|
|
|
|
delete [] propInfo;
|
|
|
|
}
|
1998-09-23 06:32:15 +04:00
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-08-19 23:52:37 +04:00
|
|
|
PRBool FixedTableLayoutStrategy::ColumnsCanBeInvalidatedBy(nsStyleCoord* aPrevStyleWidth,
|
1999-08-21 03:27:54 +04:00
|
|
|
const nsTableCellFrame& aCellFrame) const
|
1999-08-19 23:52:37 +04:00
|
|
|
{
|
|
|
|
return ColumnsCanBeInvalidatedBy(aCellFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool FixedTableLayoutStrategy::ColumnsCanBeInvalidatedBy(const nsTableCellFrame& aCellFrame,
|
|
|
|
PRBool aConsiderMinWidth) const
|
|
|
|
|
|
|
|
{
|
|
|
|
nscoord rowIndex;
|
|
|
|
aCellFrame.GetRowIndex(rowIndex);
|
|
|
|
if (0 == rowIndex) {
|
|
|
|
// It is not worth the effort to determine if the col or cell determined the col
|
|
|
|
// width. Since rebalancing the columns is fairly trival in this strategy, just force it.
|
1999-08-21 03:27:54 +04:00
|
|
|
return PR_TRUE;
|
1999-08-19 23:52:37 +04:00
|
|
|
}
|
1999-08-21 03:27:54 +04:00
|
|
|
return PR_FALSE;
|
1999-08-19 23:52:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool FixedTableLayoutStrategy::ColumnsAreValidFor(const nsTableCellFrame& aCellFrame,
|
|
|
|
nscoord aPrevCellMin,
|
|
|
|
nscoord aPrevCellDes) const
|
|
|
|
{
|
|
|
|
// take the easy way out, see comments above.
|
1999-08-21 03:27:54 +04:00
|
|
|
return !ColumnsCanBeInvalidatedBy(aCellFrame);
|
1999-08-19 23:52:37 +04:00
|
|
|
}
|
1998-09-23 06:32:15 +04:00
|
|
|
|
|
|
|
|
|
|
|
|