gecko-dev/layout/tables/nsTableFrame.h
1998-04-14 21:45:28 +00:00

446 lines
20 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.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.
*/
#ifndef nsTableFrame_h__
#define nsTableFrame_h__
#include "nscore.h"
#include "nsContainerFrame.h"
class nsCellLayoutData;
class nsTableCell;
class nsVoidArray;
class nsTableCellFrame;
class CellData;
struct nsStyleMolecule;
struct InnerTableReflowState;
/** nsTableFrame maps the inner portion of a table (everything except captions.)
* Used as a pseudo-frame within nsTableOuterFrame,
* it may also be used stand-alone as the top-level frame.
* The meaningful child frames of nsTableFrame map rowgroups.
*
* @author sclark
*
* TODO: make methods virtual so nsTableFrame can be used as a base class in the future.
*/
class nsTableFrame : public nsContainerFrame
{
public:
/** nsTableOuterFrame has intimate knowledge of the inner table frame */
friend class nsTableOuterFrame;
/** instantiate a new instance of nsTableFrame.
* @param aInstancePtrResult the new object is returned in this out-param
* @param aContent the table object to map
* @param aIndexInParent which child is the new frame?
* @param aParent the parent of the new frame
*
* @return NS_OK if the frame was properly allocated, otherwise an error code
*/
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
PRInt32 aIndexInParent,
nsIFrame* aParent);
/** @see nsIFrame::Paint */
virtual void Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
/** inner tables are reflowed in two steps.
* <pre>
* 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
* use column widths to ResizeReflow cells
* shrinkWrap Cells in each row to tallest, realigning contents within the cell
* </pre>
*
* @see ResizeReflowPass1
* @see ResizeReflowPass2
* @see BalanceColumnWidths
* @see nsIFrame::ResizeReflow
*/
virtual ReflowStatus ResizeReflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsSize* aMaxElementSize);
/** @see nsIFrame::IncrementalReflow */
virtual ReflowStatus IncrementalReflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsReflowCommand& aReflowCommand);
/** @see nsContainerFrame::CreateContinuingFrame */
virtual nsIFrame* CreateContinuingFrame(nsIPresContext* aPresContext,
nsIFrame* aParent);
/** resize myself and my children according to the arcane rules of cell height magic.
* By default, the height of a cell is the max (height of cells in its row)
* In the case of a cell with rowspan>1 (lets call this C),
* if the sum of the height of the rows spanned (excluding C in the calculation)
* is greater than or equal to the height of C,
* the cells in the rows are sized normally and
* the height of C is set to the sum of the heights (taking into account borders, padding, and margins)
* else
* the height of each row is expanded by a percentage of the difference between
* the row's desired height and the height of C
*/
virtual void ShrinkWrapChildren(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
nsSize* aMaxElementSize);
/** return the column layout data for this inner table frame.
* if this is a continuing frame, return the first-in-flow's column layout data.
*/
virtual nsVoidArray *GetColumnLayoutData();
/** Associate aData with the cell at (aRow,aCol)
* @return PR_TRUE if the data was successfully associated with a Cell
* PR_FALSE if there was an error, such as aRow or aCol being invalid
*/
virtual PRBool SetCellLayoutData(nsCellLayoutData * aData, nsTableCell *aCell);
/** Get the layout data associated with the cell at (aRow,aCol)
* @return PR_NULL if there was an error, such as aRow or aCol being invalid
* otherwise, the data is returned.
*/
virtual nsCellLayoutData * GetCellLayoutData(nsTableCell *aCell);
/** returns PR_TRUE if this table has proportional width
*/
PRBool IsProportionalWidth(nsStyleMolecule* aMol);
/**
* DEBUG METHOD
*
*/
void ListColumnLayoutData(FILE* out = stdout, PRInt32 aIndent = 0) const;
/** return the width of the column at aColIndex */
PRInt32 GetColumnWidth(PRInt32 aColIndex);
/** set the width of the column at aColIndex to aWidth */
void SetColumnWidth(PRInt32 aColIndex, PRInt32 aWidth);
/**
* Calculate Layout Information
*
*/
nsCellLayoutData* FindCellLayoutData(nsTableCell* aCell);
void AppendLayoutData(nsVoidArray* aList, nsTableCell* aTableCell);
void ResetColumnLayoutData();
void ResetCellLayoutData( nsTableCell* aCell,
nsTableCell* aAbove,
nsTableCell* aBelow,
nsTableCell* aLeft,
nsTableCell* aRight);
protected:
/** protected constructor.
* @see NewFrame
*/
nsTableFrame(nsIContent* aContent,
PRInt32 aIndexInParent,
nsIFrame* aParentFrame);
/** destructor, responsible for mColumnLayoutData and mColumnWidths */
virtual ~nsTableFrame();
/** helper method to delete contents of mColumnLayoutData
* should be called with care (ie, only by destructor)
*/
virtual void DeleteColumnLayoutData();
/** first pass of ResizeReflow.
* lays out all table content with aMaxSize(NS_UNCONSTRAINEDSIZE,NS_UNCONSTRAINEDSIZE) and
* a non-null aMaxElementSize so we get all the metrics we need to do column balancing.
* Pass 1 only needs to be executed once no matter how many times the table is resized,
* as long as content and style don't change. This is managed in the member variable mFirstPassIsValid.
* The layout information for each cell is cached in mColumLayoutData.
*
* @see ResizeReflow
*/
virtual nsIFrame::ReflowStatus ResizeReflowPass1(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
nsStyleMolecule* aTableStyle);
/** second pass of ResizeReflow.
* lays out all table content with aMaxSize(computed_table_width, given_table_height)
* Pass 2 is executed every time the table needs to resize. An optimization is included
* so that if the table doesn't need to actually be resized, no work is done (see NeedsReflow).
*
* @param aMinCaptionWidth - the max of all the minimum caption widths. 0 if no captions.
* @param aMaxCaptionWidth - the max of all the desired caption widths. 0 if no captions.
*
* @see ResizeReflow
* @see NeedsReflow
*/
virtual nsIFrame::ReflowStatus ResizeReflowPass2(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
nsStyleMolecule* aTableStyle,
PRInt32 aMinCaptionWidth,
PRInt32 mMaxCaptionWidth);
nscoord GetTopMarginFor(nsIPresContext* aCX,
InnerTableReflowState& aState,
nsStyleMolecule* aKidMol);
void PlaceChild(nsIPresContext* aPresContext,
InnerTableReflowState& aState,
nsIFrame* aKidFrame,
const nsRect& aKidRect,
nsStyleMolecule* aKidMol,
nsSize* aMaxElementSize,
nsSize& aKidMaxElementSize);
/**
* 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
*/
PRBool ReflowMappedChildren(nsIPresContext* aPresContext,
InnerTableReflowState& aState,
nsSize* aMaxElementSize);
/**
* 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
*/
PRBool PullUpChildren(nsIPresContext* aPresContext,
InnerTableReflowState& aState,
nsSize* aMaxElementSize);
/**
* Create new frames for content we haven't yet mapped
*
* @param aPresContext presentation context to use
* @param aState current inline state
* @return frComplete if all content has been mapped and frNotComplete
* if we should be continued
*/
ReflowStatus ReflowUnmappedChildren(nsIPresContext* aPresContext,
InnerTableReflowState& aState,
nsSize* aMaxElementSize);
/** assign widths for each column, taking into account the table content, the effective style,
* the layout constraints, and the compatibility mode. Sets mColumnWidths as a side effect.
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aMaxSize the height and width constraints
* @param aMaxElementSize the min size of the largest indivisible object
*/
virtual void BalanceColumnWidths(nsIPresContext* aPresContext,
nsStyleMolecule* aTableStyle,
const nsSize& aMaxSize,
nsSize* aMaxElementSize);
/** assign widths for each column that has fixed width.
* Computes the minimum and maximum table widths.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aMaxWidth the maximum width of the table
* @param aNumCols the total number of columns in the table
* @param aTableStyle the resolved style for the table
* @param aTotalFixedWidth out param, the sum of the fixed width columns
* @param aMinTableWidth out param, the min possible table width
* @param aMaxTableWidth out param, the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: should be renamed to "AssignKnownWidthInformation
*/
virtual PRBool AssignFixedColumnWidths(nsIPresContext* aPresContext,
PRInt32 aMaxWidth,
PRInt32 aNumCols,
nsStyleMolecule* aTableStyleMol,
PRInt32 & aTotalFixedWidth,
PRInt32 & aMinTableWidth,
PRInt32 & aMaxTableWidth);
/** assign widths for each column that has proportional width inside a table that
* has a fixed width.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aMinTableWidth the min possible table width
* @param aMaxTableWidth the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: rename this method to reflect that it is a Nav4 compatibility method
*/
virtual PRBool BalanceProportionalColumnsForSpecifiedWidthTable(nsIPresContext* aPresContext,
nsStyleMolecule* aTableStyleMol,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth);
/** assign widths for each column that has proportional width inside a table that
* has auto width (width set by the content and available space.)
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aMinTableWidth the min possible table width
* @param aMaxTableWidth the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: rename this method to reflect that it is a Nav4 compatibility method
*/
virtual PRBool BalanceProportionalColumnsForAutoWidthTable(nsIPresContext* aPresContext,
nsStyleMolecule* aTableStyleMol,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth);
/** assign the minimum allowed width for each column that has proportional width.
* Typically called when the min table width doesn't fit in the available space.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool SetColumnsToMinWidth(nsIPresContext* aPresContext);
/** assign the maximum allowed width for each column that has proportional width.
* Typically called when the desired max table width fits in the available space.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*/
virtual PRBool BalanceColumnsTableFits(nsIPresContext* aPresContext,
nsStyleMolecule* aTableStyleMol,
PRInt32 aAvailWidth);
/** assign widths for each column that has proportional width inside a table that
* has auto width (width set by the content and available space) according to the
* HTML 4 specification.
* Sets mColumnWidths as a side effect.
*
* @param aPresContext the presentation context
* @param aTableStyle the resolved style for the table
* @param aAvailWidth the remaining amount of horizontal space available
* @param aMaxWidth the total amount of horizontal space available
* @param aMinTableWidth the min possible table width
* @param aMaxTableWidth the max table width
*
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
* TODO: rename this method to reflect that it is a Nav4 compatibility method
*/
virtual PRBool BalanceColumnsHTML4Constrained(nsIPresContext* aPresContext,
nsStyleMolecule* aTableStyleMol,
PRInt32 aAvailWidth,
PRInt32 aMaxWidth,
PRInt32 aMinTableWidth,
PRInt32 aMaxTableWidth);
/** sets the width of the table according to the computed widths of each column. */
virtual void SetTableWidth(nsIPresContext* aPresContext,
nsStyleMolecule* aTableStyle);
/**
*/
virtual void VerticallyAlignChildren(nsIPresContext* aPresContext,
nscoord* aAscents,
nscoord aMaxAscent,
nscoord aMaxHeight);
/** support routine returns PR_TRUE if the table should be sized "automatically"
* according to its content.
* In NAV4, this is the default (no WIDTH, no COLS).
*/
virtual PRBool TableIsAutoWidth();
/** support routine returns PR_TRUE if the table columns should be sized "automatically"
* according to its content.
* In NAV4, this is when there is a COLS attribute on the table.
*/
virtual PRBool AutoColumnWidths(nsStyleMolecule* aTableStyleMol);
/** given the new parent size, do I really need to do a reflow? */
virtual PRBool NeedsReflow(const nsSize& aMaxSize);
/** what stage of reflow is currently in process? */
virtual PRInt32 GetReflowPass() const;
/** sets the reflow pass flag. use with caution! */
virtual void SetReflowPass(PRInt32 aReflowPass);
/** returns PR_TRUE if the cached pass 1 data is still valid */
virtual PRBool IsFirstPassValid() const;
private:
void nsTableFrame::DebugPrintCount() const; // Debugging routine
/** table reflow is a multi-pass operation. Use these constants to keep track of
* which pass is currently being executed.
*/
enum {kPASS_UNDEFINED=0, kPASS_FIRST=1, kPASS_SECOND=2, kPASS_THIRD=3};
nsVoidArray *mColumnLayoutData; // array of array of cellLayoutData's
PRInt32 *mColumnWidths; // widths of each column
PRBool mFirstPassValid; // PR_TRUE if first pass data is still legit
PRInt32 mPass; // which Reflow pass are we currently in?
PRBool mIsInvariantWidth; // PR_TRUE if table width cannot change
};
#endif