support work for style optimizations
fixed a bug in table columns  -- the attribute repeat defaults to 1, not 0
This commit is contained in:
buster%netscape.com 1998-08-26 17:26:38 +00:00
Родитель a56ae43131
Коммит 7b6c525170
14 изменённых файлов: 527 добавлений и 170 удалений

Просмотреть файл

@ -40,7 +40,7 @@ nsTableCol::nsTableCol(nsIAtom* aTag)
: nsTableContent(aTag),
mColGroup(0),
mColIndex(0),
mRepeat(0)
mRepeat(1)
{
Init();
}
@ -49,7 +49,7 @@ nsTableCol::nsTableCol()
: nsTableContent(NS_NewAtom(nsTablePart::kColTagString)),
mColGroup(0),
mColIndex(0),
mRepeat(0)
mRepeat(1)
{
Init();
}
@ -58,7 +58,7 @@ nsTableCol::nsTableCol (PRBool aImplicit)
: nsTableContent(NS_NewAtom(nsTablePart::kColTagString)),
mColGroup(0),
mColIndex(0),
mRepeat(0)
mRepeat(1)
{
mImplicit = aImplicit;
Init();

Просмотреть файл

@ -35,6 +35,8 @@ static const PRBool gsDebug = PR_FALSE;
static const PRBool gsNoisyRefs = PR_FALSE;
#endif
static NS_DEFINE_IID(kITableContentIID, NS_ITABLECONTENT_IID);
nsTableColGroup::nsTableColGroup(nsIAtom* aTag, int aSpan)
: nsTableContent(aTag),
@ -251,19 +253,25 @@ nsTableColGroup::RemoveChildAt (PRInt32 aIndex, PRBool aNotify)
return NS_OK;
}
/** support method to determine if the param aContent is a TableRow object */
/** support method to determine if the param aContent is an nsTableCol object */
PRBool nsTableColGroup::IsCol(nsIContent * aContent) const
{
NS_ASSERTION(nsnull!=aContent, "bad arg");
PRBool result = PR_FALSE;
if (nsnull!=aContent)
{
// is aContent a col?
nsTableContent *tableContent = (nsTableContent *)aContent;
const int contentType = tableContent->GetType();
nsITableContent *tableContentInterface = nsnull;
nsresult rv = aContent->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_SUCCEEDED(rv))
{
const int contentType = tableContentInterface->GetType();
NS_RELEASE(tableContentInterface);
if (contentType == nsITableContent::kTableColType)
result = PR_TRUE;
}
}
return result;
}

Просмотреть файл

@ -17,6 +17,7 @@
*/
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsITableContent.h"
#include "nsIReflowCommand.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
@ -28,6 +29,8 @@
NS_DEF_PTR(nsIContent);
NS_DEF_PTR(nsIStyleContext);
static NS_DEFINE_IID(kITableContentIID, NS_ITABLECONTENT_IID);
static PRBool gsDebug = PR_FALSE;
@ -51,7 +54,9 @@ NS_METHOD nsTableColGroupFrame::Paint(nsIPresContext& aPresContext,
return NS_OK;
}
// TODO: content changed notifications
// TODO: incremental reflow
// today, we just throw away the column frames and start over every time
// this is dumb, we should be able to maintain column frames and adjust incrementally
NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
@ -59,20 +64,35 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
{
NS_ASSERTION(nsnull!=mContent, "bad state -- null content for frame");
if (nsnull == mFirstChild)
{ // if we don't have any children, create them
// for every content child that (is a column thingy and does not already have a frame)
// create a frame and adjust it's style
nsIFrame* kidFrame = nsnull;
nsIFrame* prevKidFrame;
LastChild(prevKidFrame); // XXX remember this...
PRInt32 kidIndex = 0;
for (PRInt32 colIndex = 0; ;colIndex++) // colIndex is used to set the column frames' index field
PRInt32 kidIndex = 0; // index of the content child we are currently working on
PRInt32 colIndex = 0; // number of content children that are columns, normally same as kidIndex
for (;;)
{
// get the next content child, breaking if there is none
nsIContentPtr kid = mContent->ChildAt(kidIndex); // kid: REFCNT++
if (kid.IsNull()) {
break;
}
// verify that we're dealing with table content. If so, we know it's a column
nsITableContent *tableContentInterface = nsnull;
nsresult rv = kid->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_FAILED(rv))
{
kidIndex++;
continue;
}
NS_RELEASE(tableContentInterface); // tableContentInterface: REFCNT--
if (mChildCount<=colIndex)
{
// Resolve style
nsIStyleContextPtr kidSC =
aPresContext.ResolveStyleContextFor(kid, this, PR_TRUE);
@ -82,8 +102,7 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
// Create a child frame
nsIContentDelegate* kidDel = nsnull;
kidDel = kid->GetDelegate(&aPresContext);
nsresult rv = kidDel->CreateFrame(&aPresContext, kid, this, kidSC,
kidFrame);
rv = kidDel->CreateFrame(&aPresContext, kid, this, kidSC, kidFrame);
NS_RELEASE(kidDel);
// give the child frame a chance to reflow, even though we know it'll have 0 size
@ -107,10 +126,10 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
}
prevKidFrame = kidFrame;
mChildCount++;
kidIndex++;
SetStyleContextForFirstPass(&aPresContext, colIndex);
}
// now that I have all my COL children, adjust their style
SetStyleContextForFirstPass(&aPresContext);
colIndex++; // if this wasn't a column, we would not have gotten this far
kidIndex++;
}
aDesiredSize.width=0;
aDesiredSize.height=0;
@ -124,7 +143,8 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
}
// Subclass hook for style post processing
NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPresContext)
NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPresContext,
PRInt32 aColIndex)
{
// get the table frame
nsIFrame* tableFrame=nsnull;
@ -150,31 +170,31 @@ NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPre
PRInt32 colIndex=0;
nsIFrame *colFrame=nsnull;
nsIStyleContextPtr colStyleContext;
for (; colIndex<numCols; colIndex++)
ChildAt(aColIndex, colFrame);
if (nsnull!=colFrame)
{
ChildAt(colIndex, colFrame);
if (nsnull==colFrame)
break; // the attribute value specified was greater than the actual number of columns
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleContext(aPresContext, colStyleContext.AssignRef());
colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
colStyleContext->RecalcAutomaticData(aPresContext);
}
// if there are more columns, there width is set to "minimum"
PRInt32 numChildFrames;
ChildCount(numChildFrames);
for (; colIndex<numChildFrames; colIndex++)
for (; aColIndex<numChildFrames-1; colIndex++)
{
ChildAt(colIndex, colFrame);
NS_ASSERTION(nsnull!=colFrame, "bad column frame");
if (nsnull==colFrame)
break;
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleContext(aPresContext, colStyleContext.AssignRef());
colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
colPosition->mWidth.SetCoordValue(0);
colStyleContext->RecalcAutomaticData(aPresContext);
}
}
mStyleContext->RecalcAutomaticData(aPresContext);
}
@ -188,8 +208,7 @@ NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPre
*/
int nsTableColGroupFrame::GetColumnCount ()
{
if (0 == mColCount)
{
mColCount=0;
int count;
ChildCount (count);
if (0 < count)
@ -211,7 +230,6 @@ int nsTableColGroupFrame::GetColumnCount ()
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
mColCount = tableStyle->mSpan;
}
}
return mColCount;
}

Просмотреть файл

@ -70,7 +70,8 @@ protected:
* Since we need to know the full column structure before the COLS attribute
* can be interpreted, we can't just use DidSetStyleContext
*/
NS_METHOD SetStyleContextForFirstPass(nsIPresContext* aPresContext);
NS_METHOD SetStyleContextForFirstPass(nsIPresContext* aPresContext,
PRInt32 aColIndex);
PRInt32 mColCount;

Просмотреть файл

@ -574,9 +574,9 @@ void nsTableFrame::EnsureColumns(nsIPresContext* aPresContext,
// need to find the generic way to stamp out this content, and ::AppendChildTo it
// this might be ok. no matter what my mcontent is, I know it needs a colgroup as a kid?
lastColGroup = new nsTableColGroup (PR_TRUE);
// XXX: how do I know whether AppendChildTo should notify or not?
mContent->AppendChildTo(lastColGroup, PR_FALSE); // was AppendColGroup
lastColGroup = new nsTableColGroup (PR_TRUE); // create an implicit colgroup
// XXX: instead of Append, maybe this should be insertAt(0)?
mContent->AppendChildTo(lastColGroup, PR_FALSE); // add the implicit colgroup to my content
NS_ADDREF(lastColGroup); // ADDREF a: lastColGroup++
// Resolve style for the child
nsIStyleContext* colGroupStyleContext =
@ -619,6 +619,104 @@ void nsTableFrame::EnsureColumns(nsIPresContext* aPresContext,
{ //QQQ
// need to find the generic way to stamp out this content, and ::AppendChildTo it
nsTableCol *col = new nsTableCol(PR_TRUE);
NS_ADDREF(col);
lastColGroup->AppendChildTo (col, PR_FALSE);
}
NS_RELEASE(lastColGroup); // ADDREF: lastColGroup--
lastColGroupFrame->Reflow(*aPresContext, aDesiredSize, aReflowState, aStatus);
}
}
/** 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.
*/
void nsTableFrame::EnsureColumnFrameAt(PRInt32 aColIndex,
nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus)
{
if (nsnull!=mCellMap)
return; // we already have a cell map so this makes no sense
PRInt32 actualColumns = 0;
nsTableColGroupFrame *lastColGroupFrame = nsnull;
nsIFrame * firstRowGroupFrame=nsnull;
nsIFrame * prevSibFrame=nsnull;
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)
break; // we gave enough col frames at this point
}
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
{
firstRowGroupFrame = childFrame;
break;
}
prevSibFrame = childFrame;
childFrame->GetNextSibling(childFrame);
}
if (actualColumns <= aColIndex)
{
nsTableColGroup *lastColGroup=nsnull;
if (nsnull==lastColGroupFrame)
{
lastColGroup = new nsTableColGroup (PR_TRUE); // create an implicit colgroup
mContent->AppendChildTo(lastColGroup, PR_FALSE); // add the implicit colgroup to my content
NS_ADDREF(lastColGroup); // ADDREF a: lastColGroup++
// Resolve style for the child
nsIStyleContext* colGroupStyleContext =
aPresContext->ResolveStyleContextFor(lastColGroup, this, PR_TRUE); // kidStyleContext: REFCNT++
nsIContentDelegate* kidDel = nsnull;
kidDel = lastColGroup->GetDelegate(aPresContext); // kidDel: REFCNT++
nsresult rv = kidDel->CreateFrame(aPresContext, lastColGroup, this,
colGroupStyleContext, (nsIFrame *&)lastColGroupFrame);
NS_RELEASE(kidDel); // kidDel: REFCNT--
NS_RELEASE(colGroupStyleContext); // kidStyleContenxt: REFCNT--
// hook lastColGroupFrame into child list
if (nsnull==firstRowGroupFrame)
{ // make lastColGroupFrame the last frame
nsIFrame *lastChild=nsnull;
LastChild(lastChild);
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);
}
mChildCount++;
}
else
{
lastColGroupFrame->GetContent((nsIContent *&)lastColGroup); // ADDREF b: lastColGroup++
}
PRInt32 excessColumns = aColIndex - actualColumns;
for ( ; excessColumns >= 0; excessColumns--)
{
nsTableCol *col = new nsTableCol(PR_TRUE);
NS_ADDREF(col);
lastColGroup->AppendChildTo(col, PR_FALSE);
}
NS_RELEASE(lastColGroup); // ADDREF: lastColGroup--
@ -1442,6 +1540,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
nscoord bottomInset = borderPadding.bottom;
nscoord leftInset = borderPadding.left;
nsReflowReason reflowReason = aReflowState.reason;
nsIContent * prevKid; // do NOT hold a reference for this temp pointer!
/* assumes that Table's children are in the following order:
* Captions
@ -1457,6 +1556,14 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
break;
}
if (kid==prevKid)
{ // we just saw this kid, but in it's processing someone inserted something in front of it
// (probably a colgroup). So don't process it twice.
kidIndex++;
continue;
}
prevKid = kid;
mLastContentIsComplete = PR_TRUE;
// Resolve style

Просмотреть файл

@ -201,6 +201,15 @@ public:
*/
PRInt32 GetEffectiveCOLSAttribute();
/** verify that there are at least aColIndex column frames created.
* if not, create the needed col frames
*/
virtual void EnsureColumnFrameAt(PRInt32 aColIndex,
nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus);
protected:
/** protected constructor.

Просмотреть файл

@ -41,9 +41,11 @@ static NS_DEFINE_IID(kITableContentIID, NS_ITABLECONTENT_IID);
#ifdef NS_DEBUG
static PRBool gsDebug = PR_FALSE;
static PRBool gsNoisyRefs = PR_FALSE;
static PRBool gsDebugWarnings = PR_TRUE;
#else
static const PRBool gsDebug = PR_FALSE;
static const PRBool gsNoisyRefs = PR_FALSE;
static const PRBool gsDebugWarnings = PR_FALSE;
#endif
const char *nsTablePart::kCaptionTagString="CAPTION";
@ -174,9 +176,11 @@ nsTablePart::AppendChildTo (nsIContent * aContent, PRBool aNotify)
nsresult rv = aContent->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_FAILED(rv))
{ // create an implicit cell and return the result of adding it to the table
NS_ASSERTION(PR_FALSE, "non-table content insertion not implemented");
return NS_ERROR_FAILURE;
{ // hold onto the non-table content, but do nothing with it
if (PR_TRUE==gsDebugWarnings)
printf ("non-table content inserted into table.");
rv = nsHTMLContainer::AppendChildTo(aContent, aNotify);
return rv;
}
else
{
@ -389,20 +393,31 @@ PRBool nsTablePart::AppendRowGroup (nsTableRowGroup *aContent)
nsIAtom * tBodyTag = NS_NewAtom(kRowGroupBodyTagString); // tBodyTag: REFCNT++
for (childIndex = 0; childIndex < childCount; childIndex++)
{
nsTableContent *tableChild = (nsTableContent *)ChildAt(childIndex); // tableChild: REFCNT++
nsITableContent *tableContentInterface = nsnull;
nsIContent * child = ChildAt(childIndex); // tableChild: REFCNT++
nsresult rv = child->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_FAILED(rv))
{
NS_RELEASE(child); // tableChild: REFCNT-- (a)
continue;
}
nsTableContent *tableChild = (nsTableContent *)tableContentInterface;
const int tableChildType = tableChild->GetType();
// if we've found caption or colgroup, then just skip it and keep going
if ((tableChildType == nsITableContent::kTableCaptionType) ||
(tableChildType == nsITableContent::kTableColGroupType))
{
NS_RELEASE(tableChild); // tableChild: REFCNT-- (a)
NS_RELEASE(child); // tableChild: REFCNT-- (b)
NS_RELEASE(tableContentInterface); // tableContentInterface: REFCNT--
continue;
}
// if we've found a row group, our action depends on what kind of row group
else if (tableChildType == nsITableContent::kTableRowGroupType)
{
nsIAtom * tableChildTag = tableChild->GetTag();
NS_RELEASE(tableChild); // tableChild: REFCNT-- (b)
NS_RELEASE(child); // tableChild: REFCNT-- (c)
NS_RELEASE(tableContentInterface); // tableContentInterface: REFCNT--
// if aContent is a header and the current child is a header, keep going
if (tHeadTag==rowGroupTag && tHeadTag==tableChildTag)
{
@ -434,7 +449,8 @@ PRBool nsTablePart::AppendRowGroup (nsTableRowGroup *aContent)
// otherwise we're already at the right spot, so stop
else
{
NS_RELEASE(tableChild); // tableChild: REFCNT-- (c)
NS_RELEASE(child); // tableChild: REFCNT-- (d)
NS_RELEASE(tableContentInterface); // tableContentInterface: REFCNT--
break;
}
}
@ -465,9 +481,18 @@ PRBool nsTablePart::AppendColGroup(nsTableColGroup *aContent)
int childCount = ChildCount ();
for (childIndex = 0; childIndex < childCount; childIndex++)
{
nsTableContent *tableChild = (nsTableContent *)ChildAt(childIndex); // tableChild: REFCNT++
const int tableChildType = tableChild->GetType();
NS_RELEASE(tableChild); // tableChild: REFCNT--
nsIContent *child = ChildAt(childIndex); // child: REFCNT++
nsITableContent *tableContentInterface = nsnull;
nsresult rv = child->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_FAILED(rv))
{
NS_RELEASE(child);
continue;
}
const int tableChildType = tableContentInterface->GetType();
NS_RELEASE(child); // tableChild: REFCNT--
NS_RELEASE(tableContentInterface);
if (!((tableChildType == nsITableContent::kTableCaptionType) ||
(tableChildType == nsITableContent::kTableColGroupType)))
break;
@ -513,13 +538,22 @@ PRBool nsTablePart::AppendColumn(nsTableCol *aContent)
int index = ChildCount ();
while ((0 < index) && (PR_FALSE==foundColGroup))
{
nsITableContent *tableContentInterface = nsnull;
nsIContent *child = ChildAt (--index); // child: REFCNT++
if (nsnull != child)
nsresult rv = child->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
NS_RELEASE(child); // tableChild: REFCNT-- (a)
if (NS_FAILED(rv))
{
group = (nsTableColGroup *)child;
continue;
}
group = (nsTableColGroup *)tableContentInterface;
foundColGroup = (PRBool)
(group->GetType()==nsITableContent::kTableColGroupType);
NS_RELEASE(child); // child: REFCNT--
if (PR_FALSE==foundColGroup)
{ // release all the table contents that are not a col group
NS_RELEASE(tableContentInterface); // tableContentInterface: REFCNT-- (a)
}
}
PRBool groupIsImplicit = PR_FALSE;
@ -537,6 +571,7 @@ PRBool nsTablePart::AppendColumn(nsTableCol *aContent)
if (NS_OK==rv)
rv = group->AppendChildTo (aContent, PR_FALSE);
NS_IF_RELEASE(group); // tableContentInterface: REFCNT-- (b)
return (PRBool)(NS_OK==rv);
}
@ -553,9 +588,17 @@ PRBool nsTablePart::AppendCaption(nsTableCaption *aContent)
int childCount = ChildCount ();
for (childIndex = 0; childIndex < childCount; childIndex++)
{
nsTableContent *tableChild = (nsTableContent *)ChildAt(childIndex);
const int tableChildType = tableChild->GetType();
NS_RELEASE(tableChild);
nsITableContent *tableContentInterface = nsnull;
nsIContent *child = ChildAt (childIndex); // child: REFCNT++
nsresult rv = child->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
NS_RELEASE(child); // tableChild: REFCNT-- (a)
if (NS_FAILED(rv))
{
continue;
}
const int tableChildType = tableContentInterface->GetType();
NS_RELEASE(tableContentInterface);
if (tableChildType != nsITableContent::kTableCaptionType)
break;
}

Просмотреть файл

@ -20,10 +20,12 @@
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
#include "nsIHTMLAttributes.h"
#include "nsHTMLAtoms.h"
#include "nsIContent.h"
#include "nsIContentDelegate.h"
#include "nsHTMLTagContent.h"
#include "nsTableFrame.h"
#include "nsTableColFrame.h"
#include "nsTableCellFrame.h"
#include "nsIView.h"
#include "nsIPtr.h"
@ -500,6 +502,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
// Place our children, one at a time, until we are out of children
nsSize kidMaxElementSize;
PRInt32 kidIndex = 0;
PRInt32 colIndex = -1;
nsIFrame* prevKidFrame = nsnull;
nscoord maxTopMargin = 0;
nscoord maxBottomMargin = 0;
@ -513,6 +516,21 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
break; // no more content
}
// what column does this cell span to?
nsHTMLValue value;
((nsHTMLTagContent *)cell)->GetAttribute(nsHTMLAtoms::align, value);
if (value.GetUnit() == eHTMLUnit_Integer)
colIndex += value.GetIntValue();
else
colIndex += 1;
// create column frames if necessary
nsReflowStatus status;
aState.tableFrame->EnsureColumnFrameAt(colIndex,
&aPresContext,
aDesiredSize,
aState.reflowState,
status);
// Create a child frame -- always an nsTableCell frame
nsIStyleContext* kidSC = aPresContext.ResolveStyleContextFor(cell, this, PR_TRUE);
nsIContentDelegate* kidDel = cell->GetDelegate(&aPresContext);
@ -569,8 +587,6 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
nsReflowMetrics kidSize(&kidMaxElementSize);
nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize,
eReflowReason_Initial);
nsReflowStatus status;
kidFrame->WillReflow(aPresContext);
if (gsDebug) printf ("%p InitR: avail=%d\n", this, kidAvailSize.width);
status = ReflowChild(kidFrame, &aPresContext, kidSize, kidReflowState);

Просмотреть файл

@ -40,7 +40,6 @@ static const PRBool gsDebug = PR_FALSE;
static const PRBool gsNoisyRefs = PR_FALSE;
#endif
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kITableContentIID, NS_ITABLECONTENT_IID);
// nsTableContent checks aTag
@ -294,11 +293,14 @@ PRBool nsTableRowGroup::IsRow(nsIContent * aContent) const
nsresult rv = aContent->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_SUCCEEDED(rv))
{
const int contentType = tableContentInterface->GetType();
NS_RELEASE(tableContentInterface);
if (contentType == nsITableContent::kTableRowType)
result = PR_TRUE;
}
}
return result;
}
@ -312,12 +314,14 @@ PRBool nsTableRowGroup::IsTableCell(nsIContent * aContent) const
nsITableContent *tableContentInterface = nsnull;
nsresult rv = aContent->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_SUCCEEDED(rv))
{
const int contentType = tableContentInterface->GetType();
NS_RELEASE(tableContentInterface);
if (contentType == nsITableContent::kTableCellType)
result = PR_TRUE;
}
}
return result;
}

Просмотреть файл

@ -17,6 +17,7 @@
*/
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsITableContent.h"
#include "nsIReflowCommand.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
@ -28,6 +29,8 @@
NS_DEF_PTR(nsIContent);
NS_DEF_PTR(nsIStyleContext);
static NS_DEFINE_IID(kITableContentIID, NS_ITABLECONTENT_IID);
static PRBool gsDebug = PR_FALSE;
@ -51,7 +54,9 @@ NS_METHOD nsTableColGroupFrame::Paint(nsIPresContext& aPresContext,
return NS_OK;
}
// TODO: content changed notifications
// TODO: incremental reflow
// today, we just throw away the column frames and start over every time
// this is dumb, we should be able to maintain column frames and adjust incrementally
NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
@ -59,20 +64,35 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
{
NS_ASSERTION(nsnull!=mContent, "bad state -- null content for frame");
if (nsnull == mFirstChild)
{ // if we don't have any children, create them
// for every content child that (is a column thingy and does not already have a frame)
// create a frame and adjust it's style
nsIFrame* kidFrame = nsnull;
nsIFrame* prevKidFrame;
LastChild(prevKidFrame); // XXX remember this...
PRInt32 kidIndex = 0;
for (PRInt32 colIndex = 0; ;colIndex++) // colIndex is used to set the column frames' index field
PRInt32 kidIndex = 0; // index of the content child we are currently working on
PRInt32 colIndex = 0; // number of content children that are columns, normally same as kidIndex
for (;;)
{
// get the next content child, breaking if there is none
nsIContentPtr kid = mContent->ChildAt(kidIndex); // kid: REFCNT++
if (kid.IsNull()) {
break;
}
// verify that we're dealing with table content. If so, we know it's a column
nsITableContent *tableContentInterface = nsnull;
nsresult rv = kid->QueryInterface(kITableContentIID,
(void **)&tableContentInterface); // tableContentInterface: REFCNT++
if (NS_FAILED(rv))
{
kidIndex++;
continue;
}
NS_RELEASE(tableContentInterface); // tableContentInterface: REFCNT--
if (mChildCount<=colIndex)
{
// Resolve style
nsIStyleContextPtr kidSC =
aPresContext.ResolveStyleContextFor(kid, this, PR_TRUE);
@ -82,8 +102,7 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
// Create a child frame
nsIContentDelegate* kidDel = nsnull;
kidDel = kid->GetDelegate(&aPresContext);
nsresult rv = kidDel->CreateFrame(&aPresContext, kid, this, kidSC,
kidFrame);
rv = kidDel->CreateFrame(&aPresContext, kid, this, kidSC, kidFrame);
NS_RELEASE(kidDel);
// give the child frame a chance to reflow, even though we know it'll have 0 size
@ -107,10 +126,10 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
}
prevKidFrame = kidFrame;
mChildCount++;
kidIndex++;
SetStyleContextForFirstPass(&aPresContext, colIndex);
}
// now that I have all my COL children, adjust their style
SetStyleContextForFirstPass(&aPresContext);
colIndex++; // if this wasn't a column, we would not have gotten this far
kidIndex++;
}
aDesiredSize.width=0;
aDesiredSize.height=0;
@ -124,7 +143,8 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext& aPresContext,
}
// Subclass hook for style post processing
NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPresContext)
NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPresContext,
PRInt32 aColIndex)
{
// get the table frame
nsIFrame* tableFrame=nsnull;
@ -150,31 +170,31 @@ NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPre
PRInt32 colIndex=0;
nsIFrame *colFrame=nsnull;
nsIStyleContextPtr colStyleContext;
for (; colIndex<numCols; colIndex++)
ChildAt(aColIndex, colFrame);
if (nsnull!=colFrame)
{
ChildAt(colIndex, colFrame);
if (nsnull==colFrame)
break; // the attribute value specified was greater than the actual number of columns
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleContext(aPresContext, colStyleContext.AssignRef());
colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
nsStyleCoord width (1, eStyleUnit_Proportional);
colPosition->mWidth = width;
colStyleContext->RecalcAutomaticData(aPresContext);
}
// if there are more columns, there width is set to "minimum"
PRInt32 numChildFrames;
ChildCount(numChildFrames);
for (; colIndex<numChildFrames; colIndex++)
for (; aColIndex<numChildFrames-1; colIndex++)
{
ChildAt(colIndex, colFrame);
NS_ASSERTION(nsnull!=colFrame, "bad column frame");
if (nsnull==colFrame)
break;
nsStylePosition * colPosition=nsnull;
colFrame->GetStyleContext(aPresContext, colStyleContext.AssignRef());
colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
colPosition->mWidth.SetCoordValue(0);
colStyleContext->RecalcAutomaticData(aPresContext);
}
}
mStyleContext->RecalcAutomaticData(aPresContext);
}
@ -188,8 +208,7 @@ NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext* aPre
*/
int nsTableColGroupFrame::GetColumnCount ()
{
if (0 == mColCount)
{
mColCount=0;
int count;
ChildCount (count);
if (0 < count)
@ -211,7 +230,6 @@ int nsTableColGroupFrame::GetColumnCount ()
GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
mColCount = tableStyle->mSpan;
}
}
return mColCount;
}

Просмотреть файл

@ -70,7 +70,8 @@ protected:
* Since we need to know the full column structure before the COLS attribute
* can be interpreted, we can't just use DidSetStyleContext
*/
NS_METHOD SetStyleContextForFirstPass(nsIPresContext* aPresContext);
NS_METHOD SetStyleContextForFirstPass(nsIPresContext* aPresContext,
PRInt32 aColIndex);
PRInt32 mColCount;

Просмотреть файл

@ -574,9 +574,9 @@ void nsTableFrame::EnsureColumns(nsIPresContext* aPresContext,
// need to find the generic way to stamp out this content, and ::AppendChildTo it
// this might be ok. no matter what my mcontent is, I know it needs a colgroup as a kid?
lastColGroup = new nsTableColGroup (PR_TRUE);
// XXX: how do I know whether AppendChildTo should notify or not?
mContent->AppendChildTo(lastColGroup, PR_FALSE); // was AppendColGroup
lastColGroup = new nsTableColGroup (PR_TRUE); // create an implicit colgroup
// XXX: instead of Append, maybe this should be insertAt(0)?
mContent->AppendChildTo(lastColGroup, PR_FALSE); // add the implicit colgroup to my content
NS_ADDREF(lastColGroup); // ADDREF a: lastColGroup++
// Resolve style for the child
nsIStyleContext* colGroupStyleContext =
@ -619,6 +619,104 @@ void nsTableFrame::EnsureColumns(nsIPresContext* aPresContext,
{ //QQQ
// need to find the generic way to stamp out this content, and ::AppendChildTo it
nsTableCol *col = new nsTableCol(PR_TRUE);
NS_ADDREF(col);
lastColGroup->AppendChildTo (col, PR_FALSE);
}
NS_RELEASE(lastColGroup); // ADDREF: lastColGroup--
lastColGroupFrame->Reflow(*aPresContext, aDesiredSize, aReflowState, aStatus);
}
}
/** 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.
*/
void nsTableFrame::EnsureColumnFrameAt(PRInt32 aColIndex,
nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus)
{
if (nsnull!=mCellMap)
return; // we already have a cell map so this makes no sense
PRInt32 actualColumns = 0;
nsTableColGroupFrame *lastColGroupFrame = nsnull;
nsIFrame * firstRowGroupFrame=nsnull;
nsIFrame * prevSibFrame=nsnull;
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)
break; // we gave enough col frames at this point
}
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay ||
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay ||
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay )
{
firstRowGroupFrame = childFrame;
break;
}
prevSibFrame = childFrame;
childFrame->GetNextSibling(childFrame);
}
if (actualColumns <= aColIndex)
{
nsTableColGroup *lastColGroup=nsnull;
if (nsnull==lastColGroupFrame)
{
lastColGroup = new nsTableColGroup (PR_TRUE); // create an implicit colgroup
mContent->AppendChildTo(lastColGroup, PR_FALSE); // add the implicit colgroup to my content
NS_ADDREF(lastColGroup); // ADDREF a: lastColGroup++
// Resolve style for the child
nsIStyleContext* colGroupStyleContext =
aPresContext->ResolveStyleContextFor(lastColGroup, this, PR_TRUE); // kidStyleContext: REFCNT++
nsIContentDelegate* kidDel = nsnull;
kidDel = lastColGroup->GetDelegate(aPresContext); // kidDel: REFCNT++
nsresult rv = kidDel->CreateFrame(aPresContext, lastColGroup, this,
colGroupStyleContext, (nsIFrame *&)lastColGroupFrame);
NS_RELEASE(kidDel); // kidDel: REFCNT--
NS_RELEASE(colGroupStyleContext); // kidStyleContenxt: REFCNT--
// hook lastColGroupFrame into child list
if (nsnull==firstRowGroupFrame)
{ // make lastColGroupFrame the last frame
nsIFrame *lastChild=nsnull;
LastChild(lastChild);
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);
}
mChildCount++;
}
else
{
lastColGroupFrame->GetContent((nsIContent *&)lastColGroup); // ADDREF b: lastColGroup++
}
PRInt32 excessColumns = aColIndex - actualColumns;
for ( ; excessColumns >= 0; excessColumns--)
{
nsTableCol *col = new nsTableCol(PR_TRUE);
NS_ADDREF(col);
lastColGroup->AppendChildTo(col, PR_FALSE);
}
NS_RELEASE(lastColGroup); // ADDREF: lastColGroup--
@ -1442,6 +1540,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
nscoord bottomInset = borderPadding.bottom;
nscoord leftInset = borderPadding.left;
nsReflowReason reflowReason = aReflowState.reason;
nsIContent * prevKid; // do NOT hold a reference for this temp pointer!
/* assumes that Table's children are in the following order:
* Captions
@ -1457,6 +1556,14 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext,
break;
}
if (kid==prevKid)
{ // we just saw this kid, but in it's processing someone inserted something in front of it
// (probably a colgroup). So don't process it twice.
kidIndex++;
continue;
}
prevKid = kid;
mLastContentIsComplete = PR_TRUE;
// Resolve style

Просмотреть файл

@ -201,6 +201,15 @@ public:
*/
PRInt32 GetEffectiveCOLSAttribute();
/** verify that there are at least aColIndex column frames created.
* if not, create the needed col frames
*/
virtual void EnsureColumnFrameAt(PRInt32 aColIndex,
nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus);
protected:
/** protected constructor.

Просмотреть файл

@ -20,10 +20,12 @@
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
#include "nsIHTMLAttributes.h"
#include "nsHTMLAtoms.h"
#include "nsIContent.h"
#include "nsIContentDelegate.h"
#include "nsHTMLTagContent.h"
#include "nsTableFrame.h"
#include "nsTableColFrame.h"
#include "nsTableCellFrame.h"
#include "nsIView.h"
#include "nsIPtr.h"
@ -500,6 +502,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
// Place our children, one at a time, until we are out of children
nsSize kidMaxElementSize;
PRInt32 kidIndex = 0;
PRInt32 colIndex = -1;
nsIFrame* prevKidFrame = nsnull;
nscoord maxTopMargin = 0;
nscoord maxBottomMargin = 0;
@ -513,6 +516,21 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
break; // no more content
}
// what column does this cell span to?
nsHTMLValue value;
((nsHTMLTagContent *)cell)->GetAttribute(nsHTMLAtoms::align, value);
if (value.GetUnit() == eHTMLUnit_Integer)
colIndex += value.GetIntValue();
else
colIndex += 1;
// create column frames if necessary
nsReflowStatus status;
aState.tableFrame->EnsureColumnFrameAt(colIndex,
&aPresContext,
aDesiredSize,
aState.reflowState,
status);
// Create a child frame -- always an nsTableCell frame
nsIStyleContext* kidSC = aPresContext.ResolveStyleContextFor(cell, this, PR_TRUE);
nsIContentDelegate* kidDel = cell->GetDelegate(&aPresContext);
@ -569,8 +587,6 @@ nsTableRowFrame::InitialReflow(nsIPresContext& aPresContext,
nsReflowMetrics kidSize(&kidMaxElementSize);
nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize,
eReflowReason_Initial);
nsReflowStatus status;
kidFrame->WillReflow(aPresContext);
if (gsDebug) printf ("%p InitR: avail=%d\n", this, kidAvailSize.width);
status = ReflowChild(kidFrame, &aPresContext, kidSize, kidReflowState);