author Gregory Szorc <>
Wed, 28 Jan 2015 13:37:00 -0800
changeset 110514 ad02f479b381c40651355b13806cf8ee08761ccd
parent 99194 ee5b6efa9bda22a2c96e46eff2bd57a90aad0765
child 101170 0adc41ff56dcddc7533f52730b3ec2296ff52430
permissions -rw-r--r--
Close old release branch GECKO150_2012082116_RELBRANCH

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */
#ifndef nsTableRowFrame_h__
#define nsTableRowFrame_h__

#include "nscore.h"
#include "nsContainerFrame.h"
#include "nsTablePainter.h"

class  nsTableFrame;
class  nsTableCellFrame;
struct nsTableCellReflowState;

// This is also used on rows, from nsTableRowGroupFrame.h

// Indicates whether this row has any cells that have
// non-auto-height and rowspan=1


 * nsTableRowFrame is the frame that maps table rows 
 * (HTML tag TR). This class cannot be reused
 * outside of an nsTableRowGroupFrame.  It assumes that its parent is an nsTableRowGroupFrame,  
 * and its children are nsTableCellFrames.
 * @see nsTableFrame
 * @see nsTableRowGroupFrame
 * @see nsTableCellFrame
class nsTableRowFrame : public nsContainerFrame

  virtual ~nsTableRowFrame();

  NS_IMETHOD Init(nsIContent*      aContent,
                  nsIFrame*        aParent,
                  nsIFrame*        aPrevInFlow);
  /** @see nsIFrame::DidSetStyleContext */
  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
  NS_IMETHOD AppendFrames(ChildListID     aListID,
                          nsFrameList&    aFrameList);
  NS_IMETHOD InsertFrames(ChildListID     aListID,
                          nsIFrame*       aPrevFrame,
                          nsFrameList&    aFrameList);
  NS_IMETHOD RemoveFrame(ChildListID     aListID,
                         nsIFrame*       aOldFrame);

  /** instantiate a new instance of nsTableRowFrame.
    * @param aPresShell the pres shell for this frame
    * @return           the frame that was created
  friend nsIFrame* NS_NewTableRowFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);

  virtual nsMargin GetUsedMargin() const;
  virtual nsMargin GetUsedBorder() const;
  virtual nsMargin GetUsedPadding() const;

  NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                              const nsRect&           aDirtyRect,
                              const nsDisplayListSet& aLists);

  nsTableCellFrame* GetFirstCell() ;

  /** calls Reflow for all of its child cells.
    * Cells with rowspan=1 are all set to the same height and stacked horizontally.
    * <P> Cells are not split unless absolutely necessary.
    * <P> Cells are resized in nsTableFrame::BalanceColumnWidths 
    * and nsTableFrame::ShrinkWrapChildren
    * @param aDesiredSize width set to width of the sum of the cells, height set to 
    *                     height of cells with rowspan=1.
    * @see nsIFrame::Reflow
    * @see nsTableFrame::BalanceColumnWidths
    * @see nsTableFrame::ShrinkWrapChildren
  NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                    nsHTMLReflowMetrics&     aDesiredSize,
                    const nsHTMLReflowState& aReflowState,
                    nsReflowStatus&          aStatus);

  void DidResize();

   * Get the "type" of the frame
   * @see nsGkAtoms::tableRowFrame
  virtual nsIAtom* GetType() const;

#ifdef DEBUG
  NS_IMETHOD GetFrameName(nsAString& aResult) const;
  void UpdateHeight(nscoord           aHeight,
                    nscoord           aAscent,
                    nscoord           aDescent,
                    nsTableFrame*     aTableFrame = nsnull,
                    nsTableCellFrame* aCellFrame  = nsnull);

  void ResetHeight(nscoord aRowStyleHeight);

  // calculate the height, considering content height of the 
  // cells and the style height of the row and cells, excluding pct heights
  nscoord CalcHeight(const nsHTMLReflowState& aReflowState);

  // Support for cells with 'vertical-align: baseline'.

   * returns the max-ascent amongst all the cells that have 
   * 'vertical-align: baseline', *including* cells with rowspans.
   * returns 0 if we don't have any cell with 'vertical-align: baseline'
  nscoord GetMaxCellAscent() const;

  /* return the row ascent
  nscoord GetRowBaseline();
  /** returns the ordinal position of this row in its table */
  virtual PRInt32 GetRowIndex() const;

  /** set this row's starting row index */
  void SetRowIndex (int aRowIndex);

  /** used by row group frame code */
  nscoord ReflowCellFrame(nsPresContext*          aPresContext,
                          const nsHTMLReflowState& aReflowState,
                          bool                     aIsTopOfPage,
                          nsTableCellFrame*        aCellFrame,
                          nscoord                  aAvailableHeight,
                          nsReflowStatus&          aStatus);
    * Collapse the row if required, apply col and colgroup visibility: collapse
    * info to the cells in the row.
    * @return he amount to shift up all following rows
    * @param aRowOffset     - shift the row up by this amount
    * @param aWidth         - new width of the row
    * @param aCollapseGroup - parent rowgroup is collapsed so this row needs
    *                         to be collapsed
    * @param aDidCollapse   - the row has been collapsed
  nscoord CollapseRowIfNecessary(nscoord aRowOffset,
                                 nscoord aWidth,
                                 bool    aCollapseGroup,
                                 bool& aDidCollapse);

   * Insert a cell frame after the last cell frame that has a col index
   * that is less than aColIndex.  If no such cell frame is found the
   * frame to insert is prepended to the child list.
   * @param aFrame the cell frame to insert
   * @param aColIndex the col index
  void InsertCellFrame(nsTableCellFrame* aFrame,
                       PRInt32           aColIndex);

  nsresult CalculateCellActualHeight(nsTableCellFrame* aCellFrame,
                                     nscoord&          aDesiredHeight);

  bool IsFirstInserted() const;
  void   SetFirstInserted(bool aValue);

  nscoord GetContentHeight() const;
  void    SetContentHeight(nscoord aTwipValue);

  bool HasStyleHeight() const;

  bool HasFixedHeight() const;
  void   SetHasFixedHeight(bool aValue);

  bool HasPctHeight() const;
  void   SetHasPctHeight(bool aValue);

  nscoord GetFixedHeight() const;
  void    SetFixedHeight(nscoord aValue);

  float   GetPctHeight() const;
  void    SetPctHeight(float  aPctValue,
                       bool aForce = false);

  nscoord GetHeight(nscoord aBasis = 0) const;

  nsTableRowFrame* GetNextRow() const;

  bool    HasUnpaginatedHeight();
  void    SetHasUnpaginatedHeight(bool aValue);
  nscoord GetUnpaginatedHeight(nsPresContext* aPresContext);
  void    SetUnpaginatedHeight(nsPresContext* aPresContext, nscoord aValue);

  nscoord GetTopBCBorderWidth();
  void    SetTopBCBorderWidth(BCPixelSize aWidth);
  nscoord GetBottomBCBorderWidth();
  void    SetBottomBCBorderWidth(BCPixelSize aWidth);
  nsMargin* GetBCBorderWidth(nsMargin& aBorder);
   * Gets inner border widths before collapsing with cell borders
   * Caller must get bottom border from next row or from table
   * GetContinuousBCBorderWidth will not overwrite aBorder.bottom
   * see nsTablePainter about continuous borders
  void GetContinuousBCBorderWidth(nsMargin& aBorder);
   * @returns outer top bc border == prev row's bottom inner
  nscoord GetOuterTopContBCBorderWidth();
   * Sets full border widths before collapsing with cell borders
   * @param aForSide - side to set; only accepts right, left, and top
  void SetContinuousBCBorderWidth(PRUint8     aForSide,
                                  BCPixelSize aPixelValue);

  virtual already_AddRefed<Accessible> CreateAccessible();


  /** protected constructor.
    * @see NewFrame
  nsTableRowFrame(nsStyleContext *aContext);

  void InitChildReflowState(nsPresContext&         aPresContext,
                            const nsSize&           aAvailSize,
                            bool                    aBorderCollapse,
                            nsTableCellReflowState& aReflowState);
  /** implement abstract method on nsContainerFrame */
  virtual PRIntn GetSkipSides() const;

  // row-specific methods

  nscoord ComputeCellXOffset(const nsHTMLReflowState& aState,
                             nsIFrame*                aKidFrame,
                             const nsMargin&          aKidMargin) const;
   * Called for incremental/dirty and resize reflows. If aDirtyOnly is true then
   * only reflow dirty cells.
  nsresult ReflowChildren(nsPresContext*           aPresContext,
                          nsHTMLReflowMetrics&     aDesiredSize,
                          const nsHTMLReflowState& aReflowState,
                          nsTableFrame&            aTableFrame,
                          nsReflowStatus&          aStatus);

  struct RowBits {
    unsigned mRowIndex:29;
    unsigned mHasFixedHeight:1; // set if the dominating style height on the row or any cell is pixel based
    unsigned mHasPctHeight:1;   // set if the dominating style height on the row or any cell is pct based
    unsigned mFirstInserted:1;  // if true, then it was the top most newly inserted row 
  } mBits;

  // the desired height based on the content of the tallest cell in the row
  nscoord mContentHeight;
  // the height based on a style percentage height on either the row or any cell
  // if mHasPctHeight is set
  nscoord mStylePctHeight;
  // the height based on a style pixel height on the row or any
  // cell if mHasFixedHeight is set
  nscoord mStyleFixedHeight;

  // max-ascent and max-descent amongst all cells that have 'vertical-align: baseline'
  nscoord mMaxCellAscent;  // does include cells with rowspan > 1
  nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1

  // border widths in pixels in the collapsing border model of the *inner*
  // half of the border only
  BCPixelSize mTopBorderWidth;
  BCPixelSize mBottomBorderWidth;
  BCPixelSize mRightContBorderWidth;
  BCPixelSize mTopContBorderWidth;
  BCPixelSize mLeftContBorderWidth;

   * Sets the NS_ROW_HAS_CELL_WITH_STYLE_HEIGHT bit to indicate whether
   * this row has any cells that have non-auto-height.  (Row-spanning
   * cells are ignored.)
  void InitHasCellWithStyleHeight(nsTableFrame* aTableFrame);


inline PRInt32 nsTableRowFrame::GetRowIndex() const
  return PRInt32(mBits.mRowIndex);

inline void nsTableRowFrame::SetRowIndex (int aRowIndex)
  mBits.mRowIndex = aRowIndex;

inline bool nsTableRowFrame::IsFirstInserted() const
  return bool(mBits.mFirstInserted);

inline void nsTableRowFrame::SetFirstInserted(bool aValue)
  mBits.mFirstInserted = aValue;

inline bool nsTableRowFrame::HasStyleHeight() const
  return (bool)mBits.mHasFixedHeight || (bool)mBits.mHasPctHeight;

inline bool nsTableRowFrame::HasFixedHeight() const
  return (bool)mBits.mHasFixedHeight;

inline void nsTableRowFrame::SetHasFixedHeight(bool aValue)
  mBits.mHasFixedHeight = aValue;

inline bool nsTableRowFrame::HasPctHeight() const
  return (bool)mBits.mHasPctHeight;

inline void nsTableRowFrame::SetHasPctHeight(bool aValue)
  mBits.mHasPctHeight = aValue;

inline nscoord nsTableRowFrame::GetContentHeight() const
  return mContentHeight;

inline void nsTableRowFrame::SetContentHeight(nscoord aValue)
  mContentHeight = aValue;

inline nscoord nsTableRowFrame::GetFixedHeight() const
  if (mBits.mHasFixedHeight)
    return mStyleFixedHeight;
    return 0;

inline float nsTableRowFrame::GetPctHeight() const
  if (mBits.mHasPctHeight) 
    return (float)mStylePctHeight / 100.0f;
    return 0.0f;

inline bool nsTableRowFrame::HasUnpaginatedHeight()

inline void nsTableRowFrame::SetHasUnpaginatedHeight(bool aValue)
  if (aValue) {
  } else {

inline nscoord nsTableRowFrame::GetTopBCBorderWidth()
  return mTopBorderWidth;

inline void nsTableRowFrame::SetTopBCBorderWidth(BCPixelSize aWidth)
  mTopBorderWidth = aWidth;

inline nscoord nsTableRowFrame::GetBottomBCBorderWidth()
  return mBottomBorderWidth;

inline void nsTableRowFrame::SetBottomBCBorderWidth(BCPixelSize aWidth)
  mBottomBorderWidth = aWidth;

inline nsMargin* nsTableRowFrame::GetBCBorderWidth(nsMargin& aBorder)
  aBorder.left = aBorder.right = 0;    = nsPresContext::CSSPixelsToAppUnits(mTopBorderWidth);
  aBorder.bottom = nsPresContext::CSSPixelsToAppUnits(mBottomBorderWidth);

  return &aBorder;

inline void
nsTableRowFrame::GetContinuousBCBorderWidth(nsMargin& aBorder)
  PRInt32 aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
  aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips,
                                            mLeftContBorderWidth); = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
  aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips,

inline nscoord nsTableRowFrame::GetOuterTopContBCBorderWidth()
  PRInt32 aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
  return BC_BORDER_TOP_HALF_COORD(aPixelsToTwips, mTopContBorderWidth);