gecko-dev/layout/generic/nsBlockFrame.h

462 строки
17 KiB
C++

/* -*- 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 "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code 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"
class nsBlockReflowState;
class nsBulletFrame;
class nsLineBox;
class nsTextRun;
class nsFirstLineFrame;
/**
* Child list name indices
* @see #GetAdditionalChildListName()
*/
#define NS_BLOCK_FRAME_FLOATER_LIST_INDEX 0
#define NS_BLOCK_FRAME_BULLET_LIST_INDEX 1
#define NS_BLOCK_FRAME_LAST_LIST_INDEX NS_BLOCK_FRAME_BULLET_LIST_INDEX
/**
* Additional frame-state bits
*/
#define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET 0x80000000
#define NS_BLOCK_IS_HTML_PARAGRAPH 0x40000000
#ifdef BLOCK_DOES_FIRST_LINE
#define NS_BLOCK_HAS_FIRST_LINE_STYLE 0x20000000
#endif
#define NS_BLOCK_HAS_FIRST_LETTER_STYLE 0x10000000
#define nsBlockFrameSuper nsHTMLContainerFrame
#define NS_BLOCK_FRAME_CID \
{ 0xa6cf90df, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
extern const nsIID kBlockFrameCID;
// Base class for block and inline frames
class nsBlockFrame : public nsBlockFrameSuper
{
public:
friend nsresult NS_NewBlockFrame(nsIFrame** aNewFrame);
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
// nsIFrame
NS_IMETHOD Init(nsIPresContext& aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const;
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
NS_IMETHOD Destroy(nsIPresContext& aPresContext);
NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
NS_IMETHOD ReResolveStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aParentContext,
PRInt32 aParentChange,
nsStyleChangeList* aChangeList,
PRInt32* aLocalChange);
NS_IMETHOD IsPercentageBase(PRBool& aBase) const;
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
NS_IMETHOD GetFrameName(nsString& aResult) const;
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
#ifdef DEBUG
NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
#endif
NS_IMETHOD VerifyTree() const;
NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint, nsIFrame** aFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
// nsIHTMLReflow
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD MoveInSpaceManager(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
nscoord aDeltaX, nscoord aDeltaY);
NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext,
nsIContent* aChild,
nsIAtom* aAttribute,
PRInt32 aHint);
#ifdef DO_SELECTION
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
NS_IMETHOD HandleDrag(nsIPresContext& aPresContext,
nsGUIEvent* aEvent,
nsEventStatus& aEventStatus);
nsIFrame * FindHitFrame(nsBlockFrame * aBlockFrame,
const nscoord aX, const nscoord aY,
const nsPoint & aPoint);
#endif
virtual void DeleteChildsNextInFlow(nsIPresContext& aPresContext,
nsIFrame* aNextInFlow);
nsIFrame* GetTopBlockChild();
protected:
nsBlockFrame();
virtual ~nsBlockFrame();
nsIStyleContext* GetFirstLetterStyle(nsIPresContext* aPresContext);
#ifdef BLOCK_DOES_FIRST_LINE
nsIStyleContext* GetFirstLineStyle(nsIPresContext* aPresContext);
#endif
void SetFlags(PRUint32 aFlags) {
mFlags = aFlags;
}
PRBool HaveOutsideBullet() const {
return 0 != (mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET);
}
void SlideLine(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
nsLineBox* aLine, nscoord aDY);
void SlideFloaters(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
nsLineBox* aLine, nscoord aDY);
PRBool DrainOverflowLines();
virtual PRIntn GetSkipSides() const;
virtual void ComputeFinalSize(const nsHTMLReflowState& aReflowState,
nsBlockReflowState& aState,
nsHTMLReflowMetrics& aMetrics);
nsresult AddFrames(nsIPresContext* aPresContext,
nsIFrame* aFrameList,
nsIFrame* aPrevSibling);
#ifdef BLOCK_DOES_FIRST_LINE
nsresult AddFirstLineFrames(nsIPresContext* aPresContext,
nsFirstLineFrame* aLineFrame,
nsIFrame* aFrameList,
nsIFrame* aPrevSibling);
nsIFrame* TakeKidsFromLineFrame(nsFirstLineFrame* aLineFrame,
nsIFrame* aFromKid);
nsresult RemoveFirstLineFrame(nsIPresContext* aPresContext,
nsFirstLineFrame* aLineFrame,
nsIFrame* aDeletedFrame);
nsresult WrapFramesInFirstLineFrame(nsIPresContext* aPresContext);
#endif
void FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame);
nsresult DoRemoveFrame(nsIPresContext* aPresContext,
nsIFrame* aDeletedFrame);
nsresult PrepareInitialReflow(nsBlockReflowState& aState);
nsresult PrepareStyleChangedReflow(nsBlockReflowState& aState);
nsresult PrepareChildIncrementalReflow(nsBlockReflowState& aState);
nsresult PrepareResizeReflow(nsBlockReflowState& aState);
nsresult ReflowDirtyLines(nsBlockReflowState& aState);
void RecoverStateFrom(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord aDeltaY,
nsRect* aDamageRect);
//----------------------------------------
// Methods for line reflow
// XXX nuke em
nsresult ReflowLine(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool* aKeepReflowGoing,
PRBool aDamageDirtyArea = PR_FALSE);
virtual void DidReflowLine(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool aKeepReflowGoing);
nsresult PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineBox* aLine,
PRBool* aKeepReflowGoing);
// XXX blech
void PostPlaceLine(nsBlockReflowState& aState,
nsLineBox* aLine,
const nsSize& aMaxElementSize);
void ComputeLineMaxElementSize(nsBlockReflowState& aState,
nsLineBox* aLine,
nsSize* aMaxElementSize);
// XXX where to go
PRBool ShouldJustifyLine(nsBlockReflowState& aState, nsLineBox* aLine);
void FindFloaters(nsLineBox* aLine);
void DeleteLine(nsBlockReflowState& aState, nsLineBox* aLine);
//----------------------------------------
// Methods for individual frame reflow
PRBool ShouldApplyTopMargin(nsBlockReflowState& aState,
nsLineBox* aLine);
nsresult ReflowBlockFrame(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool* aKeepGoing);
nsresult ReflowInlineFrames(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool* aKeepLineGoing);
nsresult DoReflowInlineFrames(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineBox* aLine,
PRBool* aKeepReflowGoing,
PRUint8* aLineReflowStatus);
nsresult DoReflowInlineFramesAuto(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool* aKeepReflowGoing,
PRUint8* aLineReflowStatus);
nsresult DoReflowInlineFramesMalloc(nsBlockReflowState& aState,
nsLineBox* aLine,
PRBool* aKeepReflowGoing,
PRUint8* aLineReflowStatus);
nsresult ReflowInlineFrame(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineBox* aLine,
nsIFrame* aFrame,
PRUint8* aLineReflowStatus);
nsresult ReflowFloater(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRect,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult);
//----------------------------------------
// Methods for pushing/pulling lines/frames
virtual nsresult CreateContinuationFor(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame* aFrame,
PRBool& aMadeNewFrame);
nsresult SplitLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineBox* aLine,
nsIFrame* aFrame);
nsBlockFrame* FindFollowingBlockFrame(nsIFrame* aFrame);
nsresult PullFrame(nsBlockReflowState& aState,
nsLineBox* aLine,
nsIFrame*& aFrameResult);
nsresult PullFrame(nsBlockReflowState& aState,
nsLineBox* aToLine,
nsLineBox** aFromList,
PRBool aUpdateGeometricParent,
nsIFrame*& aFrameResult,
PRBool& aStopPulling);
void PushLines(nsBlockReflowState& aState);
//----------------------------------------
//XXX
virtual void PaintChildren(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
void PaintFloaters(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
nsLineBox* FindLineFor(nsIFrame* aFrame, nsLineBox** aPrevLineResult,
PRBool* aIsFloaterResult);
void PropogateReflowDamage(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord aDeltaY);
nsresult ComputeTextRuns(nsIPresContext* aPresContext);
void BuildFloaterList();
//----------------------------------------
// List handling kludge
void RenumberLists();
void RenumberListsIn(nsIFrame* aContainerFrame, PRInt32* aOrdinal);
PRBool FrameStartsCounterScope(nsIFrame* aFrame);
void UpdateBulletPosition();
void ReflowBullet(nsBlockReflowState& aState,
nsHTMLReflowMetrics& aMetrics);
//----------------------------------------
nsIFrame* LastChild();
#ifdef NS_DEBUG
PRBool IsChild(nsIFrame* aFrame);
void VerifyLines(PRBool aFinalCheckOK);
void VerifyOverflowSituation();
PRInt32 GetDepth() const;
#endif
nsLineBox* mLines;
nsLineBox* mOverflowLines;
// XXX subclass!
PRUint32 mFlags;
// Text run information
nsTextRun* mTextRuns;
// List of all floaters in this block
nsFrameList mFloaters;
// XXX_fix_me: subclass one more time!
// For list-item frames, this is the bullet frame.
nsBulletFrame* mBullet;
friend class nsBlockReflowState;
};
//----------------------------------------------------------------------
#define nsAnonymousBlockFrameSuper nsBlockFrame
// Anonymous block frame. An anonymous block is used by some other
// container (the parent frame) to provide block reflow for a set of
// child frames. The parent is responsible for the maintainance of the
// anonymous blocks child list. To accomplish this, the normal methods
// for managing the child list (AppendFrames, InsertFrames, and
// RemoveFrame) forward the operation to the parent frame (the
// container of the anonymous block).
class nsAnonymousBlockFrame : public nsAnonymousBlockFrameSuper {
public:
friend nsresult NS_NewAnonymousBlockFrame(nsIFrame** aNewFrame);
// nsIFrame overrides
// AppendFrames/InsertFrames/RemoveFrame are implemented to forward
// the method call to the parent frame.
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
// These methods are used by the parent frame to actually modify the
// child frames of the anonymous block frame.
nsresult AppendFrames2(nsIPresContext* aPresContext,
nsIPresShell* aPresShell,
nsIAtom* aListName,
nsIFrame* aFrameList);
nsresult InsertFrames2(nsIPresContext* aPresContext,
nsIPresShell* aPresShell,
nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
nsresult RemoveFrame2(nsIPresContext* aPresContext,
nsIPresShell* aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
// Take the first frame away from the anonymous block frame. The
// caller is responsible for the first frames final disposition
// (e.g. deleting it if it wants to).
void RemoveFirstFrame();
// Remove from the blocks list of children the frames starting at
// aFrame until the end of the child list. The caller is responsible
// for the first frames final disposition (e.g. deleting it if it
// wants to).
void RemoveFramesFrom(nsIFrame* aFrame);
protected:
nsAnonymousBlockFrame();
~nsAnonymousBlockFrame();
};
#endif /* nsBlockFrame_h___ */