fune/layout/tables/nsTableColGroupFrame.cpp
rods%netscape.com 99666eed8c This checkin enables mozilla to support the printing of selection, the printing of page ranges, and
the printing of headers and footers.
Printing of selection is implemented by the frames figuring out if they are in the selection and painting
if they or not they they don't paint. This also only allows the printing of the first page of
selections, alothough it is well documented where this is implemeted so it can be removed.
Bugs 63426, 31218, 61075 r=dcone,kmcclusk,erik,buster sr=waterson
2001-01-27 14:09:34 +00:00

793 lines
27 KiB
C++

/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
#include "nsTableFrame.h"
#include "nsIHTMLTableColElement.h"
#include "nsIDOMHTMLTableColElement.h"
#include "nsIReflowCommand.h"
#include "nsIStyleContext.h"
#include "nsStyleConsts.h"
#include "nsIPresContext.h"
#include "nsIHTMLContent.h"
#include "nsHTMLParts.h"
#include "nsHTMLAtoms.h"
#include "nsHTMLIIDs.h"
#include "nsCOMPtr.h"
#include "nsCSSRendering.h"
#include "nsIPresShell.h"
#include "nsLayoutAtoms.h"
#define COLGROUP_TYPE_CONTENT 0x0
#define COLGROUP_TYPE_ANONYMOUS_COL 0x1
#define COLGROUP_TYPE_ANONYMOUS_CELL 0x2
nsTableColGroupType nsTableColGroupFrame::GetType() const {
switch(mBits.mType) {
case COLGROUP_TYPE_ANONYMOUS_COL:
return eColGroupAnonymousCol;
case COLGROUP_TYPE_ANONYMOUS_CELL:
return eColGroupAnonymousCell;
default:
return eColGroupContent;
}
}
void nsTableColGroupFrame::SetType(nsTableColGroupType aType) {
mBits.mType = aType - eColGroupContent;
}
void nsTableColGroupFrame::ResetColIndices(nsIPresContext* aPresContext,
nsIFrame* aFirstColGroup,
PRInt32 aFirstColIndex,
nsIFrame* aStartColFrame)
{
nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)aFirstColGroup;
PRInt32 colIndex = aFirstColIndex;
while (colGroupFrame) {
nsCOMPtr<nsIAtom> cgType;
colGroupFrame->GetFrameType(getter_AddRefs(cgType));
if (nsLayoutAtoms::tableColGroupFrame == cgType.get()) {
// reset the starting col index for the first cg only if
// aFirstColIndex is smaller than the existing starting col index
if ((colIndex != aFirstColIndex) ||
(colIndex < colGroupFrame->GetStartColumnIndex())) {
colGroupFrame->SetStartColumnIndex(colIndex);
}
nsIFrame* colFrame = aStartColFrame;
if (!colFrame || (colIndex != aFirstColIndex)) {
colGroupFrame->FirstChild(aPresContext, nsnull, &colFrame);
}
while (colFrame) {
nsCOMPtr<nsIAtom> colType;
colFrame->GetFrameType(getter_AddRefs(colType));
if (nsLayoutAtoms::tableColFrame == colType.get()) {
((nsTableColFrame*)colFrame)->SetColIndex(colIndex);
colIndex++;
}
colFrame->GetNextSibling(&colFrame);
}
}
colGroupFrame->GetNextSibling((nsIFrame**)&colGroupFrame);
}
}
NS_IMETHODIMP
nsTableColGroupFrame::AddColsToTable(nsIPresContext& aPresContext,
PRInt32 aFirstColIndex,
PRBool aResetSubsequentColIndices,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame)
{
nsresult rv = NS_OK;
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (!(NS_SUCCEEDED(rv) && tableFrame && aFirstFrame)) {
return rv;
}
// set the col indices of the col frames and and add col info to the table
PRInt32 colIndex = aFirstColIndex;
nsIFrame* kidFrame = aFirstFrame;
PRBool foundLastFrame = PR_FALSE;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
((nsTableColFrame*)kidFrame)->SetColIndex(colIndex);
if (!foundLastFrame) {
mColCount++;
tableFrame->InsertCol(aPresContext, (nsTableColFrame &)*kidFrame, colIndex);
}
colIndex++;
}
NS_IF_RELEASE(kidType);
if (kidFrame == aLastFrame) {
foundLastFrame = PR_TRUE;
}
kidFrame->GetNextSibling(&kidFrame);
}
if (aResetSubsequentColIndices) {
nsIFrame* nextSibling;
GetNextSibling(&nextSibling);
if (nextSibling) {
ResetColIndices(&aPresContext, nextSibling, colIndex);
}
}
return rv;
}
// this is called when a col frame doesn't have an explicit col group parent.
nsTableColGroupFrame*
nsTableColGroupFrame::FindParentForAppendedCol(nsTableFrame* aTableFrame,
nsTableColType aColType)
{
nsVoidArray& cols = aTableFrame->GetColCache();
PRInt32 numCols = cols.Count();
nsIFrame* lastColGroup;
nsIFrame* lastCol = (nsIFrame*)cols.ElementAt(numCols - 1);
if (!lastCol) return nsnull; // no columns so no colgroups
lastCol->GetParent(&lastColGroup);
if (!lastColGroup) return nsnull; // shouldn't happen
nsTableColGroupFrame* relevantColGroup = (nsTableColGroupFrame *)lastColGroup;
nsTableColGroupType relevantColGroupType = relevantColGroup->GetType();
if (eColGroupAnonymousCell == relevantColGroupType) {
if (eColAnonymousCell == aColType) {
return relevantColGroup;
}
else {
// find the next to last col group
for (PRInt32 colX = numCols - 2; colX >= 0; colX--) {
nsTableColFrame* colFrame = (nsTableColFrame*)cols.ElementAt(colX);
nsTableColGroupFrame* colGroupFrame;
colFrame->GetParent((nsIFrame**)&colGroupFrame);
nsTableColGroupType cgType = colGroupFrame->GetType();
if (cgType != relevantColGroupType) {
relevantColGroup = colGroupFrame;
relevantColGroupType = cgType;
break;
}
else if (0 == colX) {
return nsnull;
}
}
}
}
if (eColGroupAnonymousCol == relevantColGroupType) {
if ((eColContent == aColType) || (eColAnonymousCol == aColType)) {
return relevantColGroup;
}
}
return nsnull;
}
PRBool
nsTableColGroupFrame::GetLastRealColGroup(nsTableFrame* aTableFrame,
nsIFrame** aLastColGroup)
{
*aLastColGroup = nsnull;
nsFrameList colGroups = aTableFrame->GetColGroups();
nsIFrame* nextToLastColGroup = nsnull;
nsIFrame* lastColGroup = colGroups.FirstChild();
while(lastColGroup) {
nsIFrame* next;
lastColGroup->GetNextSibling(&next);
if (next) {
nextToLastColGroup = lastColGroup;
lastColGroup = next;
}
else {
break;
}
}
if (!lastColGroup) return PR_TRUE; // there are no col group frames
nsTableColGroupType lastColGroupType = ((nsTableColGroupFrame *)lastColGroup)->GetType();
if (eColGroupAnonymousCell == lastColGroupType) {
*aLastColGroup = nextToLastColGroup;
return PR_FALSE;
}
else {
*aLastColGroup = lastColGroup;
return PR_TRUE;
}
}
// don't set mColCount here, it is done in AddColsToTable
NS_IMETHODIMP
nsTableColGroupFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
if (!aChildList) {
nsIFrame* firstChild;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, GetSpan(), eColAnonymousColGroup,
PR_FALSE, nsnull, &firstChild);
if (firstChild) {
SetInitialChildList(aPresContext, aListName, firstChild);
}
return NS_OK;
}
nsIFrame* kidFrame = aChildList;
while (kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
// Set the preliminary values for the column frame
PRInt32 span = ((nsTableColFrame*)kidFrame)->GetSpan();
if (span > 1) {
nsTableColFrame* firstSpannedCol;
tableFrame->CreateAnonymousColFrames(*aPresContext, *this, span - 1, eColAnonymousCol,
PR_FALSE, (nsTableColFrame*)kidFrame, (nsIFrame **)&firstSpannedCol);
nsIFrame* spanner = kidFrame;
kidFrame->GetNextSibling(&kidFrame); // need to do this before we insert the new frames
nsFrameList newChildren(aChildList); // used as a convience to hook up siblings
newChildren.InsertFrames(this, (nsTableColFrame*)spanner, (nsIFrame *)firstSpannedCol);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
mFrames.AppendFrames(this, aChildList);
return NS_OK;
}
// Helper function. It marks the table frame as dirty and generates
// a reflow command
nsresult
nsTableColGroupFrame::AddTableDirtyReflowCommand(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIFrame* aTableFrame)
{
nsFrameState frameState;
nsIFrame* tableParentFrame;
nsIReflowCommand* reflowCmd;
nsresult rv;
// Mark the table frame as dirty
aTableFrame->GetFrameState(&frameState);
frameState |= NS_FRAME_IS_DIRTY;
aTableFrame->SetFrameState(frameState);
// Target the reflow comamnd at its parent frame
aTableFrame->GetParent(&tableParentFrame);
rv = NS_NewHTMLReflowCommand(&reflowCmd, tableParentFrame,
nsIReflowCommand::ReflowDirty);
if (NS_SUCCEEDED(rv)) {
// Add the reflow command
rv = aPresShell.AppendReflowCommand(reflowCmd);
NS_RELEASE(reflowCmd);
}
return rv;
}
NS_IMETHODIMP
nsTableColGroupFrame::AppendFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList)
{
mFrames.AppendFrames(this, aFrameList);
InsertColsReflow(*aPresContext, aPresShell, mColCount, aFrameList);
return NS_OK;
}
NS_IMETHODIMP
nsTableColGroupFrame::InsertFrames(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrameIn,
nsIFrame* aFrameList)
{
nsFrameList frames(aFrameList); // convience for getting last frame
nsIFrame* lastFrame = frames.LastChild();
mFrames.InsertFrames(this, aPrevFrameIn, aFrameList);
nsIFrame* prevFrame = nsTableFrame::GetFrameAtOrBefore(aPresContext, this, aPrevFrameIn,
nsLayoutAtoms::tableColFrame);
PRInt32 colIndex = (prevFrame) ? ((nsTableColFrame*)prevFrame)->GetColIndex() + 1 : 0;
InsertColsReflow(*aPresContext, aPresShell, colIndex, aFrameList, lastFrame);
return NS_OK;
}
void
nsTableColGroupFrame::InsertColsReflow(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
PRInt32 aColIndex,
nsIFrame* aFirstFrame,
nsIFrame* aLastFrame)
{
AddColsToTable(aPresContext, aColIndex, PR_TRUE, aFirstFrame, aLastFrame);
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(&aPresContext, aPresShell, tableFrame);
}
void
nsTableColGroupFrame::RemoveChild(nsIPresContext& aPresContext,
nsTableColFrame& aChild,
PRBool aResetColIndices)
{
PRInt32 colIndex = 0;
nsIFrame* nextChild = nsnull;
if (aResetColIndices) {
colIndex = aChild.GetColIndex();
aChild.GetNextSibling(&nextChild);
}
if (mFrames.DestroyFrame(&aPresContext, (nsIFrame*)&aChild)) {
mColCount--;
if (aResetColIndices) {
ResetColIndices(&aPresContext, this, colIndex, nextChild);
}
}
}
// this removes children form the last col group (eColGroupAnonymousCell) in the
// table only,so there is no need to reset col indices for subsequent col groups.
void
nsTableColGroupFrame::RemoveChildrenAtEnd(nsIPresContext& aPresContext,
PRInt32 aNumChildrenToRemove)
{
PRInt32 numToRemove = aNumChildrenToRemove;
if (numToRemove > mColCount) {
NS_ASSERTION(PR_FALSE, "invalid arg to RemoveChildrenAtEnd");
numToRemove = mColCount;
}
PRInt32 offsetOfFirstRemoval = mColCount - numToRemove;
PRInt32 offsetX = 0;
nsIFrame* kidFrame = mFrames.FirstChild();
while(kidFrame) {
nsIAtom* kidType;
kidFrame->GetFrameType(&kidType);
if (nsLayoutAtoms::tableColFrame == kidType) {
offsetX++;
if (offsetX > offsetOfFirstRemoval) {
nsIFrame* byebye = kidFrame;
kidFrame->GetNextSibling(&kidFrame);
mFrames.DestroyFrame(&aPresContext, byebye);
NS_RELEASE(kidType);
continue;
}
}
NS_IF_RELEASE(kidType);
kidFrame->GetNextSibling(&kidFrame);
}
}
NS_IMETHODIMP
nsTableColGroupFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
if (!aOldFrame) return NS_OK;
nsIAtom* frameType = nsnull;
aOldFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableColFrame == frameType) {
nsTableColFrame* colFrame = (nsTableColFrame*)aOldFrame;
PRInt32 colIndex = colFrame->GetColIndex();
RemoveChild(*aPresContext, *colFrame, PR_TRUE);
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
if (tableFrame) {
tableFrame->RemoveCol(*aPresContext, this, colIndex, PR_TRUE, PR_TRUE);
}
tableFrame->InvalidateColumnWidths();
// Generate a reflow command so we reflow the table
AddTableDirtyReflowCommand(aPresContext, aPresShell, tableFrame);
}
else {
mFrames.DestroyFrame(aPresContext, aOldFrame);
}
NS_IF_RELEASE(frameType);
return NS_OK;
}
NS_METHOD nsTableColGroupFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) {
return NS_OK;
}
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
nsCompatibility mode;
aPresContext->GetCompatibilityMode(&mode);
if (eCompatibility_Standard == mode) {
const nsStyleDisplay* disp =
(const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
if (disp->IsVisibleOrCollapsed()) {
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
const nsStyleColor* color =
(const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *color, *spacing, 0, 0);
}
}
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
return NS_OK;
}
PRIntn
nsTableColGroupFrame::GetSkipSides() const
{
PRIntn skip = 0;
if (nsnull != mPrevInFlow) {
skip |= 1 << NS_SIDE_TOP;
}
if (nsnull != mNextInFlow) {
skip |= 1 << NS_SIDE_BOTTOM;
}
return skip;
}
NS_IMETHODIMP
nsTableColGroupFrame::GetFrameForPoint(nsIPresContext* aPresContext,
const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer,
nsIFrame** aFrame)
{
// this should act like a block, so we need to override
return GetFrameForPointUsing(aPresContext, aPoint, nsnull, aWhichLayer, (aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND), aFrame);
}
NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
DO_GLOBAL_REFLOW_COUNT("nsTableColGroupFrame", aReflowState.reason);
NS_ASSERTION(nsnull!=mContent, "bad state -- null content for frame");
nsresult rv=NS_OK;
// 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;
if (eReflowReason_Incremental == aReflowState.reason) {
rv = IncrementalReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
for (kidFrame = mFrames.FirstChild(); nsnull != kidFrame;
kidFrame->GetNextSibling(&kidFrame)) {
// Give the child frame a chance to reflow, even though we know it'll have 0 size
nsHTMLReflowMetrics kidSize(nsnull);
// XXX Use a valid reason...
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
nsSize(0,0), eReflowReason_Initial);
nsReflowStatus status;
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status);
FinishReflowChild(kidFrame, aPresContext, kidSize, 0, 0, 0);
}
aDesiredSize.width=0;
aDesiredSize.height=0;
aDesiredSize.ascent=aDesiredSize.height;
aDesiredSize.descent=0;
if (nsnull!=aDesiredSize.maxElementSize)
{
aDesiredSize.maxElementSize->width=0;
aDesiredSize.maxElementSize->height=0;
}
aStatus = NS_FRAME_COMPLETE;
return rv;
}
NS_METHOD nsTableColGroupFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
// 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))
{
if (this==target)
rv = IR_TargetIsMe(aPresContext, aDesiredSize, aReflowState, aStatus);
else
{
// Get the next frame in the reflow chain
nsIFrame* nextFrame;
aReflowState.reflowCommand->GetNext(nextFrame);
rv = IR_TargetIsChild(aPresContext, aDesiredSize, aReflowState, aStatus, nextFrame);
}
}
return rv;
}
NS_METHOD nsTableColGroupFrame::IR_TargetIsMe(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
aStatus = NS_FRAME_COMPLETE;
nsIReflowCommand::ReflowType type;
aReflowState.reflowCommand->GetType(type);
nsIFrame *objectFrame;
aReflowState.reflowCommand->GetChildFrame(objectFrame);
const nsStyleDisplay *childDisplay=nsnull;
if (nsnull!=objectFrame)
objectFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
switch (type)
{
case nsIReflowCommand::StyleChanged :
rv = IR_StyleChanged(aPresContext, aDesiredSize, aReflowState, aStatus);
break;
case nsIReflowCommand::ContentChanged :
NS_ASSERTION(PR_FALSE, "illegal reflow type: ContentChanged");
rv = NS_ERROR_ILLEGAL_VALUE;
break;
default:
NS_NOTYETIMPLEMENTED("unexpected reflow command type");
rv = NS_ERROR_NOT_IMPLEMENTED;
break;
}
return rv;
}
NS_METHOD nsTableColGroupFrame::IR_StyleChanged(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
// we presume that all the easy optimizations were done in the nsHTMLStyleSheet before we were called here
// XXX: we can optimize this when we know which style attribute changed
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && tableFrame) {
tableFrame->InvalidateColumnWidths();
tableFrame->InvalidateFirstPassCache();
}
return rv;
}
NS_METHOD nsTableColGroupFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus,
nsIFrame * aNextFrame)
{
nsresult rv;
// Pass along the reflow command
nsHTMLReflowMetrics desiredSize(nsnull);
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aNextFrame,
nsSize(aReflowState.availableWidth,
aReflowState.availableHeight));
rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, aStatus);
aNextFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
if (NS_FAILED(rv))
return rv;
nsTableFrame *tableFrame=nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame)) {
// compare the new col count to the old col count.
// If they are the same, we just need to rebalance column widths
// If they differ, we need to fix up other column groups and the column cache
tableFrame->InvalidateColumnWidths();
}
return rv;
}
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
{
return GetNextColumn(nsnull);
}
nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
{
nsTableColFrame *result = nsnull;
nsIFrame *childFrame = aChildFrame;
if (nsnull==childFrame)
childFrame = mFrames.FirstChild();
while (nsnull!=childFrame)
{
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay)
{
result = (nsTableColFrame *)childFrame;
break;
}
childFrame->GetNextSibling(&childFrame);
}
return result;
}
nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex)
{
nsTableColFrame *result = nsnull;
PRInt32 count = 0;
nsIFrame *childFrame = mFrames.FirstChild();
while (nsnull!=childFrame) {
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay) {
nsTableColFrame *col = (nsTableColFrame *)childFrame;
count++;
if (aColIndex<=count) {
result = col;
}
}
childFrame->GetNextSibling(&childFrame);
}
return result;
}
PRInt32 nsTableColGroupFrame::GetSpan()
{
PRInt32 span = 1;
nsCOMPtr<nsIContent> iContent;
nsresult rv = GetContent(getter_AddRefs(iContent));
if (NS_FAILED(rv) || !iContent) return rv;
// col group element derives from col element
nsIDOMHTMLTableColElement* cgContent = nsnull;
rv = iContent->QueryInterface(NS_GET_IID(nsIDOMHTMLTableColElement),
(void **)&cgContent);
if (cgContent && NS_SUCCEEDED(rv)) {
cgContent->GetSpan(&span);
// XXX why does this work!!
if (span == -1) {
span = 1;
}
NS_RELEASE(cgContent);
}
return span;
}
/** returns colcount because it is frequently used in the context of
* shuffling relative colgroup order, and it's convenient to not have to
* call GetColumnCount redundantly.
*/
PRInt32 nsTableColGroupFrame::SetStartColumnIndex (int aIndex)
{
PRInt32 result = mColCount;
if (aIndex != mStartColIndex) {
mStartColIndex = aIndex;
result = GetColCount();
}
return result;
}
// this could be optimized by using col group frame starting indicies,
// but typically there aren't enough very large col groups for the added complexity.
nsTableColGroupFrame*
nsTableColGroupFrame::GetColGroupFrameContaining(nsIPresContext* aPresContext,
nsFrameList& aColGroupList,
nsTableColFrame& aColFrame)
{
nsIFrame* childFrame = aColGroupList.FirstChild();
while (childFrame) {
nsIAtom* frameType = nsnull;
childFrame->GetFrameType(&frameType);
if (nsLayoutAtoms::tableColGroupFrame == frameType) {
nsTableColFrame* colFrame = nsnull;
childFrame->FirstChild(aPresContext, nsnull, (nsIFrame **)&colFrame);
while (colFrame) {
if (colFrame == &aColFrame) {
NS_RELEASE(frameType);
return (nsTableColGroupFrame *)childFrame;
}
colFrame->GetNextSibling((nsIFrame **)&colFrame);
}
}
NS_IF_RELEASE(frameType);
childFrame->GetNextSibling(&childFrame);
}
return nsnull;
}
void nsTableColGroupFrame::DeleteColFrame(nsIPresContext* aPresContext, nsTableColFrame* aColFrame)
{
mFrames.DestroyFrame(aPresContext, aColFrame);
}
/* ----- global methods ----- */
nsresult
NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsTableColGroupFrame* it = new (aPresShell) nsTableColGroupFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aNewFrame = it;
return NS_OK;
}
NS_IMETHODIMP
nsTableColGroupFrame::GetFrameType(nsIAtom** aType) const
{
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::tableColGroupFrame;
NS_ADDREF(*aType);
return NS_OK;
}
#ifdef DEBUG
NS_IMETHODIMP
nsTableColGroupFrame::GetFrameName(nsString& aResult) const
{
return MakeFrameName("TableColGroup", aResult);
}
NS_IMETHODIMP
nsTableColGroupFrame::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const
{
if (!aResult) {
return NS_ERROR_NULL_POINTER;
}
PRUint32 sum = sizeof(*this);
*aResult = sum;
return NS_OK;
}
#endif