/* -*- 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 nsBlockFrame_h___ #define nsBlockFrame_h___ #include "nsHTMLContainerFrame.h" #include "nsIFloaterContainer.h" #include "nsIHTMLFrameType.h" #include "nsIRunaround.h" #include "nsVoidArray.h" struct BlockBandData; struct nsMargin; struct nsStyleFont; /** * Block frames have some state which needs to be made * available to child frames for proper reflow. This structure * describes that state. */ struct nsBlockReflowState { // True if this is the first line of text in a block container PRPackedBool firstLine; // True if leading whitespace is allowed to show PRPackedBool allowLeadingWhitespace; // This is set when some child frame needs a break after it's placed PRPackedBool breakAfterChild; // This is set when a child needs a break before it's placed. Note // that this value is set by a child AFTER we have called it's // ResizeReflow method. PRPackedBool breakBeforeChild; // This is set when the first child should be treated specially // because it's an inside list item bullet. // XXX this can go away once we have a way for the bullet's style // molecule to *not* be the same as it's parent's PRPackedBool firstChildIsInsideBullet; // For pre-formatted text, this is our current column PRIntn column; // The next list ordinal value PRInt32 nextListOrdinal; //---------------------------------------------------------------------- // State from here on down is not to be used by block child frames! // Space manager to use nsISpaceManager* spaceManager; // Block's style data nsStyleFont* font; nsStyleMolecule* mol; // Block's available size (computed from the block's parent) nsSize availSize; // Current band of available space. Used for doing runaround BlockBandData* currentBand; // Pointer to a max-element-size (nsnull if none required) nsSize* maxElementSize; // The maximum x-most of our lines and block-level elements. This is used to // compute our desired size, and includes our left border/padding. For block- // level elements this also includes the block's right margin. nscoord kidXMost; // Current reflow position nscoord y; // Current line state nscoord x; // inline elements only. not include border/padding PRBool isInline; // whether the current is inline or block nsVoidArray lineLengths; // line length temporary storage PRIntn currentLineNumber; // index into mLines nsIFrame* lineStart; // frame starting the line PRInt32 lineLength; // length of line nscoord* ascents; // ascent information for each child nscoord maxAscent; // max ascent for this line nscoord maxDescent; // max descent for this line nscoord lineWidth; // current width of line #if 0 nscoord maxPosTopMargin; // maximum positive top margin nscoord maxNegTopMargin; // maximum negative top margin #else nscoord topMargin; // current top margin #endif nscoord maxPosBottomMargin; // maximum positive bottom margin nscoord maxNegBottomMargin; // maximum negative bottom margin nsSize lineMaxElementSize; // max element size for current line PRBool lastContentIsComplete; // reflow status of last child on line nsVoidArray floaterToDo; // list of floaters to place below current line PRInt32 maxAscents; // size of ascent buffer nscoord ascentBuf[20]; PRPackedBool needRelativePos; // some kid in line needs relative pos // Previous line state that we carry forward to the next line nsIFrame* prevLineLastFrame; nscoord prevLineHeight; // height of the previous line nscoord prevMaxPosBottomMargin; // maximum posative bottom margin nscoord prevMaxNegBottomMargin; // maximum negative bottom margin PRBool prevLineLastContentIsComplete; // Sanitized version of mol->borderPadding; if this block frame is a // pseudo-frame then the margin will be zero'd. nsMargin borderPadding; PRPackedBool justifying; // we are justifying // Status from last PlaceAndReflowChild nsIFrame::ReflowStatus reflowStatus; // Flags for whether the max size is unconstrained PRBool unconstrainedWidth; PRBool unconstrainedHeight; nsBlockReflowState(); ~nsBlockReflowState(); void Init(const nsSize& aMaxSize, nsSize* aMaxElementSize, nsStyleFont* aFont, nsStyleMolecule* aMol, nsISpaceManager* aSpaceManager); void AddAscent(nscoord aAscent); void AdvanceToNextLine(nsIFrame* aPrevLineLastFrame, nscoord aPrevLineHeight); #ifdef NS_DEBUG void DumpLine(); void DumpList(); #endif }; //---------------------------------------------------------------------- /** *

Block Reflow

* * The block frame reflow machinery performs "2D" layout. Inline * elements are flowed into logical lines (left to right or right to * left) and the lines are stacked vertically. Block elements are * flowed onto their own line after flushing out any preceeding line.

* * After a line is ready to be flushed out, vertical alignment is * performed. Vertical alignment may require the line to consume more * vertical space than is available thus causing the entire line to * be pushed.

* * After vertical alignment is done, horizontal alignment (including * justification) is performed. Finally, relative positioning is done * on any elements that require it.

* * During reflow, the block frame will make available to child frames * it's reflow state using the presentation shell's cached data * mechanism.

* *

Reflowing Mapped Content

*

Pullup

*

Reflowing Unmapped Content

*

Content Insertion Handling

*

Content Deletion Handling

*

Style Change Handling

* *

Assertions

* mLastContentIsComplete always reflects the state of the last * child frame on our chlid list. */ class nsBlockFrame : public nsHTMLContainerFrame, public nsIHTMLFrameType, public nsIRunaround, public nsIFloaterContainer { public: /** * Create a new block frame that maps the given piece of content. */ static nsresult NewFrame(nsIFrame** aInstancePtrResult, nsIContent* aContent, PRInt32 aIndexInParent, nsIFrame* aParent); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD ResizeReflow(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, const nsSize& aMaxSize, nsRect& aDesiredRect, nsSize* aMaxElementSize, ReflowStatus& aStatus); NS_IMETHOD IncrementalReflow(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, const nsSize& aMaxSize, nsRect& aDesiredRect, nsReflowCommand& aReflowCommand, ReflowStatus& aStatus); NS_IMETHOD ContentAppended(nsIPresShell* aShell, nsIPresContext* aPresContext, nsIContent* aContainer); NS_IMETHOD IsSplittable(SplittableType& aIsSplittable) const; NS_IMETHOD CreateContinuingFrame(nsIPresContext* aPresContext, nsIFrame* aParent, nsIFrame*& aContinuingFrame); virtual PRBool AddFloater(nsIPresContext* aCX, nsIFrame* aFloater, PlaceholderFrame* aPlaceholder); virtual void PlaceFloater(nsIPresContext* aCX, nsIFrame* aFloater, PlaceholderFrame* aPlaceholder); NS_IMETHOD ListTag(FILE* out = stdout) const; virtual nsHTMLFrameType GetFrameType() const; protected: nsBlockFrame(nsIContent* aContent, PRInt32 aIndexInParent, nsIFrame* aParent); virtual ~nsBlockFrame(); virtual PRIntn GetSkipSides() const; PRBool MoreToReflow(nsIPresContext* aCX); nscoord GetTopMarginFor(nsIPresContext* aCX, nsBlockReflowState& aState, nsIFrame* aKidFrame, nsStyleMolecule* aKidMol, PRBool aIsInline); PRBool AdvanceToNextLine(nsIPresContext* aPresContext, nsBlockReflowState& aState); void AddInlineChildToLine(nsIPresContext* aCX, nsBlockReflowState& aState, nsIFrame* aKidFrame, nsReflowMetrics& aKidSize, nsSize* aKidMaxElementSize, nsStyleMolecule* aKidMol); void AddBlockChild(nsIPresContext* aCX, nsBlockReflowState& aState, nsIFrame* aKidFrame, nsRect& aKidRect, nsSize* aKidMaxElementSize, nsStyleMolecule* aKidMol); void GetAvailSize(nsSize& aResult, nsBlockReflowState& aState, nsStyleMolecule* aKidMol, PRBool aIsInline); PRIntn PlaceAndReflowChild(nsIPresContext* aCX, nsBlockReflowState& aState, nsIFrame* kidFrame, nsStyleMolecule* aKidMol); void PushKids(nsBlockReflowState& aState); void SetupState(nsIPresContext* aCX, nsBlockReflowState& aState, const nsSize& aMaxSize, nsSize* aMaxElementSize, nsISpaceManager* aSpaceManager); nsresult DoResizeReflow(nsIPresContext* aPresContext, nsBlockReflowState& aState, nsRect& aDesiredRect, ReflowStatus& aStatus); PRBool ReflowMappedChildren(nsIPresContext* aPresContext, nsBlockReflowState& aState); PRBool PullUpChildren(nsIPresContext* aCX, nsBlockReflowState& aState); ReflowStatus ReflowAppendedChildren(nsIPresContext* aPresContext, nsBlockReflowState& aState); void JustifyLines(nsIPresContext* aPresContext, nsBlockReflowState& aState); PRBool IsLeftMostChild(nsIFrame* aFrame); void GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY); void PlaceBelowCurrentLineFloaters(nsIPresContext* aCX, nsBlockReflowState& aState, nscoord aY); void ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear); #ifdef NS_DEBUG void DumpFlow() const; #endif /** * Array of lines lengths. For each logical line of children, this array * contains a count of the number of children on the line. */ PRInt32* mLines; PRInt32 mNumLines; nsBlockReflowState* mCurrentState; }; #endif /* nsBlockFrame_h___ */