1998-04-14 00:24:54 +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 "nsTableFrame.h"
|
|
|
|
#include "nsIRenderingContext.h"
|
|
|
|
#include "nsIStyleContext.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsCellMap.h"
|
|
|
|
#include "nsTableCellFrame.h"
|
1998-09-15 21:58:24 +04:00
|
|
|
#include "nsHTMLParts.h"
|
1998-06-05 06:36:25 +04:00
|
|
|
#include "nsTableColFrame.h"
|
1998-06-17 20:38:24 +04:00
|
|
|
#include "nsTableColGroupFrame.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsTableRowFrame.h"
|
|
|
|
#include "nsTableRowGroupFrame.h"
|
1998-09-30 03:15:01 +04:00
|
|
|
#include "nsTableOuterFrame.h"
|
1998-09-15 21:58:24 +04:00
|
|
|
#include "nsIHTMLContent.h"
|
1998-04-30 21:57:09 +04:00
|
|
|
|
|
|
|
#include "BasicTableLayoutStrategy.h"
|
1998-09-30 03:15:01 +04:00
|
|
|
#include "FixedTableLayoutStrategy.h"
|
1998-04-30 21:57:09 +04:00
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsCSSRendering.h"
|
|
|
|
#include "nsStyleConsts.h"
|
|
|
|
#include "nsVoidArray.h"
|
1998-04-22 10:37:57 +04:00
|
|
|
#include "nsIPtr.h"
|
1998-05-22 03:43:18 +04:00
|
|
|
#include "nsIView.h"
|
1998-05-27 00:57:24 +04:00
|
|
|
#include "nsHTMLAtoms.h"
|
1998-06-05 06:36:25 +04:00
|
|
|
#include "nsHTMLIIDs.h"
|
1998-06-23 09:43:27 +04:00
|
|
|
#include "nsIReflowCommand.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
1998-06-02 01:07:56 +04:00
|
|
|
static PRBool gsDebug = PR_FALSE;
|
1998-04-14 00:24:54 +04:00
|
|
|
static PRBool gsDebugCLD = PR_FALSE;
|
1998-06-24 03:23:21 +04:00
|
|
|
static PRBool gsDebugNT = PR_FALSE;
|
1998-10-11 13:18:27 +04:00
|
|
|
static PRBool gsDebugIR = PR_FALSE;
|
1998-04-14 00:24:54 +04:00
|
|
|
#else
|
|
|
|
static const PRBool gsDebug = PR_FALSE;
|
|
|
|
static const PRBool gsDebugCLD = PR_FALSE;
|
1998-06-24 03:23:21 +04:00
|
|
|
static const PRBool gsDebugNT = PR_FALSE;
|
1998-10-11 13:18:27 +04:00
|
|
|
static const PRBool gsDebugIR = PR_FALSE;
|
1998-04-14 00:24:54 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef max
|
|
|
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
|
|
|
#endif
|
|
|
|
|
1998-04-22 10:37:57 +04:00
|
|
|
NS_DEF_PTR(nsIStyleContext);
|
|
|
|
NS_DEF_PTR(nsIContent);
|
1998-06-17 20:38:24 +04:00
|
|
|
|
1998-06-24 03:23:21 +04:00
|
|
|
const nsIID kTableFrameCID = NS_TABLEFRAME_CID;
|
|
|
|
|
1998-10-10 01:53:07 +04:00
|
|
|
static const PRInt32 kColumnWidthIncrement=100;
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
/* ----------- CellData ---------- */
|
|
|
|
|
|
|
|
/* CellData is the info stored in the cell map */
|
|
|
|
CellData::CellData()
|
|
|
|
{
|
|
|
|
mCell = nsnull;
|
|
|
|
mRealCell = nsnull;
|
|
|
|
mOverlap = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
CellData::~CellData()
|
|
|
|
{}
|
1998-04-22 10:37:57 +04:00
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
/* ----------- InnerTableReflowState ---------- */
|
|
|
|
|
|
|
|
struct InnerTableReflowState {
|
|
|
|
|
1998-05-30 00:36:05 +04:00
|
|
|
// Our reflow state
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& reflowState;
|
1998-05-30 00:36:05 +04:00
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// The body's available size (computed from the body's parent)
|
|
|
|
nsSize availSize;
|
|
|
|
|
1998-04-25 22:48:48 +04:00
|
|
|
nscoord leftInset, topInset;
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// Margin tracking information
|
|
|
|
nscoord prevMaxPosBottomMargin;
|
|
|
|
nscoord prevMaxNegBottomMargin;
|
|
|
|
|
|
|
|
// Flags for whether the max size is unconstrained
|
|
|
|
PRBool unconstrainedWidth;
|
|
|
|
PRBool unconstrainedHeight;
|
|
|
|
|
|
|
|
// Running y-offset
|
|
|
|
nscoord y;
|
|
|
|
|
1998-04-23 21:29:07 +04:00
|
|
|
// a list of the footers in this table frame, for quick access when inserting bodies
|
|
|
|
nsVoidArray *footerList;
|
|
|
|
|
|
|
|
// cache the total height of the footers for placing body rows
|
|
|
|
nscoord footerHeight;
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
InnerTableReflowState(nsIPresContext& aPresContext,
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
const nsMargin& aBorderPadding)
|
1998-05-30 00:36:05 +04:00
|
|
|
: reflowState(aReflowState)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
prevMaxPosBottomMargin = 0;
|
|
|
|
prevMaxNegBottomMargin = 0;
|
|
|
|
y=0; // border/padding/margin???
|
1998-04-25 22:48:48 +04:00
|
|
|
|
1998-05-30 00:36:05 +04:00
|
|
|
unconstrainedWidth = PRBool(aReflowState.maxSize.width == NS_UNCONSTRAINEDSIZE);
|
|
|
|
availSize.width = aReflowState.maxSize.width;
|
1998-04-25 22:48:48 +04:00
|
|
|
if (!unconstrainedWidth) {
|
1998-05-13 02:28:01 +04:00
|
|
|
availSize.width -= aBorderPadding.left + aBorderPadding.right;
|
1998-04-25 22:48:48 +04:00
|
|
|
}
|
1998-05-13 02:28:01 +04:00
|
|
|
leftInset = aBorderPadding.left;
|
1998-04-25 22:48:48 +04:00
|
|
|
|
1998-05-30 00:36:05 +04:00
|
|
|
unconstrainedHeight = PRBool(aReflowState.maxSize.height == NS_UNCONSTRAINEDSIZE);
|
|
|
|
availSize.height = aReflowState.maxSize.height;
|
1998-04-25 22:48:48 +04:00
|
|
|
if (!unconstrainedHeight) {
|
1998-05-13 02:28:01 +04:00
|
|
|
availSize.height -= aBorderPadding.top + aBorderPadding.bottom;
|
1998-04-25 22:48:48 +04:00
|
|
|
}
|
1998-05-13 02:28:01 +04:00
|
|
|
topInset = aBorderPadding.top;
|
1998-04-25 22:48:48 +04:00
|
|
|
|
1998-04-23 21:29:07 +04:00
|
|
|
footerHeight = 0;
|
|
|
|
footerList = nsnull;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
~InnerTableReflowState() {
|
1998-04-23 21:29:07 +04:00
|
|
|
if (nsnull!=footerList)
|
|
|
|
delete footerList;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
1998-06-05 06:36:25 +04:00
|
|
|
/* ----------- ColumnInfoCache ---------- */
|
|
|
|
|
|
|
|
static const PRInt32 NUM_COL_WIDTH_TYPES=4;
|
|
|
|
|
|
|
|
class ColumnInfoCache
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ColumnInfoCache(PRInt32 aNumColumns);
|
|
|
|
~ColumnInfoCache();
|
|
|
|
|
|
|
|
void AddColumnInfo(const nsStyleUnit aType,
|
|
|
|
PRInt32 aColumnIndex);
|
|
|
|
|
|
|
|
void GetColumnsByType(const nsStyleUnit aType,
|
|
|
|
PRInt32& aOutNumColumns,
|
|
|
|
PRInt32 *& aOutColumnIndexes);
|
|
|
|
enum ColWidthType {
|
|
|
|
eColWidthType_Auto = 0, // width based on contents
|
|
|
|
eColWidthType_Percent = 1, // (float) 1.0 == 100%
|
|
|
|
eColWidthType_Coord = 2, // (nscoord) value is twips
|
1998-06-27 06:47:44 +04:00
|
|
|
eColWidthType_Proportional = 3 // (int) value has proportional meaning
|
1998-06-05 06:36:25 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
PRInt32 mColCounts [4];
|
|
|
|
PRInt32 *mColIndexes[4];
|
|
|
|
PRInt32 mNumColumns;
|
|
|
|
};
|
|
|
|
|
|
|
|
ColumnInfoCache::ColumnInfoCache(PRInt32 aNumColumns)
|
|
|
|
{
|
1998-10-20 09:05:17 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("CIC constructor: aNumColumns %d\n", aNumColumns);
|
1998-06-05 06:36:25 +04:00
|
|
|
mNumColumns = aNumColumns;
|
|
|
|
for (PRInt32 i=0; i<NUM_COL_WIDTH_TYPES; i++)
|
|
|
|
{
|
|
|
|
mColCounts[i] = 0;
|
|
|
|
mColIndexes[i] = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ColumnInfoCache::~ColumnInfoCache()
|
|
|
|
{
|
|
|
|
for (PRInt32 i=0; i<NUM_COL_WIDTH_TYPES; i++)
|
|
|
|
{
|
|
|
|
if (nsnull!=mColIndexes[i])
|
|
|
|
{
|
|
|
|
delete [] mColIndexes[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ColumnInfoCache::AddColumnInfo(const nsStyleUnit aType,
|
|
|
|
PRInt32 aColumnIndex)
|
|
|
|
{
|
1998-10-20 09:05:17 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("CIC AddColumnInfo: adding col index %d of type %d\n", aColumnIndex, aType);
|
1998-10-15 02:51:50 +04:00
|
|
|
// a table may have more COLs than actual columns, so we guard against that here
|
|
|
|
if (aColumnIndex<mNumColumns)
|
1998-06-05 06:36:25 +04:00
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
switch (aType)
|
|
|
|
{
|
|
|
|
case eStyleUnit_Auto:
|
|
|
|
if (nsnull==mColIndexes[eColWidthType_Auto])
|
|
|
|
mColIndexes[eColWidthType_Auto] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
|
|
|
mColIndexes[eColWidthType_Auto][mColCounts[eColWidthType_Auto]] = aColumnIndex;
|
|
|
|
mColCounts[eColWidthType_Auto]++;
|
|
|
|
break;
|
1998-06-05 06:36:25 +04:00
|
|
|
|
1998-10-15 02:51:50 +04:00
|
|
|
case eStyleUnit_Percent:
|
|
|
|
if (nsnull==mColIndexes[eColWidthType_Percent])
|
|
|
|
mColIndexes[eColWidthType_Percent] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
|
|
|
mColIndexes[eColWidthType_Percent][mColCounts[eColWidthType_Percent]] = aColumnIndex;
|
|
|
|
mColCounts[eColWidthType_Percent]++;
|
|
|
|
break;
|
1998-06-05 06:36:25 +04:00
|
|
|
|
1998-10-15 02:51:50 +04:00
|
|
|
case eStyleUnit_Coord:
|
|
|
|
if (nsnull==mColIndexes[eColWidthType_Coord])
|
|
|
|
mColIndexes[eColWidthType_Coord] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
|
|
|
mColIndexes[eColWidthType_Coord][mColCounts[eColWidthType_Coord]] = aColumnIndex;
|
|
|
|
mColCounts[eColWidthType_Coord]++;
|
|
|
|
break;
|
1998-06-05 06:36:25 +04:00
|
|
|
|
1998-10-15 02:51:50 +04:00
|
|
|
case eStyleUnit_Proportional:
|
|
|
|
if (nsnull==mColIndexes[eColWidthType_Proportional])
|
|
|
|
mColIndexes[eColWidthType_Proportional] = new PRInt32[mNumColumns]; // TODO : be much more efficient
|
|
|
|
mColIndexes[eColWidthType_Proportional][mColCounts[eColWidthType_Proportional]] = aColumnIndex;
|
|
|
|
mColCounts[eColWidthType_Proportional]++;
|
|
|
|
break;
|
|
|
|
}
|
1998-06-05 06:36:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ColumnInfoCache::GetColumnsByType(const nsStyleUnit aType,
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32& aOutNumColumns,
|
|
|
|
PRInt32 *& aOutColumnIndexes)
|
1998-06-05 06:36:25 +04:00
|
|
|
{
|
1998-06-30 04:37:03 +04:00
|
|
|
// initialize out-params
|
|
|
|
aOutNumColumns=0;
|
|
|
|
aOutColumnIndexes=nsnull;
|
|
|
|
|
|
|
|
// fill out params with column info based on aType
|
1998-06-05 06:36:25 +04:00
|
|
|
switch (aType)
|
|
|
|
{
|
|
|
|
case eStyleUnit_Auto:
|
|
|
|
aOutNumColumns = mColCounts[eColWidthType_Auto];
|
|
|
|
aOutColumnIndexes = mColIndexes[eColWidthType_Auto];
|
|
|
|
break;
|
|
|
|
case eStyleUnit_Percent:
|
|
|
|
aOutNumColumns = mColCounts[eColWidthType_Percent];
|
|
|
|
aOutColumnIndexes = mColIndexes[eColWidthType_Percent];
|
|
|
|
break;
|
|
|
|
case eStyleUnit_Coord:
|
|
|
|
aOutNumColumns = mColCounts[eColWidthType_Coord];
|
|
|
|
aOutColumnIndexes = mColIndexes[eColWidthType_Coord];
|
|
|
|
break;
|
|
|
|
case eStyleUnit_Proportional:
|
|
|
|
aOutNumColumns = mColCounts[eColWidthType_Proportional];
|
|
|
|
aOutColumnIndexes = mColIndexes[eColWidthType_Proportional];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
/* --------------------- nsTableFrame -------------------- */
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-05-06 03:56:50 +04:00
|
|
|
nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
|
|
|
|
: nsContainerFrame(aContent, aParentFrame),
|
1998-06-17 20:38:24 +04:00
|
|
|
mCellMap(nsnull),
|
1998-06-05 06:36:25 +04:00
|
|
|
mColCache(nsnull),
|
1998-04-30 21:57:09 +04:00
|
|
|
mTableLayoutStrategy(nsnull),
|
1998-04-14 00:24:54 +04:00
|
|
|
mFirstPassValid(PR_FALSE),
|
1998-10-16 01:07:37 +04:00
|
|
|
mColumnWidthsValid(PR_FALSE),
|
1998-10-15 02:51:50 +04:00
|
|
|
mColumnCacheValid(PR_FALSE),
|
1998-10-14 20:32:45 +04:00
|
|
|
mCellMapValid(PR_TRUE),
|
1998-04-14 00:24:54 +04:00
|
|
|
mIsInvariantWidth(PR_FALSE)
|
|
|
|
{
|
1998-07-24 20:51:16 +04:00
|
|
|
mEffectiveColCount = -1; // -1 means uninitialized
|
1998-10-11 13:18:27 +04:00
|
|
|
mColumnWidthsSet=PR_FALSE;
|
|
|
|
mColumnWidthsLength = kColumnWidthIncrement;
|
1998-10-10 01:53:07 +04:00
|
|
|
mColumnWidths = new PRInt32[mColumnWidthsLength];
|
|
|
|
nsCRT::memset (mColumnWidths, 0, mColumnWidthsLength*sizeof(PRInt32));
|
1998-09-24 01:48:26 +04:00
|
|
|
mCellMap = new nsCellMap(0, 0);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsTableFrame::~nsTableFrame()
|
|
|
|
{
|
1998-06-17 20:38:24 +04:00
|
|
|
if (nsnull!=mCellMap)
|
|
|
|
delete mCellMap;
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
if (nsnull!=mColumnWidths)
|
|
|
|
delete [] mColumnWidths;
|
1998-06-17 20:38:24 +04:00
|
|
|
|
1998-04-30 21:57:09 +04:00
|
|
|
if (nsnull!=mTableLayoutStrategy)
|
|
|
|
delete mTableLayoutStrategy;
|
1998-06-17 20:38:24 +04:00
|
|
|
|
1998-06-05 06:36:25 +04:00
|
|
|
if (nsnull!=mColCache)
|
|
|
|
delete mColCache;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-09-16 21:19:20 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsTableFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
|
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
nsresult rv=NS_OK;
|
1998-09-16 21:19:20 +04:00
|
|
|
mFirstChild = aChildList;
|
1998-10-14 20:32:45 +04:00
|
|
|
// I know now that I have all my children, so build the cell map
|
|
|
|
nsIFrame *nextRowGroup=mFirstChild;
|
|
|
|
for ( ; nsnull!=nextRowGroup; nextRowGroup->GetNextSibling(nextRowGroup))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *rowGroupDisplay;
|
|
|
|
nextRowGroup->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
|
|
|
|
if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
|
|
|
|
{
|
|
|
|
rv = DidAppendRowGroup((nsTableRowGroupFrame*)nextRowGroup);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
EnsureColumns(aPresContext);
|
|
|
|
return rv;
|
1998-09-16 21:19:20 +04:00
|
|
|
}
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_IMETHODIMP nsTableFrame::DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFrame)
|
|
|
|
{
|
|
|
|
nsresult rv=NS_OK;
|
|
|
|
nsIFrame *nextRow=nsnull;
|
|
|
|
aRowGroupFrame->FirstChild(nextRow);
|
|
|
|
for ( ; nsnull!=nextRow; nextRow->GetNextSibling(nextRow))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *rowDisplay;
|
|
|
|
nextRow->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
rv = ((nsTableRowFrame *)nextRow)->InitChildren();
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
/* ****** CellMap methods ******* */
|
|
|
|
|
1998-07-02 02:22:28 +04:00
|
|
|
/* return the next row group frame after aRowGroupFrame */
|
|
|
|
nsTableRowGroupFrame* nsTableFrame::NextRowGroupFrame(nsTableRowGroupFrame* aRowGroupFrame)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-07-02 02:22:28 +04:00
|
|
|
if (nsnull == aRowGroupFrame)
|
|
|
|
{
|
|
|
|
aRowGroupFrame = (nsTableRowGroupFrame*)mFirstChild;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aRowGroupFrame->GetNextSibling((nsIFrame*&)aRowGroupFrame);
|
|
|
|
}
|
1998-06-17 20:38:24 +04:00
|
|
|
|
1998-07-02 02:22:28 +04:00
|
|
|
while (nsnull != aRowGroupFrame)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-07-02 02:22:28 +04:00
|
|
|
const nsStyleDisplay *display;
|
|
|
|
aRowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
|
1998-10-11 13:18:27 +04:00
|
|
|
if (PR_TRUE==IsRowGroup(display->mDisplay))
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
1998-07-02 02:22:28 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Get the next frame
|
|
|
|
aRowGroupFrame->GetNextSibling((nsIFrame*&)aRowGroupFrame);
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-07-02 02:22:28 +04:00
|
|
|
return aRowGroupFrame;
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* counts columns in column groups */
|
|
|
|
PRInt32 nsTableFrame::GetSpecifiedColumnCount ()
|
|
|
|
{
|
|
|
|
mColCount=0;
|
1998-10-11 13:18:27 +04:00
|
|
|
nsIFrame * childFrame = mFirstChild;
|
|
|
|
while (nsnull!=childFrame)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
|
|
|
const nsStyleDisplay *childDisplay;
|
1998-10-11 13:18:27 +04:00
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
1998-06-17 20:38:24 +04:00
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{
|
1998-10-11 13:18:27 +04:00
|
|
|
mColCount += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-10-11 13:18:27 +04:00
|
|
|
childFrame->GetNextSibling(childFrame);
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-10-20 09:05:17 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("TIF GetSpecifiedColumnCount: returning %d\n", mColCount);
|
1998-06-17 20:38:24 +04:00
|
|
|
return mColCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32 nsTableFrame::GetRowCount ()
|
|
|
|
{
|
|
|
|
PRInt32 rowCount = 0;
|
1998-08-14 20:16:43 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_ASSERTION(nsnull!=cellMap, "GetRowCount null cellmap");
|
|
|
|
if (nsnull!=cellMap)
|
|
|
|
rowCount = cellMap->GetRowCount();
|
1998-06-17 20:38:24 +04:00
|
|
|
return rowCount;
|
|
|
|
}
|
1998-07-11 04:00:31 +04:00
|
|
|
|
1998-07-24 20:51:16 +04:00
|
|
|
/* return the effective col count */
|
1998-07-22 07:53:43 +04:00
|
|
|
PRInt32 nsTableFrame::GetColCount ()
|
|
|
|
{
|
1998-08-14 20:16:43 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_ASSERTION(nsnull!=cellMap, "GetColCount null cellmap");
|
1998-07-22 07:53:43 +04:00
|
|
|
|
1998-08-14 20:16:43 +04:00
|
|
|
if (nsnull!=cellMap)
|
1998-07-24 20:51:16 +04:00
|
|
|
{
|
1998-09-29 00:38:10 +04:00
|
|
|
//if (-1==mEffectiveColCount)
|
1998-07-24 20:51:16 +04:00
|
|
|
SetEffectiveColCount();
|
|
|
|
}
|
|
|
|
return mEffectiveColCount;
|
|
|
|
}
|
1998-07-22 07:53:43 +04:00
|
|
|
|
1998-07-24 20:51:16 +04:00
|
|
|
void nsTableFrame::SetEffectiveColCount()
|
|
|
|
{
|
1998-08-14 20:16:43 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_ASSERTION(nsnull!=cellMap, "SetEffectiveColCount null cellmap");
|
1998-08-14 20:16:43 +04:00
|
|
|
if (nsnull!=cellMap)
|
1998-07-22 07:53:43 +04:00
|
|
|
{
|
1998-08-14 20:16:43 +04:00
|
|
|
PRInt32 colCount = cellMap->GetColCount();
|
1998-07-24 20:51:16 +04:00
|
|
|
mEffectiveColCount = colCount;
|
1998-08-14 20:16:43 +04:00
|
|
|
PRInt32 rowCount = cellMap->GetRowCount();
|
1998-07-24 20:51:16 +04:00
|
|
|
for (PRInt32 colIndex=colCount-1; colIndex>0; colIndex--)
|
|
|
|
{
|
|
|
|
PRBool deleteCol=PR_TRUE;
|
|
|
|
for (PRInt32 rowIndex=0; rowIndex<rowCount; rowIndex++)
|
|
|
|
{
|
1998-08-14 20:16:43 +04:00
|
|
|
CellData *cell = cellMap->GetCellAt(rowIndex, colIndex);
|
1998-07-24 20:51:16 +04:00
|
|
|
if ((nsnull!=cell) && (cell->mCell != nsnull))
|
|
|
|
{ // found a real cell, so we're done
|
|
|
|
deleteCol = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (PR_TRUE==deleteCol)
|
|
|
|
mEffectiveColCount--;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
1998-07-22 07:53:43 +04:00
|
|
|
}
|
1998-10-20 09:05:17 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("TIF SetEffectiveColumnCount: returning %d\n", mEffectiveColCount);
|
1998-07-22 07:53:43 +04:00
|
|
|
}
|
|
|
|
|
1998-07-11 04:00:31 +04:00
|
|
|
nsTableColFrame * nsTableFrame::GetColFrame(PRInt32 aColIndex)
|
|
|
|
{
|
|
|
|
nsTableColFrame *result = nsnull;
|
1998-08-14 20:16:43 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
if (nsnull!=cellMap)
|
1998-07-11 04:00:31 +04:00
|
|
|
{
|
1998-08-14 20:16:43 +04:00
|
|
|
result = cellMap->GetColumnFrame(aColIndex);
|
1998-07-11 04:00:31 +04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// can return nsnull
|
1998-09-19 02:37:14 +04:00
|
|
|
nsTableCellFrame * nsTableFrame::GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex)
|
1998-07-11 04:00:31 +04:00
|
|
|
{
|
|
|
|
nsTableCellFrame *result = nsnull;
|
1998-08-14 20:16:43 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
if (nsnull!=cellMap)
|
1998-07-11 04:00:31 +04:00
|
|
|
{
|
1998-08-14 20:16:43 +04:00
|
|
|
CellData * cellData = cellMap->GetCellAt(aRowIndex, aColIndex);
|
1998-07-11 04:00:31 +04:00
|
|
|
if (nsnull!=cellData)
|
|
|
|
{
|
|
|
|
result = cellData->mCell;
|
|
|
|
if (nsnull==result)
|
|
|
|
result = cellData->mRealCell->mCell;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-09-19 02:37:14 +04:00
|
|
|
/** returns PR_TRUE if the row at aRowIndex has any cells that are the result
|
|
|
|
* of a row-spanning cell.
|
|
|
|
* @see nsCellMap::RowIsSpannedInto
|
|
|
|
*/
|
|
|
|
PRBool nsTableFrame::RowIsSpannedInto(PRInt32 aRowIndex)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION (0<=aRowIndex && aRowIndex<GetRowCount(), "bad row index arg");
|
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
nsCellMap * cellMap = GetCellMap();
|
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "bad call, cellMap not yet allocated.");
|
|
|
|
if (nsnull!=cellMap)
|
|
|
|
{
|
|
|
|
result = cellMap->RowIsSpannedInto(aRowIndex);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1
|
|
|
|
* @see nsCellMap::RowHasSpanningCells
|
|
|
|
*/
|
|
|
|
PRBool nsTableFrame::RowHasSpanningCells(PRInt32 aRowIndex)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION (0<=aRowIndex && aRowIndex<GetRowCount(), "bad row index arg");
|
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
nsCellMap * cellMap = GetCellMap();
|
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "bad call, cellMap not yet allocated.");
|
|
|
|
if (nsnull!=cellMap)
|
|
|
|
{
|
|
|
|
result = cellMap->RowHasSpanningCells(aRowIndex);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** returns PR_TRUE if the col at aColIndex has any cells that are the result
|
|
|
|
* of a col-spanning cell.
|
|
|
|
* @see nsCellMap::ColIsSpannedInto
|
|
|
|
*/
|
|
|
|
PRBool nsTableFrame::ColIsSpannedInto(PRInt32 aColIndex)
|
|
|
|
{
|
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
nsCellMap * cellMap = GetCellMap();
|
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "bad call, cellMap not yet allocated.");
|
|
|
|
if (nsnull!=cellMap)
|
|
|
|
{
|
|
|
|
result = cellMap->ColIsSpannedInto(aColIndex);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1
|
|
|
|
* @see nsCellMap::ColHasSpanningCells
|
|
|
|
*/
|
|
|
|
PRBool nsTableFrame::ColHasSpanningCells(PRInt32 aColIndex)
|
|
|
|
{
|
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
nsCellMap * cellMap = GetCellMap();
|
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "bad call, cellMap not yet allocated.");
|
|
|
|
if (nsnull!=cellMap)
|
|
|
|
{
|
|
|
|
result = cellMap->ColHasSpanningCells(aColIndex);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-07-17 03:23:31 +04:00
|
|
|
// return the number of rows spanned by aCell starting at aRowIndex
|
1998-06-17 20:38:24 +04:00
|
|
|
// note that this is different from just the rowspan of aCell
|
|
|
|
// (that would be GetEffectiveRowSpan (indexOfRowThatContains_aCell, aCell)
|
1998-07-03 00:35:23 +04:00
|
|
|
//
|
|
|
|
// XXX This code should be in the table row group frame instead, and it
|
|
|
|
// should clip rows spans so they don't extend past a row group rather than
|
|
|
|
// clip to the table itself. Before that can happen the code that builds the
|
|
|
|
// cell map needs to take row groups into account
|
1998-06-17 20:38:24 +04:00
|
|
|
PRInt32 nsTableFrame::GetEffectiveRowSpan (PRInt32 aRowIndex, nsTableCellFrame *aCell)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION (nsnull!=aCell, "bad cell arg");
|
|
|
|
NS_PRECONDITION (0<=aRowIndex && aRowIndex<GetRowCount(), "bad row index arg");
|
|
|
|
|
1998-09-16 00:36:42 +04:00
|
|
|
if (!(0<=aRowIndex && aRowIndex<GetRowCount()))
|
|
|
|
return 1;
|
|
|
|
|
1998-07-22 07:53:43 +04:00
|
|
|
PRInt32 rowSpan = aCell->GetRowSpan();
|
|
|
|
PRInt32 rowCount = GetRowCount();
|
1998-06-17 20:38:24 +04:00
|
|
|
if (rowCount < (aRowIndex + rowSpan))
|
|
|
|
return (rowCount - aRowIndex);
|
|
|
|
return rowSpan;
|
|
|
|
}
|
|
|
|
|
1998-07-17 03:23:31 +04:00
|
|
|
// return the number of cols spanned by aCell starting at aColIndex
|
|
|
|
// note that this is different from just the colspan of aCell
|
|
|
|
// (that would be GetEffectiveColSpan (indexOfColThatContains_aCell, aCell)
|
|
|
|
//
|
|
|
|
// XXX Should be moved to colgroup, as GetEffectiveRowSpan should be moved to rowgroup?
|
|
|
|
PRInt32 nsTableFrame::GetEffectiveColSpan (PRInt32 aColIndex, nsTableCellFrame *aCell)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION (nsnull!=aCell, "bad cell arg");
|
1998-08-14 20:16:43 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
1998-08-18 03:37:04 +04:00
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "bad call, cellMap not yet allocated.");
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 colCount = mCellMap->GetColCount();
|
1998-09-23 03:36:06 +04:00
|
|
|
NS_PRECONDITION (0<=aColIndex && aColIndex<colCount, "bad col index arg");
|
1998-07-17 03:23:31 +04:00
|
|
|
|
1998-08-19 19:43:51 +04:00
|
|
|
PRInt32 result;
|
1998-09-16 04:48:14 +04:00
|
|
|
/*
|
1998-08-14 20:16:43 +04:00
|
|
|
if (cellMap->GetRowCount()==1)
|
1998-07-22 07:53:43 +04:00
|
|
|
return 1;
|
1998-09-16 04:48:14 +04:00
|
|
|
*/
|
1998-07-22 07:53:43 +04:00
|
|
|
PRInt32 colSpan = aCell->GetColSpan();
|
1998-07-17 03:23:31 +04:00
|
|
|
if (colCount < (aColIndex + colSpan))
|
1998-08-19 19:43:51 +04:00
|
|
|
result = colCount - aColIndex;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = colSpan;
|
|
|
|
// check for case where all cells in a column have a colspan
|
|
|
|
PRInt32 initialColIndex = aCell->GetColIndex();
|
|
|
|
PRInt32 minColSpanForCol = cellMap->GetMinColSpan(initialColIndex);
|
|
|
|
result -= (minColSpanForCol - 1); // minColSpanForCol is always at least 1
|
|
|
|
// and we want to treat default as 0 (no effect)
|
|
|
|
}
|
1998-09-19 02:37:14 +04:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
if (0>=result)
|
|
|
|
{
|
|
|
|
printf("ERROR!\n");
|
|
|
|
DumpCellMap();
|
|
|
|
printf("aColIndex=%d, cell->colIndex=%d\n", aColIndex, aCell->GetColIndex());
|
|
|
|
printf("aCell->colSpan=%d\n", aCell->GetColSpan());
|
|
|
|
printf("colCount=%d\n", mCellMap->GetColCount());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
NS_ASSERTION(0<result, "bad effective col span");
|
1998-08-19 19:43:51 +04:00
|
|
|
return result;
|
1998-07-17 03:23:31 +04:00
|
|
|
}
|
|
|
|
|
1998-07-22 07:53:43 +04:00
|
|
|
PRInt32 nsTableFrame::GetEffectiveCOLSAttribute()
|
|
|
|
{
|
1998-08-14 20:16:43 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
|
1998-07-22 07:53:43 +04:00
|
|
|
PRInt32 result;
|
|
|
|
nsIFrame *tableFrame = this;
|
1998-09-15 21:58:24 +04:00
|
|
|
nsStyleTable *tableStyle=nsnull;
|
|
|
|
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
|
1998-07-22 07:53:43 +04:00
|
|
|
result = tableStyle->mCols;
|
|
|
|
PRInt32 numCols = GetColCount();
|
|
|
|
if (result>numCols)
|
|
|
|
result = numCols;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
/** sum the columns represented by all nsTableColGroup objects
|
|
|
|
* if the cell map says there are more columns than this,
|
|
|
|
* add extra implicit columns to the content tree.
|
|
|
|
*/
|
1998-09-23 03:36:06 +04:00
|
|
|
|
1998-09-24 01:48:26 +04:00
|
|
|
// XXX this and EnsureColumnsAt should be 1 method, with -1 for aColIndex meaning "do them all"
|
1998-10-11 13:18:27 +04:00
|
|
|
void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-10-20 09:05:17 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("TIF EnsureColumns\n");
|
1998-09-23 03:36:06 +04:00
|
|
|
nsresult rv;
|
1998-09-24 01:48:26 +04:00
|
|
|
NS_PRECONDITION(nsnull!=mCellMap, "bad state: null cellmap");
|
1998-08-14 20:16:43 +04:00
|
|
|
// XXX sec should only be called on firstInFlow
|
1998-09-01 01:23:28 +04:00
|
|
|
SetMinColSpanForTable();
|
1998-07-07 04:20:21 +04:00
|
|
|
if (nsnull==mCellMap)
|
|
|
|
return; // no info yet, so nothing useful to do
|
1998-06-17 20:38:24 +04:00
|
|
|
|
1998-07-26 08:23:01 +04:00
|
|
|
// make sure we've accounted for the COLS attribute
|
|
|
|
AdjustColumnsForCOLSAttribute();
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
PRInt32 actualColumns = 0;
|
|
|
|
nsTableColGroupFrame *lastColGroupFrame = nsnull;
|
|
|
|
nsIFrame * firstRowGroupFrame=nsnull;
|
1998-10-14 20:32:45 +04:00
|
|
|
nsIFrame * prevSibFrame=nsnull; // this is the child just before the first row group frame
|
1998-07-11 04:00:31 +04:00
|
|
|
nsIFrame * childFrame=mFirstChild;
|
1998-06-17 20:38:24 +04:00
|
|
|
while (nsnull!=childFrame)
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
PRInt32 numCols = ((nsTableColGroupFrame*)childFrame)->GetColumnCount();
|
|
|
|
actualColumns += numCols;
|
|
|
|
lastColGroupFrame = (nsTableColGroupFrame *)childFrame;
|
1998-09-24 01:48:26 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("EC: found a col group %p\n", lastColGroupFrame);
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-10-11 13:18:27 +04:00
|
|
|
else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
|
|
|
if (nsnull==firstRowGroupFrame)
|
|
|
|
{
|
|
|
|
firstRowGroupFrame = childFrame;
|
|
|
|
if (PR_TRUE==gsDebug) printf("EC: found a row group %p\n", firstRowGroupFrame);
|
|
|
|
}
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
if (nsnull==firstRowGroupFrame)
|
|
|
|
prevSibFrame = childFrame;
|
1998-06-17 20:38:24 +04:00
|
|
|
childFrame->GetNextSibling(childFrame);
|
1998-09-24 01:48:26 +04:00
|
|
|
}
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 colCount = mCellMap->GetColCount();
|
1998-09-24 01:48:26 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("EC: actual = %d, colCount=%d\n", actualColumns, colCount);
|
|
|
|
if (actualColumns < colCount)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-10-20 09:05:17 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("TIF EnsureColumns: actual %d < colCount %d\n", actualColumns, colCount);
|
1998-09-23 03:36:06 +04:00
|
|
|
nsIHTMLContent *lastColGroup=nsnull;
|
1998-06-17 20:38:24 +04:00
|
|
|
if (nsnull==lastColGroupFrame)
|
|
|
|
{
|
1998-10-20 09:05:17 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("EnsureColumns:creating colgroup\n", actualColumns, colCount);
|
1998-09-23 03:36:06 +04:00
|
|
|
// create an implicit colgroup
|
|
|
|
nsAutoString colGroupTag;
|
|
|
|
nsHTMLAtoms::colgroup->ToString(colGroupTag);
|
|
|
|
rv = NS_CreateHTMLElement(&lastColGroup, colGroupTag); // ADDREF a: lastColGroup++
|
1998-10-14 20:32:45 +04:00
|
|
|
//XXX: make synthetic
|
1998-08-26 21:26:38 +04:00
|
|
|
mContent->AppendChildTo(lastColGroup, PR_FALSE); // add the implicit colgroup to my content
|
1998-06-17 20:38:24 +04:00
|
|
|
// Resolve style for the child
|
|
|
|
nsIStyleContext* colGroupStyleContext =
|
1998-10-11 13:18:27 +04:00
|
|
|
aPresContext.ResolveStyleContextFor(lastColGroup, this, PR_TRUE); // kidStyleContext: REFCNT++
|
1998-09-23 03:36:06 +04:00
|
|
|
|
|
|
|
// Create a col group frame
|
|
|
|
nsIFrame* newFrame;
|
|
|
|
NS_NewTableColGroupFrame(lastColGroup, this, newFrame);
|
|
|
|
lastColGroupFrame = (nsTableColGroupFrame*)newFrame;
|
1998-10-11 13:18:27 +04:00
|
|
|
lastColGroupFrame->SetStyleContext(&aPresContext, colGroupStyleContext);
|
1998-06-17 20:38:24 +04:00
|
|
|
NS_RELEASE(colGroupStyleContext); // kidStyleContenxt: REFCNT--
|
|
|
|
|
|
|
|
// hook lastColGroupFrame into child list
|
|
|
|
if (nsnull==firstRowGroupFrame)
|
|
|
|
{ // make lastColGroupFrame the last frame
|
1998-09-23 03:36:06 +04:00
|
|
|
nsIFrame *lastChild = LastFrame(mFirstChild);
|
1998-06-17 20:38:24 +04:00
|
|
|
lastChild->SetNextSibling(lastColGroupFrame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // insert lastColGroupFrame before the first row group frame
|
|
|
|
if (nsnull!=prevSibFrame)
|
|
|
|
{ // lastColGroupFrame is inserted between prevSibFrame and lastColGroupFrame
|
|
|
|
prevSibFrame->SetNextSibling(lastColGroupFrame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // lastColGroupFrame is inserted as the first child of this table
|
|
|
|
mFirstChild = lastColGroupFrame;
|
|
|
|
}
|
|
|
|
lastColGroupFrame->SetNextSibling(firstRowGroupFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lastColGroupFrame->GetContent((nsIContent *&)lastColGroup); // ADDREF b: lastColGroup++
|
|
|
|
}
|
|
|
|
|
1998-09-23 03:36:06 +04:00
|
|
|
// XXX It would be better to do this in the style code while constructing
|
|
|
|
// the table's frames
|
|
|
|
nsAutoString colTag;
|
|
|
|
nsHTMLAtoms::col->ToString(colTag);
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 excessColumns = colCount - actualColumns;
|
1998-09-23 03:36:06 +04:00
|
|
|
nsIFrame* firstNewColFrame = nsnull;
|
|
|
|
nsIFrame* lastNewColFrame = nsnull;
|
1998-06-17 20:38:24 +04:00
|
|
|
for ( ; excessColumns > 0; excessColumns--)
|
1998-09-23 03:36:06 +04:00
|
|
|
{
|
1998-09-24 01:48:26 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("EC:creating col\n", actualColumns, colCount);
|
1998-09-23 03:36:06 +04:00
|
|
|
nsIHTMLContent *col=nsnull;
|
|
|
|
// create an implicit col
|
|
|
|
rv = NS_CreateHTMLElement(&col, colTag); // ADDREF: col++
|
1998-10-14 20:32:45 +04:00
|
|
|
//XXX: make synthetic
|
1998-09-23 03:36:06 +04:00
|
|
|
lastColGroup->AppendChildTo((nsIContent*)col, PR_FALSE);
|
|
|
|
|
|
|
|
// Create a new col frame
|
|
|
|
nsIFrame* colFrame;
|
|
|
|
NS_NewTableColFrame(col, lastColGroupFrame, colFrame);
|
|
|
|
|
|
|
|
// Set its style context
|
|
|
|
nsIStyleContextPtr colStyleContext =
|
1998-10-11 13:18:27 +04:00
|
|
|
aPresContext.ResolveStyleContextFor(col, lastColGroupFrame, PR_TRUE);
|
|
|
|
colFrame->SetStyleContext(&aPresContext, colStyleContext);
|
|
|
|
colFrame->Init(aPresContext, nsnull);
|
1998-09-23 03:36:06 +04:00
|
|
|
|
|
|
|
// XXX Don't release this style context (or we'll end up with a double-free).\
|
|
|
|
// This code is doing what nsTableColGroupFrame::Reflow() does...
|
|
|
|
//NS_RELEASE(colStyleContext);
|
|
|
|
|
|
|
|
// Add it to our list
|
|
|
|
if (nsnull == lastNewColFrame) {
|
|
|
|
firstNewColFrame = colFrame;
|
|
|
|
} else {
|
|
|
|
lastNewColFrame->SetNextSibling(colFrame);
|
|
|
|
}
|
|
|
|
lastNewColFrame = colFrame;
|
|
|
|
NS_RELEASE(col); // ADDREF: col--
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-10-11 13:18:27 +04:00
|
|
|
lastColGroupFrame->Init(aPresContext, firstNewColFrame);
|
1998-06-17 20:38:24 +04:00
|
|
|
NS_RELEASE(lastColGroup); // ADDREF: lastColGroup--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-26 21:26:38 +04:00
|
|
|
/** sum the columns represented by all nsTableColGroup objects
|
|
|
|
* if the cell map says there are more columns than this,
|
|
|
|
* add extra implicit columns to the content tree.
|
|
|
|
*/
|
1998-09-15 21:58:24 +04:00
|
|
|
// XXX should be nsresult, not void
|
1998-08-26 21:26:38 +04:00
|
|
|
void nsTableFrame::EnsureColumnFrameAt(PRInt32 aColIndex,
|
1998-10-11 13:18:27 +04:00
|
|
|
nsIPresContext& aPresContext)
|
1998-08-26 21:26:38 +04:00
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
nsresult rv;
|
1998-08-26 21:26:38 +04:00
|
|
|
PRInt32 actualColumns = 0;
|
|
|
|
nsTableColGroupFrame *lastColGroupFrame = nsnull;
|
|
|
|
nsIFrame * firstRowGroupFrame=nsnull;
|
1998-10-14 20:32:45 +04:00
|
|
|
nsIFrame * prevSibFrame=nsnull; // this is the child just before the first row group frame
|
1998-08-26 21:26:38 +04:00
|
|
|
nsIFrame * childFrame=mFirstChild;
|
|
|
|
while (nsnull!=childFrame)
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
PRInt32 numCols = ((nsTableColGroupFrame*)childFrame)->GetColumnCount();
|
|
|
|
actualColumns += numCols;
|
|
|
|
lastColGroupFrame = (nsTableColGroupFrame *)childFrame;
|
|
|
|
if (actualColumns > aColIndex)
|
1998-09-15 21:58:24 +04:00
|
|
|
break; // we have enough col frames at this point
|
1998-08-26 21:26:38 +04:00
|
|
|
}
|
1998-10-11 13:18:27 +04:00
|
|
|
else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
|
|
|
if (nsnull==firstRowGroupFrame)
|
|
|
|
firstRowGroupFrame = childFrame;
|
1998-08-26 21:26:38 +04:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
if (nsnull==firstRowGroupFrame)
|
|
|
|
prevSibFrame = childFrame;
|
1998-08-26 21:26:38 +04:00
|
|
|
childFrame->GetNextSibling(childFrame);
|
|
|
|
}
|
|
|
|
if (actualColumns <= aColIndex)
|
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
nsIHTMLContent *lastColGroup=nsnull;
|
1998-08-26 21:26:38 +04:00
|
|
|
if (nsnull==lastColGroupFrame)
|
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
// create an implicit colgroup
|
|
|
|
nsAutoString colGroupTag;
|
|
|
|
nsHTMLAtoms::colgroup->ToString(colGroupTag);
|
|
|
|
rv = NS_CreateHTMLElement(&lastColGroup, colGroupTag); // ADDREF a: lastColGroup++
|
1998-10-14 20:32:45 +04:00
|
|
|
//XXX: make synthetic
|
1998-09-15 21:58:24 +04:00
|
|
|
//XXX mark it as implicit!
|
1998-08-26 21:26:38 +04:00
|
|
|
mContent->AppendChildTo(lastColGroup, PR_FALSE); // add the implicit colgroup to my content
|
|
|
|
// Resolve style for the child
|
|
|
|
nsIStyleContext* colGroupStyleContext =
|
1998-10-11 13:18:27 +04:00
|
|
|
aPresContext.ResolveStyleContextFor(lastColGroup, this, PR_TRUE); // kidStyleContext: REFCNT++
|
1998-09-18 21:18:37 +04:00
|
|
|
|
|
|
|
// Create a col group frame
|
|
|
|
nsIFrame* newFrame;
|
|
|
|
NS_NewTableColGroupFrame(lastColGroup, this, newFrame);
|
|
|
|
lastColGroupFrame = (nsTableColGroupFrame*)newFrame;
|
1998-10-11 13:18:27 +04:00
|
|
|
lastColGroupFrame->SetStyleContext(&aPresContext, colGroupStyleContext);
|
1998-08-26 21:26:38 +04:00
|
|
|
NS_RELEASE(colGroupStyleContext); // kidStyleContenxt: REFCNT--
|
|
|
|
|
|
|
|
// hook lastColGroupFrame into child list
|
|
|
|
if (nsnull==firstRowGroupFrame)
|
|
|
|
{ // make lastColGroupFrame the last frame
|
1998-09-19 07:24:26 +04:00
|
|
|
nsIFrame *lastChild = LastFrame(mFirstChild);
|
1998-08-26 21:26:38 +04:00
|
|
|
lastChild->SetNextSibling(lastColGroupFrame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // insert lastColGroupFrame before the first row group frame
|
|
|
|
if (nsnull!=prevSibFrame)
|
|
|
|
{ // lastColGroupFrame is inserted between prevSibFrame and lastColGroupFrame
|
|
|
|
prevSibFrame->SetNextSibling(lastColGroupFrame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // lastColGroupFrame is inserted as the first child of this table
|
|
|
|
mFirstChild = lastColGroupFrame;
|
|
|
|
}
|
|
|
|
lastColGroupFrame->SetNextSibling(firstRowGroupFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lastColGroupFrame->GetContent((nsIContent *&)lastColGroup); // ADDREF b: lastColGroup++
|
|
|
|
}
|
|
|
|
|
1998-09-15 21:58:24 +04:00
|
|
|
nsAutoString colTag;
|
|
|
|
nsHTMLAtoms::col->ToString(colTag);
|
1998-08-26 21:26:38 +04:00
|
|
|
PRInt32 excessColumns = aColIndex - actualColumns;
|
1998-09-16 21:19:20 +04:00
|
|
|
nsIFrame* firstNewColFrame = nsnull;
|
|
|
|
nsIFrame* lastNewColFrame = nsnull;
|
1998-08-26 21:26:38 +04:00
|
|
|
for ( ; excessColumns >= 0; excessColumns--)
|
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
nsIHTMLContent *col=nsnull;
|
|
|
|
// create an implicit col
|
|
|
|
rv = NS_CreateHTMLElement(&col, colTag); // ADDREF: col++
|
1998-10-14 20:32:45 +04:00
|
|
|
//XXX: make synthetic
|
1998-09-15 21:58:24 +04:00
|
|
|
lastColGroup->AppendChildTo((nsIContent*)col, PR_FALSE);
|
1998-09-16 21:19:20 +04:00
|
|
|
|
|
|
|
// Create a new col frame
|
|
|
|
nsIFrame* colFrame;
|
|
|
|
NS_NewTableColFrame(col, lastColGroupFrame, colFrame);
|
|
|
|
|
|
|
|
// Set its style context
|
|
|
|
nsIStyleContextPtr colStyleContext =
|
1998-10-11 13:18:27 +04:00
|
|
|
aPresContext.ResolveStyleContextFor(col, lastColGroupFrame, PR_TRUE);
|
|
|
|
colFrame->SetStyleContext(&aPresContext, colStyleContext);
|
1998-09-16 21:19:20 +04:00
|
|
|
|
|
|
|
// XXX Don't release this style context (or we'll end up with a double-free).\
|
|
|
|
// This code is doing what nsTableColGroupFrame::Reflow() does...
|
|
|
|
//NS_RELEASE(colStyleContext);
|
|
|
|
|
|
|
|
// Add it to our list
|
|
|
|
if (nsnull == lastNewColFrame) {
|
|
|
|
firstNewColFrame = colFrame;
|
|
|
|
} else {
|
|
|
|
lastNewColFrame->SetNextSibling(colFrame);
|
|
|
|
}
|
|
|
|
lastNewColFrame = colFrame;
|
1998-09-15 21:58:24 +04:00
|
|
|
NS_RELEASE(col); // ADDREF: col--
|
1998-08-26 21:26:38 +04:00
|
|
|
}
|
|
|
|
NS_RELEASE(lastColGroup); // ADDREF: lastColGroup--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-09-01 01:23:28 +04:00
|
|
|
void nsTableFrame::AddColumnFrame (nsTableColFrame *aColFrame)
|
|
|
|
{
|
1998-10-20 09:05:17 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("TIF: AddColumnFrame %p\n", aColFrame);
|
1998-10-14 20:32:45 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
|
|
|
|
if (nsnull!=cellMap)
|
|
|
|
cellMap->AppendColumnFrame(aColFrame);
|
1998-09-01 01:23:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** return the index of the next row that is not yet assigned */
|
|
|
|
PRInt32 nsTableFrame::GetNextAvailRowIndex() const
|
|
|
|
{
|
|
|
|
PRInt32 result=0;
|
1998-10-14 20:32:45 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
|
|
|
|
if (nsnull!=cellMap)
|
1998-09-01 01:23:28 +04:00
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
result = cellMap->GetRowCount(); // the next index is the current count
|
|
|
|
cellMap->GrowToRow(result+1); // expand the cell map to include this new row
|
1998-09-01 01:23:28 +04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** return the index of the next column in aRowIndex that does not have a cell assigned to it */
|
|
|
|
PRInt32 nsTableFrame::GetNextAvailColIndex(PRInt32 aRowIndex, PRInt32 aColIndex) const
|
|
|
|
{
|
|
|
|
PRInt32 result=0;
|
1998-10-14 20:32:45 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
|
|
|
|
if (nsnull!=cellMap)
|
|
|
|
result = cellMap->GetNextAvailColIndex(aRowIndex, aColIndex);
|
1998-10-20 09:05:17 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("TIF: GetNextAvailColIndex returning %d\n", result);
|
1998-09-01 01:23:28 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-08-14 20:16:43 +04:00
|
|
|
/** Get the cell map for this table frame. It is not always mCellMap.
|
|
|
|
* Only the firstInFlow has a legit cell map
|
|
|
|
*/
|
1998-10-14 20:32:45 +04:00
|
|
|
nsCellMap * nsTableFrame::GetCellMap() const
|
1998-08-14 20:16:43 +04:00
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
if (this!=firstInFlow)
|
|
|
|
{
|
|
|
|
return firstInFlow->GetCellMap();
|
|
|
|
}
|
|
|
|
return mCellMap;
|
|
|
|
}
|
|
|
|
|
1998-09-01 01:23:28 +04:00
|
|
|
void nsTableFrame::SetMinColSpanForTable()
|
1998-08-18 03:37:04 +04:00
|
|
|
{ // XXX: must be called ONLY on first-in-flow
|
1998-09-01 01:23:28 +04:00
|
|
|
// set the minColSpan for each column
|
|
|
|
PRInt32 rowCount = mCellMap->GetRowCount();
|
1998-10-20 03:43:06 +04:00
|
|
|
PRInt32 colCount = mCellMap->GetColCount();
|
|
|
|
for (PRInt32 colIndex=0; colIndex<colCount; colIndex++)
|
1998-09-01 01:23:28 +04:00
|
|
|
{
|
|
|
|
PRInt32 minColSpan;
|
|
|
|
for (PRInt32 rowIndex=0; rowIndex<rowCount; rowIndex++)
|
|
|
|
{
|
|
|
|
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(rowIndex, colIndex);
|
|
|
|
if (nsnull!=cellFrame)
|
|
|
|
{
|
|
|
|
PRInt32 colSpan = cellFrame->GetColSpan();
|
|
|
|
if (0==rowIndex)
|
|
|
|
minColSpan = colSpan;
|
|
|
|
else
|
|
|
|
minColSpan = PR_MIN(minColSpan, colSpan);
|
|
|
|
}
|
|
|
|
}
|
1998-09-03 10:15:18 +04:00
|
|
|
if (1<minColSpan)
|
1998-09-01 01:23:28 +04:00
|
|
|
mCellMap->SetMinColSpan(colIndex, minColSpan);
|
|
|
|
}
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
|
|
|
|
1998-09-01 01:23:28 +04:00
|
|
|
void nsTableFrame::AddCellToTable (nsTableRowFrame *aRowFrame,
|
|
|
|
nsTableCellFrame *aCellFrame,
|
|
|
|
PRBool aAddRow)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-09-01 01:23:28 +04:00
|
|
|
NS_ASSERTION(nsnull!=aRowFrame, "bad aRowFrame arg");
|
|
|
|
NS_ASSERTION(nsnull!=aCellFrame, "bad aCellFrame arg");
|
|
|
|
NS_PRECONDITION(nsnull!=mCellMap, "bad cellMap");
|
|
|
|
|
1998-08-18 03:37:04 +04:00
|
|
|
// XXX: must be called only on first-in-flow!
|
1998-10-20 09:05:17 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("TIF AddCellToTable: frame %p\n", aCellFrame);
|
1998-06-17 20:38:24 +04:00
|
|
|
|
|
|
|
// Make an educated guess as to how many columns we have. It's
|
|
|
|
// only a guess because we can't know exactly until we have
|
|
|
|
// processed the last row.
|
|
|
|
if (0 == mColCount)
|
1998-07-02 02:22:28 +04:00
|
|
|
mColCount = GetSpecifiedColumnCount();
|
1998-06-17 20:38:24 +04:00
|
|
|
if (0 == mColCount) // no column parts
|
|
|
|
{
|
1998-09-01 01:23:28 +04:00
|
|
|
mColCount = aRowFrame->GetMaxColumns();
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-07-02 02:22:28 +04:00
|
|
|
|
1998-09-01 01:23:28 +04:00
|
|
|
PRInt32 rowIndex;
|
|
|
|
// also determine the index of aRowFrame and set it if necessary
|
|
|
|
if (0==mCellMap->GetRowCount())
|
|
|
|
{ // this is the first time we've ever been called
|
|
|
|
rowIndex = 0;
|
|
|
|
if (gsDebug==PR_TRUE) printf("rowFrame %p set to index %d\n", aRowFrame, rowIndex);
|
|
|
|
}
|
1998-06-17 20:38:24 +04:00
|
|
|
else
|
1998-09-01 01:23:28 +04:00
|
|
|
{
|
|
|
|
rowIndex = mCellMap->GetRowCount() - 1; // rowIndex is 0-indexed, rowCount is 1-indexed
|
|
|
|
}
|
1998-07-02 02:22:28 +04:00
|
|
|
|
1998-09-01 01:23:28 +04:00
|
|
|
PRInt32 colIndex=0;
|
|
|
|
while (PR_TRUE)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-09-01 01:23:28 +04:00
|
|
|
CellData *data = mCellMap->GetCellAt(rowIndex, colIndex);
|
|
|
|
if (nsnull == data)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-09-01 01:23:28 +04:00
|
|
|
BuildCellIntoMap(aCellFrame, rowIndex, colIndex);
|
|
|
|
break;
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-09-01 01:23:28 +04:00
|
|
|
colIndex++;
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-09-01 01:23:28 +04:00
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
if (gsDebug==PR_TRUE)
|
|
|
|
DumpCellMap ();
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_METHOD nsTableFrame::ReBuildCellMap()
|
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF: ReBuildCellMap.\n");
|
1998-10-14 20:32:45 +04:00
|
|
|
nsresult rv=NS_OK;
|
|
|
|
nsIFrame *rowGroupFrame=mFirstChild;
|
|
|
|
for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *rowGroupDisplay;
|
|
|
|
rowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
|
|
|
|
if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
|
|
|
|
{
|
|
|
|
nsIFrame *rowFrame;
|
|
|
|
rowGroupFrame->FirstChild(rowFrame);
|
|
|
|
for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(rowFrame))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *rowDisplay;
|
|
|
|
rowFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
rv = ((nsTableRowFrame *)rowFrame)->InitChildren();
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-20 03:43:06 +04:00
|
|
|
mCellMapValid=PR_TRUE;
|
1998-10-14 20:32:45 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
/**
|
1998-06-17 20:38:24 +04:00
|
|
|
*/
|
1998-07-24 20:51:16 +04:00
|
|
|
void nsTableFrame::DumpCellMap ()
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
|
|
|
printf("dumping CellMap:\n");
|
|
|
|
if (nsnull != mCellMap)
|
|
|
|
{
|
|
|
|
PRInt32 rowCount = mCellMap->GetRowCount();
|
1998-09-19 02:37:14 +04:00
|
|
|
PRInt32 colCount = mCellMap->GetColCount();
|
|
|
|
for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
|
|
|
if (gsDebug==PR_TRUE)
|
1998-09-19 02:37:14 +04:00
|
|
|
{ printf("row %d", rowIndex);
|
1998-06-17 20:38:24 +04:00
|
|
|
printf(": ");
|
|
|
|
}
|
1998-09-19 02:37:14 +04:00
|
|
|
for (PRInt32 colIndex = 0; colIndex < colCount; colIndex++)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-09-19 02:37:14 +04:00
|
|
|
CellData *cd =mCellMap->GetCellAt(rowIndex, colIndex);
|
1998-06-17 20:38:24 +04:00
|
|
|
if (cd != nsnull)
|
|
|
|
{
|
|
|
|
if (cd->mCell != nsnull)
|
|
|
|
{
|
1998-09-19 02:37:14 +04:00
|
|
|
printf("C%d,%d ", rowIndex, colIndex);
|
1998-06-17 20:38:24 +04:00
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nsTableCellFrame *cell = cd->mRealCell->mCell;
|
|
|
|
nsTableRowFrame *row;
|
|
|
|
cell->GetGeometricParent((nsIFrame *&)row);
|
|
|
|
int rr = row->GetRowIndex ();
|
|
|
|
int cc = cell->GetColIndex ();
|
|
|
|
printf("S%d,%d ", rr, cc);
|
|
|
|
if (cd->mOverlap != nsnull)
|
|
|
|
{
|
|
|
|
cell = cd->mOverlap->mCell;
|
|
|
|
nsTableRowFrame* row2;
|
1998-06-26 19:07:09 +04:00
|
|
|
cell->GetGeometricParent((nsIFrame *&)row2);
|
1998-06-17 20:38:24 +04:00
|
|
|
rr = row2->GetRowIndex ();
|
|
|
|
cc = cell->GetColIndex ();
|
|
|
|
printf("O%d,%c ", rr, cc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf(" ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf("---- ");
|
|
|
|
}
|
1998-09-19 02:37:14 +04:00
|
|
|
PRBool spanners = RowHasSpanningCells(rowIndex);
|
|
|
|
PRBool spannedInto = RowIsSpannedInto(rowIndex);
|
|
|
|
printf (" spanners=%s spannedInto=%s\n", spanners?"T":"F", spannedInto?"T":"F");
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-09-19 02:37:14 +04:00
|
|
|
// output colspan info
|
|
|
|
for (PRInt32 colIndex=0; colIndex<colCount; colIndex++)
|
|
|
|
{
|
|
|
|
PRBool colSpanners = ColHasSpanningCells(colIndex);
|
|
|
|
PRBool colSpannedInto = ColIsSpannedInto(colIndex);
|
|
|
|
printf ("%d colSpanners=%s colSpannedInto=%s\n",
|
|
|
|
colIndex, colSpanners?"T":"F", colSpannedInto?"T":"F");
|
|
|
|
}
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
printf ("[nsnull]");
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsTableFrame::BuildCellIntoMap (nsTableCellFrame *aCell, PRInt32 aRowIndex, PRInt32 aColIndex)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION (nsnull!=aCell, "bad cell arg");
|
1998-09-01 01:23:28 +04:00
|
|
|
NS_PRECONDITION (0 <= aColIndex, "bad column index arg");
|
|
|
|
NS_PRECONDITION (0 <= aRowIndex, "bad row index arg");
|
1998-06-17 20:38:24 +04:00
|
|
|
|
|
|
|
// Setup CellMap for this cell
|
1998-09-01 01:23:28 +04:00
|
|
|
int rowSpan = aCell->GetRowSpan();
|
|
|
|
int colSpan = aCell->GetColSpan();
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: rowSpan = %d, colSpan = %d\n", rowSpan, colSpan);
|
1998-06-17 20:38:24 +04:00
|
|
|
|
|
|
|
// Grow the mCellMap array if we will end up addressing
|
|
|
|
// some new columns.
|
1998-09-01 01:23:28 +04:00
|
|
|
if (mCellMap->GetColCount() < (aColIndex + colSpan))
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-09-01 01:23:28 +04:00
|
|
|
if (gsDebug==PR_TRUE)
|
1998-10-14 20:32:45 +04:00
|
|
|
printf("BCIM: calling GrowCellMap(%d)\n", aColIndex+colSpan);
|
1998-06-17 20:38:24 +04:00
|
|
|
GrowCellMap (aColIndex + colSpan);
|
|
|
|
}
|
|
|
|
|
1998-09-01 01:23:28 +04:00
|
|
|
if (mCellMap->GetRowCount() < (aRowIndex+1))
|
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
printf("BCIM: calling GrowToRow(%d)\n", aRowIndex+1);
|
1998-09-01 01:23:28 +04:00
|
|
|
mCellMap->GrowToRow(aRowIndex+1);
|
|
|
|
}
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
// Setup CellMap for this cell in the table
|
|
|
|
CellData *data = new CellData ();
|
|
|
|
data->mCell = aCell;
|
|
|
|
data->mRealCell = data;
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: calling mCellMap->SetCellAt(data, %d, %d)\n", aRowIndex, aColIndex);
|
1998-06-17 20:38:24 +04:00
|
|
|
mCellMap->SetCellAt(data, aRowIndex, aColIndex);
|
|
|
|
|
|
|
|
// Create CellData objects for the rows that this cell spans. Set
|
|
|
|
// their mCell to nsnull and their mRealCell to point to data. If
|
|
|
|
// there were no column overlaps then we could use the same
|
|
|
|
// CellData object for each row that we span...
|
|
|
|
if ((1 < rowSpan) || (1 < colSpan))
|
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: spans\n");
|
1998-06-17 20:38:24 +04:00
|
|
|
for (int rowIndex = 0; rowIndex < rowSpan; rowIndex++)
|
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: rowIndex = %d\n", rowIndex);
|
1998-06-17 20:38:24 +04:00
|
|
|
int workRow = aRowIndex + rowIndex;
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: workRow = %d\n", workRow);
|
1998-06-17 20:38:24 +04:00
|
|
|
for (int colIndex = 0; colIndex < colSpan; colIndex++)
|
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: colIndex = %d\n", colIndex);
|
1998-06-17 20:38:24 +04:00
|
|
|
int workCol = aColIndex + colIndex;
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: workCol = %d\n", workCol);
|
1998-06-17 20:38:24 +04:00
|
|
|
CellData *testData = mCellMap->GetCellAt(workRow, workCol);
|
|
|
|
if (nsnull == testData)
|
|
|
|
{
|
|
|
|
CellData *spanData = new CellData ();
|
|
|
|
spanData->mRealCell = data;
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: null GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
|
1998-06-17 20:38:24 +04:00
|
|
|
mCellMap->SetCellAt(spanData, workRow, workCol);
|
|
|
|
}
|
|
|
|
else if ((0 < rowIndex) || (0 < colIndex))
|
|
|
|
{ // we overlap, replace existing data, it might be shared
|
1998-10-14 20:32:45 +04:00
|
|
|
if (gsDebug==PR_TRUE) printf("BCIM: overlapping Cell from GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
|
1998-06-17 20:38:24 +04:00
|
|
|
CellData *overlap = new CellData ();
|
|
|
|
overlap->mCell = testData->mCell;
|
|
|
|
overlap->mRealCell = testData->mRealCell;
|
|
|
|
overlap->mOverlap = data;
|
|
|
|
mCellMap->SetCellAt(overlap, workRow, workCol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsTableFrame::GrowCellMap (PRInt32 aColCount)
|
|
|
|
{
|
|
|
|
if (nsnull!=mCellMap)
|
|
|
|
{
|
1998-09-01 01:23:28 +04:00
|
|
|
mCellMap->GrowToCol(aColCount);
|
1998-06-17 20:38:24 +04:00
|
|
|
mColCount = aColCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ***** Column Layout Data methods ***** */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lists the column layout data which turns
|
|
|
|
* around and lists the cell layout data.
|
|
|
|
* This is for debugging purposes only.
|
|
|
|
*/
|
1998-07-24 20:51:16 +04:00
|
|
|
void nsTableFrame::ListColumnLayoutData(FILE* out, PRInt32 aIndent)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-07-11 04:00:31 +04:00
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
if (this!=firstInFlow)
|
|
|
|
{
|
|
|
|
firstInFlow->ListColumnLayoutData(out, aIndent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-08-18 03:37:04 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
if (nsnull!=cellMap)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
fprintf(out,"Column Layout Data \n");
|
|
|
|
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 numCols = cellMap->GetColCount();
|
1998-08-18 03:37:04 +04:00
|
|
|
PRInt32 numRows = cellMap->GetRowCount();
|
1998-07-11 04:00:31 +04:00
|
|
|
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-07-11 04:00:31 +04:00
|
|
|
for (PRInt32 indent = aIndent; --indent >= 0; )
|
|
|
|
fputs(" ", out);
|
|
|
|
fprintf(out,"Column Data [%d] \n",colIndex);
|
|
|
|
for (PRInt32 rowIndex = 0; rowIndex < numRows; rowIndex++)
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
nsTableCellFrame *cellFrame = cellMap->GetCellFrameAt(rowIndex, colIndex);
|
1998-07-11 04:00:31 +04:00
|
|
|
PRInt32 rowIndent;
|
|
|
|
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
|
|
|
fprintf(out,"Cell Data [%d] \n",rowIndex);
|
|
|
|
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
|
|
|
nsMargin margin;
|
|
|
|
cellFrame->GetMargin(margin);
|
|
|
|
fprintf(out,"Margin -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
1998-08-01 03:34:45 +04:00
|
|
|
NSTwipsToIntPoints(margin.top),
|
|
|
|
NSTwipsToIntPoints(margin.left),
|
|
|
|
NSTwipsToIntPoints(margin.bottom),
|
|
|
|
NSTwipsToIntPoints(margin.right));
|
1998-07-11 04:00:31 +04:00
|
|
|
|
|
|
|
for (rowIndent = aIndent+2; --rowIndent >= 0; ) fputs(" ", out);
|
|
|
|
|
|
|
|
/*
|
1998-07-30 00:19:08 +04:00
|
|
|
nscoord top,left,bottom,right;
|
1998-07-11 04:00:31 +04:00
|
|
|
top = (mBorderFrame[NS_SIDE_TOP] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_TOP], NS_SIDE_TOP) : 0);
|
|
|
|
left = (mBorderFrame[NS_SIDE_LEFT] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_LEFT], NS_SIDE_LEFT) : 0);
|
|
|
|
bottom = (mBorderFrame[NS_SIDE_BOTTOM] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_BOTTOM], NS_SIDE_BOTTOM) : 0);
|
|
|
|
right = (mBorderFrame[NS_SIDE_RIGHT] ? cellFrame->GetBorderWidth((nsIFrame*)mBorderFrame[NS_SIDE_RIGHT], NS_SIDE_RIGHT) : 0);
|
|
|
|
|
|
|
|
fprintf(out,"Border -- Top: %d Left: %d Bottom: %d Right: %d \n",
|
1998-08-01 03:34:45 +04:00
|
|
|
NSTwipsToIntPoints(top),
|
|
|
|
NSTwipsToIntPoints(left),
|
|
|
|
NSTwipsToIntPoints(bottom),
|
|
|
|
NSTwipsToIntPoints(right));
|
1998-07-30 00:19:08 +04:00
|
|
|
*/
|
1998-07-11 04:00:31 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
1998-07-11 04:00:31 +04:00
|
|
|
* For the TableCell in CellData, add it to the list
|
|
|
|
*/
|
1998-06-17 20:38:24 +04:00
|
|
|
void nsTableFrame::AppendLayoutData(nsVoidArray* aList, nsTableCellFrame* aTableCell)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
if (aTableCell != nsnull)
|
|
|
|
{
|
1998-07-11 04:00:31 +04:00
|
|
|
aList->AppendElement((void*)aTableCell);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-29 02:41:25 +04:00
|
|
|
void nsTableFrame::RecalcLayoutData()
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
if (nsnull==cellMap)
|
1998-07-07 04:20:21 +04:00
|
|
|
return; // no info yet, so nothing useful to do
|
|
|
|
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 colCount = cellMap->GetColCount();
|
1998-08-18 03:37:04 +04:00
|
|
|
PRInt32 rowCount = cellMap->GetRowCount();
|
1998-06-17 20:38:24 +04:00
|
|
|
PRInt32 row = 0;
|
|
|
|
PRInt32 col = 0;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
nsTableCellFrame* above = nsnull;
|
|
|
|
nsTableCellFrame* below = nsnull;
|
|
|
|
nsTableCellFrame* left = nsnull;
|
|
|
|
nsTableCellFrame* right = nsnull;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
|
|
|
|
PRInt32 edge = 0;
|
|
|
|
nsVoidArray* boundaryCells[4];
|
|
|
|
|
|
|
|
for (edge = 0; edge < 4; edge++)
|
|
|
|
boundaryCells[edge] = new nsVoidArray();
|
|
|
|
|
|
|
|
|
|
|
|
if (colCount != 0 && rowCount != 0)
|
|
|
|
{
|
|
|
|
for (row = 0; row < rowCount; row++)
|
|
|
|
{
|
|
|
|
for (col = 0; col < colCount; col++)
|
|
|
|
{
|
1998-06-17 20:38:24 +04:00
|
|
|
nsTableCellFrame* cell = nsnull;
|
1998-08-18 03:37:04 +04:00
|
|
|
CellData* cellData = cellMap->GetCellAt(row,col);
|
1998-05-27 00:57:24 +04:00
|
|
|
|
|
|
|
if (cellData)
|
|
|
|
cell = cellData->mCell;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
if (nsnull==cell)
|
1998-04-14 00:24:54 +04:00
|
|
|
continue;
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
PRInt32 colSpan = cell->GetColSpan();
|
|
|
|
PRInt32 rowSpan = cell->GetRowSpan();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
// clear the cells for all for edges
|
|
|
|
for (edge = 0; edge < 4; edge++)
|
|
|
|
boundaryCells[edge]->Clear();
|
|
|
|
|
|
|
|
// Check to see if the cell data represents the top,left
|
|
|
|
// corner of a a table cell
|
|
|
|
|
1998-05-22 03:43:18 +04:00
|
|
|
// Check to see if cell the represents a top edge cell
|
1998-06-17 20:38:24 +04:00
|
|
|
if (0 == row)
|
1998-04-14 00:24:54 +04:00
|
|
|
above = nsnull;
|
|
|
|
else
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
cellData = cellMap->GetCellAt(row-1,col);
|
1998-06-17 20:38:24 +04:00
|
|
|
if (nsnull != cellData)
|
1998-05-22 03:43:18 +04:00
|
|
|
above = cellData->mRealCell->mCell;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
// Does the cell data point to the same cell?
|
|
|
|
// If it is, then continue
|
1998-06-17 20:38:24 +04:00
|
|
|
if ((nsnull != above) && (above == cell))
|
1998-04-14 00:24:54 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
1998-05-22 03:43:18 +04:00
|
|
|
// Check to see if cell the represents a left edge cell
|
1998-06-17 20:38:24 +04:00
|
|
|
if (0 == col)
|
1998-04-26 06:59:29 +04:00
|
|
|
left = nsnull;
|
1998-04-14 00:24:54 +04:00
|
|
|
else
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
cellData = cellMap->GetCellAt(row,col-1);
|
1998-04-14 00:24:54 +04:00
|
|
|
if (cellData != nsnull)
|
1998-05-22 03:43:18 +04:00
|
|
|
left = cellData->mRealCell->mCell;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
if ((nsnull != left) && (left == cell))
|
1998-04-14 00:24:54 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is the top,left edged cell
|
|
|
|
// Then add the cells on the for edges to the array
|
|
|
|
|
|
|
|
// Do the top and bottom edge
|
|
|
|
PRInt32 r,c;
|
|
|
|
PRInt32 r1,r2;
|
|
|
|
PRInt32 c1,c2;
|
|
|
|
PRInt32 last;
|
|
|
|
|
|
|
|
|
|
|
|
r1 = row - 1;
|
|
|
|
r2 = row + rowSpan;
|
|
|
|
c = col;
|
|
|
|
last = col + colSpan -1;
|
1998-05-28 22:31:44 +04:00
|
|
|
last = PR_MIN(last,colCount-1);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
while (c <= last)
|
|
|
|
{
|
|
|
|
if (r1 != -1)
|
|
|
|
{
|
|
|
|
// Add top edge cells
|
|
|
|
if (c != col)
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
cellData = cellMap->GetCellAt(r1,c);
|
1998-05-27 00:57:24 +04:00
|
|
|
if ((cellData != nsnull) && (cellData->mCell != above))
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
above = cellData->mCell;
|
|
|
|
if (above != nsnull)
|
|
|
|
AppendLayoutData(boundaryCells[NS_SIDE_TOP],above);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (above != nsnull)
|
|
|
|
{
|
|
|
|
AppendLayoutData(boundaryCells[NS_SIDE_TOP],above);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r2 < rowCount)
|
|
|
|
{
|
|
|
|
// Add bottom edge cells
|
1998-08-18 03:37:04 +04:00
|
|
|
cellData = cellMap->GetCellAt(r2,c);
|
1998-05-27 00:57:24 +04:00
|
|
|
if ((cellData != nsnull) && cellData->mCell != below)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
below = cellData->mCell;
|
|
|
|
if (below != nsnull)
|
|
|
|
AppendLayoutData(boundaryCells[NS_SIDE_BOTTOM],below);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the left and right edge
|
|
|
|
c1 = col - 1;
|
|
|
|
c2 = col + colSpan;
|
|
|
|
r = row ;
|
|
|
|
last = row + rowSpan-1;
|
1998-05-28 22:31:44 +04:00
|
|
|
last = PR_MIN(last,rowCount-1);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
while (r <= last)
|
|
|
|
{
|
|
|
|
// Add left edge cells
|
|
|
|
if (c1 != -1)
|
|
|
|
{
|
|
|
|
if (r != row)
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
cellData = cellMap->GetCellAt(r,c1);
|
1998-05-27 00:57:24 +04:00
|
|
|
if ((cellData != nsnull) && (cellData->mCell != left))
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
left = cellData->mCell;
|
|
|
|
if (left != nsnull)
|
|
|
|
AppendLayoutData(boundaryCells[NS_SIDE_LEFT],left);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (left != nsnull)
|
|
|
|
{
|
|
|
|
AppendLayoutData(boundaryCells[NS_SIDE_LEFT],left);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c2 < colCount)
|
|
|
|
{
|
|
|
|
// Add right edge cells
|
1998-08-18 03:37:04 +04:00
|
|
|
cellData = cellMap->GetCellAt(r,c2);
|
1998-05-27 00:57:24 +04:00
|
|
|
if ((cellData != nsnull) && (cellData->mCell != right))
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
right = cellData->mCell;
|
|
|
|
if (right != nsnull)
|
|
|
|
AppendLayoutData(boundaryCells[NS_SIDE_RIGHT],right);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r++;
|
|
|
|
}
|
|
|
|
|
1998-07-11 04:00:31 +04:00
|
|
|
cell->RecalcLayoutData(this,boundaryCells);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (edge = 0; edge < 4; edge++)
|
|
|
|
delete boundaryCells[edge];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* SEC: TODO: adjust the rect for captions */
|
1998-04-17 05:41:24 +04:00
|
|
|
NS_METHOD nsTableFrame::Paint(nsIPresContext& aPresContext,
|
|
|
|
nsIRenderingContext& aRenderingContext,
|
|
|
|
const nsRect& aDirtyRect)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
// table paint code is concerned primarily with borders and bg color
|
1998-06-05 10:09:09 +04:00
|
|
|
const nsStyleDisplay* disp =
|
|
|
|
(const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
|
1998-05-27 03:17:29 +04:00
|
|
|
|
|
|
|
if (disp->mVisible) {
|
1998-07-21 03:58:00 +04:00
|
|
|
const nsStyleSpacing* spacing =
|
1998-06-05 10:09:09 +04:00
|
|
|
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
1998-07-21 12:12:22 +04:00
|
|
|
const nsStyleColor* color =
|
|
|
|
(const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
|
1998-07-21 03:58:00 +04:00
|
|
|
|
1998-07-22 09:02:07 +04:00
|
|
|
nsRect rect(0, 0, mRect.width, mRect.height);
|
1998-07-21 03:58:00 +04:00
|
|
|
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
|
1998-09-26 21:17:20 +04:00
|
|
|
aDirtyRect, rect, *color, 0, 0);
|
1998-07-21 03:58:00 +04:00
|
|
|
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
|
1998-07-22 09:02:07 +04:00
|
|
|
aDirtyRect, rect, *spacing, 0);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// for debug...
|
|
|
|
if (nsIFrame::GetShowFrameBorders()) {
|
|
|
|
aRenderingContext.SetColor(NS_RGB(0,128,0));
|
|
|
|
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
PaintChildren(aPresContext, aRenderingContext, aDirtyRect);
|
1998-04-17 05:41:24 +04:00
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
PRBool result = PR_TRUE;
|
1998-10-14 20:32:45 +04:00
|
|
|
if (eReflowReason_Incremental != aReflowState.reason)
|
|
|
|
{ // incremental reflows always need to be reflowed (for now)
|
|
|
|
if (PR_TRUE==mIsInvariantWidth)
|
|
|
|
result = PR_FALSE;
|
|
|
|
// XXX TODO: other optimization cases...
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
nsresult nsTableFrame::AdjustSiblingsAfterReflow(nsIPresContext& aPresContext,
|
1998-07-07 01:39:23 +04:00
|
|
|
InnerTableReflowState& aState,
|
|
|
|
nsIFrame* aKidFrame,
|
|
|
|
nscoord aDeltaY)
|
|
|
|
{
|
|
|
|
nsIFrame* lastKidFrame = aKidFrame;
|
|
|
|
|
|
|
|
if (aDeltaY != 0) {
|
|
|
|
// Move the frames that follow aKidFrame by aDeltaY
|
|
|
|
nsIFrame* kidFrame;
|
|
|
|
|
|
|
|
aKidFrame->GetNextSibling(kidFrame);
|
|
|
|
while (nsnull != kidFrame) {
|
1998-10-01 08:46:11 +04:00
|
|
|
nsPoint origin;
|
|
|
|
nsIHTMLReflow* htmlReflow;
|
1998-07-07 01:39:23 +04:00
|
|
|
|
|
|
|
// XXX We can't just slide the child if it has a next-in-flow
|
|
|
|
kidFrame->GetOrigin(origin);
|
|
|
|
origin.y += aDeltaY;
|
|
|
|
|
|
|
|
// XXX We need to send move notifications to the frame...
|
1998-10-01 08:46:11 +04:00
|
|
|
if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
|
1998-10-11 13:18:27 +04:00
|
|
|
htmlReflow->WillReflow(aPresContext);
|
1998-10-01 08:46:11 +04:00
|
|
|
}
|
1998-07-07 01:39:23 +04:00
|
|
|
kidFrame->MoveTo(origin.x, origin.y);
|
|
|
|
|
|
|
|
// Get the next frame
|
|
|
|
lastKidFrame = kidFrame;
|
|
|
|
kidFrame->GetNextSibling(kidFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Get the last frame
|
1998-09-19 07:24:26 +04:00
|
|
|
lastKidFrame = LastFrame(mFirstChild);
|
1998-07-07 01:39:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update our running y-offset to reflect the bottommost child
|
|
|
|
nsRect rect;
|
|
|
|
lastKidFrame->GetRect(rect);
|
|
|
|
aState.y = rect.YMost();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// SEC: TODO need to worry about continuing frames prev/next in flow for splitting across pages.
|
|
|
|
// SEC: TODO need to keep "first pass done" state, update it when ContentChanged notifications come in
|
|
|
|
|
|
|
|
/* overview:
|
|
|
|
if mFirstPassValid is false, this is our first time through since content was last changed
|
|
|
|
set pass to 1
|
|
|
|
do pass 1
|
|
|
|
get min/max info for all cells in an infinite space
|
|
|
|
do column balancing
|
|
|
|
set mFirstPassValid to true
|
|
|
|
do pass 2
|
|
|
|
if pass is 1,
|
|
|
|
set pass to 2
|
|
|
|
use column widths to ResizeReflow cells
|
|
|
|
*/
|
|
|
|
|
1998-05-29 01:39:22 +04:00
|
|
|
/* Layout the entire inner table. */
|
1998-07-15 06:53:09 +04:00
|
|
|
NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
|
1998-10-01 08:46:11 +04:00
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
1998-05-25 21:31:49 +04:00
|
|
|
nsReflowStatus& aStatus)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
if (gsDebug==PR_TRUE)
|
|
|
|
{
|
|
|
|
printf("-----------------------------------------------------------------\n");
|
1998-08-08 01:53:27 +04:00
|
|
|
printf("nsTableFrame::Reflow: table %p reason %d given maxSize=%d,%d\n",
|
|
|
|
this, aReflowState.reason, aReflowState.maxSize.width, aReflowState.maxSize.height);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-07-07 01:39:23 +04:00
|
|
|
// Initialize out parameter
|
|
|
|
if (nsnull != aDesiredSize.maxElementSize) {
|
|
|
|
aDesiredSize.maxElementSize->width = 0;
|
|
|
|
aDesiredSize.maxElementSize->height = 0;
|
|
|
|
}
|
1998-05-12 08:17:56 +04:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
nsresult rv = NS_OK;
|
1998-10-01 08:46:11 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
if (eReflowReason_Incremental == aReflowState.reason) {
|
|
|
|
rv = IncrementalReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
1998-06-23 09:43:27 +04:00
|
|
|
}
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
// NeedsReflow and IsFirstPassValid take into account reflow type = Initial_Reflow
|
|
|
|
if (PR_TRUE==NeedsReflow(aReflowState, aReflowState.maxSize))
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
PRBool needsRecalc=PR_FALSE;
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs reflow\n");
|
1998-10-14 20:32:45 +04:00
|
|
|
if (eReflowReason_Initial!=aReflowState.reason && PR_FALSE==IsCellMapValid())
|
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: cell map invalid, rebuilding...\n");
|
1998-10-14 20:32:45 +04:00
|
|
|
if (nsnull!=mCellMap)
|
|
|
|
delete mCellMap;
|
|
|
|
mCellMap = new nsCellMap(0,0);
|
|
|
|
ReBuildCellMap();
|
|
|
|
needsRecalc=PR_TRUE;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
if (PR_FALSE==IsFirstPassValid())
|
1998-09-24 01:48:26 +04:00
|
|
|
{
|
1998-10-16 01:07:37 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: first pass is invalid, rebuilding...\n");
|
1998-10-20 03:43:06 +04:00
|
|
|
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus, nsnull, aReflowState.reason, PR_TRUE);
|
1998-10-11 13:18:27 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1998-10-14 20:32:45 +04:00
|
|
|
needsRecalc=PR_TRUE;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1998-10-15 02:51:50 +04:00
|
|
|
if (PR_FALSE==IsColumnCacheValid())
|
1998-10-16 01:07:37 +04:00
|
|
|
{
|
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: column cache is invalid, rebuilding...\n");
|
1998-10-15 02:51:50 +04:00
|
|
|
needsRecalc=PR_TRUE;
|
1998-10-16 01:07:37 +04:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
if (PR_TRUE==needsRecalc)
|
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: needs recalc. Calling BuildColumnCache...\n");
|
|
|
|
BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus);
|
|
|
|
RecalcLayoutData(); // Recalculate Layout Dependencies
|
|
|
|
// if we needed to rebuild the column cache, the data stored in the layout strategy is invalid
|
1998-10-14 20:32:45 +04:00
|
|
|
if (nsnull!=mTableLayoutStrategy)
|
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
|
|
|
|
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, mCellMap->GetColCount());
|
|
|
|
mColumnWidthsValid=PR_TRUE; //so we don't do this a second time below
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
}
|
1998-10-16 01:07:37 +04:00
|
|
|
if (PR_FALSE==IsColumnWidthsValid())
|
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
|
1998-10-16 01:07:37 +04:00
|
|
|
if (nsnull!=mTableLayoutStrategy)
|
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, mCellMap->GetColCount());
|
1998-10-16 01:07:37 +04:00
|
|
|
mColumnWidthsValid=PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-08-14 20:16:43 +04:00
|
|
|
if (nsnull==mPrevInFlow)
|
1998-10-14 20:32:45 +04:00
|
|
|
{ // only do this for a first-in-flow table frame
|
1998-08-14 20:16:43 +04:00
|
|
|
// assign column widths, and assign aMaxElementSize->width
|
1998-10-11 13:18:27 +04:00
|
|
|
BalanceColumnWidths(aPresContext, aReflowState, aReflowState.maxSize,
|
1998-08-14 20:16:43 +04:00
|
|
|
aDesiredSize.maxElementSize);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-08-14 20:16:43 +04:00
|
|
|
// assign table width
|
1998-10-11 13:18:27 +04:00
|
|
|
SetTableWidth(aPresContext);
|
1998-08-14 20:16:43 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-24 08:38:52 +04:00
|
|
|
// Constrain our reflow width to the computed table width
|
1998-10-02 08:10:00 +04:00
|
|
|
nsHTMLReflowState reflowState(aReflowState);
|
1998-06-24 08:38:52 +04:00
|
|
|
reflowState.maxSize.width = mRect.width;
|
1998-10-11 13:18:27 +04:00
|
|
|
rv = ResizeReflowPass2(aPresContext, aDesiredSize, reflowState, aStatus);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// set aDesiredSize and aMaxElementSize
|
|
|
|
}
|
|
|
|
|
1998-07-07 01:39:23 +04:00
|
|
|
if (gsDebugNT==PR_TRUE)
|
|
|
|
{
|
|
|
|
if (nsnull!=aDesiredSize.maxElementSize)
|
|
|
|
printf("%p: Inner table reflow complete, returning aDesiredSize = %d,%d and aMaxElementSize=%d,%d\n",
|
|
|
|
this, aDesiredSize.width, aDesiredSize.height,
|
|
|
|
aDesiredSize.maxElementSize->width, aDesiredSize.maxElementSize->height);
|
|
|
|
else
|
|
|
|
printf("%p: Inner table reflow complete, returning aDesiredSize = %d,%d and NSNULL aMaxElementSize\n",
|
|
|
|
this, aDesiredSize.width, aDesiredSize.height);
|
|
|
|
}
|
|
|
|
|
1998-06-08 19:47:03 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("end reflow for table %p\n", this);
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** the first of 2 reflow passes
|
|
|
|
* lay out the captions and row groups in an infinite space (NS_UNCONSTRAINEDSIZE)
|
|
|
|
* cache the results for each caption and cell.
|
|
|
|
* if successful, set mFirstPassValid=PR_TRUE, so we know we can skip this step
|
|
|
|
* next time. mFirstPassValid is set to PR_FALSE when content is changed.
|
|
|
|
* NOTE: should never get called on a continuing frame! All cached pass1 state
|
|
|
|
* is stored in the inner table first-in-flow.
|
|
|
|
*/
|
1998-10-15 11:46:16 +04:00
|
|
|
NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
nsTableRowGroupFrame * aStartingFrame,
|
1998-10-20 03:43:06 +04:00
|
|
|
nsReflowReason aReason,
|
|
|
|
PRBool aDoSiblingFrames)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-05-30 00:36:05 +04:00
|
|
|
NS_PRECONDITION(aReflowState.frame == this, "bad reflow state");
|
|
|
|
NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent,
|
|
|
|
"bad parent reflow state");
|
1998-04-14 00:24:54 +04:00
|
|
|
NS_ASSERTION(nsnull==mPrevInFlow, "illegal call, cannot call pass 1 on a continuing frame.");
|
1998-06-17 20:38:24 +04:00
|
|
|
NS_ASSERTION(nsnull != mContent, "null content");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-24 03:23:21 +04:00
|
|
|
if (PR_TRUE==gsDebugNT) printf("%p nsTableFrame::ResizeReflow Pass1: maxSize=%d,%d\n",
|
1998-06-08 19:47:03 +04:00
|
|
|
this, aReflowState.maxSize.width, aReflowState.maxSize.height);
|
1998-10-11 13:18:27 +04:00
|
|
|
nsresult rv=NS_OK;
|
|
|
|
// set out params
|
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
nsSize availSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); // availSize is the space available at any given time in the process
|
|
|
|
nsSize maxSize(0, 0); // maxSize is the size of the largest child so far in the process
|
|
|
|
nsSize kidMaxSize(0,0);
|
1998-10-01 08:46:11 +04:00
|
|
|
nsHTMLReflowMetrics kidSize(&kidMaxSize);
|
1998-04-14 00:24:54 +04:00
|
|
|
nscoord y = 0;
|
|
|
|
nscoord maxAscent = 0;
|
|
|
|
nscoord maxDescent = 0;
|
|
|
|
PRInt32 kidIndex = 0;
|
1998-08-30 00:20:38 +04:00
|
|
|
PRInt32 lastIndex;
|
|
|
|
mContent->ChildCount(lastIndex);
|
1998-04-14 00:24:54 +04:00
|
|
|
PRInt32 contentOffset=0;
|
|
|
|
nsIFrame* prevKidFrame = nsnull;/* XXX incremental reflow! */
|
|
|
|
|
|
|
|
// Compute the insets (sum of border and padding)
|
1998-06-05 10:09:09 +04:00
|
|
|
const nsStyleSpacing* spacing =
|
|
|
|
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
1998-05-13 02:28:01 +04:00
|
|
|
nsMargin borderPadding;
|
|
|
|
spacing->CalcBorderPaddingFor(this, borderPadding);
|
|
|
|
nscoord topInset = borderPadding.top;
|
|
|
|
nscoord rightInset = borderPadding.right;
|
|
|
|
nscoord bottomInset = borderPadding.bottom;
|
|
|
|
nscoord leftInset = borderPadding.left;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-09-23 03:36:06 +04:00
|
|
|
nsStyleTable* tableStyle;
|
|
|
|
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
|
1998-09-24 01:48:26 +04:00
|
|
|
if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy)
|
1998-09-23 03:36:06 +04:00
|
|
|
{
|
1998-10-15 11:46:16 +04:00
|
|
|
nsIFrame* kidFrame = aStartingFrame;
|
|
|
|
if (nsnull==kidFrame)
|
|
|
|
kidFrame=mFirstChild;
|
|
|
|
for ( ; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame))
|
1998-09-24 20:37:22 +04:00
|
|
|
{
|
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
|
|
|
if ((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP != childDisplay->mDisplay) &&
|
|
|
|
(NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP != childDisplay->mDisplay) &&
|
|
|
|
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP != childDisplay->mDisplay) &&
|
|
|
|
(NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP != childDisplay->mDisplay))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
1998-09-23 03:36:06 +04:00
|
|
|
nsSize maxKidElementSize(0,0);
|
1998-10-12 18:48:02 +04:00
|
|
|
nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aReflowState,
|
1998-10-15 11:46:16 +04:00
|
|
|
availSize, aReason);
|
1998-10-06 04:27:22 +04:00
|
|
|
PRInt32 yCoord = y;
|
|
|
|
if (NS_UNCONSTRAINEDSIZE!=yCoord)
|
|
|
|
yCoord+= topInset;
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 1 of frame %p with reason=%d\n", kidFrame, aReason);
|
1998-10-11 13:18:27 +04:00
|
|
|
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, aStatus);
|
1998-10-01 08:46:11 +04:00
|
|
|
|
1998-10-06 04:27:22 +04:00
|
|
|
// Place the child since some of its content fit in us.
|
|
|
|
if (PR_TRUE==gsDebugNT) {
|
|
|
|
printf ("%p: reflow of row group returned desired=%d,%d, max-element=%d,%d\n",
|
|
|
|
this, kidSize.width, kidSize.height, kidMaxSize.width, kidMaxSize.height);
|
|
|
|
}
|
|
|
|
kidFrame->SetRect(nsRect(leftInset, yCoord, kidSize.width, kidSize.height));
|
|
|
|
if (NS_UNCONSTRAINEDSIZE==kidSize.height)
|
|
|
|
y = NS_UNCONSTRAINEDSIZE;
|
|
|
|
else
|
|
|
|
y += kidSize.height;
|
|
|
|
if (kidMaxSize.width > maxSize.width) {
|
|
|
|
maxSize.width = kidMaxSize.width;
|
|
|
|
}
|
|
|
|
if (kidMaxSize.height > maxSize.height) {
|
|
|
|
maxSize.height = kidMaxSize.height;
|
|
|
|
}
|
1998-09-16 21:19:20 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
1998-10-06 04:27:22 +04:00
|
|
|
// If the child didn't finish layout then it means that it used
|
|
|
|
// up all of our available space (or needs us to split).
|
|
|
|
break;
|
1998-09-23 03:36:06 +04:00
|
|
|
}
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_FALSE==aDoSiblingFrames)
|
|
|
|
break;
|
1998-09-16 21:19:20 +04:00
|
|
|
}
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-24 03:23:21 +04:00
|
|
|
aDesiredSize.width = kidSize.width;
|
1998-04-14 00:24:54 +04:00
|
|
|
mFirstPassValid = PR_TRUE;
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** the second of 2 reflow passes
|
|
|
|
*/
|
1998-10-11 13:18:27 +04:00
|
|
|
NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-09-19 02:37:14 +04:00
|
|
|
//DumpCellMap();
|
1998-05-30 00:36:05 +04:00
|
|
|
NS_PRECONDITION(aReflowState.frame == this, "bad reflow state");
|
|
|
|
NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent,
|
|
|
|
"bad parent reflow state");
|
1998-06-24 03:23:21 +04:00
|
|
|
if (PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p nsTableFrame::ResizeReflow Pass2: maxSize=%d,%d\n",
|
1998-06-08 19:47:03 +04:00
|
|
|
this, aReflowState.maxSize.width, aReflowState.maxSize.height);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
// set out param
|
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-07-07 01:39:23 +04:00
|
|
|
const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
|
|
|
|
mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
|
|
|
nsMargin myBorderPadding;
|
|
|
|
mySpacing->CalcBorderPaddingFor(this, myBorderPadding);
|
|
|
|
|
|
|
|
InnerTableReflowState state(aPresContext, aReflowState, myBorderPadding);
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// now that we've computed the column width information, reflow all children
|
|
|
|
nsIContent* c = mContent;
|
|
|
|
NS_ASSERTION(nsnull != c, "null kid");
|
|
|
|
nsSize kidMaxSize(0,0);
|
|
|
|
|
|
|
|
PRInt32 kidIndex = 0;
|
1998-08-30 00:20:38 +04:00
|
|
|
PRInt32 lastIndex;
|
|
|
|
c->ChildCount(lastIndex);
|
1998-04-14 00:24:54 +04:00
|
|
|
nsIFrame* prevKidFrame = nsnull;/* XXX incremental reflow! */
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
1998-04-23 21:29:07 +04:00
|
|
|
//PreReflowCheck();
|
1998-04-14 00:24:54 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
PRBool reflowMappedOK = PR_TRUE;
|
|
|
|
|
|
|
|
// Check for an overflow list
|
|
|
|
MoveOverflowToChildList();
|
|
|
|
|
|
|
|
// Reflow the existing frames
|
|
|
|
if (nsnull != mFirstChild) {
|
1998-06-03 04:43:53 +04:00
|
|
|
reflowMappedOK = ReflowMappedChildren(aPresContext, state, aDesiredSize.maxElementSize);
|
1998-04-14 00:24:54 +04:00
|
|
|
if (PR_FALSE == reflowMappedOK) {
|
1998-10-11 13:18:27 +04:00
|
|
|
aStatus = NS_FRAME_NOT_COMPLETE;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-15 01:45:28 +04:00
|
|
|
// Did we successfully reflow our mapped children?
|
1998-04-14 00:24:54 +04:00
|
|
|
if (PR_TRUE == reflowMappedOK) {
|
|
|
|
// Any space left?
|
1998-08-30 00:20:38 +04:00
|
|
|
PRInt32 numKids;
|
|
|
|
mContent->ChildCount(numKids);
|
1998-09-24 07:36:52 +04:00
|
|
|
if (state.availSize.height > 0) {
|
1998-04-14 00:24:54 +04:00
|
|
|
// Try and pull-up some children from a next-in-flow
|
1998-09-18 04:49:40 +04:00
|
|
|
if (!PullUpChildren(aPresContext, state, aDesiredSize.maxElementSize)) {
|
1998-04-14 00:24:54 +04:00
|
|
|
// We were unable to pull-up all the existing frames from the
|
|
|
|
// next in flow
|
1998-10-11 13:18:27 +04:00
|
|
|
aStatus = NS_FRAME_NOT_COMPLETE;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return our size and our status
|
1998-09-01 01:23:28 +04:00
|
|
|
aDesiredSize.width = ComputeDesiredWidth(aReflowState);
|
1998-07-07 01:39:23 +04:00
|
|
|
aDesiredSize.height = state.y + myBorderPadding.top + myBorderPadding.bottom;
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
1998-04-14 00:24:54 +04:00
|
|
|
// Don't forget to add in the bottom margin from our last child.
|
|
|
|
// Only add it in if there's room for it.
|
|
|
|
nscoord margin = state.prevMaxPosBottomMargin -
|
|
|
|
state.prevMaxNegBottomMargin;
|
|
|
|
if (state.availSize.height >= margin) {
|
|
|
|
state.y += margin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NS_DEBUG
|
1998-10-11 13:18:27 +04:00
|
|
|
//PostReflowCheck(aStatus);
|
1998-04-14 00:24:54 +04:00
|
|
|
#endif
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
|
|
|
{
|
|
|
|
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: IncrementalReflow\n");
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
// create an inner table reflow state
|
|
|
|
const nsStyleSpacing* mySpacing = (const nsStyleSpacing*)
|
|
|
|
mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
|
|
|
nsMargin myBorderPadding;
|
|
|
|
mySpacing->CalcBorderPaddingFor(this, myBorderPadding);
|
|
|
|
InnerTableReflowState state(aPresContext, aReflowState, myBorderPadding);
|
|
|
|
|
|
|
|
// determine if this frame is the target or not
|
|
|
|
nsIFrame *target=nsnull;
|
|
|
|
rv = aReflowState.reflowCommand->GetTarget(target);
|
|
|
|
if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
|
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
// this is the target if target is either this or the outer table frame containing this inner frame
|
|
|
|
nsIFrame *outerTableFrame=nsnull;
|
|
|
|
GetGeometricParent(outerTableFrame);
|
|
|
|
if ((this==target) || (outerTableFrame==target))
|
1998-10-11 13:18:27 +04:00
|
|
|
rv = IR_TargetIsMe(aPresContext, aDesiredSize, state, aStatus);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Get the next frame in the reflow chain
|
|
|
|
nsIFrame* nextFrame;
|
|
|
|
aReflowState.reflowCommand->GetNext(nextFrame);
|
|
|
|
|
|
|
|
// Recover our reflow state
|
|
|
|
//RecoverState(state, nextFrame);
|
|
|
|
rv = IR_TargetIsChild(aPresContext, aDesiredSize, state, aStatus, nextFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
|
|
|
{
|
1998-10-16 01:07:37 +04:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
1998-10-11 13:18:27 +04:00
|
|
|
nsIReflowCommand::ReflowType type;
|
|
|
|
aReflowState.reflowState.reflowCommand->GetType(type);
|
|
|
|
nsIFrame *objectFrame;
|
|
|
|
aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame);
|
1998-10-14 20:32:45 +04:00
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
1998-10-11 13:18:27 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case nsIReflowCommand::FrameInserted :
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
rv = IR_ColGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
(nsTableColGroupFrame*)objectFrame, PR_FALSE);
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
else if (IsRowGroup(childDisplay->mDisplay))
|
|
|
|
{
|
|
|
|
rv = IR_RowGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
(nsTableRowGroupFrame*)objectFrame, PR_FALSE);
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
|
|
|
objectFrame, PR_FALSE);
|
|
|
|
}
|
|
|
|
break;
|
1998-10-14 20:32:45 +04:00
|
|
|
|
|
|
|
case nsIReflowCommand::FrameAppended :
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
|
|
|
|
(nsTableColGroupFrame*)objectFrame);
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
else if (IsRowGroup(childDisplay->mDisplay))
|
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus,
|
|
|
|
(nsTableRowGroupFrame*)objectFrame);
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // no optimization to be done for Unknown frame types, so just reuse the Inserted method
|
|
|
|
rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus,
|
|
|
|
objectFrame, PR_FALSE);
|
|
|
|
}
|
|
|
|
break;
|
1998-10-11 13:18:27 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
case nsIReflowCommand::FrameReplaced :
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
case nsIReflowCommand::FrameRemoved :
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
rv = IR_ColGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
(nsTableColGroupFrame*)objectFrame);
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
else if (IsRowGroup(childDisplay->mDisplay))
|
|
|
|
{
|
|
|
|
rv = IR_RowGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
(nsTableRowGroupFrame*)objectFrame);
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
objectFrame);
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIReflowCommand::StyleChanged :
|
|
|
|
NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
|
|
|
|
rv = NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF IR: StyleChanged not implemented.\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIReflowCommand::ContentChanged :
|
|
|
|
NS_ASSERTION(PR_FALSE, "illegal reflow type: ContentChanged");
|
|
|
|
rv = NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIReflowCommand::PullupReflow:
|
|
|
|
case nsIReflowCommand::PushReflow:
|
|
|
|
case nsIReflowCommand::CheckPullupReflow :
|
|
|
|
case nsIReflowCommand::UserDefined :
|
|
|
|
NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
|
|
|
|
rv = NS_ERROR_NOT_IMPLEMENTED;
|
1998-10-16 01:07:37 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF IR: reflow command not implemented.\n");
|
1998-10-11 13:18:27 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD nsTableFrame::IR_ColGroupInserted(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
nsTableColGroupFrame * aInsertedFrame,
|
1998-10-11 13:18:27 +04:00
|
|
|
PRBool aReplace)
|
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
nsresult rv=NS_OK;
|
|
|
|
PRBool adjustStartingColIndex=PR_FALSE;
|
|
|
|
PRInt32 startingColIndex=0;
|
|
|
|
// find out what frame to insert aInsertedFrame after
|
|
|
|
nsIFrame *frameToInsertAfter=nsnull;
|
|
|
|
rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(frameToInsertAfter);
|
|
|
|
// insert aInsertedFrame as the first child. Set its start col index to 0
|
|
|
|
if (nsnull==frameToInsertAfter)
|
|
|
|
{
|
|
|
|
aInsertedFrame->SetNextSibling(mFirstChild);
|
|
|
|
mFirstChild=aInsertedFrame;
|
|
|
|
startingColIndex += aInsertedFrame->SetStartColumnIndex(0);
|
|
|
|
adjustStartingColIndex=PR_TRUE;
|
|
|
|
}
|
|
|
|
nsIFrame *childFrame=mFirstChild;
|
|
|
|
nsIFrame *prevSib=nsnull;
|
|
|
|
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
|
|
|
{
|
|
|
|
if ((nsnull!=frameToInsertAfter) && (childFrame==frameToInsertAfter))
|
|
|
|
{
|
|
|
|
nsIFrame *nextSib=nsnull;
|
|
|
|
frameToInsertAfter->GetNextSibling(nextSib);
|
|
|
|
aInsertedFrame->SetNextSibling(nextSib);
|
|
|
|
frameToInsertAfter->SetNextSibling(aInsertedFrame);
|
|
|
|
// account for childFrame being a COLGROUP now
|
|
|
|
const nsStyleDisplay *display;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
|
|
|
|
{
|
|
|
|
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
|
|
|
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
|
|
|
}
|
|
|
|
// skip ahead to aInsertedFrame, since we just handled the frame we inserted after
|
|
|
|
childFrame=aInsertedFrame;
|
|
|
|
adjustStartingColIndex=PR_TRUE; // now that we've inserted aInsertedFrame,
|
|
|
|
// start adjusting subsequent col groups' starting col index including aInsertedFrame
|
|
|
|
}
|
|
|
|
const nsStyleDisplay *display;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
|
|
|
|
{
|
|
|
|
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
|
|
|
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
|
|
|
else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups
|
|
|
|
startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex);
|
|
|
|
}
|
|
|
|
prevSib=childFrame;
|
|
|
|
rv = childFrame->GetNextSibling(childFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
InvalidateColumnCache();
|
|
|
|
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
|
|
|
// if not, skip invalidating the first passs
|
|
|
|
// if so, and we can fix the first pass info
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
1998-10-15 02:51:50 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
nsTableColGroupFrame * aAppendedFrame)
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
|
|
|
nsresult rv=NS_OK;
|
1998-10-15 02:51:50 +04:00
|
|
|
PRInt32 startingColIndex=0;
|
1998-10-14 20:32:45 +04:00
|
|
|
nsIFrame *childFrame=mFirstChild;
|
|
|
|
nsIFrame *lastChild=mFirstChild;
|
|
|
|
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *display;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
|
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
lastChild=childFrame;
|
|
|
|
rv = childFrame->GetNextSibling(childFrame);
|
|
|
|
}
|
|
|
|
// append aAppendedFrame
|
|
|
|
if (nsnull!=lastChild)
|
|
|
|
lastChild->SetNextSibling(aAppendedFrame);
|
|
|
|
else
|
|
|
|
mFirstChild = aAppendedFrame;
|
|
|
|
|
1998-10-15 02:51:50 +04:00
|
|
|
aAppendedFrame->SetStartColumnIndex(startingColIndex);
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
we would only want to do this if manufactured col groups were invisible to the DOM. Since they
|
|
|
|
currently are visible, they should behave just as if they were content-backed "real" colgroups
|
|
|
|
If this decision is changed, the code below is a half-finished attempt to rationalize the situation.
|
|
|
|
It requires having built a list of the colGroups before we get to this point.
|
|
|
|
|
|
|
|
// look at the last col group. If it is implicit, and it's cols are implicit, then
|
|
|
|
// it and its cols were manufactured for table layout.
|
|
|
|
// Delete it if possible, otherwise move it to the end of the list
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
if (0<colGroupCount)
|
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
nsTableColGroupFrame *colGroup = (nsTableColGroupFrame *)(colGroupList.ElementAt(colGroupCount-1));
|
|
|
|
if (PR_TRUE==colGroup->IsManufactured())
|
|
|
|
{ // account for the new COLs that were added in aAppendedFrame
|
|
|
|
// first, try to delete the implicit colgroup
|
|
|
|
|
|
|
|
// if we couldn't delete it, move the implicit colgroup to the end of the list
|
|
|
|
// and adjust it's col indexes
|
|
|
|
nsIFrame *colGroupNextSib;
|
|
|
|
colGroup->GetNextSibling(colGroupNextSib);
|
|
|
|
childFrame=mFirstChild;
|
|
|
|
nsIFrame * prevSib=nsnull;
|
|
|
|
rv = NS_OK;
|
|
|
|
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
|
|
|
{
|
|
|
|
if (childFrame==colGroup)
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
if (nsnull!=prevSib) // colGroup is in the middle of the list, remove it
|
|
|
|
prevSib->SetNextSibling(colGroupNextSib);
|
|
|
|
else // colGroup was the first child, so set it's next sib to first child
|
|
|
|
mFirstChild = colGroupNextSib;
|
|
|
|
aAppendedFrame->SetNextSibling(colGroup); // place colGroup at the end of the list
|
|
|
|
colGroup->SetNextSibling(nsnull);
|
|
|
|
break;
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
1998-10-15 02:51:50 +04:00
|
|
|
prevSib=childFrame;
|
|
|
|
rv = childFrame->GetNextSibling(childFrame);
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-15 02:51:50 +04:00
|
|
|
#endif
|
1998-10-14 20:32:45 +04:00
|
|
|
|
1998-10-15 02:51:50 +04:00
|
|
|
|
|
|
|
InvalidateColumnCache();
|
1998-10-14 20:32:45 +04:00
|
|
|
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
|
|
|
// if not, skip invalidating the first passs
|
|
|
|
// if so, and we can fix the first pass info
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
NS_METHOD nsTableFrame::IR_ColGroupRemoved(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
nsTableColGroupFrame * aDeletedFrame)
|
1998-10-11 13:18:27 +04:00
|
|
|
{
|
1998-10-15 02:51:50 +04:00
|
|
|
nsresult rv=NS_OK;
|
|
|
|
PRBool adjustStartingColIndex=PR_FALSE;
|
|
|
|
PRInt32 startingColIndex=0;
|
|
|
|
nsIFrame *childFrame=mFirstChild;
|
|
|
|
nsIFrame *prevSib=nsnull;
|
|
|
|
while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
|
|
|
|
{
|
|
|
|
if (childFrame==aDeletedFrame)
|
|
|
|
{
|
|
|
|
nsIFrame *deleteFrameNextSib=nsnull;
|
|
|
|
aDeletedFrame->GetNextSibling(deleteFrameNextSib);
|
|
|
|
if (nsnull!=prevSib)
|
|
|
|
prevSib->SetNextSibling(deleteFrameNextSib);
|
|
|
|
else
|
|
|
|
mFirstChild = deleteFrameNextSib;
|
|
|
|
childFrame=deleteFrameNextSib;
|
|
|
|
if (nsnull==childFrame)
|
|
|
|
break;
|
|
|
|
adjustStartingColIndex=PR_TRUE; // now that we've removed aDeletedFrame, start adjusting subsequent col groups' starting col index
|
|
|
|
}
|
|
|
|
const nsStyleDisplay *display;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
|
|
|
|
{
|
|
|
|
if (PR_FALSE==adjustStartingColIndex) // we haven't gotten to aDeletedFrame yet
|
|
|
|
startingColIndex += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
|
|
|
else // we've removed aDeletedFrame, now adjust the starting col index of all subsequent col groups
|
|
|
|
startingColIndex += ((nsTableColGroupFrame *)childFrame)->SetStartColumnIndex(startingColIndex);
|
|
|
|
}
|
|
|
|
prevSib=childFrame;
|
|
|
|
rv = childFrame->GetNextSibling(childFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
InvalidateColumnCache();
|
|
|
|
//XXX: what we want to do here is determine if the new COL information changes anything about layout
|
|
|
|
// if not, skip invalidating the first passs
|
|
|
|
// if so, and we can fix the first pass info
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
nsTableRowGroupFrame * aInsertedFrame,
|
1998-10-11 13:18:27 +04:00
|
|
|
PRBool aReplace)
|
|
|
|
{
|
1998-10-15 11:46:16 +04:00
|
|
|
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
|
|
|
|
aStatus, (nsIFrame*)aInsertedFrame, aReplace);
|
1998-10-20 03:43:06 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// do a pass-1 layout of all the cells in all the rows of the rowgroup
|
|
|
|
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
|
|
|
|
aInsertedFrame, eReflowReason_Initial, PR_FALSE);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
InvalidateCellMap();
|
|
|
|
InvalidateColumnCache();
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// since we know we're doing an append here, we can optimize
|
|
|
|
NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
nsTableRowGroupFrame * aAppendedFrame)
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
|
|
|
// hook aAppendedFrame into the child list
|
1998-10-15 11:46:16 +04:00
|
|
|
nsresult rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState,
|
|
|
|
aStatus, (nsIFrame*)aAppendedFrame, PR_FALSE);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1998-10-14 20:32:45 +04:00
|
|
|
|
|
|
|
// account for the cells in the rows that are children of aAppendedFrame
|
1998-10-16 01:07:37 +04:00
|
|
|
// this will add the content of the rowgroup to the cell map
|
1998-10-15 11:46:16 +04:00
|
|
|
rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame);
|
1998-10-20 03:43:06 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1998-10-14 20:32:45 +04:00
|
|
|
|
|
|
|
// do a pass-1 layout of all the cells in all the rows of the rowgroup
|
1998-10-15 11:46:16 +04:00
|
|
|
rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.reflowState, aStatus,
|
1998-10-20 03:43:06 +04:00
|
|
|
aAppendedFrame, eReflowReason_Initial, PR_TRUE);
|
1998-10-15 11:46:16 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1998-10-14 20:32:45 +04:00
|
|
|
|
1998-10-15 11:46:16 +04:00
|
|
|
// if any column widths have to change due to this, rebalance column widths
|
1998-10-16 01:07:37 +04:00
|
|
|
//XXX need to calculate this, but for now just do it
|
|
|
|
InvalidateColumnWidths();
|
1998-10-14 20:32:45 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD nsTableFrame::IR_RowGroupRemoved(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
1998-10-15 02:51:50 +04:00
|
|
|
nsTableRowGroupFrame * aDeletedFrame)
|
1998-10-11 13:18:27 +04:00
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
nsresult rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus,
|
|
|
|
aDeletedFrame);
|
|
|
|
InvalidateCellMap();
|
|
|
|
InvalidateColumnCache();
|
1998-10-16 01:07:37 +04:00
|
|
|
|
|
|
|
// if any column widths have to change due to this, rebalance column widths
|
|
|
|
//XXX need to calculate this, but for now just do it
|
|
|
|
InvalidateColumnWidths();
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
//XXX: handle aReplace
|
|
|
|
NS_METHOD nsTableFrame::IR_UnknownFrameInserted(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
nsIFrame * aInsertedFrame,
|
|
|
|
PRBool aReplace)
|
|
|
|
{
|
|
|
|
nsIReflowCommand::ReflowType type;
|
|
|
|
aReflowState.reflowState.reflowCommand->GetType(type);
|
|
|
|
// we have a generic frame that gets inserted but doesn't effect reflow
|
|
|
|
// hook it up then ignore it
|
|
|
|
if (nsIReflowCommand::FrameAppended==type)
|
|
|
|
{ // frameAppended reflow -- find the last child and make aInsertedFrame its next sibling
|
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF IR: FrameAppended adding unknown frame type.\n");
|
|
|
|
nsIFrame *lastChild=mFirstChild;
|
|
|
|
nsIFrame *nextChild=mFirstChild;
|
|
|
|
while (nsnull!=nextChild)
|
|
|
|
{
|
|
|
|
lastChild=nextChild;
|
|
|
|
nextChild->GetNextSibling(nextChild);
|
|
|
|
}
|
|
|
|
if (nsnull==lastChild)
|
|
|
|
mFirstChild = aInsertedFrame;
|
|
|
|
else
|
|
|
|
lastChild->SetNextSibling(aInsertedFrame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // frameInserted reflow -- hook up aInsertedFrame as prevSibling's next sibling,
|
|
|
|
// and be sure to hook in aInsertedFrame's nextSibling (from prevSibling)
|
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF IR: FrameInserted adding unknown frame type.\n");
|
|
|
|
nsIFrame *prevSibling=nsnull;
|
|
|
|
nsresult rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(prevSibling);
|
|
|
|
if (NS_SUCCEEDED(rv) && (nsnull!=prevSibling))
|
|
|
|
{
|
|
|
|
nsIFrame *nextSibling=nsnull;
|
|
|
|
prevSibling->GetNextSibling(nextSibling);
|
|
|
|
prevSibling->SetNextSibling(aInsertedFrame);
|
|
|
|
aInsertedFrame->SetNextSibling(nextSibling);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
nsIFrame *nextSibling = mFirstChild;
|
1998-10-11 13:18:27 +04:00
|
|
|
mFirstChild = aInsertedFrame;
|
|
|
|
aInsertedFrame->SetNextSibling(nextSibling);
|
|
|
|
}
|
|
|
|
}
|
1998-10-16 01:07:37 +04:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
return NS_OK;
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD nsTableFrame::IR_UnknownFrameRemoved(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
nsIFrame * aRemovedFrame)
|
|
|
|
{
|
|
|
|
// we have a generic frame that gets removed but doesn't effect reflow
|
|
|
|
// unhook it then ignore it
|
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF IR: FrameRemoved removing unknown frame type.\n");
|
|
|
|
nsIFrame *prevChild=nsnull;
|
|
|
|
nsIFrame *nextChild=mFirstChild;
|
|
|
|
while (nextChild!=aRemovedFrame)
|
|
|
|
{
|
|
|
|
prevChild=nextChild;
|
|
|
|
nextChild->GetNextSibling(nextChild);
|
|
|
|
}
|
|
|
|
nextChild=nsnull;
|
|
|
|
aRemovedFrame->GetNextSibling(nextChild);
|
|
|
|
if (nsnull==prevChild) // objectFrame was first child
|
|
|
|
mFirstChild = nextChild;
|
|
|
|
else
|
|
|
|
prevChild->SetNextSibling(nextChild);
|
1998-10-16 01:07:37 +04:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
return NS_OK;;
|
1998-10-11 13:18:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
InnerTableReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
nsIFrame * aNextFrame)
|
|
|
|
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: IR_TargetIsChild\n");
|
|
|
|
|
|
|
|
// Remember the old rect
|
|
|
|
nsRect oldKidRect;
|
|
|
|
aNextFrame->GetRect(oldKidRect);
|
|
|
|
|
|
|
|
// Pass along the reflow command
|
|
|
|
nsHTMLReflowMetrics desiredSize(nsnull);
|
|
|
|
// XXX Correctly compute the available space...
|
1998-10-12 18:48:02 +04:00
|
|
|
nsHTMLReflowState kidReflowState(aPresContext, aNextFrame,
|
|
|
|
aReflowState.reflowState,
|
|
|
|
aReflowState.reflowState.maxSize);
|
1998-10-11 13:18:27 +04:00
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
|
1998-10-11 13:18:27 +04:00
|
|
|
|
|
|
|
// Resize the row group frame
|
|
|
|
nsRect kidRect;
|
|
|
|
aNextFrame->GetRect(kidRect);
|
|
|
|
aNextFrame->SizeTo(desiredSize.width, desiredSize.height);
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
// XXX For the time being just fall through and treat it like a
|
|
|
|
// pass 2 reflow...
|
|
|
|
// calling intialize here resets all the cached info based on new table content
|
1998-10-16 01:07:37 +04:00
|
|
|
InvalidateColumnWidths();
|
1998-10-11 13:18:27 +04:00
|
|
|
#else
|
|
|
|
// XXX Hack...
|
|
|
|
AdjustSiblingsAfterReflow(&aPresContext, aReflowState, aNextFrame, desiredSize.height -
|
|
|
|
oldKidRect.height);
|
|
|
|
aDesiredSize.width = mRect.width;
|
|
|
|
aDesiredSize.height = state.y + myBorderPadding.top + myBorderPadding.bottom;
|
|
|
|
return NS_OK;
|
|
|
|
#endif
|
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-10-02 08:10:00 +04:00
|
|
|
nscoord nsTableFrame::ComputeDesiredWidth(const nsHTMLReflowState& aReflowState) const
|
1998-09-01 01:23:28 +04:00
|
|
|
{
|
|
|
|
nscoord desiredWidth=aReflowState.maxSize.width;
|
|
|
|
// this is the biggest hack in the world. But there's no other rational way to handle nested percent tables
|
|
|
|
nsStylePosition* position;
|
|
|
|
PRBool isNested=IsNested(aReflowState, position);
|
|
|
|
if((eReflowReason_Initial==aReflowState.reason) &&
|
|
|
|
(PR_TRUE==isNested) && (eStyleUnit_Percent==position->mWidth.GetUnit()))
|
|
|
|
{
|
|
|
|
desiredWidth = mTableLayoutStrategy->GetTableMaxWidth();
|
|
|
|
}
|
|
|
|
return desiredWidth;
|
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// Collapse child's top margin with previous bottom margin
|
1998-10-11 13:18:27 +04:00
|
|
|
nscoord nsTableFrame::GetTopMarginFor(nsIPresContext& aCX,
|
1998-04-14 00:24:54 +04:00
|
|
|
InnerTableReflowState& aState,
|
1998-05-13 02:28:01 +04:00
|
|
|
const nsMargin& aKidMargin)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
nscoord margin;
|
|
|
|
nscoord maxNegTopMargin = 0;
|
|
|
|
nscoord maxPosTopMargin = 0;
|
1998-05-13 02:28:01 +04:00
|
|
|
if ((margin = aKidMargin.top) < 0) {
|
1998-04-14 00:24:54 +04:00
|
|
|
maxNegTopMargin = -margin;
|
|
|
|
} else {
|
|
|
|
maxPosTopMargin = margin;
|
|
|
|
}
|
|
|
|
|
|
|
|
nscoord maxPos = PR_MAX(aState.prevMaxPosBottomMargin, maxPosTopMargin);
|
|
|
|
nscoord maxNeg = PR_MAX(aState.prevMaxNegBottomMargin, maxNegTopMargin);
|
|
|
|
margin = maxPos - maxNeg;
|
|
|
|
|
|
|
|
return margin;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Position and size aKidFrame and update our reflow state. The origin of
|
|
|
|
// aKidRect is relative to the upper-left origin of our frame, and includes
|
|
|
|
// any left/top margin.
|
1998-10-11 13:18:27 +04:00
|
|
|
void nsTableFrame::PlaceChild(nsIPresContext& aPresContext,
|
1998-04-14 00:24:54 +04:00
|
|
|
InnerTableReflowState& aState,
|
|
|
|
nsIFrame* aKidFrame,
|
|
|
|
const nsRect& aKidRect,
|
|
|
|
nsSize* aMaxElementSize,
|
|
|
|
nsSize& aKidMaxElementSize)
|
|
|
|
{
|
1998-04-21 02:49:15 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf ("table: placing row group at %d, %d, %d, %d\n",
|
|
|
|
aKidRect.x, aKidRect.y, aKidRect.width, aKidRect.height);
|
1998-04-14 00:24:54 +04:00
|
|
|
// Place and size the child
|
|
|
|
aKidFrame->SetRect(aKidRect);
|
|
|
|
|
|
|
|
// Adjust the running y-offset
|
|
|
|
aState.y += aKidRect.height;
|
|
|
|
|
|
|
|
// If our height is constrained then update the available height
|
|
|
|
if (PR_FALSE == aState.unconstrainedHeight) {
|
|
|
|
aState.availSize.height -= aKidRect.height;
|
|
|
|
}
|
|
|
|
|
1998-04-23 21:29:07 +04:00
|
|
|
// If this is a footer row group, add it to the list of footer row groups
|
1998-06-17 20:38:24 +04:00
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
aKidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay)
|
1998-04-23 21:29:07 +04:00
|
|
|
{
|
|
|
|
if (nsnull==aState.footerList)
|
|
|
|
aState.footerList = new nsVoidArray();
|
|
|
|
aState.footerList->AppendElement((void *)aKidFrame);
|
|
|
|
aState.footerHeight += aKidRect.height;
|
|
|
|
}
|
|
|
|
// else if this is a body row group, push down all the footer row groups
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// don't bother unless there are footers to push down
|
|
|
|
if (nsnull!=aState.footerList && 0!=aState.footerList->Count())
|
|
|
|
{
|
|
|
|
nsPoint origin;
|
|
|
|
aKidFrame->GetOrigin(origin);
|
|
|
|
origin.y -= aState.footerHeight;
|
|
|
|
aKidFrame->MoveTo(origin.x, origin.y);
|
1998-06-17 20:38:24 +04:00
|
|
|
// XXX do we need to check for headers here also, or is that implicit?
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay)
|
1998-04-23 21:29:07 +04:00
|
|
|
{
|
|
|
|
PRInt32 numFooters = aState.footerList->Count();
|
|
|
|
for (PRInt32 footerIndex = 0; footerIndex < numFooters; footerIndex++)
|
|
|
|
{
|
|
|
|
nsTableRowGroupFrame * footer = (nsTableRowGroupFrame *)(aState.footerList->ElementAt(footerIndex));
|
|
|
|
NS_ASSERTION(nsnull!=footer, "bad footer list in table inner frame.");
|
|
|
|
if (nsnull!=footer)
|
|
|
|
{
|
|
|
|
footer->GetOrigin(origin);
|
|
|
|
origin.y += aKidRect.height;
|
|
|
|
footer->MoveTo(origin.x, origin.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-09 23:59:45 +04:00
|
|
|
//XXX: this should call into layout strategy to get the width field
|
1998-08-07 06:11:51 +04:00
|
|
|
if (nsnull != aMaxElementSize)
|
|
|
|
{
|
|
|
|
nsMargin borderPadding;
|
|
|
|
const nsStyleSpacing* tableSpacing;
|
1998-09-24 20:37:22 +04:00
|
|
|
GetStyleData(eStyleStruct_Spacing , ((nsStyleStruct *&)tableSpacing));
|
1998-08-07 06:11:51 +04:00
|
|
|
tableSpacing->CalcBorderPaddingFor(this, borderPadding);
|
|
|
|
nscoord cellSpacing = GetCellSpacing();
|
|
|
|
nscoord kidWidth = aKidMaxElementSize.width + borderPadding.left + borderPadding.right + cellSpacing*2;
|
|
|
|
aMaxElementSize->width = PR_MAX(aMaxElementSize->width, kidWidth);
|
|
|
|
aMaxElementSize->height += aKidMaxElementSize.height;
|
|
|
|
if (gsDebug)
|
|
|
|
printf("%p placeChild set MES->width to %d\n",
|
|
|
|
this, aMaxElementSize->width);
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reflow the frames we've already created
|
|
|
|
*
|
|
|
|
* @param aPresContext presentation context to use
|
|
|
|
* @param aState current inline state
|
|
|
|
* @return true if we successfully reflowed all the mapped children and false
|
|
|
|
* otherwise, e.g. we pushed children to the next in flow
|
|
|
|
*/
|
1998-10-16 01:07:37 +04:00
|
|
|
// XXX: this interface should change to pass in aStatus, return nsresult
|
1998-10-11 13:18:27 +04:00
|
|
|
PRBool nsTableFrame::ReflowMappedChildren( nsIPresContext& aPresContext,
|
1998-04-14 00:24:54 +04:00
|
|
|
InnerTableReflowState& aState,
|
1998-06-24 03:23:21 +04:00
|
|
|
nsSize* aMaxElementSize)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != mFirstChild, "no children");
|
|
|
|
|
|
|
|
PRInt32 childCount = 0;
|
|
|
|
nsIFrame* prevKidFrame = nsnull;
|
1998-06-03 04:43:53 +04:00
|
|
|
nsSize kidMaxElementSize(0,0);
|
1998-04-14 00:24:54 +04:00
|
|
|
nsSize* pKidMaxElementSize = (nsnull != aMaxElementSize) ? &kidMaxElementSize : nsnull;
|
|
|
|
PRBool result = PR_TRUE;
|
|
|
|
|
1998-09-24 01:48:26 +04:00
|
|
|
nsReflowReason reason;
|
|
|
|
nsStyleTable* tableStyle;
|
|
|
|
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
|
|
|
|
if (NS_STYLE_TABLE_LAYOUT_FIXED==tableStyle->mLayoutStrategy)
|
|
|
|
{
|
|
|
|
reason = aState.reflowState.reason;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
reason = eReflowReason_Resize;
|
|
|
|
|
1998-09-24 20:37:22 +04:00
|
|
|
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; )
|
|
|
|
{
|
1998-10-01 08:46:11 +04:00
|
|
|
nsSize kidAvailSize(aState.availSize);
|
|
|
|
nsHTMLReflowMetrics desiredSize(pKidMaxElementSize);
|
1998-06-03 04:43:53 +04:00
|
|
|
desiredSize.width=desiredSize.height=desiredSize.ascent=desiredSize.descent=0;
|
1998-10-01 08:46:11 +04:00
|
|
|
nsReflowStatus status;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
1998-10-11 13:18:27 +04:00
|
|
|
if ((PR_TRUE==IsRowGroup(childDisplay->mDisplay)) ||
|
1998-09-24 20:37:22 +04:00
|
|
|
(NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay))
|
1998-05-29 01:39:22 +04:00
|
|
|
{ // for all colgroups and rowgroups...
|
1998-06-17 20:38:24 +04:00
|
|
|
const nsStyleSpacing* kidSpacing;
|
|
|
|
kidFrame->GetStyleData(eStyleStruct_Spacing, ((nsStyleStruct *&)kidSpacing));
|
1998-05-13 02:28:01 +04:00
|
|
|
nsMargin kidMargin;
|
|
|
|
kidSpacing->CalcMarginFor(kidFrame, kidMargin);
|
|
|
|
|
|
|
|
nscoord topMargin = GetTopMarginFor(aPresContext, aState, kidMargin);
|
|
|
|
nscoord bottomMargin = kidMargin.bottom;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
// Figure out the amount of available size for the child (subtract
|
|
|
|
// off the top margin we are going to apply to it)
|
|
|
|
if (PR_FALSE == aState.unconstrainedHeight) {
|
|
|
|
kidAvailSize.height -= topMargin;
|
|
|
|
}
|
|
|
|
// Subtract off for left and right margin
|
|
|
|
if (PR_FALSE == aState.unconstrainedWidth) {
|
1998-05-13 02:28:01 +04:00
|
|
|
kidAvailSize.width -= kidMargin.left + kidMargin.right;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1998-09-24 01:48:26 +04:00
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// Reflow the child into the available space
|
1998-10-12 18:48:02 +04:00
|
|
|
nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
|
|
|
|
aState.reflowState, kidAvailSize,
|
1998-10-02 08:10:00 +04:00
|
|
|
reason);
|
1998-10-01 08:46:11 +04:00
|
|
|
|
1998-10-06 04:27:22 +04:00
|
|
|
nscoord x = aState.leftInset + kidMargin.left;
|
|
|
|
nscoord y = aState.topInset + aState.y + topMargin;
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("\nTIF IR: Reflow Pass 2 of frame %p with reason=%d\n", kidFrame, reason);
|
1998-10-11 13:18:27 +04:00
|
|
|
ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
|
1998-10-06 04:27:22 +04:00
|
|
|
// Did the child fit?
|
|
|
|
if ((kidFrame != mFirstChild) && (desiredSize.height > kidAvailSize.height))
|
|
|
|
{
|
|
|
|
// The child is too wide to fit in the available space, and it's
|
|
|
|
// not our first child
|
|
|
|
PushChildren(kidFrame, prevKidFrame);
|
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-10-06 04:27:22 +04:00
|
|
|
// Place the child after taking into account it's margin
|
|
|
|
aState.y += topMargin;
|
|
|
|
nsRect kidRect (x, y, desiredSize.width, desiredSize.height);
|
1998-10-11 13:18:27 +04:00
|
|
|
if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
|
1998-10-06 04:27:22 +04:00
|
|
|
{
|
|
|
|
// we don't want to adjust the maxElementSize if this is an initial reflow
|
|
|
|
// it was set by the TableLayoutStrategy and shouldn't be changed.
|
|
|
|
nsSize *requestedMaxElementSize = nsnull;
|
|
|
|
if (eReflowReason_Initial != aState.reflowState.reason)
|
|
|
|
requestedMaxElementSize = aMaxElementSize;
|
|
|
|
PlaceChild(aPresContext, aState, kidFrame, kidRect,
|
|
|
|
requestedMaxElementSize, kidMaxElementSize);
|
|
|
|
if (bottomMargin < 0) {
|
|
|
|
aState.prevMaxNegBottomMargin = -bottomMargin;
|
|
|
|
} else {
|
|
|
|
aState.prevMaxPosBottomMargin = bottomMargin;
|
1998-05-29 01:39:22 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
childCount++;
|
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// Remember where we just were in case we end up pushing children
|
|
|
|
prevKidFrame = kidFrame;
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// Special handling for incomplete children
|
1998-05-12 08:17:56 +04:00
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(status)) {
|
1998-04-17 05:41:24 +04:00
|
|
|
nsIFrame* kidNextInFlow;
|
|
|
|
|
|
|
|
kidFrame->GetNextInFlow(kidNextInFlow);
|
1998-04-14 00:24:54 +04:00
|
|
|
if (nsnull == kidNextInFlow) {
|
1998-04-17 02:21:32 +04:00
|
|
|
// The child doesn't have a next-in-flow so create a continuing
|
|
|
|
// frame. This hooks the child into the flow
|
1998-04-17 05:41:24 +04:00
|
|
|
nsIFrame* continuingFrame;
|
|
|
|
|
1998-05-07 04:08:20 +04:00
|
|
|
nsIStyleContext* kidSC;
|
1998-10-11 13:18:27 +04:00
|
|
|
kidFrame->GetStyleContext(&aPresContext, kidSC);
|
|
|
|
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame);
|
1998-05-07 04:08:20 +04:00
|
|
|
NS_RELEASE(kidSC);
|
1998-04-17 02:21:32 +04:00
|
|
|
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// Add the continuing frame to the sibling list
|
1998-04-17 05:41:24 +04:00
|
|
|
nsIFrame* nextSib;
|
|
|
|
|
|
|
|
kidFrame->GetNextSibling(nextSib);
|
1998-04-14 00:24:54 +04:00
|
|
|
continuingFrame->SetNextSibling(nextSib);
|
|
|
|
kidFrame->SetNextSibling(continuingFrame);
|
|
|
|
}
|
1998-04-17 02:21:32 +04:00
|
|
|
// We've used up all of our available space so push the remaining
|
|
|
|
// children to the next-in-flow
|
1998-04-17 05:41:24 +04:00
|
|
|
nsIFrame* nextSibling;
|
|
|
|
|
|
|
|
kidFrame->GetNextSibling(nextSibling);
|
1998-04-17 02:21:32 +04:00
|
|
|
if (nsnull != nextSibling) {
|
1998-09-24 08:18:58 +04:00
|
|
|
PushChildren(nextSibling, kidFrame);
|
1998-04-17 02:21:32 +04:00
|
|
|
}
|
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the next child
|
1998-04-17 05:41:24 +04:00
|
|
|
kidFrame->GetNextSibling(kidFrame);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
// XXX talk with troy about checking for available space here
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the child count
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Try and pull-up frames from our next-in-flow
|
|
|
|
*
|
|
|
|
* @param aPresContext presentation context to use
|
|
|
|
* @param aState current inline state
|
|
|
|
* @return true if we successfully pulled-up all the children and false
|
|
|
|
* otherwise, e.g. child didn't fit
|
|
|
|
*/
|
1998-10-11 13:18:27 +04:00
|
|
|
PRBool nsTableFrame::PullUpChildren(nsIPresContext& aPresContext,
|
1998-04-17 02:21:32 +04:00
|
|
|
InnerTableReflowState& aState,
|
|
|
|
nsSize* aMaxElementSize)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-09-21 07:40:32 +04:00
|
|
|
nsTableFrame* nextInFlow = (nsTableFrame*)mNextInFlow;
|
1998-06-03 04:43:53 +04:00
|
|
|
nsSize kidMaxElementSize(0,0);
|
1998-04-17 02:21:32 +04:00
|
|
|
nsSize* pKidMaxElementSize = (nsnull != aMaxElementSize) ? &kidMaxElementSize : nsnull;
|
1998-09-19 07:24:26 +04:00
|
|
|
nsIFrame* prevKidFrame = LastFrame(mFirstChild);
|
1998-09-21 07:40:32 +04:00
|
|
|
PRBool result = PR_TRUE;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
while (nsnull != nextInFlow) {
|
1998-10-01 08:46:11 +04:00
|
|
|
nsHTMLReflowMetrics kidSize(pKidMaxElementSize);
|
1998-06-03 04:43:53 +04:00
|
|
|
kidSize.width=kidSize.height=kidSize.ascent=kidSize.descent=0;
|
1998-05-12 08:17:56 +04:00
|
|
|
nsReflowStatus status;
|
1998-04-17 02:21:32 +04:00
|
|
|
|
|
|
|
// Get the next child
|
|
|
|
nsIFrame* kidFrame = nextInFlow->mFirstChild;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// Any more child frames?
|
1998-04-14 00:24:54 +04:00
|
|
|
if (nsnull == kidFrame) {
|
1998-04-17 02:21:32 +04:00
|
|
|
// No. Any frames on its overflow list?
|
|
|
|
if (nsnull != nextInFlow->mOverflowList) {
|
|
|
|
// Move the overflow list to become the child list
|
|
|
|
nextInFlow->AppendChildren(nextInFlow->mOverflowList);
|
|
|
|
nextInFlow->mOverflowList = nsnull;
|
|
|
|
kidFrame = nextInFlow->mFirstChild;
|
|
|
|
} else {
|
|
|
|
// We've pulled up all the children, so move to the next-in-flow.
|
1998-04-17 05:41:24 +04:00
|
|
|
nextInFlow->GetNextInFlow((nsIFrame*&)nextInFlow);
|
1998-04-17 02:21:32 +04:00
|
|
|
continue;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// See if the child fits in the available space. If it fits or
|
|
|
|
// it's splittable then reflow it. The reason we can't just move
|
|
|
|
// it is that we still need ascent/descent information
|
1998-06-03 04:43:53 +04:00
|
|
|
nsSize kidFrameSize(0,0);
|
1998-05-22 08:54:11 +04:00
|
|
|
nsSplittableType kidIsSplittable;
|
1998-04-17 05:41:24 +04:00
|
|
|
|
|
|
|
kidFrame->GetSize(kidFrameSize);
|
|
|
|
kidFrame->IsSplittable(kidIsSplittable);
|
1998-04-18 03:08:20 +04:00
|
|
|
if ((kidFrameSize.height > aState.availSize.height) &&
|
1998-05-22 08:54:11 +04:00
|
|
|
NS_FRAME_IS_NOT_SPLITTABLE(kidIsSplittable)) {
|
1998-04-17 02:21:32 +04:00
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1998-10-12 18:48:02 +04:00
|
|
|
nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
|
|
|
|
aState.reflowState, aState.availSize,
|
1998-10-02 08:10:00 +04:00
|
|
|
eReflowReason_Resize);
|
1998-04-17 02:21:32 +04:00
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, status);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-10-06 04:27:22 +04:00
|
|
|
// Did the child fit?
|
|
|
|
if ((kidSize.height > aState.availSize.height) && (nsnull != mFirstChild)) {
|
|
|
|
// The child is too wide to fit in the available space, and it's
|
|
|
|
// not our first child
|
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
1998-10-01 08:46:11 +04:00
|
|
|
|
1998-10-06 04:27:22 +04:00
|
|
|
// Advance y by the topMargin between children. Zero out the
|
|
|
|
// topMargin in case this frame is continued because
|
|
|
|
// continuations do not have a top margin. Update the prev
|
|
|
|
// bottom margin state in the body reflow state so that we can
|
|
|
|
// apply the bottom margin when we hit the next child (or
|
|
|
|
// finish).
|
|
|
|
//aState.y += topMargin;
|
|
|
|
nsRect kidRect (0, 0, kidSize.width, kidSize.height);
|
|
|
|
//kidRect.x += kidMol->margin.left;
|
|
|
|
kidRect.y += aState.y;
|
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
1998-10-11 13:18:27 +04:00
|
|
|
if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
|
1998-10-06 04:27:22 +04:00
|
|
|
{
|
|
|
|
PlaceChild(aPresContext, aState, kidFrame, kidRect, aMaxElementSize, *pKidMaxElementSize);
|
1998-05-29 01:39:22 +04:00
|
|
|
}
|
1998-04-17 02:21:32 +04:00
|
|
|
|
|
|
|
// Remove the frame from its current parent
|
1998-04-17 05:41:24 +04:00
|
|
|
kidFrame->GetNextSibling(nextInFlow->mFirstChild);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// Link the frame into our list of children
|
|
|
|
kidFrame->SetGeometricParent(this);
|
1998-04-17 05:41:24 +04:00
|
|
|
nsIFrame* contentParent;
|
|
|
|
|
|
|
|
kidFrame->GetContentParent(contentParent);
|
|
|
|
if (nextInFlow == contentParent) {
|
1998-04-17 02:21:32 +04:00
|
|
|
kidFrame->SetContentParent(this);
|
|
|
|
}
|
|
|
|
if (nsnull == prevKidFrame) {
|
|
|
|
mFirstChild = kidFrame;
|
|
|
|
} else {
|
|
|
|
prevKidFrame->SetNextSibling(kidFrame);
|
|
|
|
}
|
|
|
|
kidFrame->SetNextSibling(nsnull);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// Remember where we just were in case we end up pushing children
|
|
|
|
prevKidFrame = kidFrame;
|
1998-05-12 08:17:56 +04:00
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(status)) {
|
1998-04-17 02:21:32 +04:00
|
|
|
// No the child isn't complete
|
1998-04-17 05:41:24 +04:00
|
|
|
nsIFrame* kidNextInFlow;
|
|
|
|
|
|
|
|
kidFrame->GetNextInFlow(kidNextInFlow);
|
1998-04-17 02:21:32 +04:00
|
|
|
if (nsnull == kidNextInFlow) {
|
|
|
|
// The child doesn't have a next-in-flow so create a
|
|
|
|
// continuing frame. The creation appends it to the flow and
|
|
|
|
// prepares it for reflow.
|
1998-04-17 05:41:24 +04:00
|
|
|
nsIFrame* continuingFrame;
|
|
|
|
|
1998-05-07 04:08:20 +04:00
|
|
|
nsIStyleContext* kidSC;
|
1998-10-11 13:18:27 +04:00
|
|
|
kidFrame->GetStyleContext(&aPresContext, kidSC);
|
|
|
|
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame);
|
1998-05-07 04:08:20 +04:00
|
|
|
NS_RELEASE(kidSC);
|
1998-04-17 02:21:32 +04:00
|
|
|
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
|
|
|
|
|
|
|
|
// Add the continuing frame to our sibling list and then push
|
|
|
|
// it to the next-in-flow. This ensures the next-in-flow's
|
|
|
|
// content offsets and child count are set properly. Note that
|
|
|
|
// we can safely assume that the continuation is complete so
|
1998-09-21 07:40:32 +04:00
|
|
|
// we pass PR_TRUE into PushChidren
|
1998-04-17 02:21:32 +04:00
|
|
|
kidFrame->SetNextSibling(continuingFrame);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-09-24 08:18:58 +04:00
|
|
|
PushChildren(continuingFrame, kidFrame);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-04-17 02:21:32 +04:00
|
|
|
// If the child isn't complete then it means that we've used up
|
|
|
|
// all of our available space.
|
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Now I've got all the cells laid out in an infinite space.
|
|
|
|
For each column, use the min size for each cell in that column
|
|
|
|
along with the attributes of the table, column group, and column
|
|
|
|
to assign widths to each column.
|
|
|
|
*/
|
|
|
|
// use the cell map to determine which cell is in which column.
|
1998-10-11 13:18:27 +04:00
|
|
|
void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
1998-04-14 00:24:54 +04:00
|
|
|
const nsSize& aMaxSize,
|
|
|
|
nsSize* aMaxElementSize)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
|
1998-09-01 01:23:28 +04:00
|
|
|
NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!");
|
1998-10-10 01:53:07 +04:00
|
|
|
NS_ASSERTION(nsnull!=mColumnWidths, "never ever call me until the col widths array is built!");
|
1998-07-07 04:20:21 +04:00
|
|
|
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 numCols = mCellMap->GetColCount();
|
1998-10-10 01:53:07 +04:00
|
|
|
if (numCols>mColumnWidthsLength)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-10-10 01:53:07 +04:00
|
|
|
PRInt32 priorColumnWidthsLength=mColumnWidthsLength;
|
|
|
|
while (numCols>mColumnWidthsLength)
|
|
|
|
mColumnWidthsLength += kColumnWidthIncrement;
|
|
|
|
PRInt32 * newColumnWidthsArray = new PRInt32[mColumnWidthsLength];
|
|
|
|
nsCRT::memset (newColumnWidthsArray, 0, mColumnWidthsLength*sizeof(PRInt32));
|
|
|
|
nsCRT::memcpy (newColumnWidthsArray, mColumnWidths, priorColumnWidthsLength*sizeof(PRInt32));
|
|
|
|
delete [] mColumnWidths;
|
|
|
|
mColumnWidths = newColumnWidthsArray;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-05 10:09:09 +04:00
|
|
|
const nsStyleSpacing* spacing =
|
|
|
|
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
1998-05-13 02:28:01 +04:00
|
|
|
nsMargin borderPadding;
|
|
|
|
spacing->CalcBorderPaddingFor(this, borderPadding);
|
1998-04-25 22:48:48 +04:00
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// need to figure out the overall table width constraint
|
1998-04-25 22:48:48 +04:00
|
|
|
// default case, get 100% of available space
|
1998-07-11 04:00:31 +04:00
|
|
|
|
1998-09-30 03:15:01 +04:00
|
|
|
PRInt32 maxWidth = aMaxSize.width;
|
1998-06-05 10:09:09 +04:00
|
|
|
const nsStylePosition* position =
|
|
|
|
(const nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
|
1998-09-30 03:15:01 +04:00
|
|
|
if (eStyleUnit_Coord==position->mWidth.GetUnit())
|
1998-04-30 23:55:51 +04:00
|
|
|
maxWidth = position->mWidth.GetCoordValue();
|
1998-08-07 06:11:51 +04:00
|
|
|
|
1998-07-18 01:02:28 +04:00
|
|
|
if (0>maxWidth) // nonsense style specification
|
|
|
|
maxWidth = 0;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-24 03:23:21 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
|
|
|
printf ("%p: maxWidth=%d from aMaxSize=%d,%d\n",
|
|
|
|
this, maxWidth, aMaxSize.width, aMaxSize.height);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-04-30 21:57:09 +04:00
|
|
|
// based on the compatibility mode, create a table layout strategy
|
|
|
|
if (nsnull==mTableLayoutStrategy)
|
1998-09-23 03:36:06 +04:00
|
|
|
{
|
|
|
|
nsStyleTable* tableStyle;
|
|
|
|
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
|
|
|
|
if (NS_STYLE_TABLE_LAYOUT_FIXED==tableStyle->mLayoutStrategy)
|
1998-10-20 03:43:06 +04:00
|
|
|
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
|
1998-09-23 03:36:06 +04:00
|
|
|
else
|
1998-10-20 03:43:06 +04:00
|
|
|
mTableLayoutStrategy = new BasicTableLayoutStrategy(this);
|
|
|
|
mTableLayoutStrategy->Initialize(aMaxElementSize, mCellMap->GetColCount());
|
1998-10-16 01:07:37 +04:00
|
|
|
mColumnWidthsValid=PR_TRUE;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1998-07-17 03:23:31 +04:00
|
|
|
mTableLayoutStrategy->BalanceColumnWidths(mStyleContext, aReflowState, maxWidth);
|
1998-10-11 13:18:27 +04:00
|
|
|
mColumnWidthsSet=PR_TRUE;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
sum the width of each column
|
|
|
|
add in table insets
|
|
|
|
set rect
|
|
|
|
*/
|
1998-10-11 13:18:27 +04:00
|
|
|
void nsTableFrame::SetTableWidth(nsIPresContext& aPresContext)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
|
1998-09-01 01:23:28 +04:00
|
|
|
NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-07-22 09:38:41 +04:00
|
|
|
nscoord cellSpacing = GetCellSpacing();
|
|
|
|
if (gsDebug==PR_TRUE)
|
|
|
|
printf ("SetTableWidth with cellSpacing = %d ", cellSpacing);
|
|
|
|
PRInt32 tableWidth = cellSpacing;
|
1998-07-07 04:20:21 +04:00
|
|
|
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 numCols = mCellMap->GetColCount();
|
1998-07-11 04:00:31 +04:00
|
|
|
for (PRInt32 colIndex = 0; colIndex<numCols; colIndex++)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-07-11 04:00:31 +04:00
|
|
|
nscoord totalColWidth = mColumnWidths[colIndex];
|
1998-07-22 09:38:41 +04:00
|
|
|
totalColWidth += cellSpacing;
|
1998-06-24 03:23:21 +04:00
|
|
|
if (gsDebug==PR_TRUE)
|
1998-07-11 04:00:31 +04:00
|
|
|
printf (" += %d ", totalColWidth);
|
|
|
|
tableWidth += totalColWidth;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the insets (sum of border and padding)
|
1998-06-05 10:09:09 +04:00
|
|
|
const nsStyleSpacing* spacing =
|
|
|
|
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
|
1998-05-13 02:28:01 +04:00
|
|
|
nsMargin borderPadding;
|
|
|
|
spacing->CalcBorderPaddingFor(this, borderPadding);
|
|
|
|
|
|
|
|
nscoord rightInset = borderPadding.right;
|
|
|
|
nscoord leftInset = borderPadding.left;
|
1998-04-14 00:24:54 +04:00
|
|
|
tableWidth += (leftInset + rightInset);
|
1998-04-17 05:41:24 +04:00
|
|
|
nsRect tableSize = mRect;
|
1998-04-14 00:24:54 +04:00
|
|
|
tableSize.width = tableWidth;
|
1998-06-24 03:23:21 +04:00
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-06-24 03:23:21 +04:00
|
|
|
printf ("%p: setting table rect to %d, %d after adding insets %d, %d\n",
|
|
|
|
this, tableSize.width, tableSize.height, rightInset, leftInset);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
SetRect(tableSize);
|
|
|
|
}
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
void nsTableFrame::VerticallyAlignChildren(nsIPresContext& aPresContext,
|
1998-06-05 06:36:25 +04:00
|
|
|
nscoord* aAscents,
|
|
|
|
nscoord aMaxAscent,
|
|
|
|
nscoord aMaxHeight)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1998-07-26 08:23:01 +04:00
|
|
|
void nsTableFrame::AdjustColumnsForCOLSAttribute()
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
NS_ASSERTION(nsnull!=cellMap, "bad cell map");
|
1998-07-26 08:23:01 +04:00
|
|
|
|
|
|
|
// any specified-width column turns off COLS attribute
|
|
|
|
nsStyleTable* tableStyle = (nsStyleTable *)mStyleContext->GetMutableStyleData(eStyleStruct_Table);
|
|
|
|
if (tableStyle->mCols != NS_STYLE_TABLE_COLS_NONE)
|
|
|
|
{
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 numCols = cellMap->GetColCount();
|
|
|
|
PRInt32 numRows = cellMap->GetRowCount();
|
1998-07-26 08:23:01 +04:00
|
|
|
for (PRInt32 rowIndex=0; rowIndex<numRows; rowIndex++)
|
|
|
|
{
|
|
|
|
for (PRInt32 colIndex=0; colIndex<numCols; colIndex++)
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
nsTableCellFrame *cellFrame = cellMap->GetCellFrameAt(rowIndex, colIndex);
|
1998-07-26 08:23:01 +04:00
|
|
|
// get the cell style info
|
|
|
|
const nsStylePosition* cellPosition;
|
|
|
|
if (nsnull!=cellFrame)
|
|
|
|
{
|
|
|
|
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
|
|
|
|
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
|
|
|
|
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit()))
|
|
|
|
{
|
|
|
|
tableStyle->mCols = NS_STYLE_TABLE_COLS_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
NS_METHOD
|
1998-10-11 13:18:27 +04:00
|
|
|
nsTableFrame::SetColumnStyleFromCell(nsIPresContext & aPresContext,
|
1998-06-17 20:38:24 +04:00
|
|
|
nsTableCellFrame* aCellFrame,
|
|
|
|
nsTableRowFrame * aRowFrame)
|
|
|
|
{
|
1998-07-26 08:23:01 +04:00
|
|
|
// if this cell is the first non-col-spanning cell to have a width attribute,
|
|
|
|
// then the width attribute also acts as the width attribute for the entire column
|
|
|
|
// if the cell has a colspan, the width is used provisionally, divided equally among
|
|
|
|
// the spanned columns
|
1998-10-11 13:18:27 +04:00
|
|
|
if ((nsnull!=aCellFrame) && (nsnull!=aRowFrame))
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-07-22 07:53:43 +04:00
|
|
|
// get the cell style info
|
|
|
|
const nsStylePosition* cellPosition;
|
|
|
|
aCellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)cellPosition);
|
|
|
|
if ((eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) ||
|
|
|
|
(eStyleUnit_Percent==cellPosition->mWidth.GetUnit())) {
|
|
|
|
// compute the width per column spanned
|
1998-07-24 20:51:16 +04:00
|
|
|
PRInt32 colSpan = GetEffectiveColSpan(aCellFrame->GetColIndex(), aCellFrame);
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf("for col %d with colspan %d\n",aCellFrame->GetColIndex(), colSpan);
|
1998-07-22 07:53:43 +04:00
|
|
|
for (PRInt32 i=0; i<colSpan; i++)
|
|
|
|
{
|
|
|
|
// get the appropriate column frame
|
|
|
|
nsTableColFrame *colFrame;
|
|
|
|
GetColumnFrame(i+aCellFrame->GetColIndex(), colFrame);
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf(" for col %d\n",i+aCellFrame->GetColIndex());
|
1998-08-17 23:03:36 +04:00
|
|
|
if (nsTableColFrame::eWIDTH_SOURCE_CELL != colFrame->GetWidthSource())
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf(" width not yet set from a cell...\n");
|
1998-08-19 19:43:51 +04:00
|
|
|
if ((1==colSpan) ||
|
|
|
|
(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN != colFrame->GetWidthSource()))
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf(" colspan was 1 or width was not set from a span\n");
|
1998-08-19 19:43:51 +04:00
|
|
|
// get the column style and set the width attribute
|
|
|
|
nsIStyleContext *colSC;
|
1998-10-11 13:18:27 +04:00
|
|
|
colFrame->GetStyleContext(&aPresContext, colSC);
|
1998-08-19 19:43:51 +04:00
|
|
|
nsStylePosition* colPosition = (nsStylePosition*) colSC->GetMutableStyleData(eStyleStruct_Position);
|
|
|
|
NS_RELEASE(colSC);
|
|
|
|
// set the column width attribute
|
|
|
|
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
|
|
|
|
{
|
|
|
|
nscoord width = cellPosition->mWidth.GetCoordValue();
|
|
|
|
colPosition->mWidth.SetCoordValue(width/colSpan);
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf(" col fixed width set to %d ", (width/colSpan));
|
1998-08-19 19:43:51 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float width = cellPosition->mWidth.GetPercentValue();
|
|
|
|
colPosition->mWidth.SetPercentValue(width/colSpan);
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf(" col percent width set to %d ", (width/colSpan));
|
1998-08-19 19:43:51 +04:00
|
|
|
}
|
|
|
|
// set the column width-set-type
|
|
|
|
if (1==colSpan)
|
1998-10-03 00:36:35 +04:00
|
|
|
{
|
1998-08-19 19:43:51 +04:00
|
|
|
colFrame->SetWidthSource(nsTableColFrame::eWIDTH_SOURCE_CELL);
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf(" source=cell\n");
|
|
|
|
}
|
1998-08-19 19:43:51 +04:00
|
|
|
else
|
1998-10-03 00:36:35 +04:00
|
|
|
{
|
1998-08-19 19:43:51 +04:00
|
|
|
colFrame->SetWidthSource(nsTableColFrame::eWIDTH_SOURCE_CELL_WITH_SPAN);
|
1998-10-03 00:36:35 +04:00
|
|
|
if (PR_TRUE==gsDebug)
|
|
|
|
printf(" source=cell_with_span\n");
|
|
|
|
}
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-06-05 06:36:25 +04:00
|
|
|
/* there's an easy way and a hard way. The easy way is to look in our
|
|
|
|
* cache and pull the frame from there.
|
|
|
|
* If the cache isn't built yet, then we have to go hunting.
|
|
|
|
*/
|
|
|
|
NS_METHOD nsTableFrame::GetColumnFrame(PRInt32 aColIndex, nsTableColFrame *&aColFrame)
|
|
|
|
{
|
|
|
|
aColFrame = nsnull; // initialize out parameter
|
1998-08-18 03:37:04 +04:00
|
|
|
nsCellMap *cellMap = GetCellMap();
|
|
|
|
if (nsnull!=cellMap)
|
1998-06-05 06:36:25 +04:00
|
|
|
{ // hooray, we get to do this the easy way because the info is cached
|
1998-08-18 03:37:04 +04:00
|
|
|
aColFrame = cellMap->GetColumnFrame(aColIndex);
|
1998-06-05 06:36:25 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // ah shucks, we have to go hunt for the column frame brute-force style
|
|
|
|
nsIFrame *childFrame;
|
|
|
|
FirstChild(childFrame);
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (nsnull==childFrame)
|
|
|
|
{
|
|
|
|
NS_ASSERTION (PR_FALSE, "scanned the frame hierarchy and no column frame could be found.");
|
|
|
|
break;
|
|
|
|
}
|
1998-06-17 20:38:24 +04:00
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
1998-06-05 06:36:25 +04:00
|
|
|
{
|
1998-06-17 20:38:24 +04:00
|
|
|
PRInt32 colGroupStartingIndex = ((nsTableColGroupFrame *)childFrame)->GetStartColumnIndex();
|
1998-06-05 06:36:25 +04:00
|
|
|
if (aColIndex >= colGroupStartingIndex)
|
|
|
|
{ // the cell's col might be in this col group
|
1998-09-24 20:37:22 +04:00
|
|
|
PRInt32 colCount = ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
|
|
|
|
if (aColIndex < colGroupStartingIndex + colCount)
|
|
|
|
{ // yep, we've found it. GetColumnAt gives us the column at the offset colCount, not the absolute colIndex for the whole table
|
|
|
|
aColFrame = ((nsTableColGroupFrame *)childFrame)->GetColumnAt(colCount);
|
1998-06-05 06:36:25 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
childFrame->GetNextSibling(childFrame);
|
|
|
|
}
|
|
|
|
}
|
1998-09-24 20:37:22 +04:00
|
|
|
NS_POSTCONDITION(nsnull!=aColFrame, "no column frame could be found.");
|
1998-06-05 06:36:25 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
PRBool nsTableFrame::IsColumnWidthsSet()
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
return firstInFlow->mColumnWidthsSet;
|
|
|
|
}
|
|
|
|
|
1998-06-30 04:37:03 +04:00
|
|
|
/* We have to go through our child list twice.
|
|
|
|
* The first time, we scan until we find the first row.
|
|
|
|
* We set column style from the cells in the first row.
|
|
|
|
* Then we terminate that loop and start a second pass.
|
|
|
|
* In the second pass, we build column and cell cache info.
|
|
|
|
*/
|
1998-10-16 01:07:37 +04:00
|
|
|
void nsTableFrame::BuildColumnCache( nsIPresContext& aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
1998-10-16 01:07:37 +04:00
|
|
|
nsReflowStatus& aStatus)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
|
1998-09-01 01:23:28 +04:00
|
|
|
NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!");
|
1998-09-23 03:36:06 +04:00
|
|
|
nsStyleTable* tableStyle;
|
|
|
|
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
|
1998-09-24 01:48:26 +04:00
|
|
|
EnsureColumns(aPresContext);
|
1998-10-14 20:32:45 +04:00
|
|
|
if (nsnull!=mColCache)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF BCC: clearing column cache and cell map column frame cache.\n");
|
1998-10-14 20:32:45 +04:00
|
|
|
mCellMap->ClearColumnCache();
|
|
|
|
delete mColCache;
|
|
|
|
}
|
1998-07-11 04:00:31 +04:00
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
mColCache = new ColumnInfoCache(mColCount);
|
|
|
|
nsIFrame * childFrame = mFirstChild;
|
|
|
|
while (nsnull!=childFrame)
|
|
|
|
{ // in this loop, we cache column info and set column style info from cells in first row
|
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
|
|
|
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{ // if it's a col group then get the columns and cache them in the CellMap
|
|
|
|
nsTableColFrame *colFrame=nsnull;
|
|
|
|
childFrame->FirstChild((nsIFrame *&)colFrame);
|
|
|
|
while (nsnull!=colFrame)
|
|
|
|
{
|
|
|
|
mCellMap->AppendColumnFrame(colFrame);
|
|
|
|
colFrame->GetNextSibling((nsIFrame *&)colFrame);
|
1998-07-11 04:00:31 +04:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
|
|
|
|
{ // if it's a row group, get the cells and set the column style if appropriate
|
|
|
|
if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy)
|
|
|
|
{
|
|
|
|
nsIFrame *rowFrame;
|
|
|
|
childFrame->FirstChild(rowFrame);
|
|
|
|
while (nsnull!=rowFrame)
|
1998-06-30 04:37:03 +04:00
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
const nsStyleDisplay *rowDisplay;
|
|
|
|
rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay)
|
1998-07-11 04:00:31 +04:00
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
nsIFrame *cellFrame;
|
|
|
|
rowFrame->FirstChild(cellFrame);
|
|
|
|
while (nsnull!=cellFrame)
|
1998-09-23 03:36:06 +04:00
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
/* this is the first time we are guaranteed to have both the cell frames
|
|
|
|
* and the column frames, so it's a good time to
|
|
|
|
* set the column style from the cell's width attribute (if this is the first row)
|
|
|
|
*/
|
|
|
|
const nsStyleDisplay *cellDisplay;
|
|
|
|
cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)cellDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay)
|
|
|
|
SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)cellFrame, (nsTableRowFrame *)rowFrame);
|
|
|
|
cellFrame->GetNextSibling(cellFrame);
|
1998-09-23 03:36:06 +04:00
|
|
|
}
|
1998-07-11 04:00:31 +04:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
rowFrame->GetNextSibling(rowFrame);
|
1998-06-30 04:37:03 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
childFrame->GetNextSibling(childFrame);
|
|
|
|
}
|
1998-07-11 04:00:31 +04:00
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
// second time through, set column cache info for each column
|
|
|
|
// we can't do this until the loop above has set the column style info from the cells in the first row
|
|
|
|
childFrame = mFirstChild;
|
|
|
|
while (nsnull!=childFrame)
|
|
|
|
{ // for every child, if it's a col group then get the columns
|
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
nsTableColFrame *colFrame=nsnull;
|
|
|
|
childFrame->FirstChild((nsIFrame *&)colFrame);
|
|
|
|
while (nsnull!=colFrame)
|
|
|
|
{ // for every column, create an entry in the column cache
|
|
|
|
// assumes that the col style has been twiddled to account for first cell width attribute
|
|
|
|
const nsStyleDisplay *colDisplay;
|
|
|
|
colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
const nsStylePosition* colPosition;
|
|
|
|
colFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)colPosition));
|
|
|
|
mColCache->AddColumnInfo(colPosition->mWidth.GetUnit(), colFrame->GetColumnIndex());
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
colFrame->GetNextSibling((nsIFrame *&)colFrame);
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
childFrame->GetNextSibling(childFrame);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF BCC: mColumnCacheValid=PR_TRUE.\n");
|
1998-10-15 02:51:50 +04:00
|
|
|
mColumnCacheValid=PR_TRUE;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-10-16 01:07:37 +04:00
|
|
|
void nsTableFrame::InvalidateColumnWidths()
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
firstInFlow->mColumnWidthsValid=PR_FALSE;
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF: ColWidths invalidated.\n");
|
1998-10-16 01:07:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsTableFrame::IsColumnWidthsValid() const
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
return firstInFlow->mColumnWidthsValid;
|
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
PRBool nsTableFrame::IsFirstPassValid() const
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
return firstInFlow->mFirstPassValid;
|
|
|
|
}
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
void nsTableFrame::InvalidateFirstPassCache()
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
firstInFlow->mFirstPassValid=PR_FALSE;
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF: FirstPass invalidated.\n");
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
|
1998-10-15 02:51:50 +04:00
|
|
|
PRBool nsTableFrame::IsColumnCacheValid() const
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
return firstInFlow->mColumnCacheValid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsTableFrame::InvalidateColumnCache()
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
firstInFlow->mColumnCacheValid=PR_FALSE;
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF: ColCache invalidated.\n");
|
1998-10-15 02:51:50 +04:00
|
|
|
}
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
PRBool nsTableFrame::IsCellMapValid() const
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
return firstInFlow->mCellMapValid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsTableFrame::InvalidateCellMap()
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
firstInFlow->mCellMapValid=PR_FALSE;
|
|
|
|
// reset the state in each row
|
|
|
|
nsIFrame *rowGroupFrame=mFirstChild;
|
|
|
|
for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *rowGroupDisplay;
|
|
|
|
rowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
|
|
|
|
if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
|
|
|
|
{
|
|
|
|
nsIFrame *rowFrame;
|
|
|
|
rowGroupFrame->FirstChild(rowFrame);
|
|
|
|
for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(rowFrame))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *rowDisplay;
|
|
|
|
rowFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
((nsTableRowFrame *)rowFrame)->ResetInitChildren();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-10-20 03:43:06 +04:00
|
|
|
if (PR_TRUE==gsDebugIR) printf("TIF: CellMap invalidated.\n");
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
|
1998-05-07 04:08:20 +04:00
|
|
|
NS_METHOD
|
1998-07-15 07:23:23 +04:00
|
|
|
nsTableFrame::CreateContinuingFrame(nsIPresContext& aPresContext,
|
1998-05-07 04:08:20 +04:00
|
|
|
nsIFrame* aParent,
|
|
|
|
nsIStyleContext* aStyleContext,
|
|
|
|
nsIFrame*& aContinuingFrame)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-05-06 03:56:50 +04:00
|
|
|
nsTableFrame* cf = new nsTableFrame(mContent, aParent);
|
1998-05-07 04:08:20 +04:00
|
|
|
if (nsnull == cf) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
|
1998-04-14 00:24:54 +04:00
|
|
|
if (PR_TRUE==gsDebug) printf("nsTableFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf);
|
|
|
|
// set my width, because all frames in a table flow are the same width
|
|
|
|
// code in nsTableOuterFrame depends on this being set
|
1998-04-17 05:41:24 +04:00
|
|
|
cf->SetRect(nsRect(0, 0, mRect.width, 0));
|
1998-04-14 00:24:54 +04:00
|
|
|
// add headers and footers to cf
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
1998-04-23 21:29:07 +04:00
|
|
|
nsIFrame * rg = nsnull;
|
1998-07-11 04:00:31 +04:00
|
|
|
firstInFlow->FirstChild(rg);
|
1998-04-23 21:29:07 +04:00
|
|
|
NS_ASSERTION (nsnull!=rg, "previous frame has no children");
|
|
|
|
PRInt32 index = 0;
|
|
|
|
nsIFrame * bodyRowGroupFromOverflow = mOverflowList;
|
|
|
|
nsIFrame * lastSib = nsnull;
|
|
|
|
for ( ; nsnull!=rg; index++)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-04-23 21:29:07 +04:00
|
|
|
nsIContent *content = nsnull;
|
|
|
|
rg->GetContent(content); // content: REFCNT++
|
|
|
|
NS_ASSERTION(nsnull!=content, "bad frame, returned null content.");
|
1998-09-15 21:58:24 +04:00
|
|
|
const nsStyleDisplay* display;
|
1998-09-24 20:37:22 +04:00
|
|
|
//XXX: TROY: this was just this->GetStyleData which can't be right
|
|
|
|
rg->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
|
1998-09-15 21:58:24 +04:00
|
|
|
if ((display->mDisplay == NS_STYLE_DISPLAY_TABLE_HEADER_GROUP) ||
|
|
|
|
(display->mDisplay == NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP))
|
1998-04-23 21:29:07 +04:00
|
|
|
{
|
|
|
|
printf("found a head or foot in continuing frame\n");
|
|
|
|
// Resolve style for the child
|
|
|
|
nsIStyleContext* kidStyleContext =
|
1998-07-15 07:23:23 +04:00
|
|
|
aPresContext.ResolveStyleContextFor(content, cf); // kidStyleContext: REFCNT++
|
1998-09-18 21:18:37 +04:00
|
|
|
|
1998-05-07 04:08:20 +04:00
|
|
|
nsIFrame* duplicateFrame;
|
1998-09-18 21:18:37 +04:00
|
|
|
NS_NewTableRowGroupFrame(content, cf, duplicateFrame);
|
|
|
|
duplicateFrame->SetStyleContext(&aPresContext, kidStyleContext);
|
1998-04-23 21:29:07 +04:00
|
|
|
NS_RELEASE(kidStyleContext); // kidStyleContenxt: REFCNT--
|
|
|
|
|
|
|
|
if (nsnull==lastSib)
|
|
|
|
{
|
|
|
|
mOverflowList = duplicateFrame;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lastSib->SetNextSibling(duplicateFrame);
|
|
|
|
}
|
|
|
|
duplicateFrame->SetNextSibling(bodyRowGroupFromOverflow);
|
|
|
|
lastSib = duplicateFrame;
|
|
|
|
}
|
|
|
|
NS_RELEASE(content); // content: REFCNT--
|
|
|
|
// get the next row group
|
|
|
|
rg->GetNextSibling(rg);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1998-04-17 05:41:24 +04:00
|
|
|
aContinuingFrame = cf;
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32 nsTableFrame::GetColumnWidth(PRInt32 aColIndex)
|
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
|
|
|
PRInt32 result = 0;
|
|
|
|
if (this!=firstInFlow)
|
|
|
|
result = firstInFlow->GetColumnWidth(aColIndex);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NS_ASSERTION(nsnull!=mColumnWidths, "illegal state");
|
1998-09-01 01:23:28 +04:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
NS_ASSERTION(nsnull!=mCellMap, "no cell map");
|
1998-10-20 09:05:17 +04:00
|
|
|
PRInt32 numCols = mCellMap->GetColCount();
|
1998-04-17 02:21:32 +04:00
|
|
|
NS_ASSERTION (numCols > aColIndex, "bad arg, col index out of bounds");
|
|
|
|
#endif
|
1998-04-14 00:24:54 +04:00
|
|
|
if (nsnull!=mColumnWidths)
|
|
|
|
result = mColumnWidths[aColIndex];
|
|
|
|
}
|
1998-04-17 02:21:32 +04:00
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-06-05 22:11:20 +04:00
|
|
|
void nsTableFrame::SetColumnWidth(PRInt32 aColIndex, nscoord aWidth)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
|
|
|
NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
|
1998-09-01 01:23:28 +04:00
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
if (this!=firstInFlow)
|
|
|
|
firstInFlow->SetColumnWidth(aColIndex, aWidth);
|
|
|
|
else
|
|
|
|
{
|
1998-10-11 13:18:27 +04:00
|
|
|
NS_ASSERTION(nsnull!=mColumnWidths, "illegal state, nsnull mColumnWidths");
|
|
|
|
NS_ASSERTION(aColIndex<mColumnWidthsLength, "illegal state, aColIndex<mColumnWidthsLength");
|
|
|
|
if (nsnull!=mColumnWidths && aColIndex<mColumnWidthsLength)
|
1998-04-14 00:24:54 +04:00
|
|
|
mColumnWidths[aColIndex] = aWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-05-27 00:57:24 +04:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Update the border style to map to the HTML border style
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void nsTableFrame::MapHTMLBorderStyle(nsStyleSpacing& aSpacingStyle, nscoord aBorderWidth)
|
|
|
|
{
|
|
|
|
nsStyleCoord width;
|
|
|
|
width.SetCoordValue(aBorderWidth);
|
|
|
|
aSpacingStyle.mBorder.SetTop(width);
|
|
|
|
aSpacingStyle.mBorder.SetLeft(width);
|
|
|
|
aSpacingStyle.mBorder.SetBottom(width);
|
|
|
|
aSpacingStyle.mBorder.SetRight(width);
|
|
|
|
|
|
|
|
aSpacingStyle.mBorderStyle[NS_SIDE_TOP] = NS_STYLE_BORDER_STYLE_OUTSET;
|
|
|
|
aSpacingStyle.mBorderStyle[NS_SIDE_LEFT] = NS_STYLE_BORDER_STYLE_OUTSET;
|
|
|
|
aSpacingStyle.mBorderStyle[NS_SIDE_BOTTOM] = NS_STYLE_BORDER_STYLE_OUTSET;
|
|
|
|
aSpacingStyle.mBorderStyle[NS_SIDE_RIGHT] = NS_STYLE_BORDER_STYLE_OUTSET;
|
|
|
|
|
|
|
|
nsIStyleContext* styleContext = mStyleContext;
|
1998-06-17 20:38:24 +04:00
|
|
|
const nsStyleColor* colorData = (const nsStyleColor*)
|
|
|
|
styleContext->GetStyleData(eStyleStruct_Color);
|
1998-05-27 00:57:24 +04:00
|
|
|
|
|
|
|
// Look until we find a style context with a NON-transparent background color
|
|
|
|
while (styleContext)
|
|
|
|
{
|
|
|
|
if ((colorData->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)!=0)
|
|
|
|
{
|
|
|
|
nsIStyleContext* temp = styleContext;
|
|
|
|
styleContext = styleContext->GetParent();
|
|
|
|
if (temp != mStyleContext)
|
|
|
|
NS_RELEASE(temp);
|
1998-06-05 10:09:09 +04:00
|
|
|
colorData = (const nsStyleColor*)styleContext->GetStyleData(eStyleStruct_Color);
|
1998-05-27 00:57:24 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Yaahoo, we found a style context which has a background color
|
|
|
|
|
|
|
|
nscolor borderColor = 0xFFC0C0C0;
|
|
|
|
|
|
|
|
if (styleContext != nsnull)
|
|
|
|
{
|
|
|
|
borderColor = colorData->mBackgroundColor;
|
|
|
|
if (styleContext != mStyleContext)
|
|
|
|
NS_RELEASE(styleContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the border color is white, then shift to grey
|
|
|
|
if (borderColor == 0xFFFFFFFF)
|
|
|
|
borderColor = 0xFFC0C0C0;
|
|
|
|
|
|
|
|
aSpacingStyle.mBorderColor[NS_SIDE_TOP] = borderColor;
|
|
|
|
aSpacingStyle.mBorderColor[NS_SIDE_LEFT] = borderColor;
|
|
|
|
aSpacingStyle.mBorderColor[NS_SIDE_BOTTOM] = borderColor;
|
|
|
|
aSpacingStyle.mBorderColor[NS_SIDE_RIGHT] = borderColor;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PRBool nsTableFrame::ConvertToPixelValue(nsHTMLValue& aValue, PRInt32 aDefault, PRInt32& aResult)
|
|
|
|
{
|
|
|
|
PRInt32 result = 0;
|
|
|
|
|
|
|
|
if (aValue.GetUnit() == eHTMLUnit_Pixel)
|
|
|
|
aResult = aValue.GetPixelValue();
|
|
|
|
else if (aValue.GetUnit() == eHTMLUnit_Empty)
|
|
|
|
aResult = aDefault;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NS_ERROR("Unit must be pixel or empty");
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
void nsTableFrame::MapBorderMarginPadding(nsIPresContext& aPresContext)
|
1998-05-27 00:57:24 +04:00
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
#if 0
|
1998-05-27 00:57:24 +04:00
|
|
|
// Check to see if the table has either cell padding or
|
|
|
|
// Cell spacing defined for the table. If true, then
|
|
|
|
// this setting overrides any specific border, margin or
|
|
|
|
// padding information in the cell. If these attributes
|
|
|
|
// are not defined, the the cells attributes are used
|
|
|
|
|
|
|
|
nsHTMLValue padding_value;
|
|
|
|
nsHTMLValue spacing_value;
|
|
|
|
nsHTMLValue border_value;
|
|
|
|
|
|
|
|
|
1998-08-30 00:20:38 +04:00
|
|
|
nsresult border_result;
|
1998-05-27 00:57:24 +04:00
|
|
|
|
|
|
|
nscoord padding = 0;
|
|
|
|
nscoord spacing = 0;
|
|
|
|
nscoord border = 1;
|
|
|
|
|
1998-10-11 13:18:27 +04:00
|
|
|
float p2t = aPresContext.GetPixelsToTwips();
|
1998-05-27 00:57:24 +04:00
|
|
|
|
1998-09-15 21:58:24 +04:00
|
|
|
nsIHTMLContent* table = (nsIHTMLContent*)mContent;
|
1998-05-27 00:57:24 +04:00
|
|
|
|
|
|
|
NS_ASSERTION(table,"Table Must not be null");
|
|
|
|
if (!table)
|
|
|
|
return;
|
|
|
|
|
1998-06-05 10:09:09 +04:00
|
|
|
nsStyleSpacing* spacingData = (nsStyleSpacing*)mStyleContext->GetMutableStyleData(eStyleStruct_Spacing);
|
1998-05-27 00:57:24 +04:00
|
|
|
|
|
|
|
border_result = table->GetAttribute(nsHTMLAtoms::border,border_value);
|
1998-08-30 00:20:38 +04:00
|
|
|
if (border_result == NS_CONTENT_ATTR_HAS_VALUE)
|
1998-05-27 00:57:24 +04:00
|
|
|
{
|
|
|
|
PRInt32 intValue = 0;
|
|
|
|
|
|
|
|
if (ConvertToPixelValue(border_value,1,intValue))
|
1998-08-01 03:34:45 +04:00
|
|
|
border = NSIntPixelsToTwips(intValue, p2t);
|
1998-05-27 00:57:24 +04:00
|
|
|
}
|
|
|
|
MapHTMLBorderStyle(*spacingData,border);
|
1998-09-15 21:58:24 +04:00
|
|
|
#endif
|
1998-05-27 00:57:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-05-02 00:44:55 +04:00
|
|
|
// Subclass hook for style post processing
|
1998-10-11 13:18:27 +04:00
|
|
|
NS_METHOD nsTableFrame::DidSetStyleContext(nsIPresContext& aPresContext)
|
1998-05-02 00:44:55 +04:00
|
|
|
{
|
|
|
|
#ifdef NOISY_STYLE
|
|
|
|
printf("nsTableFrame::DidSetStyleContext \n");
|
1998-07-21 12:12:22 +04:00
|
|
|
#endif
|
1998-05-02 00:44:55 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
NS_METHOD nsTableFrame::GetCellMarginData(nsTableCellFrame* aKidFrame, nsMargin& aMargin)
|
1998-05-22 03:43:18 +04:00
|
|
|
{
|
|
|
|
nsresult result = NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
if (nsnull != aKidFrame)
|
1998-05-22 03:43:18 +04:00
|
|
|
{
|
1998-07-11 04:00:31 +04:00
|
|
|
result = aKidFrame->GetMargin(aMargin);
|
1998-05-22 03:43:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-07-17 03:23:31 +04:00
|
|
|
nscoord nsTableFrame::GetCellSpacing()
|
|
|
|
{
|
|
|
|
nsTableFrame* tableFrame = this;
|
|
|
|
nsStyleTable* tableStyle;
|
1998-09-15 21:58:24 +04:00
|
|
|
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
|
1998-07-17 03:23:31 +04:00
|
|
|
nscoord cellSpacing = 0;
|
|
|
|
if (tableStyle->mCellSpacing.GetUnit() == eStyleUnit_Coord)
|
|
|
|
cellSpacing = tableStyle->mCellSpacing.GetCoordValue();
|
|
|
|
return cellSpacing;
|
|
|
|
}
|
|
|
|
|
1998-06-05 06:36:25 +04:00
|
|
|
void nsTableFrame::GetColumnsByType(const nsStyleUnit aType,
|
|
|
|
PRInt32& aOutNumColumns,
|
|
|
|
PRInt32 *& aOutColumnIndexes)
|
|
|
|
{
|
|
|
|
mColCache->GetColumnsByType(aType, aOutNumColumns, aOutColumnIndexes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-06-24 03:23:21 +04:00
|
|
|
NS_METHOD
|
|
|
|
nsTableFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(0 != aInstancePtr, "null ptr");
|
|
|
|
if (NULL == aInstancePtr) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
if (aIID.Equals(kTableFrameCID)) {
|
|
|
|
*aInstancePtr = (void*) (this);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return nsContainerFrame::QueryInterface(aIID, aInstancePtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-09-15 21:58:24 +04:00
|
|
|
/* ----- global methods ----- */
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-09-15 21:58:24 +04:00
|
|
|
nsresult
|
|
|
|
NS_NewTableFrame(nsIContent* aContent,
|
|
|
|
nsIFrame* aParentFrame,
|
|
|
|
nsIFrame*& aResult)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
nsIFrame* it = new nsTableFrame(aContent, aParentFrame);
|
1998-04-14 00:24:54 +04:00
|
|
|
if (nsnull == it) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
1998-09-15 21:58:24 +04:00
|
|
|
aResult = it;
|
1998-04-14 00:24:54 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_METHOD nsTableFrame::GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aTableFrame)
|
1998-09-24 20:37:22 +04:00
|
|
|
{
|
|
|
|
nsresult result = NS_OK;
|
1998-10-14 20:32:45 +04:00
|
|
|
aTableFrame = nsnull; // initialize out-param
|
1998-09-24 20:37:22 +04:00
|
|
|
if (nsnull!=aSourceFrame)
|
|
|
|
{
|
1998-10-14 20:32:45 +04:00
|
|
|
nsresult result = aSourceFrame->GetContentParent((nsIFrame *&)aTableFrame);
|
|
|
|
while ((NS_OK==result) && (nsnull!=aTableFrame))
|
1998-09-24 20:37:22 +04:00
|
|
|
{
|
|
|
|
const nsStyleDisplay *display;
|
1998-10-14 20:32:45 +04:00
|
|
|
aTableFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
|
1998-09-24 20:37:22 +04:00
|
|
|
if (NS_STYLE_DISPLAY_TABLE == display->mDisplay)
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
|
|
|
// at this point, aTableFrame could be an outer frame,
|
|
|
|
// to find out, scan it's children for another frame with a table display type
|
|
|
|
// if found, the childFrame must be the inner frame
|
|
|
|
nsresult rv;
|
|
|
|
nsIFrame *childFrame=nsnull;
|
|
|
|
rv = aTableFrame->FirstChild(childFrame);
|
|
|
|
while ((NS_OK==rv) && (nsnull!=childFrame))
|
|
|
|
{
|
|
|
|
const nsStyleDisplay *childDisplay;
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)childDisplay);
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE == childDisplay->mDisplay)
|
|
|
|
{
|
|
|
|
aTableFrame = (nsTableFrame *)childFrame;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rv = childFrame->GetNextSibling(childFrame);
|
|
|
|
}
|
1998-09-24 20:37:22 +04:00
|
|
|
break;
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
result = aTableFrame->GetContentParent((nsIFrame *&)aTableFrame);
|
1998-09-24 20:37:22 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
result = NS_ERROR_UNEXPECTED; // bad source param
|
1998-10-14 20:32:45 +04:00
|
|
|
NS_POSTCONDITION(nsnull!=aTableFrame, "unable to find table parent. aTableFrame null.");
|
1998-09-24 20:37:22 +04:00
|
|
|
NS_POSTCONDITION(NS_OK==result, "unable to find table parent. result!=NS_OK");
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-09-01 01:23:28 +04:00
|
|
|
/* helper method for determining if this is a nested table or not */
|
1998-10-02 08:10:00 +04:00
|
|
|
PRBool nsTableFrame::IsNested(const nsHTMLReflowState& aReflowState, nsStylePosition *& aPosition) const
|
1998-09-01 01:23:28 +04:00
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
nsresult rv;
|
1998-09-01 01:23:28 +04:00
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
PRInt32 counter=0;
|
|
|
|
#endif
|
|
|
|
// Walk up the reflow state chain until we find a cell or the root
|
|
|
|
const nsReflowState* rs = aReflowState.parentReflowState;
|
|
|
|
while (nsnull != rs)
|
|
|
|
{
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
counter++;
|
|
|
|
NS_ASSERTION(counter<100000, "infinite loop in IsNested");
|
1998-09-24 20:37:22 +04:00
|
|
|
break;
|
1998-09-01 01:23:28 +04:00
|
|
|
#endif
|
|
|
|
nsIFrame* parentTable = nsnull;
|
1998-09-15 21:58:24 +04:00
|
|
|
rv = rs->frame->QueryInterface(kTableFrameCID, (void**) &parentTable);
|
|
|
|
if (NS_OK==rv)
|
1998-09-01 01:23:28 +04:00
|
|
|
{
|
|
|
|
result = PR_TRUE;
|
|
|
|
parentTable->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)aPosition));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rs = rs->parentReflowState;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-09-24 08:57:30 +04:00
|
|
|
static PRBool
|
|
|
|
IsPseudoFrame(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
nsIContent* content;
|
|
|
|
nsIFrame* parentFrame;
|
|
|
|
PRBool result = PR_FALSE;
|
|
|
|
|
|
|
|
aFrame->GetContent(content);
|
|
|
|
aFrame->GetGeometricParent(parentFrame);
|
|
|
|
if (nsnull != parentFrame) {
|
|
|
|
nsIContent* parentContent;
|
|
|
|
|
|
|
|
parentFrame->GetContent(parentContent);
|
|
|
|
if (parentContent == content) {
|
|
|
|
result = PR_TRUE;
|
|
|
|
}
|
|
|
|
NS_RELEASE(parentContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_RELEASE(content);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-06-05 06:36:25 +04:00
|
|
|
/* helper method for getting the width of the table's containing block */
|
1998-10-02 08:10:00 +04:00
|
|
|
nscoord nsTableFrame::GetTableContainerWidth(const nsHTMLReflowState& aReflowState)
|
1998-06-05 06:36:25 +04:00
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
nsresult rv;
|
1998-06-05 06:36:25 +04:00
|
|
|
nscoord parentWidth = aReflowState.maxSize.width;
|
|
|
|
|
|
|
|
// Walk up the reflow state chain until we find a block
|
|
|
|
// frame. Our width is computed relative to there.
|
|
|
|
const nsReflowState* rs = &aReflowState;
|
1998-06-24 03:23:21 +04:00
|
|
|
nsIFrame *childFrame=nsnull;
|
|
|
|
nsIFrame *grandchildFrame=nsnull;
|
|
|
|
nsIFrame *greatgrandchildFrame=nsnull;
|
|
|
|
while (nsnull != rs)
|
|
|
|
{
|
|
|
|
// if it's a block, use its max width
|
1998-06-05 06:36:25 +04:00
|
|
|
nsIFrame* block = nsnull;
|
1998-09-15 21:58:24 +04:00
|
|
|
rv = rs->frame->QueryInterface(kBlockFrameCID, (void**) &block);
|
|
|
|
if (NS_OK==rv)
|
1998-06-24 03:23:21 +04:00
|
|
|
{ // we found a block, see if it's really a table cell (which means we're a nested table)
|
|
|
|
PRBool skipThisBlock=PR_FALSE;
|
1998-09-24 08:57:30 +04:00
|
|
|
// XXX FIX ME...
|
|
|
|
if (IsPseudoFrame(block))
|
1998-06-24 03:23:21 +04:00
|
|
|
{
|
|
|
|
const nsReflowState* parentRS = rs->parentReflowState;
|
|
|
|
if (nsnull!=parentRS)
|
|
|
|
{
|
|
|
|
parentRS = parentRS->parentReflowState;
|
|
|
|
if (nsnull!=parentRS)
|
|
|
|
{
|
|
|
|
nsIFrame* cell = nsnull;
|
1998-09-15 21:58:24 +04:00
|
|
|
rv = parentRS->frame->QueryInterface(kTableCellFrameCID, (void**) &cell);
|
|
|
|
if (rv == NS_OK) {
|
1998-06-24 03:23:21 +04:00
|
|
|
if (PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p: found a block pframe %p in a cell, skipping it.\n", aReflowState.frame, block);
|
|
|
|
skipThisBlock = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// at this point, we know we have a block. If we're sure it's not a table cell pframe,
|
|
|
|
// then we can use it
|
|
|
|
if (PR_FALSE==skipThisBlock)
|
|
|
|
{
|
1998-07-18 01:02:28 +04:00
|
|
|
if (NS_UNCONSTRAINEDSIZE!=rs->maxSize.width)
|
|
|
|
{
|
|
|
|
parentWidth = rs->maxSize.width;
|
|
|
|
if (PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p: found a block frame %p, returning width %d\n",
|
|
|
|
aReflowState.frame, block, parentWidth);
|
|
|
|
break;
|
|
|
|
}
|
1998-06-24 03:23:21 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// or if it's another table (we're nested) use its computed width
|
1998-06-24 23:13:19 +04:00
|
|
|
if (rs->frame!=aReflowState.frame)
|
|
|
|
{
|
1998-06-26 04:48:44 +04:00
|
|
|
nsMargin borderPadding;
|
|
|
|
const nsStylePosition* tablePosition;
|
|
|
|
const nsStyleSpacing* spacing;
|
|
|
|
nsIFrame* cell = nsnull;
|
1998-09-15 21:58:24 +04:00
|
|
|
rv = rs->frame->QueryInterface(kTableCellFrameCID, (void**) &cell);
|
1998-07-02 21:40:56 +04:00
|
|
|
// if the cell has a specified width, use it
|
1998-09-15 21:58:24 +04:00
|
|
|
if (NS_OK==rv)
|
1998-07-02 21:40:56 +04:00
|
|
|
{
|
1998-06-24 23:13:19 +04:00
|
|
|
// Compute and subtract out the insets (sum of border and padding) for the table
|
1998-09-16 04:48:14 +04:00
|
|
|
const nsStylePosition* cellPosition;
|
|
|
|
cell->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)cellPosition));
|
|
|
|
if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit())
|
1998-06-24 04:40:33 +04:00
|
|
|
{
|
1998-08-10 06:16:18 +04:00
|
|
|
nsTableFrame *tableParent;
|
1998-09-24 20:37:22 +04:00
|
|
|
rv=GetTableFrame(cell, tableParent);
|
|
|
|
if ((NS_OK==rv) && (nsnull!=tableParent) && (nsnull!=tableParent->mColumnWidths))
|
1998-08-10 06:16:18 +04:00
|
|
|
{
|
1998-09-16 04:48:14 +04:00
|
|
|
parentWidth=0;
|
1998-08-10 06:16:18 +04:00
|
|
|
PRInt32 colIndex = ((nsTableCellFrame *)cell)->GetColIndex();
|
1998-09-16 04:48:14 +04:00
|
|
|
PRInt32 colSpan = tableParent->GetEffectiveColSpan(colIndex, (nsTableCellFrame *)cell);
|
|
|
|
for (PRInt32 i=0; i<colSpan; i++)
|
|
|
|
parentWidth += tableParent->GetColumnWidth(colIndex);
|
1998-08-10 06:16:18 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// if the column width of this cell is already computed, it overrides the attribute
|
|
|
|
// otherwise, use the attribute becauase the actual column width has not yet been computed
|
|
|
|
else
|
|
|
|
{
|
1998-09-16 04:48:14 +04:00
|
|
|
parentWidth = cellPosition->mWidth.GetCoordValue();
|
1998-08-10 06:16:18 +04:00
|
|
|
// subtract out cell border and padding
|
|
|
|
cell->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
|
|
|
spacing->CalcBorderPaddingFor(cell, borderPadding);
|
|
|
|
parentWidth -= (borderPadding.right + borderPadding.left);
|
|
|
|
if (PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p: found a cell frame %p with fixed coord width %d, returning parentWidth %d\n",
|
1998-09-16 04:48:14 +04:00
|
|
|
aReflowState.frame, cell, cellPosition->mWidth.GetCoordValue(), parentWidth);
|
1998-08-10 06:16:18 +04:00
|
|
|
break;
|
|
|
|
}
|
1998-06-26 04:48:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nsIFrame* table = nsnull;
|
1998-09-15 21:58:24 +04:00
|
|
|
rv = rs->frame->QueryInterface(kTableFrameCID, (void**) &table);
|
|
|
|
if (NS_OK==rv) {
|
1998-06-26 04:48:44 +04:00
|
|
|
/* We found the nearest containing table (actually, the inner table).
|
|
|
|
This defines what our percentage size is relative to. Use its desired width
|
|
|
|
as the basis for computing our width.
|
|
|
|
**********************************************************************************
|
|
|
|
Nav4 compatibility code: if the inner table has a percent width and the outer
|
|
|
|
table has an auto width, the parentWidth is the width the containing cell would be
|
|
|
|
without the inner table.
|
|
|
|
**********************************************************************************
|
|
|
|
*/
|
|
|
|
// Compute and subtract out the insets (sum of border and padding) for the table
|
1998-09-15 21:58:24 +04:00
|
|
|
table->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)tablePosition);
|
|
|
|
table->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
1998-06-26 04:48:44 +04:00
|
|
|
if (eStyleUnit_Auto == tablePosition->mWidth.GetUnit())
|
1998-06-24 23:13:19 +04:00
|
|
|
{
|
1998-07-18 01:02:28 +04:00
|
|
|
parentWidth = NS_UNCONSTRAINEDSIZE;
|
1998-06-26 04:48:44 +04:00
|
|
|
if (nsnull != ((nsTableFrame*)table)->mColumnWidths)
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
parentWidth=0;
|
1998-06-26 04:48:44 +04:00
|
|
|
PRInt32 colIndex = ((nsTableCellFrame *)greatgrandchildFrame)->GetColIndex();
|
1998-07-24 20:51:16 +04:00
|
|
|
PRInt32 colSpan = ((nsTableFrame*)table)->GetEffectiveColSpan(colIndex, ((nsTableCellFrame *)greatgrandchildFrame));
|
1998-06-26 04:48:44 +04:00
|
|
|
for (PRInt32 i = 0; i<colSpan; i++)
|
|
|
|
parentWidth += ((nsTableFrame*)table)->GetColumnWidth(i+colIndex);
|
|
|
|
// subtract out cell border and padding
|
|
|
|
greatgrandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
|
|
|
spacing->CalcBorderPaddingFor(greatgrandchildFrame, borderPadding);
|
|
|
|
parentWidth -= (borderPadding.right + borderPadding.left);
|
|
|
|
if (PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p: found a table frame %p with auto width, returning parentWidth %d from cell in col %d with span %d\n",
|
|
|
|
aReflowState.frame, table, parentWidth, colIndex, colSpan);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p: found a table frame %p with auto width, returning parentWidth %d because parent has no info yet.\n",
|
|
|
|
aReflowState.frame, table, parentWidth);
|
|
|
|
}
|
1998-06-24 23:13:19 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-07-17 03:23:31 +04:00
|
|
|
if (nsnull!=((nsTableFrame*)table)->mColumnWidths)
|
|
|
|
{
|
1998-08-18 03:37:04 +04:00
|
|
|
parentWidth=0;
|
1998-07-17 03:23:31 +04:00
|
|
|
PRInt32 colIndex = ((nsTableCellFrame*)greatgrandchildFrame)->GetColIndex();
|
1998-08-18 03:37:04 +04:00
|
|
|
PRInt32 colSpan = ((nsTableFrame*)table)->GetEffectiveColSpan(colIndex, ((nsTableCellFrame *)greatgrandchildFrame));
|
|
|
|
for (PRInt32 i = 0; i<colSpan; i++)
|
|
|
|
parentWidth += ((nsTableFrame*)table)->GetColumnWidth(i+colIndex);
|
|
|
|
if (eStyleUnit_Percent == tablePosition->mWidth.GetUnit())
|
|
|
|
{
|
|
|
|
float percent = tablePosition->mWidth.GetPercentValue();
|
|
|
|
parentWidth = (nscoord)(percent*((float)parentWidth));
|
|
|
|
}
|
1998-07-17 03:23:31 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nsSize tableSize;
|
|
|
|
table->GetSize(tableSize);
|
|
|
|
parentWidth = tableSize.width;
|
1998-08-18 03:37:04 +04:00
|
|
|
if (0!=tableSize.width)
|
|
|
|
{ // the table has been sized, so we can compute the available space for the child
|
|
|
|
spacing->CalcBorderPaddingFor(rs->frame, borderPadding);
|
|
|
|
parentWidth -= (borderPadding.right + borderPadding.left);
|
|
|
|
// same for the row group
|
|
|
|
childFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
|
|
|
spacing->CalcBorderPaddingFor(childFrame, borderPadding);
|
|
|
|
parentWidth -= (borderPadding.right + borderPadding.left);
|
|
|
|
// same for the row
|
|
|
|
grandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
|
|
|
spacing->CalcBorderPaddingFor(grandchildFrame, borderPadding);
|
|
|
|
parentWidth -= (borderPadding.right + borderPadding.left);
|
|
|
|
// same for the cell
|
|
|
|
greatgrandchildFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
|
|
|
spacing->CalcBorderPaddingFor(greatgrandchildFrame, borderPadding);
|
|
|
|
parentWidth -= (borderPadding.right + borderPadding.left);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// the table has not yet been sized, so we need to infer the available space
|
|
|
|
parentWidth = rs->maxSize.width;
|
|
|
|
if (eStyleUnit_Percent == tablePosition->mWidth.GetUnit())
|
|
|
|
{
|
|
|
|
float percent = tablePosition->mWidth.GetPercentValue();
|
|
|
|
parentWidth = (nscoord)(percent*((float)parentWidth));
|
|
|
|
}
|
|
|
|
}
|
1998-07-17 03:23:31 +04:00
|
|
|
}
|
1998-06-24 23:13:19 +04:00
|
|
|
if (PR_TRUE==gsDebugNT)
|
1998-07-17 03:23:31 +04:00
|
|
|
printf("%p: found a table frame %p, returning parentWidth %d \n",
|
|
|
|
aReflowState.frame, table, parentWidth);
|
1998-06-24 23:13:19 +04:00
|
|
|
}
|
1998-06-26 04:48:44 +04:00
|
|
|
break;
|
1998-06-24 04:40:33 +04:00
|
|
|
}
|
|
|
|
}
|
1998-06-05 06:36:25 +04:00
|
|
|
}
|
1998-06-24 03:23:21 +04:00
|
|
|
|
|
|
|
if (nsnull==childFrame)
|
|
|
|
childFrame = rs->frame;
|
|
|
|
else if (nsnull==grandchildFrame)
|
|
|
|
{
|
|
|
|
grandchildFrame = childFrame;
|
|
|
|
childFrame = rs->frame;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
greatgrandchildFrame = grandchildFrame;
|
|
|
|
grandchildFrame = childFrame;
|
|
|
|
childFrame = rs->frame;
|
|
|
|
}
|
1998-06-05 06:36:25 +04:00
|
|
|
rs = rs->parentReflowState;
|
|
|
|
}
|
|
|
|
|
|
|
|
return parentWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
// aSpecifiedTableWidth is filled if the table witdth is not auto
|
|
|
|
PRBool nsTableFrame::TableIsAutoWidth(nsTableFrame *aTableFrame,
|
|
|
|
nsIStyleContext *aTableStyle,
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
1998-06-05 06:36:25 +04:00
|
|
|
nscoord& aSpecifiedTableWidth)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(nsnull!=aTableStyle, "bad arg - aTableStyle");
|
|
|
|
PRBool result = PR_TRUE; // the default
|
|
|
|
if (nsnull!=aTableStyle)
|
|
|
|
{
|
1998-09-15 21:58:24 +04:00
|
|
|
nsStylePosition* tablePosition = (nsStylePosition*)aTableStyle->GetStyleData(eStyleStruct_Position);
|
1998-06-24 03:23:21 +04:00
|
|
|
nsMargin borderPadding;
|
|
|
|
const nsStyleSpacing* spacing;
|
1998-06-05 06:36:25 +04:00
|
|
|
switch (tablePosition->mWidth.GetUnit()) {
|
|
|
|
case eStyleUnit_Auto: // specified auto width
|
|
|
|
case eStyleUnit_Proportional: // illegal for table, so ignored
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eStyleUnit_Inherit:
|
|
|
|
// get width of parent and see if it is a specified value or not
|
|
|
|
// XXX for now, just return true
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eStyleUnit_Coord:
|
1998-06-24 03:23:21 +04:00
|
|
|
// XXX: subtract out this table frame's borderpadding?
|
1998-06-05 06:36:25 +04:00
|
|
|
aSpecifiedTableWidth = tablePosition->mWidth.GetCoordValue();
|
1998-06-24 03:23:21 +04:00
|
|
|
aReflowState.frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
|
|
|
spacing->CalcBorderPaddingFor(aReflowState.frame, borderPadding);
|
|
|
|
aSpecifiedTableWidth -= (borderPadding.right + borderPadding.left);
|
1998-06-05 06:36:25 +04:00
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eStyleUnit_Percent:
|
|
|
|
// set aSpecifiedTableWidth to be the given percent of the parent.
|
1998-06-24 03:23:21 +04:00
|
|
|
// first, get the effective parent width (parent width - insets)
|
1998-06-05 06:36:25 +04:00
|
|
|
nscoord parentWidth = nsTableFrame::GetTableContainerWidth(aReflowState);
|
1998-07-18 01:02:28 +04:00
|
|
|
if (NS_UNCONSTRAINEDSIZE!=parentWidth)
|
|
|
|
{
|
|
|
|
aReflowState.frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing);
|
|
|
|
spacing->CalcBorderPaddingFor(aReflowState.frame, borderPadding);
|
|
|
|
parentWidth -= (borderPadding.right + borderPadding.left);
|
|
|
|
|
|
|
|
// then set aSpecifiedTableWidth to the given percent of the computed parent width
|
|
|
|
float percent = tablePosition->mWidth.GetPercentValue();
|
|
|
|
aSpecifiedTableWidth = (PRInt32)(parentWidth*percent);
|
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p: TableIsAutoWidth setting aSpecifiedTableWidth = %d with parentWidth = %d and percent = %f\n",
|
|
|
|
aTableFrame, aSpecifiedTableWidth, parentWidth, percent);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aSpecifiedTableWidth=parentWidth;
|
|
|
|
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugNT)
|
|
|
|
printf("%p: TableIsAutoWidth setting aSpecifiedTableWidth = %d with parentWidth = %d\n",
|
|
|
|
aTableFrame, aSpecifiedTableWidth, parentWidth);
|
|
|
|
}
|
1998-06-05 06:36:25 +04:00
|
|
|
result = PR_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-09-30 03:15:01 +04:00
|
|
|
nscoord nsTableFrame::GetMinCaptionWidth()
|
|
|
|
{
|
|
|
|
nsIFrame *outerTableFrame=nsnull;
|
|
|
|
GetContentParent(outerTableFrame);
|
|
|
|
return (((nsTableOuterFrame *)outerTableFrame)->GetMinCaptionWidth());
|
|
|
|
}
|
|
|
|
|
1998-10-08 19:34:48 +04:00
|
|
|
/** return the minimum width of the table. Return 0 if the min width is unknown. */
|
|
|
|
nscoord nsTableFrame::GetMinTableWidth()
|
|
|
|
{
|
|
|
|
nscoord result = 0;
|
|
|
|
if (nsnull!=mTableLayoutStrategy)
|
|
|
|
result = mTableLayoutStrategy->GetTableMinWidth();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** return the maximum width of the table caption. Return 0 if the max width is unknown. */
|
|
|
|
nscoord nsTableFrame::GetMaxTableWidth()
|
|
|
|
{
|
|
|
|
nscoord result = 0;
|
|
|
|
if (nsnull!=mTableLayoutStrategy)
|
|
|
|
result = mTableLayoutStrategy->GetTableMaxWidth();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-10-09 23:59:45 +04:00
|
|
|
void nsTableFrame::SetMaxElementSize(nsSize* aMaxElementSize)
|
|
|
|
{
|
|
|
|
if (nsnull!=mTableLayoutStrategy)
|
|
|
|
mTableLayoutStrategy->SetMaxElementSize(aMaxElementSize);
|
|
|
|
}
|
|
|
|
|
1998-09-30 03:15:01 +04:00
|
|
|
|
1998-09-03 01:59:54 +04:00
|
|
|
/* ----- debugging methods ----- */
|
|
|
|
NS_METHOD nsTableFrame::List(FILE* out, PRInt32 aIndent, nsIListFilter *aFilter) const
|
|
|
|
{
|
|
|
|
// if a filter is present, only output this frame if the filter says we should
|
|
|
|
// since this could be any "tag" with the right display type, we'll
|
|
|
|
// just pretend it's a table
|
|
|
|
if (nsnull==aFilter)
|
|
|
|
return nsContainerFrame::List(out, aIndent, aFilter);
|
|
|
|
|
|
|
|
nsAutoString tagString("table");
|
|
|
|
PRBool outputMe = aFilter->OutputTag(&tagString);
|
|
|
|
if (PR_TRUE==outputMe)
|
|
|
|
{
|
|
|
|
// Indent
|
|
|
|
for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
|
|
|
|
|
|
|
|
// Output the tag and rect
|
|
|
|
nsIAtom* tag;
|
|
|
|
mContent->GetTag(tag);
|
|
|
|
if (tag != nsnull) {
|
|
|
|
nsAutoString buf;
|
|
|
|
tag->ToString(buf);
|
|
|
|
fputs(buf, out);
|
|
|
|
NS_RELEASE(tag);
|
|
|
|
}
|
|
|
|
|
1998-10-09 00:35:16 +04:00
|
|
|
fprintf(out, "(%d)", ContentIndexInContainer(this));
|
1998-09-03 01:59:54 +04:00
|
|
|
out << mRect;
|
|
|
|
if (0 != mState) {
|
|
|
|
fprintf(out, " [state=%08x]", mState);
|
|
|
|
}
|
|
|
|
fputs("\n", out);
|
|
|
|
if (nsnull!=mTableLayoutStrategy)
|
|
|
|
{
|
|
|
|
for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
|
|
|
|
fprintf(out, "min=%d, max=%d, fixed=%d, cols=%d, numCols=%d\n",
|
|
|
|
mTableLayoutStrategy->GetTableMinWidth(),
|
|
|
|
mTableLayoutStrategy->GetTableMaxWidth(),
|
|
|
|
mTableLayoutStrategy->GetTableFixedWidth(),
|
|
|
|
mTableLayoutStrategy->GetCOLSAttribute(),
|
|
|
|
mTableLayoutStrategy->GetNumCols()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Output the children
|
1998-09-21 07:40:32 +04:00
|
|
|
if (nsnull != mFirstChild) {
|
1998-09-03 01:59:54 +04:00
|
|
|
if (PR_TRUE==outputMe)
|
|
|
|
{
|
|
|
|
if (0 != mState) {
|
|
|
|
fprintf(out, " [state=%08x]\n", mState);
|
|
|
|
}
|
|
|
|
}
|
1998-09-19 07:24:26 +04:00
|
|
|
for (nsIFrame* child = mFirstChild; child; child->GetNextSibling(child)) {
|
1998-09-03 01:59:54 +04:00
|
|
|
child->List(out, aIndent + 1, aFilter);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (PR_TRUE==outputMe)
|
|
|
|
{
|
|
|
|
if (0 != mState) {
|
|
|
|
fprintf(out, " [state=%08x]\n", mState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|