michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: #ifndef nsTableRowFrame_h__ michael@0: #define nsTableRowFrame_h__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nscore.h" michael@0: #include "nsContainerFrame.h" michael@0: #include "nsTablePainter.h" michael@0: michael@0: class nsTableFrame; michael@0: class nsTableCellFrame; michael@0: struct nsTableCellReflowState; michael@0: michael@0: /** michael@0: * nsTableRowFrame is the frame that maps table rows michael@0: * (HTML tag TR). This class cannot be reused michael@0: * outside of an nsTableRowGroupFrame. It assumes that its parent is an nsTableRowGroupFrame, michael@0: * and its children are nsTableCellFrames. michael@0: * michael@0: * @see nsTableFrame michael@0: * @see nsTableRowGroupFrame michael@0: * @see nsTableCellFrame michael@0: */ michael@0: class nsTableRowFrame : public nsContainerFrame michael@0: { michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsTableRowFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: virtual ~nsTableRowFrame(); michael@0: michael@0: virtual void Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: michael@0: /** @see nsIFrame::DidSetStyleContext */ michael@0: virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult AppendFrames(ChildListID aListID, michael@0: nsFrameList& aFrameList) MOZ_OVERRIDE; michael@0: virtual nsresult InsertFrames(ChildListID aListID, michael@0: nsIFrame* aPrevFrame, michael@0: nsFrameList& aFrameList) MOZ_OVERRIDE; michael@0: virtual nsresult RemoveFrame(ChildListID aListID, michael@0: nsIFrame* aOldFrame) MOZ_OVERRIDE; michael@0: michael@0: /** instantiate a new instance of nsTableRowFrame. michael@0: * @param aPresShell the pres shell for this frame michael@0: * michael@0: * @return the frame that was created michael@0: */ michael@0: friend nsIFrame* NS_NewTableRowFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); michael@0: michael@0: virtual nsMargin GetUsedMargin() const MOZ_OVERRIDE; michael@0: virtual nsMargin GetUsedBorder() const MOZ_OVERRIDE; michael@0: virtual nsMargin GetUsedPadding() const MOZ_OVERRIDE; michael@0: michael@0: virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) MOZ_OVERRIDE; michael@0: michael@0: nsTableCellFrame* GetFirstCell() ; michael@0: michael@0: /** calls Reflow for all of its child cells. michael@0: * Cells with rowspan=1 are all set to the same height and stacked horizontally. michael@0: *
Cells are not split unless absolutely necessary. michael@0: *
Cells are resized in nsTableFrame::BalanceColumnWidths michael@0: * and nsTableFrame::ShrinkWrapChildren michael@0: * michael@0: * @param aDesiredSize width set to width of the sum of the cells, height set to michael@0: * height of cells with rowspan=1. michael@0: * michael@0: * @see nsIFrame::Reflow michael@0: * @see nsTableFrame::BalanceColumnWidths michael@0: * @see nsTableFrame::ShrinkWrapChildren michael@0: */ michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: michael@0: void DidResize(); michael@0: michael@0: /** michael@0: * Get the "type" of the frame michael@0: * michael@0: * @see nsGkAtoms::tableRowFrame michael@0: */ michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: void UpdateHeight(nscoord aHeight, michael@0: nscoord aAscent, michael@0: nscoord aDescent, michael@0: nsTableFrame* aTableFrame = nullptr, michael@0: nsTableCellFrame* aCellFrame = nullptr); michael@0: michael@0: void ResetHeight(nscoord aRowStyleHeight); michael@0: michael@0: // calculate the height, considering content height of the michael@0: // cells and the style height of the row and cells, excluding pct heights michael@0: nscoord CalcHeight(const nsHTMLReflowState& aReflowState); michael@0: michael@0: // Support for cells with 'vertical-align: baseline'. michael@0: michael@0: /** michael@0: * returns the max-ascent amongst all the cells that have michael@0: * 'vertical-align: baseline', *including* cells with rowspans. michael@0: * returns 0 if we don't have any cell with 'vertical-align: baseline' michael@0: */ michael@0: nscoord GetMaxCellAscent() const; michael@0: michael@0: /* return the row ascent michael@0: */ michael@0: nscoord GetRowBaseline(); michael@0: michael@0: /** returns the ordinal position of this row in its table */ michael@0: virtual int32_t GetRowIndex() const; michael@0: michael@0: /** set this row's starting row index */ michael@0: void SetRowIndex (int aRowIndex); michael@0: michael@0: /** used by row group frame code */ michael@0: nscoord ReflowCellFrame(nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: bool aIsTopOfPage, michael@0: nsTableCellFrame* aCellFrame, michael@0: nscoord aAvailableHeight, michael@0: nsReflowStatus& aStatus); michael@0: /** michael@0: * Collapse the row if required, apply col and colgroup visibility: collapse michael@0: * info to the cells in the row. michael@0: * @return he amount to shift up all following rows michael@0: * @param aRowOffset - shift the row up by this amount michael@0: * @param aWidth - new width of the row michael@0: * @param aCollapseGroup - parent rowgroup is collapsed so this row needs michael@0: * to be collapsed michael@0: * @param aDidCollapse - the row has been collapsed michael@0: */ michael@0: nscoord CollapseRowIfNecessary(nscoord aRowOffset, michael@0: nscoord aWidth, michael@0: bool aCollapseGroup, michael@0: bool& aDidCollapse); michael@0: michael@0: /** michael@0: * Insert a cell frame after the last cell frame that has a col index michael@0: * that is less than aColIndex. If no such cell frame is found the michael@0: * frame to insert is prepended to the child list. michael@0: * @param aFrame the cell frame to insert michael@0: * @param aColIndex the col index michael@0: */ michael@0: void InsertCellFrame(nsTableCellFrame* aFrame, michael@0: int32_t aColIndex); michael@0: michael@0: nsresult CalculateCellActualHeight(nsTableCellFrame* aCellFrame, michael@0: nscoord& aDesiredHeight); michael@0: michael@0: bool IsFirstInserted() const; michael@0: void SetFirstInserted(bool aValue); michael@0: michael@0: nscoord GetContentHeight() const; michael@0: void SetContentHeight(nscoord aTwipValue); michael@0: michael@0: bool HasStyleHeight() const; michael@0: michael@0: bool HasFixedHeight() const; michael@0: void SetHasFixedHeight(bool aValue); michael@0: michael@0: bool HasPctHeight() const; michael@0: void SetHasPctHeight(bool aValue); michael@0: michael@0: nscoord GetFixedHeight() const; michael@0: void SetFixedHeight(nscoord aValue); michael@0: michael@0: float GetPctHeight() const; michael@0: void SetPctHeight(float aPctValue, michael@0: bool aForce = false); michael@0: michael@0: nscoord GetHeight(nscoord aBasis = 0) const; michael@0: michael@0: nsTableRowFrame* GetNextRow() const; michael@0: michael@0: bool HasUnpaginatedHeight(); michael@0: void SetHasUnpaginatedHeight(bool aValue); michael@0: nscoord GetUnpaginatedHeight(nsPresContext* aPresContext); michael@0: void SetUnpaginatedHeight(nsPresContext* aPresContext, nscoord aValue); michael@0: michael@0: nscoord GetTopBCBorderWidth(); michael@0: void SetTopBCBorderWidth(BCPixelSize aWidth); michael@0: nscoord GetBottomBCBorderWidth(); michael@0: void SetBottomBCBorderWidth(BCPixelSize aWidth); michael@0: nsMargin* GetBCBorderWidth(nsMargin& aBorder); michael@0: michael@0: /** michael@0: * Gets inner border widths before collapsing with cell borders michael@0: * Caller must get bottom border from next row or from table michael@0: * GetContinuousBCBorderWidth will not overwrite aBorder.bottom michael@0: * see nsTablePainter about continuous borders michael@0: */ michael@0: void GetContinuousBCBorderWidth(nsMargin& aBorder); michael@0: /** michael@0: * @returns outer top bc border == prev row's bottom inner michael@0: */ michael@0: nscoord GetOuterTopContBCBorderWidth(); michael@0: /** michael@0: * Sets full border widths before collapsing with cell borders michael@0: * @param aForSide - side to set; only accepts right, left, and top michael@0: */ michael@0: void SetContinuousBCBorderWidth(uint8_t aForSide, michael@0: BCPixelSize aPixelValue); michael@0: michael@0: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE michael@0: { michael@0: return nsContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eTablePart)); michael@0: } michael@0: michael@0: virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; michael@0: virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE; michael@0: virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); } michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: protected: michael@0: michael@0: /** protected constructor. michael@0: * @see NewFrame michael@0: */ michael@0: nsTableRowFrame(nsStyleContext *aContext); michael@0: michael@0: void InitChildReflowState(nsPresContext& aPresContext, michael@0: const nsSize& aAvailSize, michael@0: bool aBorderCollapse, michael@0: nsTableCellReflowState& aReflowState); michael@0: michael@0: virtual int GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; michael@0: michael@0: // row-specific methods michael@0: michael@0: nscoord ComputeCellXOffset(const nsHTMLReflowState& aState, michael@0: nsIFrame* aKidFrame, michael@0: const nsMargin& aKidMargin) const; michael@0: /** michael@0: * Called for incremental/dirty and resize reflows. If aDirtyOnly is true then michael@0: * only reflow dirty cells. michael@0: */ michael@0: nsresult ReflowChildren(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsTableFrame& aTableFrame, michael@0: nsReflowStatus& aStatus); michael@0: michael@0: private: michael@0: struct RowBits { michael@0: unsigned mRowIndex:29; michael@0: unsigned mHasFixedHeight:1; // set if the dominating style height on the row or any cell is pixel based michael@0: unsigned mHasPctHeight:1; // set if the dominating style height on the row or any cell is pct based michael@0: unsigned mFirstInserted:1; // if true, then it was the top most newly inserted row michael@0: } mBits; michael@0: michael@0: // the desired height based on the content of the tallest cell in the row michael@0: nscoord mContentHeight; michael@0: // the height based on a style percentage height on either the row or any cell michael@0: // if mHasPctHeight is set michael@0: nscoord mStylePctHeight; michael@0: // the height based on a style pixel height on the row or any michael@0: // cell if mHasFixedHeight is set michael@0: nscoord mStyleFixedHeight; michael@0: michael@0: // max-ascent and max-descent amongst all cells that have 'vertical-align: baseline' michael@0: nscoord mMaxCellAscent; // does include cells with rowspan > 1 michael@0: nscoord mMaxCellDescent; // does *not* include cells with rowspan > 1 michael@0: michael@0: // border widths in pixels in the collapsing border model of the *inner* michael@0: // half of the border only michael@0: BCPixelSize mTopBorderWidth; michael@0: BCPixelSize mBottomBorderWidth; michael@0: BCPixelSize mRightContBorderWidth; michael@0: BCPixelSize mTopContBorderWidth; michael@0: BCPixelSize mLeftContBorderWidth; michael@0: michael@0: /** michael@0: * Sets the NS_ROW_HAS_CELL_WITH_STYLE_HEIGHT bit to indicate whether michael@0: * this row has any cells that have non-auto-height. (Row-spanning michael@0: * cells are ignored.) michael@0: */ michael@0: void InitHasCellWithStyleHeight(nsTableFrame* aTableFrame); michael@0: michael@0: }; michael@0: michael@0: inline int32_t nsTableRowFrame::GetRowIndex() const michael@0: { michael@0: return int32_t(mBits.mRowIndex); michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetRowIndex (int aRowIndex) michael@0: { michael@0: mBits.mRowIndex = aRowIndex; michael@0: } michael@0: michael@0: inline bool nsTableRowFrame::IsFirstInserted() const michael@0: { michael@0: return bool(mBits.mFirstInserted); michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetFirstInserted(bool aValue) michael@0: { michael@0: mBits.mFirstInserted = aValue; michael@0: } michael@0: michael@0: inline bool nsTableRowFrame::HasStyleHeight() const michael@0: { michael@0: return (bool)mBits.mHasFixedHeight || (bool)mBits.mHasPctHeight; michael@0: } michael@0: michael@0: inline bool nsTableRowFrame::HasFixedHeight() const michael@0: { michael@0: return (bool)mBits.mHasFixedHeight; michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetHasFixedHeight(bool aValue) michael@0: { michael@0: mBits.mHasFixedHeight = aValue; michael@0: } michael@0: michael@0: inline bool nsTableRowFrame::HasPctHeight() const michael@0: { michael@0: return (bool)mBits.mHasPctHeight; michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetHasPctHeight(bool aValue) michael@0: { michael@0: mBits.mHasPctHeight = aValue; michael@0: } michael@0: michael@0: inline nscoord nsTableRowFrame::GetContentHeight() const michael@0: { michael@0: return mContentHeight; michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetContentHeight(nscoord aValue) michael@0: { michael@0: mContentHeight = aValue; michael@0: } michael@0: michael@0: inline nscoord nsTableRowFrame::GetFixedHeight() const michael@0: { michael@0: if (mBits.mHasFixedHeight) michael@0: return mStyleFixedHeight; michael@0: else michael@0: return 0; michael@0: } michael@0: michael@0: inline float nsTableRowFrame::GetPctHeight() const michael@0: { michael@0: if (mBits.mHasPctHeight) michael@0: return (float)mStylePctHeight / 100.0f; michael@0: else michael@0: return 0.0f; michael@0: } michael@0: michael@0: inline bool nsTableRowFrame::HasUnpaginatedHeight() michael@0: { michael@0: return (mState & NS_TABLE_ROW_HAS_UNPAGINATED_HEIGHT) == michael@0: NS_TABLE_ROW_HAS_UNPAGINATED_HEIGHT; michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetHasUnpaginatedHeight(bool aValue) michael@0: { michael@0: if (aValue) { michael@0: mState |= NS_TABLE_ROW_HAS_UNPAGINATED_HEIGHT; michael@0: } else { michael@0: mState &= ~NS_TABLE_ROW_HAS_UNPAGINATED_HEIGHT; michael@0: } michael@0: } michael@0: michael@0: inline nscoord nsTableRowFrame::GetTopBCBorderWidth() michael@0: { michael@0: return mTopBorderWidth; michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetTopBCBorderWidth(BCPixelSize aWidth) michael@0: { michael@0: mTopBorderWidth = aWidth; michael@0: } michael@0: michael@0: inline nscoord nsTableRowFrame::GetBottomBCBorderWidth() michael@0: { michael@0: return mBottomBorderWidth; michael@0: } michael@0: michael@0: inline void nsTableRowFrame::SetBottomBCBorderWidth(BCPixelSize aWidth) michael@0: { michael@0: mBottomBorderWidth = aWidth; michael@0: } michael@0: michael@0: inline nsMargin* nsTableRowFrame::GetBCBorderWidth(nsMargin& aBorder) michael@0: { michael@0: aBorder.left = aBorder.right = 0; michael@0: michael@0: aBorder.top = nsPresContext::CSSPixelsToAppUnits(mTopBorderWidth); michael@0: aBorder.bottom = nsPresContext::CSSPixelsToAppUnits(mBottomBorderWidth); michael@0: michael@0: return &aBorder; michael@0: } michael@0: michael@0: inline void michael@0: nsTableRowFrame::GetContinuousBCBorderWidth(nsMargin& aBorder) michael@0: { michael@0: int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); michael@0: aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips, michael@0: mLeftContBorderWidth); michael@0: aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips, michael@0: mTopContBorderWidth); michael@0: aBorder.left = BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, michael@0: mRightContBorderWidth); michael@0: } michael@0: michael@0: inline nscoord nsTableRowFrame::GetOuterTopContBCBorderWidth() michael@0: { michael@0: int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); michael@0: return BC_BORDER_TOP_HALF_COORD(aPixelsToTwips, mTopContBorderWidth); michael@0: } michael@0: michael@0: #endif