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 nsTableRowGroupFrame_h__ michael@0: #define nsTableRowGroupFrame_h__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nscore.h" michael@0: #include "nsContainerFrame.h" michael@0: #include "nsIAtom.h" michael@0: #include "nsILineIterator.h" michael@0: #include "nsTablePainter.h" michael@0: #include "nsTArray.h" michael@0: michael@0: class nsTableFrame; michael@0: class nsTableRowFrame; michael@0: class nsTableCellFrame; michael@0: michael@0: struct nsRowGroupReflowState { michael@0: const nsHTMLReflowState& reflowState; // Our reflow state michael@0: michael@0: nsTableFrame* tableFrame; michael@0: michael@0: // The available size (computed from the parent) michael@0: nsSize availSize; michael@0: michael@0: // Running y-offset michael@0: nscoord y; michael@0: michael@0: nsRowGroupReflowState(const nsHTMLReflowState& aReflowState, michael@0: nsTableFrame* aTableFrame) michael@0: :reflowState(aReflowState), tableFrame(aTableFrame) michael@0: { michael@0: availSize.width = reflowState.AvailableWidth(); michael@0: availSize.height = reflowState.AvailableHeight(); michael@0: y = 0; michael@0: } michael@0: michael@0: ~nsRowGroupReflowState() {} michael@0: }; michael@0: michael@0: #define MIN_ROWS_NEEDING_CURSOR 20 michael@0: michael@0: /** michael@0: * nsTableRowGroupFrame is the frame that maps row groups michael@0: * (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused michael@0: * outside of an nsTableFrame. It assumes that its parent is an nsTableFrame, and michael@0: * its children are nsTableRowFrames. michael@0: * michael@0: * @see nsTableFrame michael@0: * @see nsTableRowFrame michael@0: */ michael@0: class nsTableRowGroupFrame michael@0: : public nsContainerFrame michael@0: , public nsILineIterator michael@0: { michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsTableRowGroupFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS 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_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); michael@0: virtual ~nsTableRowGroupFrame(); 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: michael@0: virtual nsresult InsertFrames(ChildListID aListID, michael@0: nsIFrame* aPrevFrame, michael@0: nsFrameList& aFrameList) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult RemoveFrame(ChildListID aListID, michael@0: nsIFrame* aOldFrame) MOZ_OVERRIDE; 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: /** calls Reflow for all of its child rows. michael@0: * Rows are all set to the same width and stacked vertically. michael@0: *
rows are not split unless absolutely necessary.
michael@0: *
michael@0: * @param aDesiredSize width set to width of rows, height set to
michael@0: * sum of height of rows that fit in aMaxSize.height.
michael@0: *
michael@0: * @see nsIFrame::Reflow
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: virtual bool UpdateOverflow() MOZ_OVERRIDE;
michael@0:
michael@0: /**
michael@0: * Get the "type" of the frame
michael@0: *
michael@0: * @see nsGkAtoms::tableRowGroupFrame
michael@0: */
michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE;
michael@0:
michael@0: nsTableRowFrame* GetFirstRow();
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: /** return the number of child rows (not necessarily == number of child frames) */
michael@0: int32_t GetRowCount();
michael@0:
michael@0: /** return the table-relative row index of the first row in this rowgroup.
michael@0: * if there are no rows, -1 is returned.
michael@0: */
michael@0: int32_t GetStartRowIndex();
michael@0:
michael@0: /** Adjust the row indices of all rows whose index is >= aRowIndex.
michael@0: * @param aRowIndex - start adjusting with this index
michael@0: * @param aAdjustment - shift the row index by this amount
michael@0: */
michael@0: void AdjustRowIndices(int32_t aRowIndex,
michael@0: int32_t anAdjustment);
michael@0:
michael@0: /**
michael@0: * Used for header and footer row group frames that are repeated when
michael@0: * splitting a table frame.
michael@0: *
michael@0: * Performs any table specific initialization
michael@0: *
michael@0: * @param aHeaderFooterFrame the original header or footer row group frame
michael@0: * that was repeated
michael@0: */
michael@0: nsresult InitRepeatedFrame(nsPresContext* aPresContext,
michael@0: nsTableRowGroupFrame* aHeaderFooterFrame);
michael@0:
michael@0:
michael@0: /**
michael@0: * Get the total height of all the row rects
michael@0: */
michael@0: nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState);
michael@0:
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 top border from previous row group or from table
michael@0: * GetContinuousBCBorderWidth will not overwrite aBorder.top
michael@0: * see nsTablePainter about continuous borders
michael@0: */
michael@0: void GetContinuousBCBorderWidth(nsMargin& aBorder);
michael@0: /**
michael@0: * Sets full border widths before collapsing with cell borders
michael@0: * @param aForSide - side to set; only right, left, and bottom valid
michael@0: */
michael@0: void SetContinuousBCBorderWidth(uint8_t aForSide,
michael@0: BCPixelSize aPixelValue);
michael@0: /**
michael@0: * Adjust to the effect of visibibility:collapse on the row group and
michael@0: * its children
michael@0: * @return additional shift upward that should be applied to
michael@0: * subsequent rowgroups due to rows and this rowgroup
michael@0: * being collapsed
michael@0: * @param aYTotalOffset the total amount that the rowgroup is shifted up
michael@0: * @param aWidth new width of the rowgroup
michael@0: */
michael@0: nscoord CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
michael@0: nscoord aWidth);
michael@0:
michael@0: // nsILineIterator methods
michael@0: public:
michael@0: virtual void DisposeLineIterator() MOZ_OVERRIDE { }
michael@0:
michael@0: // The table row is the equivalent to a line in block layout.
michael@0: // The nsILineIterator assumes that a line resides in a block, this role is
michael@0: // fullfilled by the row group. Rows in table are counted relative to the
michael@0: // table. The row index of row corresponds to the cellmap coordinates. The
michael@0: // line index with respect to a row group can be computed by substracting the
michael@0: // row index of the first row in the row group.
michael@0:
michael@0: /** Get the number of rows in a row group
michael@0: * @return the number of lines in a row group
michael@0: */
michael@0: virtual int32_t GetNumLines() MOZ_OVERRIDE;
michael@0:
michael@0: /** @see nsILineIterator.h GetDirection
michael@0: * @return true if the table is rtl
michael@0: */
michael@0: virtual bool GetDirection() MOZ_OVERRIDE;
michael@0:
michael@0: /** Return structural information about a line.
michael@0: * @param aLineNumber - the index of the row relative to the row group
michael@0: * If the line-number is invalid then
michael@0: * aFirstFrameOnLine will be nullptr and
michael@0: * aNumFramesOnLine will be zero.
michael@0: * @param aFirstFrameOnLine - the first cell frame that originates in row
michael@0: * with a rowindex that matches a line number
michael@0: * @param aNumFramesOnLine - return the numbers of cells originating in
michael@0: * this row
michael@0: * @param aLineBounds - rect of the row
michael@0: * @param aLineFlags - unused set to 0
michael@0: */
michael@0: NS_IMETHOD GetLine(int32_t aLineNumber,
michael@0: nsIFrame** aFirstFrameOnLine,
michael@0: int32_t* aNumFramesOnLine,
michael@0: nsRect& aLineBounds,
michael@0: uint32_t* aLineFlags) MOZ_OVERRIDE;
michael@0:
michael@0: /** Given a frame that's a child of the rowgroup, find which line its on.
michael@0: * @param aFrame - frame, should be a row
michael@0: * @param aStartLine - minimal index to return
michael@0: * @return row index relative to the row group if this a row
michael@0: * frame and the index is at least aStartLine.
michael@0: * -1 if the frame cannot be found.
michael@0: */
michael@0: virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) MOZ_OVERRIDE;
michael@0:
michael@0: /** Find the orginating cell frame on a row that is the nearest to the
michael@0: * coordinate X.
michael@0: * @param aLineNumber - the index of the row relative to the row group
michael@0: * @param aX - X coordinate in twips relative to the
michael@0: * origin of the row group
michael@0: * @param aFrameFound - pointer to the cellframe
michael@0: * @param aXIsBeforeFirstFrame - the point is before the first originating
michael@0: * cellframe
michael@0: * @param aXIsAfterLastFrame - the point is after the last originating
michael@0: * cellframe
michael@0: */
michael@0: NS_IMETHOD FindFrameAt(int32_t aLineNumber,
michael@0: nscoord aX,
michael@0: nsIFrame** aFrameFound,
michael@0: bool* aXIsBeforeFirstFrame,
michael@0: bool* aXIsAfterLastFrame) MOZ_OVERRIDE;
michael@0:
michael@0: /** Check whether visual and logical order of cell frames within a line are
michael@0: * identical. As the layout will reorder them this is always the case
michael@0: * @param aLine - the index of the row relative to the table
michael@0: * @param aIsReordered - returns false
michael@0: * @param aFirstVisual - if the table is rtl first originating cell frame
michael@0: * @param aLastVisual - if the table is rtl last originating cell frame
michael@0: */
michael@0:
michael@0: NS_IMETHOD CheckLineOrder(int32_t aLine,
michael@0: bool *aIsReordered,
michael@0: nsIFrame **aFirstVisual,
michael@0: nsIFrame **aLastVisual) MOZ_OVERRIDE;
michael@0:
michael@0: /** Find the next originating cell frame that originates in the row.
michael@0: * @param aFrame - cell frame to start with, will return the next cell
michael@0: * originating in a row
michael@0: * @param aLineNumber - the index of the row relative to the table
michael@0: */
michael@0: NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) MOZ_OVERRIDE;
michael@0:
michael@0: // row cursor methods to speed up searching for the row(s)
michael@0: // containing a point. The basic idea is that we set the cursor
michael@0: // property if the rows' y and yMosts are non-decreasing (considering only
michael@0: // rows with nonempty overflowAreas --- empty overflowAreas never participate
michael@0: // in event handling or painting), and the rowgroup has sufficient number of
michael@0: // rows. The cursor property points to a "recently used" row. If we get a
michael@0: // series of requests that work on rows "near" the cursor, then we can find
michael@0: // those nearby rows quickly by starting our search at the cursor.
michael@0: // This code is based on the line cursor code in nsBlockFrame. It's more general
michael@0: // though, and could be extracted and used elsewhere.
michael@0: struct FrameCursorData {
michael@0: nsTArray