diff --git a/content/html/style/src/nsCSSLayout.cpp b/content/html/style/src/nsCSSLayout.cpp index e408609ed7c..effcaa0aa96 100644 --- a/content/html/style/src/nsCSSLayout.cpp +++ b/content/html/style/src/nsCSSLayout.cpp @@ -20,6 +20,7 @@ #include "nsStyleConsts.h" #include "nsIContent.h" #include "nsIFrame.h" +#include "nsIFrameReflow.h" #include "nsIFontMetrics.h" #include "nsIPresContext.h" #include "nsRect.h" diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 12e931335f9..02ffcf56ab5 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -32,6 +32,7 @@ #include "nsIPref.h" #include "nsIViewObserver.h" #include "nsContainerFrame.h" +#include "nsHTMLIIDs.h" static PRBool gsNoisyRefs = PR_FALSE; #undef NOISY @@ -495,20 +496,23 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) mRootFrame->VerifyTree(); } #endif - nsRect bounds; + nsRect bounds; mPresContext->GetVisibleArea(bounds); - nsSize maxSize(bounds.width, bounds.height); - nsReflowMetrics desiredSize(nsnull); - nsReflowStatus status; - nsReflowState reflowState(mRootFrame, eReflowReason_Initial, maxSize); + nsSize maxSize(bounds.width, bounds.height); + nsHTMLReflowMetrics desiredSize(nsnull); + nsReflowStatus status; + nsReflowState reflowState(mRootFrame, eReflowReason_Initial, maxSize); + nsIHTMLReflow* htmlReflow; - mRootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); - mRootFrame->SizeTo(desiredSize.width, desiredSize.height); + if (NS_OK == mRootFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { + htmlReflow->Reflow(*mPresContext, desiredSize, reflowState, status); + mRootFrame->SizeTo(desiredSize.width, desiredSize.height); #ifdef NS_DEBUG - if (nsIFrame::GetVerifyTreeEnable()) { - mRootFrame->VerifyTree(); - } + if (nsIFrame::GetVerifyTreeEnable()) { + mRootFrame->VerifyTree(); + } #endif + } NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::InitialReflow")); } @@ -538,20 +542,23 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) mRootFrame->VerifyTree(); } #endif - nsRect bounds; + nsRect bounds; mPresContext->GetVisibleArea(bounds); - nsSize maxSize(bounds.width, bounds.height); - nsReflowMetrics desiredSize(nsnull); - nsReflowStatus status; - nsReflowState reflowState(mRootFrame, eReflowReason_Resize, maxSize); + nsSize maxSize(bounds.width, bounds.height); + nsHTMLReflowMetrics desiredSize(nsnull); + nsReflowStatus status; + nsReflowState reflowState(mRootFrame, eReflowReason_Resize, maxSize); + nsIHTMLReflow* htmlReflow; - mRootFrame->Reflow(*mPresContext, desiredSize, reflowState, status); - mRootFrame->SizeTo(desiredSize.width, desiredSize.height); + if (NS_OK == mRootFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { + htmlReflow->Reflow(*mPresContext, desiredSize, reflowState, status); + mRootFrame->SizeTo(desiredSize.width, desiredSize.height); #ifdef NS_DEBUG - if (nsIFrame::GetVerifyTreeEnable()) { - mRootFrame->VerifyTree(); - } + if (nsIFrame::GetVerifyTreeEnable()) { + mRootFrame->VerifyTree(); + } #endif + } NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::ResizeReflow")); // XXX if debugging then we should assert that the cache is empty @@ -624,7 +631,7 @@ void PresShell::ProcessReflowCommands() { if (0 != mReflowCommands.Count()) { - nsReflowMetrics desiredSize(nsnull); + nsHTMLReflowMetrics desiredSize(nsnull); while (0 != mReflowCommands.Count()) { nsIReflowCommand* rc = (nsIReflowCommand*) mReflowCommands.ElementAt(0); diff --git a/layout/base/public/makefile.win b/layout/base/public/makefile.win index 28e7f59b9fa..4cebc14b81d 100644 --- a/layout/base/public/makefile.win +++ b/layout/base/public/makefile.win @@ -24,6 +24,7 @@ EXPORTS = \ nsIDocumentContainer.h \ nsIDocumentObserver.h \ nsIFrame.h \ + nsIFrameReflow.h \ nsIFrameImageLoader.h \ nsIPresContext.h \ nsIPresShell.h \ diff --git a/layout/base/public/nsIFrame.h b/layout/base/public/nsIFrame.h index 5d0eb7712f9..d01e66e3b8a 100644 --- a/layout/base/public/nsIFrame.h +++ b/layout/base/public/nsIFrame.h @@ -43,7 +43,6 @@ class nsString; struct nsPoint; struct nsRect; -struct nsReflowMetrics; struct nsStyleStruct; struct PRLogModuleInfo; @@ -53,168 +52,6 @@ struct PRLogModuleInfo; #define NS_IFRAME_IID \ { 0xa6cf9050, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} -/** - * Reflow metrics used to return the frame's desired size and alignment - * information. - * - * @see #Reflow() - * @see #GetReflowMetrics() - */ -struct nsReflowMetrics { - nscoord width, height; // desired width and height - nscoord ascent, descent; - - // Set this to null if you don't need to compute the max element size - nsSize* maxElementSize; - - // XXX Explain this better somehow! - - // The caller of nsIFrame::Reflow will set these to the top margin - // value carried into the child frame. This allows the the child - // container to collapse the top margin with its first childs - // margin. - nscoord mCarriedInTopMargin; // in - - // These values are set by the child frame indicating its final - // inner bottom margin value (the value of the childs last child - // bottom margin) - nscoord mCarriedOutBottomMargin; // out - - nsReflowMetrics(nsSize* aMaxElementSize) { - maxElementSize = aMaxElementSize; - mCarriedInTopMargin = 0; - mCarriedOutBottomMargin = 0; - width = 0; - height = 0; - ascent = 0; - descent = 0; - } -}; - -/** - * Constant used to indicate an unconstrained size. - * - * @see #Reflow() - */ -#define NS_UNCONSTRAINEDSIZE NS_MAXSIZE - -/** - * The reason the frame is being reflowed. - * - * @see nsReflowState - */ -enum nsReflowReason { - eReflowReason_Initial = 0, // initial reflow of a newly created frame - eReflowReason_Incremental = 1, // an incremental change has occured. see the reflow command for details - eReflowReason_Resize = 2 // general request to determine a desired size -}; - -/** - * The type of size constraint that applies to a particular dimension. - * For the fixed and fixed content cases the min size in the reflow state - * structure is ignored and you should use the max size value when reflowing - * the frame. - * - * @see nsReflowState - */ -//XXX enum's are prefixed wrong -enum nsReflowConstraint { - eReflowSize_Unconstrained = 0, // choose whatever frame size you want - eReflowSize_Constrained = 1, // choose a frame size between the min and max sizes - eReflowSize_Fixed = 2, // frame size is fixed - eReflowSize_FixedContent = 3 // size of your content area is fixed -}; - -/** - * Reflow state passed to a frame during reflow. The reflow states are linked - * together. The max size represents the max available space in which to reflow - * your frame, and is computed as the parent frame's available content area - * minus any room for margins that your frame requests. The min size represents - * the min available space in which to reflow your frame - * - * @see #Reflow() - */ -struct nsReflowState { - const nsReflowState* parentReflowState; // pointer to parent's reflow state - nsIFrame* frame; // the frame being reflowed - nsReflowReason reason; // the reason for the reflow - nsIReflowCommand* reflowCommand; // only used for incremental changes - nsReflowConstraint widthConstraint; // constraint that applies to width dimension - nsReflowConstraint heightConstraint; // constraint that applies to height dimension - nsSize maxSize; // the max available space in which to reflow - nsSize minSize; // the min available space in which to reflow. - // Only used for eReflowSize_Constrained - - // Note: there is no copy constructor so that the compiler can - // generate an optimal one. - - // Constructs an initial reflow state (no parent reflow state) for a - // non-incremental reflow command - nsReflowState(nsIFrame* aFrame, - nsReflowReason aReason, - const nsSize& aMaxSize); - - // Constructs an initial reflow state (no parent reflow state) for an - // incremental reflow command - nsReflowState(nsIFrame* aFrame, - nsIReflowCommand& aReflowCommand, - const nsSize& aMaxSize); - - // Construct a reflow state for the given frame, parent reflow state, and - // max size. Uses the reflow reason and reflow command from the parent's - // reflow state - nsReflowState(nsIFrame* aFrame, - const nsReflowState& aParentReflowState, - const nsSize& aMaxSize); - - // Constructs a reflow state that overrides the reflow reason of the parent - // reflow state. Sets the reflow command to NULL - nsReflowState(nsIFrame* aFrame, - const nsReflowState& aParentReflowState, - const nsSize& aMaxSize, - nsReflowReason aReflowReason); -}; - -//---------------------------------------------------------------------- - -/** - * Reflow status returned by the reflow methods. - * - * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its - * content, and that the parent frame should create a continuing frame. - * If this bit isn't set it means the frame does map all its content. - * - * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is - * dirty, and also needs to be reflowed. This status only makes sense - * for a frame that is not complete, i.e. you wouldn't set both - * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW - * - * The low 8 bits of the nsReflowStatus are reserved for future extensions; - * the remaining 24 bits are zero (and available for extensions; however - * API's that accept/return nsReflowStatus must not receive/return any - * extension bits). - * - * @see #Reflow() - * @see #CreateContinuingFrame() - */ -typedef PRUint32 nsReflowStatus; - -#define NS_FRAME_COMPLETE 0 // Note: not a bit! -#define NS_FRAME_NOT_COMPLETE 0x1 -#define NS_FRAME_REFLOW_NEXTINFLOW 0x2 - -#define NS_FRAME_IS_COMPLETE(status) \ - (0 == ((status) & NS_FRAME_NOT_COMPLETE)) - -#define NS_FRAME_IS_NOT_COMPLETE(status) \ - (0 != ((status) & NS_FRAME_NOT_COMPLETE)) - -// This macro tests to see if an nsReflowStatus is an error value -// or just a regular return value -#define NS_IS_REFLOW_ERROR(_status) (PRInt32(_status) < 0) - -//---------------------------------------------------------------------- - /** * Indication of how the frame can be split. This is used when doing runaround * of floaters, and when pulling up child frames from a next-in-flow. @@ -257,16 +94,6 @@ typedef PRUint32 nsFrameState; //---------------------------------------------------------------------- -/** - * DidReflow status values. - */ -typedef PRBool nsDidReflowStatus; - -#define NS_FRAME_REFLOW_NOT_FINISHED PR_FALSE -#define NS_FRAME_REFLOW_FINISHED PR_TRUE - -//---------------------------------------------------------------------- - /** * A frame in the layout model. This interface is supported by all frame * objects. @@ -418,64 +245,6 @@ public: */ NS_IMETHOD SetFrameState(nsFrameState aNewState) = 0; - /** - * Pre-reflow hook. Before a frame is incrementally reflowed or - * resize-reflowed this method will be called warning the frame of - * the impending reflow. This call may be invoked zero or more times - * before a subsequent DidReflow call. This method when called the - * first time will set the NS_FRAME_IN_REFLOW bit in the frame - * state bits. - */ - NS_IMETHOD WillReflow(nsIPresContext& aPresContext) = 0; - - /** - * The frame is given a maximum size and asked for its desired size. - * This is the frame's opportunity to reflow its children. - * - * @param aDesiredSize out parameter where you should return the - * desired size and ascent/descent info. You should include any - * space you want for border/padding in the desired size you return. - * - * It's okay to return a desired size that exceeds the max - * size if that's the smallest you can be, i.e. it's your - * minimum size. - * - * maxElementSize is an optional parameter for returning your - * maximum element size. If may be null in which case you - * don't have to compute a maximum element size. The - * maximum element size must be less than or equal to your - * desired size. - * - * @param aReflowState information about your reflow including the reason - * for the reflow and the available space in which to lay out. Each - * dimension of the available space can either be constrained or - * unconstrained (a value of NS_UNCONSTRAINEDSIZE). If constrained - * you should choose a value that's less than or equal to the - * constrained size. If unconstrained you can choose as - * large a value as you like. - * - * Note that the available space can be negative. In this case you - * still must return an accurate desired size. If you're a container - * you must always reflow at least one frame regardless of the - * available space - */ - NS_IMETHOD Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsReflowStatus& aStatus) = 0; - - /** - * Post-reflow hook. After a frame is incrementally reflowed or - * resize-reflowed this method will be called telling the frame of - * the outcome. This call may be invoked many times, while - * NS_FRAME_IN_REFLOW is set, before it is finally called once with - * a NS_FRAME_REFLOW_COMPLETE value. When called with a - * NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the - * frame state will be cleared. - */ - NS_IMETHOD DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus) = 0; - /** * This call is invoked when content is changed in the content tree. * The first frame that maps that content is asked to deal with the @@ -502,17 +271,6 @@ public: nsIAtom* aAttribute, PRInt32 aHint) = 0; - /** - * Return the reflow metrics for this frame. If the frame is a - * container then the values for ascent and descent are computed - * across the the various children in the appropriate manner - * (e.g. for a line frame the ascent value would be the maximum - * ascent of the line's children). Note that the metrics returned - * apply to the frame as it exists at the time of the call. - */ - NS_IMETHOD GetReflowMetrics(nsIPresContext& aPresContext, - nsReflowMetrics& aMetrics) = 0; - /** * Return how your frame can be split. */ @@ -631,91 +389,6 @@ private: NS_IMETHOD_(nsrefcnt) Release(void) = 0; }; -// Constructs an initial reflow state (no parent reflow state) for a -// non-incremental reflow command -inline nsReflowState::nsReflowState(nsIFrame* aFrame, - nsReflowReason aReason, - const nsSize& aMaxSize) -{ - NS_PRECONDITION(aReason != eReflowReason_Incremental, "unexpected reflow reason"); -// the following was removed because framesets need to force a reflow on themselves and didn't -// have nsReflowState parentage available -#if 0 -#ifdef NS_DEBUG - nsIFrame* parent; - aFrame->GetGeometricParent(parent); - NS_PRECONDITION(nsnull == parent, "not root frame"); -#endif -#endif - reason = aReason; - reflowCommand = nsnull; - maxSize = aMaxSize; - parentReflowState = nsnull; - frame = aFrame; - widthConstraint = eReflowSize_Constrained; - heightConstraint = eReflowSize_Constrained; - minSize.width = 0; - minSize.height = 0; -} - -// Constructs an initial reflow state (no parent reflow state) for an -// incremental reflow command -inline nsReflowState::nsReflowState(nsIFrame* aFrame, - nsIReflowCommand& aReflowCommand, - const nsSize& aMaxSize) -{ -#ifdef NS_DEBUG - nsIFrame* parent; - aFrame->GetGeometricParent(parent); - NS_PRECONDITION(nsnull == parent, "not root frame"); -#endif - reason = eReflowReason_Incremental; - reflowCommand = &aReflowCommand; - maxSize = aMaxSize; - parentReflowState = nsnull; - frame = aFrame; - widthConstraint = eReflowSize_Constrained; - heightConstraint = eReflowSize_Constrained; - minSize.width = 0; - minSize.height = 0; -} - -// Construct a reflow state for the given frame, parent reflow state, and -// max size. Uses the reflow reason and reflow command from the parent's -// reflow state -inline nsReflowState::nsReflowState(nsIFrame* aFrame, - const nsReflowState& aParentReflowState, - const nsSize& aMaxSize) -{ - reason = aParentReflowState.reason; - reflowCommand = aParentReflowState.reflowCommand; - maxSize = aMaxSize; - parentReflowState = &aParentReflowState; - frame = aFrame; - widthConstraint = eReflowSize_Constrained; - heightConstraint = eReflowSize_Constrained; - minSize.width = 0; - minSize.height = 0; -} - -// Constructs a reflow state that overrides the reflow reason of the parent -// reflow state. Sets the reflow command to NULL -inline nsReflowState::nsReflowState(nsIFrame* aFrame, - const nsReflowState& aParentReflowState, - const nsSize& aMaxSize, - nsReflowReason aReflowReason) -{ - reason = aReflowReason; - reflowCommand = nsnull; - maxSize = aMaxSize; - parentReflowState = &aParentReflowState; - frame = aFrame; - widthConstraint = eReflowSize_Constrained; - heightConstraint = eReflowSize_Constrained; - minSize.width = 0; - minSize.height = 0; -} - /* ----- nsIListFilter definition ----- */ class nsIListFilter { diff --git a/layout/base/public/nsIFrameReflow.h b/layout/base/public/nsIFrameReflow.h new file mode 100644 index 00000000000..723454c236f --- /dev/null +++ b/layout/base/public/nsIFrameReflow.h @@ -0,0 +1,310 @@ +/* -*- 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 nsIFrameReflow_h___ +#define nsIFrameReflow_h___ + +#include "nslayout.h" +#include "nsISupports.h" +#include "nsSize.h" + +class nsIFrame; +class nsIPresContext; +class nsIReflowCommand; + +//---------------------------------------------------------------------- + +/** + * Reflow metrics used to return the frame's desired size and alignment + * information. + * + * @see #Reflow() + * @see #GetReflowMetrics() + */ +struct nsReflowMetrics { + nscoord width, height; // desired width and height + nscoord ascent, descent; + + // Set this to null if you don't need to compute the max element size + nsSize* maxElementSize; + + nsReflowMetrics(nsSize* aMaxElementSize) { + maxElementSize = aMaxElementSize; + } +}; + +//---------------------------------------------------------------------- + +/** + * Constant used to indicate an unconstrained size. + * + * @see #Reflow() + */ +#define NS_UNCONSTRAINEDSIZE NS_MAXSIZE + +//---------------------------------------------------------------------- + +/** + * The reason the frame is being reflowed. + * XXX Should probably be a #define so it can be extended for specialized + * reflow interfaces... + * + * @see nsReflowState + */ +enum nsReflowReason { + eReflowReason_Initial = 0, // initial reflow of a newly created frame + eReflowReason_Incremental = 1, // an incremental change has occured. see the reflow command for details + eReflowReason_Resize = 2 // general request to determine a desired size +}; + +//---------------------------------------------------------------------- + +/** + * Reflow state passed to a frame during reflow. The reflow states are linked + * together. The max size represents the max available space in which to reflow + * your frame, and is computed as the parent frame's available content area + * minus any room for margins that your frame requests. The min size represents + * the min available space in which to reflow your frame + * + * @see #Reflow() + */ +struct nsReflowState { + const nsReflowState* parentReflowState; // pointer to parent's reflow state + nsIFrame* frame; // the frame being reflowed + nsReflowReason reason; // the reason for the reflow + nsIReflowCommand* reflowCommand; // only used for incremental changes + nsSize maxSize; // the max available space in which to reflow + + // Note: there is no copy constructor so that the compiler can + // generate an optimal one. + + // Constructs an initial reflow state (no parent reflow state) for a + // non-incremental reflow command + nsReflowState(nsIFrame* aFrame, + nsReflowReason aReason, + const nsSize& aMaxSize); + + // Constructs an initial reflow state (no parent reflow state) for an + // incremental reflow command + nsReflowState(nsIFrame* aFrame, + nsIReflowCommand& aReflowCommand, + const nsSize& aMaxSize); + + // Construct a reflow state for the given frame, parent reflow state, and + // max size. Uses the reflow reason and reflow command from the parent's + // reflow state + nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize); + + // Constructs a reflow state that overrides the reflow reason of the parent + // reflow state. Sets the reflow command to NULL + nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize, + nsReflowReason aReflowReason); +}; + +//---------------------------------------------------------------------- + +/** + * Reflow status returned by the reflow methods. + * + * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its + * content, and that the parent frame should create a continuing frame. + * If this bit isn't set it means the frame does map all its content. + * + * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is + * dirty, and also needs to be reflowed. This status only makes sense + * for a frame that is not complete, i.e. you wouldn't set both + * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW + * + * The low 8 bits of the nsReflowStatus are reserved for future extensions; + * the remaining 24 bits are zero (and available for extensions; however + * API's that accept/return nsReflowStatus must not receive/return any + * extension bits). + * + * @see #Reflow() + * @see #CreateContinuingFrame() + */ +typedef PRUint32 nsReflowStatus; + +#define NS_FRAME_COMPLETE 0 // Note: not a bit! +#define NS_FRAME_NOT_COMPLETE 0x1 +#define NS_FRAME_REFLOW_NEXTINFLOW 0x2 + +#define NS_FRAME_IS_COMPLETE(status) \ + (0 == ((status) & NS_FRAME_NOT_COMPLETE)) + +#define NS_FRAME_IS_NOT_COMPLETE(status) \ + (0 != ((status) & NS_FRAME_NOT_COMPLETE)) + +// This macro tests to see if an nsReflowStatus is an error value +// or just a regular return value +#define NS_IS_REFLOW_ERROR(_status) (PRInt32(_status) < 0) + +//---------------------------------------------------------------------- + +/** + * DidReflow status values. + */ +typedef PRBool nsDidReflowStatus; + +#define NS_FRAME_REFLOW_NOT_FINISHED PR_FALSE +#define NS_FRAME_REFLOW_FINISHED PR_TRUE + +//---------------------------------------------------------------------- + +/** + * Basic layout protocol. + */ +template class nsIFrameReflow : public nsISupports { +public: + /** + * Pre-reflow hook. Before a frame is incrementally reflowed or + * resize-reflowed this method will be called warning the frame of + * the impending reflow. This call may be invoked zero or more times + * before a subsequent DidReflow call. This method when called the + * first time will set the NS_FRAME_IN_REFLOW bit in the frame + * state bits. + */ + NS_IMETHOD WillReflow(nsIPresContext& aPresContext) = 0; + + /** + * The frame is given a maximum size and asked for its desired size. + * This is the frame's opportunity to reflow its children. + * + * @param aDesiredSize out parameter where you should return the + * desired size and ascent/descent info. You should include any + * space you want for border/padding in the desired size you return. + * + * It's okay to return a desired size that exceeds the max + * size if that's the smallest you can be, i.e. it's your + * minimum size. + * + * maxElementSize is an optional parameter for returning your + * maximum element size. If may be null in which case you + * don't have to compute a maximum element size. The + * maximum element size must be less than or equal to your + * desired size. + * + * @param aReflowState information about your reflow including the reason + * for the reflow and the available space in which to lay out. Each + * dimension of the available space can either be constrained or + * unconstrained (a value of NS_UNCONSTRAINEDSIZE). If constrained + * you should choose a value that's less than or equal to the + * constrained size. If unconstrained you can choose as + * large a value as you like. + * + * Note that the available space can be negative. In this case you + * still must return an accurate desired size. If you're a container + * you must always reflow at least one frame regardless of the + * available space + */ + NS_IMETHOD Reflow(nsIPresContext& aPresContext, + ReflowMetrics& aDesiredSize, + const ReflowState& aReflowState, + nsReflowStatus& aStatus) = 0; + + /** + * Post-reflow hook. After a frame is incrementally reflowed or + * resize-reflowed this method will be called telling the frame of + * the outcome. This call may be invoked many times, while + * NS_FRAME_IN_REFLOW is set, before it is finally called once with + * a NS_FRAME_REFLOW_COMPLETE value. When called with a + * NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the + * frame state will be cleared. + */ + NS_IMETHOD DidReflow(nsIPresContext& aPresContext, + nsDidReflowStatus aStatus) = 0; + + /** + * Return the reflow metrics for this frame. If the frame is a + * container then the values for ascent and descent are computed + * across the the various children in the appropriate manner + * (e.g. for a line frame the ascent value would be the maximum + * ascent of the line's children). Note that the metrics returned + * apply to the frame as it exists at the time of the call. + */ + NS_IMETHOD GetReflowMetrics(nsIPresContext& aPresContext, + ReflowMetrics& aMetrics) = 0; + +private: + NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; + NS_IMETHOD_(nsrefcnt) Release(void) = 0; +}; + +//---------------------------------------------------------------------- + +// Constructs an initial reflow state (no parent reflow state) for a +// non-incremental reflow command +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + nsReflowReason aReason, + const nsSize& aMaxSize) +{ + NS_PRECONDITION(aReason != eReflowReason_Incremental, "unexpected reflow reason"); + reason = aReason; + reflowCommand = nsnull; + maxSize = aMaxSize; + parentReflowState = nsnull; + frame = aFrame; +} + +// Constructs an initial reflow state (no parent reflow state) for an +// incremental reflow command +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + nsIReflowCommand& aReflowCommand, + const nsSize& aMaxSize) +{ + reason = eReflowReason_Incremental; + reflowCommand = &aReflowCommand; + maxSize = aMaxSize; + parentReflowState = nsnull; + frame = aFrame; +} + +// Construct a reflow state for the given frame, parent reflow state, and +// max size. Uses the reflow reason and reflow command from the parent's +// reflow state +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize) +{ + reason = aParentReflowState.reason; + reflowCommand = aParentReflowState.reflowCommand; + maxSize = aMaxSize; + parentReflowState = &aParentReflowState; + frame = aFrame; +} + +// Constructs a reflow state that overrides the reflow reason of the parent +// reflow state. Sets the reflow command to NULL +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize, + nsReflowReason aReflowReason) +{ + reason = aReflowReason; + reflowCommand = nsnull; + maxSize = aMaxSize; + parentReflowState = &aParentReflowState; + frame = aFrame; +} + +#endif /* nsIFrameReflow_h___ */ + + diff --git a/layout/base/public/nsIReflowCommand.h b/layout/base/public/nsIReflowCommand.h index f3fcb55f516..5818b52f0a5 100644 --- a/layout/base/public/nsIReflowCommand.h +++ b/layout/base/public/nsIReflowCommand.h @@ -22,7 +22,7 @@ class nsIFrame; class nsIPresContext; -struct nsReflowMetrics; +struct nsHTMLReflowMetrics; struct nsSize; // IID for the nsIReflowCommand interface {C3658E40-FF20-11d1-85BC-00A02468FAB6} @@ -91,9 +91,9 @@ public: * * @see nsIFrame#Reflow() */ - NS_IMETHOD Dispatch(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize) = 0; + NS_IMETHOD Dispatch(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsSize& aMaxSize) = 0; /** * Get the next frame in the command processing path. Note that this removes diff --git a/layout/base/public/nsIRunaround.h b/layout/base/public/nsIRunaround.h index 4ded27862c9..e69de29bb2d 100644 --- a/layout/base/public/nsIRunaround.h +++ b/layout/base/public/nsIRunaround.h @@ -1,75 +0,0 @@ -/* -*- 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 nsIRunaround_h___ -#define nsIRunaround_h___ - -#include "nsIFrame.h" - -// IID for the nsIRunaround interface {3C6ABCF0-C028-11d1-853F-00A02468FAB6} -#define NS_IRUNAROUND_IID \ -{ 0x3c6abcf0, 0xc028, 0x11d1, \ - {0x85, 0x3f, 0x0, 0xa0, 0x24, 0x68, 0xfa, 0xb6}} - -/** - * An interface for handling reflow that allows direct access to the space - * manager. Note that this interface is not an nsISupports interface, and - * therefore you cannot QueryInterface() back - */ -class nsIRunaround -{ -public: - /** - * Reflow. The frame is given a maximum size and asked for its desired - * rect. The space manager should be used to do runaround of anchored - * items. - * - * @param aSpaceManager the space manager to use. The caller has translated - * the coordinate system so the frame has its own local coordinate - * space with an origin of (0, 0). If you translate the coordinate - * space you must restore it before returning. - * @param aMaxSize the available space in which to lay out. Each dimension - * can either be constrained or unconstrained (a value of - * NS_UNCONSTRAINEDSIZE). If constrained you should choose a value - * that's less than or equal to the constrained size. If unconstrained - * you can choose as large a value as you like. - * - * It's okay to return a desired size that exceeds the max size if - * that's the smallest you can be, i.e. it's your minimum size. - * - * @param aDesiredRect out parameter where you should return the desired - * origin and size. You should include any space you want for border - * and padding in the desired size. - * - * The origin of the desired rect is relative to the upper-left of the - * local coordinate space. - * - * @param aMaxElementSize an optional parameter for returning your maximum - * element size. If may be null in which case you don't have to compute - * a maximum element size - * - * @see nsISpaceManager#Translate() - */ - NS_IMETHOD ReflowAround(nsIPresContext& aPresContext, - nsISpaceManager* aSpaceManager, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsRect& aDesiredRect, // XXX FIX ME - nsReflowStatus& aStatus) = 0; -}; - -#endif /* nsIRunaround_h___ */ diff --git a/layout/forms/nsFileControlFrame.cpp b/layout/forms/nsFileControlFrame.cpp index 68dd250e68d..22da587aafa 100644 --- a/layout/forms/nsFileControlFrame.cpp +++ b/layout/forms/nsFileControlFrame.cpp @@ -184,7 +184,7 @@ void SetType(nsIHTMLContent* aElement, nsString& aValue) } NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsReflowStatus& aStatus) { @@ -219,23 +219,27 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, } nsSize maxSize = aReflowState.maxSize; - nsReflowMetrics desiredSize = aDesiredSize; + nsHTMLReflowMetrics desiredSize = aDesiredSize; aDesiredSize.width = CONTROL_SPACING; aDesiredSize.height = 0; childFrame = mFirstChild; nsPoint offset(0,0); while (nsnull != childFrame) { // reflow, place, size the children nsReflowState reflowState(childFrame, aReflowState, maxSize); - childFrame->WillReflow(aPresContext); - nsresult result = childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - nsRect rect(offset.x, offset.y, desiredSize.width, desiredSize.height); - childFrame->SetRect(rect); - maxSize.width -= desiredSize.width; - aDesiredSize.width += desiredSize.width; - aDesiredSize.height = desiredSize.height; - childFrame->GetNextSibling(childFrame); - offset.x += desiredSize.width + CONTROL_SPACING; + nsIHTMLReflow* htmlReflow; + + if (NS_OK == childFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { + htmlReflow->WillReflow(aPresContext); + nsresult result = htmlReflow->Reflow(aPresContext, desiredSize, reflowState, aStatus); + NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + nsRect rect(offset.x, offset.y, desiredSize.width, desiredSize.height); + childFrame->SetRect(rect); + maxSize.width -= desiredSize.width; + aDesiredSize.width += desiredSize.width; + aDesiredSize.height = desiredSize.height; + childFrame->GetNextSibling(childFrame); + offset.x += desiredSize.width + CONTROL_SPACING; + } } aDesiredSize.ascent = aDesiredSize.height; diff --git a/layout/forms/nsFileControlFrame.h b/layout/forms/nsFileControlFrame.h index 537575a1b02..35edda5f9e1 100644 --- a/layout/forms/nsFileControlFrame.h +++ b/layout/forms/nsFileControlFrame.h @@ -35,7 +35,7 @@ public: NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD Reflow(nsIPresContext& aCX, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsReflowStatus& aStatus); diff --git a/layout/forms/nsFormControlFrame.cpp b/layout/forms/nsFormControlFrame.cpp index 4998674b5c1..93bb61c3668 100644 --- a/layout/forms/nsFormControlFrame.cpp +++ b/layout/forms/nsFormControlFrame.cpp @@ -164,7 +164,7 @@ nsFormControlFrame::Paint(nsIPresContext& aPresContext, void nsFormControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, + nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize) { // get the css size and let the frame use or override it @@ -183,7 +183,7 @@ nsFormControlFrame::GetDesiredSize(nsIPresContext* aPresContext, void nsFormControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredSize) + nsHTMLReflowMetrics& aDesiredSize) { nsSize ignore; GetDesiredSize(aPresContext, aReflowState, aDesiredSize, ignore); @@ -209,7 +209,7 @@ nsFormControlFrame::DidReflow(nsIPresContext& aPresContext, NS_METHOD nsFormControlFrame::Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsReflowStatus& aStatus) { diff --git a/layout/forms/nsFormControlFrame.h b/layout/forms/nsFormControlFrame.h index 429a298d751..708044cf24f 100644 --- a/layout/forms/nsFormControlFrame.h +++ b/layout/forms/nsFormControlFrame.h @@ -118,7 +118,7 @@ public: * @see nsIFrame::Reflow */ NS_IMETHOD Reflow(nsIPresContext& aCX, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsReflowStatus& aStatus); @@ -216,11 +216,11 @@ protected: */ virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredSize); + nsHTMLReflowMetrics& aDesiredSize); virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, + nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); NS_IMETHOD GetFont(nsIPresContext* aPresContext, nsFont& aFont); diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index 89137e5be66..0054efd54aa 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -170,7 +170,7 @@ nsTextControlFrame::EnterPressed(nsIPresContext& aPresContext) void nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, + nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize) { nsCompatibility mode; diff --git a/layout/forms/nsTextControlFrame.h b/layout/forms/nsTextControlFrame.h index 7a792801a05..1f26d667323 100644 --- a/layout/forms/nsTextControlFrame.h +++ b/layout/forms/nsTextControlFrame.h @@ -59,7 +59,7 @@ protected: virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, + nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); }; diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp index f373107dbea..b7aae99a48c 100644 --- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -43,7 +43,7 @@ public: NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout, nsIReflowCommand* aReflowCommand); NS_IMETHOD InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState); protected: @@ -110,7 +110,7 @@ BRFrame::FindTextRuns(nsLineLayout& aLineLayout, NS_IMETHODIMP BRFrame::InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState) { if (nsnull != aMetrics.maxElementSize) { diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index ebc709d69be..5929f72bb5c 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -126,7 +126,7 @@ class nsBlockFrame; struct nsBlockReflowState : public nsFrameReflowState { nsBlockReflowState(nsIPresContext& aPresContext, const nsReflowState& aReflowState, - const nsReflowMetrics& aMetrics, + const nsHTMLReflowMetrics& aMetrics, nsISpaceManager* aSpaceManager); ~nsBlockReflowState(); @@ -251,7 +251,7 @@ public: // nsIRunaround NS_IMETHOD ReflowAround(nsIPresContext& aPresContext, nsISpaceManager* aSpaceManager, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus); @@ -312,9 +312,9 @@ public: nsresult ResizeReflow(nsBlockReflowState& aState); - void ComputeFinalSize(nsBlockReflowState& aState, - nsReflowMetrics& aMetrics, - nsRect& aDesiredRect); + void ComputeFinalSize(nsBlockReflowState& aState, + nsHTMLReflowMetrics& aMetrics, + nsRect& aDesiredRect); nsresult ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine); @@ -412,14 +412,14 @@ public: NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout, nsIReflowCommand* aReflowCommand); NS_IMETHOD InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState); void SetListItemOrdinal(nsBlockReflowState& aBlockState); void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aMetrics); + nsHTMLReflowMetrics& aMetrics); void GetListItemText(nsIPresContext& aCX, const nsStyleList& aMol, @@ -749,7 +749,7 @@ UpdateBulletCB(nsIPresContext& aPresContext, nsIFrame* aFrame, PRIntn aStatus) void BulletFrame::GetDesiredSize(nsIPresContext* aCX, const nsReflowState& aReflowState, - nsReflowMetrics& aMetrics) + nsHTMLReflowMetrics& aMetrics) { const nsStyleList* myList = (const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List); @@ -831,7 +831,7 @@ BulletFrame::GetDesiredSize(nsIPresContext* aCX, NS_IMETHODIMP BulletFrame::InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState) { // Get the base size @@ -1295,7 +1295,7 @@ GetParentLeftPadding(const nsReflowState* aReflowState) nsBlockReflowState::nsBlockReflowState(nsIPresContext& aPresContext, const nsReflowState& aReflowState, - const nsReflowMetrics& aMetrics, + const nsHTMLReflowMetrics& aMetrics, nsISpaceManager* aSpaceManager) : nsFrameReflowState(aPresContext, aReflowState, aMetrics), mLineLayout(aPresContext, aSpaceManager) @@ -1691,7 +1691,7 @@ nsBlockFrame::FirstChild(nsIFrame*& aFirstChild) const NS_IMETHODIMP nsBlockFrame::ReflowAround(nsIPresContext& aPresContext, nsISpaceManager* aSpaceManager, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) @@ -1851,9 +1851,9 @@ nsBlockFrame::RenumberLists(nsBlockReflowState& aState) } void -nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState, - nsReflowMetrics& aMetrics, - nsRect& aDesiredRect) +nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState, + nsHTMLReflowMetrics& aMetrics, + nsRect& aDesiredRect) { aDesiredRect.x = 0; aDesiredRect.y = 0; @@ -3190,7 +3190,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, availSize.width = NS_UNCONSTRAINEDSIZE; availSize.height = NS_UNCONSTRAINEDSIZE; nsReflowState reflowState(mBullet, aState, availSize); - nsReflowMetrics metrics(nsnull); + nsHTMLReflowMetrics metrics(nsnull); nsIInlineReflow* iir; if (NS_OK == mBullet->QueryInterface(kIInlineReflowIID, (void**) &iir)) { mBullet->WillReflow(aState.mPresContext); @@ -3724,11 +3724,14 @@ nsBlockFrame::ReflowFloater(nsIPresContext& aPresContext, // Resize reflow the anchored item into the available space // XXX Check for complete? - nsReflowMetrics desiredSize(nsnull); - nsReflowStatus status; - aFloaterFrame->WillReflow(aPresContext); - aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status); - aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height); + nsIHTMLReflow* floaterReflow; + if (NS_OK == aFloaterFrame->QueryInterface(kIHTMLReflowIID, (void**)&floaterReflow)) { + nsHTMLReflowMetrics desiredSize(nsnull); + nsReflowStatus status; + floaterReflow->WillReflow(aPresContext); + floaterReflow->Reflow(aPresContext, desiredSize, reflowState, status); + aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height); + } } PRBool diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index ebc709d69be..5929f72bb5c 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -126,7 +126,7 @@ class nsBlockFrame; struct nsBlockReflowState : public nsFrameReflowState { nsBlockReflowState(nsIPresContext& aPresContext, const nsReflowState& aReflowState, - const nsReflowMetrics& aMetrics, + const nsHTMLReflowMetrics& aMetrics, nsISpaceManager* aSpaceManager); ~nsBlockReflowState(); @@ -251,7 +251,7 @@ public: // nsIRunaround NS_IMETHOD ReflowAround(nsIPresContext& aPresContext, nsISpaceManager* aSpaceManager, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus); @@ -312,9 +312,9 @@ public: nsresult ResizeReflow(nsBlockReflowState& aState); - void ComputeFinalSize(nsBlockReflowState& aState, - nsReflowMetrics& aMetrics, - nsRect& aDesiredRect); + void ComputeFinalSize(nsBlockReflowState& aState, + nsHTMLReflowMetrics& aMetrics, + nsRect& aDesiredRect); nsresult ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine); @@ -412,14 +412,14 @@ public: NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout, nsIReflowCommand* aReflowCommand); NS_IMETHOD InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState); void SetListItemOrdinal(nsBlockReflowState& aBlockState); void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aMetrics); + nsHTMLReflowMetrics& aMetrics); void GetListItemText(nsIPresContext& aCX, const nsStyleList& aMol, @@ -749,7 +749,7 @@ UpdateBulletCB(nsIPresContext& aPresContext, nsIFrame* aFrame, PRIntn aStatus) void BulletFrame::GetDesiredSize(nsIPresContext* aCX, const nsReflowState& aReflowState, - nsReflowMetrics& aMetrics) + nsHTMLReflowMetrics& aMetrics) { const nsStyleList* myList = (const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List); @@ -831,7 +831,7 @@ BulletFrame::GetDesiredSize(nsIPresContext* aCX, NS_IMETHODIMP BulletFrame::InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState) { // Get the base size @@ -1295,7 +1295,7 @@ GetParentLeftPadding(const nsReflowState* aReflowState) nsBlockReflowState::nsBlockReflowState(nsIPresContext& aPresContext, const nsReflowState& aReflowState, - const nsReflowMetrics& aMetrics, + const nsHTMLReflowMetrics& aMetrics, nsISpaceManager* aSpaceManager) : nsFrameReflowState(aPresContext, aReflowState, aMetrics), mLineLayout(aPresContext, aSpaceManager) @@ -1691,7 +1691,7 @@ nsBlockFrame::FirstChild(nsIFrame*& aFirstChild) const NS_IMETHODIMP nsBlockFrame::ReflowAround(nsIPresContext& aPresContext, nsISpaceManager* aSpaceManager, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) @@ -1851,9 +1851,9 @@ nsBlockFrame::RenumberLists(nsBlockReflowState& aState) } void -nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState, - nsReflowMetrics& aMetrics, - nsRect& aDesiredRect) +nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState, + nsHTMLReflowMetrics& aMetrics, + nsRect& aDesiredRect) { aDesiredRect.x = 0; aDesiredRect.y = 0; @@ -3190,7 +3190,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, availSize.width = NS_UNCONSTRAINEDSIZE; availSize.height = NS_UNCONSTRAINEDSIZE; nsReflowState reflowState(mBullet, aState, availSize); - nsReflowMetrics metrics(nsnull); + nsHTMLReflowMetrics metrics(nsnull); nsIInlineReflow* iir; if (NS_OK == mBullet->QueryInterface(kIInlineReflowIID, (void**) &iir)) { mBullet->WillReflow(aState.mPresContext); @@ -3724,11 +3724,14 @@ nsBlockFrame::ReflowFloater(nsIPresContext& aPresContext, // Resize reflow the anchored item into the available space // XXX Check for complete? - nsReflowMetrics desiredSize(nsnull); - nsReflowStatus status; - aFloaterFrame->WillReflow(aPresContext); - aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status); - aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height); + nsIHTMLReflow* floaterReflow; + if (NS_OK == aFloaterFrame->QueryInterface(kIHTMLReflowIID, (void**)&floaterReflow)) { + nsHTMLReflowMetrics desiredSize(nsnull); + nsReflowStatus status; + floaterReflow->WillReflow(aPresContext); + floaterReflow->Reflow(aPresContext, desiredSize, reflowState, status); + aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height); + } } PRBool diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index ebc709d69be..5929f72bb5c 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -126,7 +126,7 @@ class nsBlockFrame; struct nsBlockReflowState : public nsFrameReflowState { nsBlockReflowState(nsIPresContext& aPresContext, const nsReflowState& aReflowState, - const nsReflowMetrics& aMetrics, + const nsHTMLReflowMetrics& aMetrics, nsISpaceManager* aSpaceManager); ~nsBlockReflowState(); @@ -251,7 +251,7 @@ public: // nsIRunaround NS_IMETHOD ReflowAround(nsIPresContext& aPresContext, nsISpaceManager* aSpaceManager, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus); @@ -312,9 +312,9 @@ public: nsresult ResizeReflow(nsBlockReflowState& aState); - void ComputeFinalSize(nsBlockReflowState& aState, - nsReflowMetrics& aMetrics, - nsRect& aDesiredRect); + void ComputeFinalSize(nsBlockReflowState& aState, + nsHTMLReflowMetrics& aMetrics, + nsRect& aDesiredRect); nsresult ReflowLinesAt(nsBlockReflowState& aState, LineData* aLine); @@ -412,14 +412,14 @@ public: NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout, nsIReflowCommand* aReflowCommand); NS_IMETHOD InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState); void SetListItemOrdinal(nsBlockReflowState& aBlockState); void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aMetrics); + nsHTMLReflowMetrics& aMetrics); void GetListItemText(nsIPresContext& aCX, const nsStyleList& aMol, @@ -749,7 +749,7 @@ UpdateBulletCB(nsIPresContext& aPresContext, nsIFrame* aFrame, PRIntn aStatus) void BulletFrame::GetDesiredSize(nsIPresContext* aCX, const nsReflowState& aReflowState, - nsReflowMetrics& aMetrics) + nsHTMLReflowMetrics& aMetrics) { const nsStyleList* myList = (const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List); @@ -831,7 +831,7 @@ BulletFrame::GetDesiredSize(nsIPresContext* aCX, NS_IMETHODIMP BulletFrame::InlineReflow(nsLineLayout& aLineLayout, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState) { // Get the base size @@ -1295,7 +1295,7 @@ GetParentLeftPadding(const nsReflowState* aReflowState) nsBlockReflowState::nsBlockReflowState(nsIPresContext& aPresContext, const nsReflowState& aReflowState, - const nsReflowMetrics& aMetrics, + const nsHTMLReflowMetrics& aMetrics, nsISpaceManager* aSpaceManager) : nsFrameReflowState(aPresContext, aReflowState, aMetrics), mLineLayout(aPresContext, aSpaceManager) @@ -1691,7 +1691,7 @@ nsBlockFrame::FirstChild(nsIFrame*& aFirstChild) const NS_IMETHODIMP nsBlockFrame::ReflowAround(nsIPresContext& aPresContext, nsISpaceManager* aSpaceManager, - nsReflowMetrics& aMetrics, + nsHTMLReflowMetrics& aMetrics, const nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) @@ -1851,9 +1851,9 @@ nsBlockFrame::RenumberLists(nsBlockReflowState& aState) } void -nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState, - nsReflowMetrics& aMetrics, - nsRect& aDesiredRect) +nsBlockFrame::ComputeFinalSize(nsBlockReflowState& aState, + nsHTMLReflowMetrics& aMetrics, + nsRect& aDesiredRect) { aDesiredRect.x = 0; aDesiredRect.y = 0; @@ -3190,7 +3190,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, availSize.width = NS_UNCONSTRAINEDSIZE; availSize.height = NS_UNCONSTRAINEDSIZE; nsReflowState reflowState(mBullet, aState, availSize); - nsReflowMetrics metrics(nsnull); + nsHTMLReflowMetrics metrics(nsnull); nsIInlineReflow* iir; if (NS_OK == mBullet->QueryInterface(kIInlineReflowIID, (void**) &iir)) { mBullet->WillReflow(aState.mPresContext); @@ -3724,11 +3724,14 @@ nsBlockFrame::ReflowFloater(nsIPresContext& aPresContext, // Resize reflow the anchored item into the available space // XXX Check for complete? - nsReflowMetrics desiredSize(nsnull); - nsReflowStatus status; - aFloaterFrame->WillReflow(aPresContext); - aFloaterFrame->Reflow(aPresContext, desiredSize, reflowState, status); - aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height); + nsIHTMLReflow* floaterReflow; + if (NS_OK == aFloaterFrame->QueryInterface(kIHTMLReflowIID, (void**)&floaterReflow)) { + nsHTMLReflowMetrics desiredSize(nsnull); + nsReflowStatus status; + floaterReflow->WillReflow(aPresContext); + floaterReflow->Reflow(aPresContext, desiredSize, reflowState, status); + aFloaterFrame->SizeTo(desiredSize.width, desiredSize.height); + } } PRBool diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index f89b29ce1fd..3f38dd9d251 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -29,6 +29,7 @@ #include "nsIView.h" #include "nsVoidArray.h" #include "nsISizeOfHandler.h" +#include "nsHTMLIIDs.h" #ifdef NS_DEBUG #undef NOISY @@ -114,7 +115,11 @@ nsContainerFrame::DidReflow(nsIPresContext& aPresContext, nsIFrame* kid; FirstChild(kid); while (nsnull != kid) { - kid->DidReflow(aPresContext, aStatus); + nsIHTMLReflow* htmlReflow; + + if (NS_OK == kid->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { + htmlReflow->DidReflow(aPresContext, aStatus); + } kid->GetNextSibling(kid); } } @@ -287,7 +292,7 @@ NS_METHOD nsContainerFrame::GetCursorAndContentAt(nsIPresContext& aPresContext, */ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState) { nsReflowStatus status; @@ -299,7 +304,10 @@ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, aKidFrame->GetFrameState(kidFrameState); NS_ASSERTION(kidFrameState & NS_FRAME_IN_REFLOW, "kid frame is not in reflow"); #endif - aKidFrame->Reflow(*aPresContext, aDesiredSize, aReflowState, status); + nsIHTMLReflow* htmlReflow; + if (NS_OK == aKidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { + htmlReflow->Reflow(*aPresContext, aDesiredSize, aReflowState, status); + } if (NS_FRAME_IS_COMPLETE(status)) { nsIFrame* kidNextInFlow; diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index 9b32bc28405..5f4db36dda1 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -115,7 +115,7 @@ protected: */ nsReflowStatus ReflowChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState); /** diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 36b0705e8c2..1473415f81e 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -39,6 +39,7 @@ #include "nsDocument.h" #include "nsIDeviceContext.h" #include "nsIPresShell.h" +#include "nsHTMLIIDs.h" // Some Misc #defines #define SELECTION_DEBUG 0 @@ -267,7 +268,10 @@ nsresult nsFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) } static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kClassIID, kIFrameIID); - if (aIID.Equals(kClassIID) || (aIID.Equals(kISupportsIID))) { + if (aIID.Equals(kIHTMLReflowIID)) { + *aInstancePtr = (void*)(nsIHTMLReflow*)this; + return NS_OK; + } else if (aIID.Equals(kClassIID) || aIID.Equals(kISupportsIID)) { *aInstancePtr = (void*)this; return NS_OK; } @@ -1083,7 +1087,7 @@ nsFrame::SetFrameState(nsFrameState aNewState) return NS_OK; } -// Resize reflow methods +// nsIHTMLReflow member functions NS_METHOD nsFrame::WillReflow(nsIPresContext& aPresContext) @@ -1120,7 +1124,7 @@ nsFrame::DidReflow(nsIPresContext& aPresContext, } NS_METHOD nsFrame::Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsReflowStatus& aStatus) { @@ -1141,6 +1145,16 @@ NS_METHOD nsFrame::Reflow(nsIPresContext& aPresContext, return NS_OK; } +NS_METHOD nsFrame::GetReflowMetrics(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aMetrics) +{ + aMetrics.width = mRect.width; + aMetrics.height = mRect.height; + aMetrics.ascent = mRect.height; + aMetrics.descent = 0; + return NS_OK; +} + NS_METHOD nsFrame::ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, nsISupports* aSubContent) @@ -1156,16 +1170,6 @@ NS_IMETHODIMP nsFrame::AttributeChanged(nsIPresContext* aPresContext, return NS_OK; } -NS_METHOD nsFrame::GetReflowMetrics(nsIPresContext& aPresContext, - nsReflowMetrics& aMetrics) -{ - aMetrics.width = mRect.width; - aMetrics.height = mRect.height; - aMetrics.ascent = mRect.height; - aMetrics.descent = 0; - return NS_OK; -} - // Flow member functions NS_METHOD nsFrame::IsSplittable(nsSplittableType& aIsSplittable) const diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 8e75f321579..3dd3028853e 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -19,6 +19,7 @@ #define nsFrame_h___ #include "nsIFrame.h" +#include "nsIHTMLReflow.h" #include "nsRect.h" #include "nsISelection.h" #include "nsSelectionRange.h" @@ -87,7 +88,7 @@ //---------------------------------------------------------------------- // Implementation of a simple frame with no children and that isn't splittable -class nsFrame : public nsIFrame +class nsFrame : public nsIFrame, public nsIHTMLReflow { public: /** @@ -140,13 +141,6 @@ public: PRInt32& aCursor); NS_IMETHOD GetFrameState(nsFrameState& aResult); NS_IMETHOD SetFrameState(nsFrameState aNewState); - NS_IMETHOD WillReflow(nsIPresContext& aPresContext); - NS_IMETHOD DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus); - NS_IMETHOD Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsReflowStatus& aStatus); NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, @@ -155,8 +149,6 @@ public: nsIContent* aChild, nsIAtom* aAttribute, PRInt32 aHint); - NS_IMETHOD GetReflowMetrics(nsIPresContext& aPresContext, - nsReflowMetrics& aMetrics); NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const; NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext, nsIFrame* aParent, @@ -186,6 +178,17 @@ public: NS_IMETHOD ListTag(FILE* out = stdout) const; NS_IMETHOD VerifyTree() const; + // nsIHTMLReflow + NS_IMETHOD WillReflow(nsIPresContext& aPresContext); + NS_IMETHOD Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus); + NS_IMETHOD DidReflow(nsIPresContext& aPresContext, + nsDidReflowStatus aStatus); + NS_IMETHOD GetReflowMetrics(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aMetrics); + // Selection Methods NS_IMETHOD HandlePress(nsIPresContext& aPresContext, nsGUIEvent * aEvent, diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp index e13d3c350b7..a8488f0239b 100644 --- a/layout/generic/nsFrameFrame.cpp +++ b/layout/generic/nsFrameFrame.cpp @@ -113,7 +113,7 @@ public: const nsRect& aDirtyRect); NS_IMETHOD Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsReflowStatus& aStatus); NS_IMETHOD VerifyTree() const; @@ -124,7 +124,7 @@ protected: virtual ~nsHTMLFrameOuterFrame(); virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredSize); + nsHTMLReflowMetrics& aDesiredSize); virtual PRIntn GetSkipSides() const; PRBool *mIsInline; }; @@ -151,7 +151,7 @@ public: * @see nsIFrame::Reflow */ NS_IMETHOD Reflow(nsIPresContext& aCX, - nsReflowMetrics& aDesiredSize, + nsHTMLReflowMetrics& aDesiredSize, const nsReflowState& aReflowState, nsReflowStatus& aStatus); @@ -172,7 +172,7 @@ protected: virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredSize); + nsHTMLReflowMetrics& aDesiredSize); nsIWebShell* mWebShell; PRBool mCreatingViewer; @@ -224,7 +224,7 @@ nsHTMLFrameOuterFrame::GetSkipSides() const void nsHTMLFrameOuterFrame::GetDesiredSize(nsIPresContext* aPresContext, const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredSize) + nsHTMLReflowMetrics& aDesiredSize) { // processing does not use this routine, only