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 nsTableColFrame_h__ michael@0: #define nsTableColFrame_h__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "celldata.h" michael@0: #include "nscore.h" michael@0: #include "nsContainerFrame.h" michael@0: #include "nsTArray.h" michael@0: michael@0: class nsTableCellFrame; michael@0: michael@0: enum nsTableColType { michael@0: eColContent = 0, // there is real col content associated michael@0: eColAnonymousCol = 1, // the result of a span on a col michael@0: eColAnonymousColGroup = 2, // the result of a span on a col group michael@0: eColAnonymousCell = 3 // the result of a cell alone michael@0: }; michael@0: michael@0: class nsTableColFrame : public nsSplittableFrame { michael@0: public: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: enum {eWIDTH_SOURCE_NONE =0, // no cell has contributed to the width style michael@0: eWIDTH_SOURCE_CELL =1, // a cell specified a width michael@0: eWIDTH_SOURCE_CELL_WITH_SPAN=2 // a cell implicitly specified a width via colspan michael@0: }; michael@0: michael@0: nsTableColType GetColType() const; michael@0: void SetColType(nsTableColType aType); 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 nsTableColFrame* NS_NewTableColFrame(nsIPresShell* aPresShell, michael@0: nsStyleContext* aContext); michael@0: /** @see nsIFrame::DidSetStyleContext */ michael@0: virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; michael@0: michael@0: int32_t GetColIndex() const; michael@0: michael@0: void SetColIndex (int32_t aColIndex); michael@0: michael@0: nsTableColFrame* GetNextCol() const; 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: /** michael@0: * Table columns never paint anything, nor receive events. 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: /** michael@0: * Get the "type" of the frame michael@0: * michael@0: * @see nsGkAtoms::tableColFrame 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: virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE; michael@0: michael@0: /** return the number of the columns the col represents. always >= 1 */ michael@0: int32_t GetSpan(); michael@0: michael@0: /** convenience method, calls into cellmap */ michael@0: int32_t Count() const; michael@0: michael@0: nscoord GetLeftBorderWidth(); michael@0: void SetLeftBorderWidth(BCPixelSize aWidth); michael@0: nscoord GetRightBorderWidth(); michael@0: void SetRightBorderWidth(BCPixelSize aWidth); michael@0: michael@0: /** michael@0: * Gets inner border widths before collapsing with cell borders michael@0: * Caller must get left border from previous column or from table michael@0: * GetContinuousBCBorderWidth will not overwrite aBorder.left michael@0: * see nsTablePainter about continuous borders michael@0: * michael@0: * @return outer right border width (left inner for next column) michael@0: */ michael@0: nscoord GetContinuousBCBorderWidth(nsMargin& aBorder); michael@0: /** michael@0: * Set full border widths before collapsing with cell borders michael@0: * @param aForSide - side to set; only valid for top, right, and bottom michael@0: */ michael@0: void SetContinuousBCBorderWidth(uint8_t aForSide, michael@0: BCPixelSize aPixelValue); michael@0: #ifdef DEBUG michael@0: void Dump(int32_t aIndent); michael@0: #endif michael@0: michael@0: /** michael@0: * Restore the default values of the intrinsic widths, so that we can michael@0: * re-accumulate intrinsic widths from the cells in the column. michael@0: */ michael@0: void ResetIntrinsics() { michael@0: mMinCoord = 0; michael@0: mPrefCoord = 0; michael@0: mPrefPercent = 0.0f; michael@0: mHasSpecifiedCoord = false; michael@0: } michael@0: michael@0: /** michael@0: * Restore the default value of the preferred percentage width (the michael@0: * only intrinsic width used by FixedTableLayoutStrategy. michael@0: */ michael@0: void ResetPrefPercent() { michael@0: mPrefPercent = 0.0f; michael@0: } michael@0: michael@0: /** michael@0: * Restore the default values of the temporary buffer for michael@0: * spanning-cell intrinsic widths (as we process spanning cells). michael@0: */ michael@0: void ResetSpanIntrinsics() { michael@0: mSpanMinCoord = 0; michael@0: mSpanPrefCoord = 0; michael@0: mSpanPrefPercent = 0.0f; michael@0: } michael@0: michael@0: /** michael@0: * Add the widths for a cell or column element, or the contribution of michael@0: * the widths from a column-spanning cell: michael@0: * @param aMinCoord The minimum intrinsic width michael@0: * @param aPrefCoord The preferred intrinsic width or, if there is a michael@0: * specified non-percentage width, max(specified width, minimum intrinsic michael@0: * width). michael@0: * @param aHasSpecifiedCoord Whether there is a specified michael@0: * non-percentage width. michael@0: * michael@0: * Note that the implementation of this functions is a bit tricky michael@0: * since mPrefCoord means different things depending on michael@0: * whether mHasSpecifiedCoord is true (and likewise for aPrefCoord and michael@0: * aHasSpecifiedCoord). If mHasSpecifiedCoord is false, then michael@0: * all widths added had aHasSpecifiedCoord false and mPrefCoord is the michael@0: * largest of the pref widths. But if mHasSpecifiedCoord is true, michael@0: * then mPrefCoord is the largest of (1) the pref widths for cells michael@0: * with aHasSpecifiedCoord true and (2) the min widths for cells with michael@0: * aHasSpecifiedCoord false. michael@0: */ michael@0: void AddCoords(nscoord aMinCoord, nscoord aPrefCoord, michael@0: bool aHasSpecifiedCoord) { michael@0: NS_ASSERTION(aMinCoord <= aPrefCoord, "intrinsic widths out of order"); michael@0: michael@0: if (aHasSpecifiedCoord && !mHasSpecifiedCoord) { michael@0: mPrefCoord = mMinCoord; michael@0: mHasSpecifiedCoord = true; michael@0: } michael@0: if (!aHasSpecifiedCoord && mHasSpecifiedCoord) { michael@0: aPrefCoord = aMinCoord; // NOTE: modifying argument michael@0: } michael@0: michael@0: if (aMinCoord > mMinCoord) michael@0: mMinCoord = aMinCoord; michael@0: if (aPrefCoord > mPrefCoord) michael@0: mPrefCoord = aPrefCoord; michael@0: michael@0: NS_ASSERTION(mMinCoord <= mPrefCoord, "min larger than pref"); michael@0: } michael@0: michael@0: /** michael@0: * Add a percentage width specified on a cell or column element or the michael@0: * contribution to this column of a percentage width specified on a michael@0: * column-spanning cell. michael@0: */ michael@0: void AddPrefPercent(float aPrefPercent) { michael@0: if (aPrefPercent > mPrefPercent) michael@0: mPrefPercent = aPrefPercent; michael@0: } michael@0: michael@0: /** michael@0: * Get the largest minimum intrinsic width for this column. michael@0: */ michael@0: nscoord GetMinCoord() const { return mMinCoord; } michael@0: /** michael@0: * Get the largest preferred width for this column, or, if there were michael@0: * any specified non-percentage widths (see GetHasSpecifiedCoord), the michael@0: * largest minimum intrinsic width or specified width. michael@0: */ michael@0: nscoord GetPrefCoord() const { return mPrefCoord; } michael@0: /** michael@0: * Get whether there were any specified widths contributing to this michael@0: * column. michael@0: */ michael@0: bool GetHasSpecifiedCoord() const { return mHasSpecifiedCoord; } michael@0: michael@0: /** michael@0: * Get the largest specified percentage width contributing to this michael@0: * column (returns 0 if there were none). michael@0: */ michael@0: float GetPrefPercent() const { return mPrefPercent; } michael@0: michael@0: /** michael@0: * Like AddCoords, but into a temporary buffer used for groups of michael@0: * column-spanning cells. michael@0: */ michael@0: void AddSpanCoords(nscoord aSpanMinCoord, nscoord aSpanPrefCoord, michael@0: bool aSpanHasSpecifiedCoord) { michael@0: NS_ASSERTION(aSpanMinCoord <= aSpanPrefCoord, michael@0: "intrinsic widths out of order"); michael@0: michael@0: if (!aSpanHasSpecifiedCoord && mHasSpecifiedCoord) { michael@0: aSpanPrefCoord = aSpanMinCoord; // NOTE: modifying argument michael@0: } michael@0: michael@0: if (aSpanMinCoord > mSpanMinCoord) michael@0: mSpanMinCoord = aSpanMinCoord; michael@0: if (aSpanPrefCoord > mSpanPrefCoord) michael@0: mSpanPrefCoord = aSpanPrefCoord; michael@0: michael@0: NS_ASSERTION(mSpanMinCoord <= mSpanPrefCoord, "min larger than pref"); michael@0: } michael@0: michael@0: /* michael@0: * Accumulate percentage widths on column spanning cells into michael@0: * temporary variables. michael@0: */ michael@0: void AddSpanPrefPercent(float aSpanPrefPercent) { michael@0: if (aSpanPrefPercent > mSpanPrefPercent) michael@0: mSpanPrefPercent = aSpanPrefPercent; michael@0: } michael@0: michael@0: /* michael@0: * Accumulate the temporary variables for column spanning cells into michael@0: * the primary variables. michael@0: */ michael@0: void AccumulateSpanIntrinsics() { michael@0: AddCoords(mSpanMinCoord, mSpanPrefCoord, mHasSpecifiedCoord); michael@0: AddPrefPercent(mSpanPrefPercent); michael@0: } michael@0: michael@0: // Used to adjust a column's pref percent so that the table's total michael@0: // never exceeeds 100% (by only allowing percentages to be used, michael@0: // starting at the first column, until they reach 100%). michael@0: void AdjustPrefPercent(float *aTableTotalPercent) { michael@0: float allowed = 1.0f - *aTableTotalPercent; michael@0: if (mPrefPercent > allowed) michael@0: mPrefPercent = allowed; michael@0: *aTableTotalPercent += mPrefPercent; michael@0: } michael@0: michael@0: // The final width of the column. michael@0: void ResetFinalWidth() { michael@0: mFinalWidth = nscoord_MIN; // so we detect that it changed michael@0: } michael@0: void SetFinalWidth(nscoord aFinalWidth) { michael@0: mFinalWidth = aFinalWidth; michael@0: } michael@0: nscoord GetFinalWidth() { michael@0: return mFinalWidth; michael@0: } michael@0: michael@0: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE michael@0: { michael@0: return nsSplittableFrame::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: protected: michael@0: michael@0: nsTableColFrame(nsStyleContext* aContext); michael@0: ~nsTableColFrame(); michael@0: michael@0: nscoord mMinCoord; michael@0: nscoord mPrefCoord; michael@0: nscoord mSpanMinCoord; // XXX... michael@0: nscoord mSpanPrefCoord; // XXX... michael@0: float mPrefPercent; michael@0: float mSpanPrefPercent; // XXX... michael@0: // ...XXX the four members marked above could be allocated as part of michael@0: // a separate array allocated only during michael@0: // BasicTableLayoutStrategy::ComputeColumnIntrinsicWidths (and only michael@0: // when colspans were present). michael@0: nscoord mFinalWidth; michael@0: michael@0: // the index of the column with respect to the whole table (starting at 0) michael@0: // it should never be smaller then the start column index of the parent michael@0: // colgroup michael@0: uint32_t mColIndex; michael@0: michael@0: // border width in pixels of the inner half of the border only michael@0: BCPixelSize mLeftBorderWidth; michael@0: BCPixelSize mRightBorderWidth; michael@0: BCPixelSize mTopContBorderWidth; michael@0: BCPixelSize mRightContBorderWidth; michael@0: BCPixelSize mBottomContBorderWidth; michael@0: michael@0: bool mHasSpecifiedCoord; michael@0: }; michael@0: michael@0: inline int32_t nsTableColFrame::GetColIndex() const michael@0: { michael@0: return mColIndex; michael@0: } michael@0: michael@0: inline void nsTableColFrame::SetColIndex (int32_t aColIndex) michael@0: { michael@0: mColIndex = aColIndex; michael@0: } michael@0: michael@0: inline nscoord nsTableColFrame::GetLeftBorderWidth() michael@0: { michael@0: return mLeftBorderWidth; michael@0: } michael@0: michael@0: inline void nsTableColFrame::SetLeftBorderWidth(BCPixelSize aWidth) michael@0: { michael@0: mLeftBorderWidth = aWidth; michael@0: } michael@0: michael@0: inline nscoord nsTableColFrame::GetRightBorderWidth() michael@0: { michael@0: return mRightBorderWidth; michael@0: } michael@0: michael@0: inline void nsTableColFrame::SetRightBorderWidth(BCPixelSize aWidth) michael@0: { michael@0: mRightBorderWidth = aWidth; michael@0: } michael@0: michael@0: inline nscoord michael@0: nsTableColFrame::GetContinuousBCBorderWidth(nsMargin& aBorder) michael@0: { michael@0: int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel(); michael@0: aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips, michael@0: mTopContBorderWidth); michael@0: aBorder.right = BC_BORDER_LEFT_HALF_COORD(aPixelsToTwips, michael@0: mRightContBorderWidth); michael@0: aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips, michael@0: mBottomContBorderWidth); michael@0: return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mRightContBorderWidth); michael@0: } michael@0: michael@0: #endif michael@0: