/* -*- 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.1 (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.org 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. * * Contributor(s): */ #ifndef nsIFrame_h___ #define nsIFrame_h___ #include #include "nslayout.h" #include "nsISupports.h" #include "nsSize.h" #include "nsGUIEvent.h" #include "nsStyleConsts.h" #include "nsStyleStruct.h" #include "nsStyleCoord.h" #include "nsHTMLReflowState.h" class nsIAtom; class nsIContent; class nsIPresContext; class nsIPresShell; class nsIRenderingContext; class nsISizeOfHandler; class nsIStyleContext; class nsIView; class nsIWidget; class nsAutoString; class nsString; class nsIFocusTracker; class nsStyleChangeList; class nsBlockFrame; class nsLineLayout; struct nsPeekOffsetStruct; struct nsPoint; struct nsRect; struct nsStyleStruct; class nsIDOMRange; class nsICaret; struct PRLogModuleInfo; // IID for the nsIFrame interface // a6cf9050-15b3-11d2-932e-00805f8add32 #define NS_IFRAME_IID \ { 0xa6cf9050, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} /** * 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. * * The choices are splittable, not splittable at all, and splittable in * a non-rectangular fashion. This last type only applies to block-level * elements, and indicates whether splitting can be used when doing runaround. * If you can split across page boundaries, but you expect each continuing * frame to be the same width then return frSplittable and not * frSplittableNonRectangular. * * @see #IsSplittable() */ typedef PRUint32 nsSplittableType; #define NS_FRAME_NOT_SPLITTABLE 0 // Note: not a bit! #define NS_FRAME_SPLITTABLE 0x1 #define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3 #define NS_FRAME_IS_SPLITTABLE(type)\ (0 != ((type) & NS_FRAME_SPLITTABLE)) #define NS_FRAME_IS_NOT_SPLITTABLE(type)\ (0 == ((type) & NS_FRAME_SPLITTABLE)) //---------------------------------------------------------------------- /** * Frame state bits. Any bits not listed here are reserved for future * extensions, but must be stored by the frames. */ typedef PRUint32 nsFrameState; #define NS_FRAME_IN_REFLOW 0x00000001 // This bit is set when a frame is created. After it has been reflowed // once (during the DidReflow with a finished state) the bit is // cleared. #define NS_FRAME_FIRST_REFLOW 0x00000002 // If this bit is is set, then the view position and size should be // kept in sync with the frame position and size. If the bit is not // set then it's the responsibility of the frame itself (or whoever // created the view) to position and size its associated view #define NS_FRAME_SYNC_FRAME_AND_VIEW 0x00000004 // If this bit is set, then there is a child frame in the frame that // extends outside this frame's bounding box. The implication is that // the frames rect does not completely cover its children and // therefore operations like rendering and hit testing (for example) // must operate differently. #define NS_FRAME_OUTSIDE_CHILDREN 0x00000008 // If this bit is set, then a reference to the frame is being held // elsewhere. The frame may want to send a notification when it is // destroyed to allow these references to be cleared. #define NS_FRAME_EXTERNAL_REFERENCE 0x00000010 // If this bit is set, then the frame is a replaced element. For example, // a frame displaying an image #define NS_FRAME_REPLACED_ELEMENT 0x00000020 // If this bit is set, then the frame corresponds to generated content #define NS_FRAME_GENERATED_CONTENT 0x00000040 // If this bit is set, then the frame has requested one or more image // loads via the nsIPresContext.StartLoadImage API at some time during // its lifetime. #define NS_FRAME_HAS_LOADED_IMAGES 0x00000080 // If this bit is set, then the frame is has been moved out of the flow, // e.g., it is absolutely positioned or floated #define NS_FRAME_OUT_OF_FLOW 0x00000100 // If this bit is set, then the frame reflects content that may be selected #define NS_FRAME_SELECTED_CONTENT 0x00000200 // If this bit is set, then the frame is dirty and needs to be reflowed. // This bit is set when the frame is first created #define NS_FRAME_IS_DIRTY 0x00000400 // If this bit is set then the frame is unflowable. #define NS_FRAME_IS_UNFLOWABLE 0x00000800 // The low 16 bits of the frame state word are reserved by this API. #define NS_FRAME_RESERVED 0x0000FFFF // The upper 16 bits of the frame state word are reserved for frame // implementations. #define NS_FRAME_IMPL_RESERVED 0xFFFF0000 //---------------------------------------------------------------------- enum nsFramePaintLayer { eFramePaintLayer_Underlay = 0, eFramePaintLayer_Content = 1, eFramePaintLayer_Overlay = 2 }; enum nsSelectionAmount { eSelectCharacter = 0, eSelectWord = 1, eSelectLine = 2, //previous drawn line in flow. eSelectBeginLine = 3, eSelectEndLine = 4, eSelectNoAmount = 5, //just bounce back current offset. eSelectDir = 6 //select next/previous frame based on direction }; enum nsDirection { eDirNext = 0, eDirPrevious= 1 }; enum nsSpread { eSpreadNone = 0, eSpreadAcross = 1, eSpreadDown = 2 }; //---------------------------------------------------------------------- /** * Reflow metrics used to return the frame's desired size and alignment * information. * * @see #Reflow() */ struct nsHTMLReflowMetrics { nscoord width, height; // [OUT] desired width and height nscoord ascent, descent; // [OUT] ascent and descent information // Set this to null if you don't need to compute the max element size nsSize* maxElementSize; // [IN OUT] // Carried out bottom margin values. This is the collapsed // (generational) bottom margin value. nscoord mCarriedOutBottomMargin; // For frames that have children that stick outside their rect // (NS_FRAME_OUTSIDE_CHILDREN) this rectangle will contain the // absolute bounds of the frame. Since the frame doesn't know where // it is going to be positioned in its parent, the assumption is // that it is placed at 0,0 when computing this area. nsRect mCombinedArea; nsHTMLReflowMetrics(nsSize* aMaxElementSize) { maxElementSize = aMaxElementSize; mCarriedOutBottomMargin = 0; mCombinedArea.x = 0; mCombinedArea.y = 0; mCombinedArea.width = 0; mCombinedArea.height = 0; // XXX These are OUT parameters and so they shouldn't have to be // initialized, but there are some bad frame classes that aren't // properly setting them when returning from Reflow()... width = height = 0; ascent = descent = 0; } void AddBorderPaddingToMaxElementSize(const nsMargin& aBorderPadding) { maxElementSize->width += aBorderPadding.left + aBorderPadding.right; maxElementSize->height += aBorderPadding.top + aBorderPadding.bottom; } }; // Carried out margin flags #define NS_CARRIED_TOP_MARGIN_IS_AUTO 0x1 #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2 //---------------------------------------------------------------------- // For HTML reflow we rename with the different paint layers are // actually used for. #define NS_FRAME_PAINT_LAYER_BACKGROUND eFramePaintLayer_Underlay #define NS_FRAME_PAINT_LAYER_FLOATERS eFramePaintLayer_Content #define NS_FRAME_PAINT_LAYER_FOREGROUND eFramePaintLayer_Overlay #define NS_FRAME_PAINT_LAYER_DEBUG eFramePaintLayer_Overlay /** * 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() */ 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) /** * Extensions to the reflow status bits defined by nsIFrameReflow */ // This bit is set, when a break is requested. This bit is orthogonal // to the nsIFrame::nsReflowStatus completion bits. #define NS_INLINE_BREAK 0x0100 // When a break is requested, this bit when set indicates that the // break should occur after the frame just reflowed; when the bit is // clear the break should occur before the frame just reflowed. #define NS_INLINE_BREAK_BEFORE 0x0000 #define NS_INLINE_BREAK_AFTER 0x0200 // The type of break requested can be found in these bits. #define NS_INLINE_BREAK_TYPE_MASK 0xF000 //---------------------------------------- // Macros that use those bits #define NS_INLINE_IS_BREAK(_status) \ (0 != ((_status) & NS_INLINE_BREAK)) #define NS_INLINE_IS_BREAK_AFTER(_status) \ (0 != ((_status) & NS_INLINE_BREAK_AFTER)) #define NS_INLINE_IS_BREAK_BEFORE(_status) \ (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER))) #define NS_INLINE_GET_BREAK_TYPE(_status) (((_status) >> 12) & 0xF) #define NS_INLINE_MAKE_BREAK_TYPE(_type) ((_type) << 12) // Construct a line-break-before status. Note that there is no // completion status for a line-break before because we *know* that // the frame will be reflowed later and hence it's current completion // status doesn't matter. #define NS_INLINE_LINE_BREAK_BEFORE() \ (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE | \ NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE)) // Take a completion status and add to it the desire to have a // line-break after. For this macro we do need the completion status // because the user of the status will need to know whether to // continue the frame or not. #define NS_INLINE_LINE_BREAK_AFTER(_completionStatus) \ ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | \ NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE)) //---------------------------------------------------------------------- /** * 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. * * Frames can have multiple child lists: the default unnamed child list * (referred to as the principal child list, and additional named * child lists. There is an ordering of frames within a child list, but * there is no order defined between frames in different child lists of * the same parent frame. * * Frames are NOT reference counted. Use the Destroy() member function * to destroy a frame. The lifetime of the frame hierarchy is bounded by the * lifetime of the presentation shell which owns the frames. */ class nsIFrame : public nsISupports { public: /** * Called to initialize the frame. This is called immediately after creating * the frame. * * If the frame is a continuing frame, then aPrevInFlow indicates the previous * frame (the frame that was split). You should connect the continuing frame to * its prev-in-flow, e.g. by using the AppendToFlow() function * * If you want a view associated with your frame, you should create the view * now. * * @param aContent the content object associated with the frame * @param aGeometricParent the geometric parent frame * @param aContentParent the content parent frame * @param aContext the style context associated with the frame * @param aPrevInFlow the prev-in-flow frame * @see #AppendToFlow() */ NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) = 0; /** * Destroys this frame and each of its child frames (recursively calls * Destroy() for each child) */ NS_IMETHOD Destroy(nsIPresContext& aPresContext) = 0; /** * Called to set the initial list of frames. This happens after the frame * has been initialized. * * This is only called once for a given child list, and won't be called * at all for child lists with no initial list of frames. * * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aChildList list of child frames. Each of the frames has its * NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the * initial list of frames has already been set for that child list, * NS_OK otherwise * @see #Init() */ NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, nsIFrame* aChildList) = 0; /** * This method is responsible for appending frames to the frame * list. The implementation should append the frames to the specified * child list and then generate a reflow command. * * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aFrameList list of child frames to append. Each of the frames has * its NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD AppendFrames(nsIPresContext& aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, nsIFrame* aFrameList) = 0; /** * This method is responsible for inserting frames into the frame * list. The implementation should insert the new frames into the specified * child list and then generate a reflow command. * * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aPrevFrame the frame to insert frames after * @param aFrameList list of child frames to insert after aPrevFrame. * Each of the frames has its NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD InsertFrames(nsIPresContext& aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, nsIFrame* aPrevFrame, nsIFrame* aFrameList) = 0; /** * This method is responsible for removing a frame in the frame * list. The implementation should do something with the removed frame * and then generate a reflow command. The implementation is responsible * for destroying aOldFrame (the caller mustn't destroy aOldFrame). * * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aOldFrame the frame to remove * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_FAILURE if the child frame is not in the specified * child list, * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, nsIFrame* aOldFrame) = 0; /** * This method is responsible for replacing the old frame with the * new frame. The old frame should be destroyed and the new frame inserted * in its place in the specified child list. * * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @param aOldFrame the frame to remove * @param aNewFrame the frame to replace it with. The new frame has its * NS_FRAME_IS_DIRTY bit set * @return NS_ERROR_INVALID_ARG if there is no child list with the specified * name, * NS_ERROR_FAILURE if the old child frame is not in the specified * child list, * NS_ERROR_UNEXPECTED if the frame is an atomic frame, * NS_OK otherwise */ NS_IMETHOD ReplaceFrame(nsIPresContext& aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, nsIFrame* aOldFrame, nsIFrame* aNewFrame) = 0; /** * Get the content object associated with this frame. Adds a reference to * the content object so the caller must do a release. * * @see nsISupports#Release() */ NS_IMETHOD GetContent(nsIContent** aContent) const = 0; /** * Get the offsets of the frame. most will be 0,0 * */ NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end) const = 0; /** * Get the style context associated with this frame. Note that GetStyleContext() * adds a reference to the style context so the caller must do a release. * * @see nsISupports#Release() */ NS_IMETHOD GetStyleContext(nsIStyleContext** aStyleContext) const = 0; NS_IMETHOD SetStyleContext(nsIPresContext* aPresContext, nsIStyleContext* aContext) = 0; /** * Get the style data associated with this frame. */ NS_IMETHOD GetStyleData(nsStyleStructID aSID, const nsStyleStruct*& aStyleStruct) const = 0; /** * These methods are to access any additional style contexts that * the frame may be holding. These are contexts that are children * of the frame's primary context and are NOT used as style contexts * for any child frames. These contexts also MUST NOT have any child * contexts whatsoever. If you need to insert style contexts into the * style tree, then you should create pseudo element frames to own them * The indicies must be consecutive and implementations MUST return an * NS_ERROR_INVALID_ARG if asked for an index that is out of range. */ NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext** aStyleContext) const = 0; NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext* aStyleContext) = 0; /** * Accessor functions for geometric parent */ NS_IMETHOD GetParent(nsIFrame** aParent) const = 0; NS_IMETHOD SetParent(const nsIFrame* aParent) = 0; /** * Bounding rect of the frame. The values are in twips, and the origin is * relative to the upper-left of the geometric parent. The size includes the * content area, borders, and padding. */ NS_IMETHOD GetRect(nsRect& aRect) const = 0; NS_IMETHOD GetOrigin(nsPoint& aPoint) const = 0; NS_IMETHOD GetSize(nsSize& aSize) const = 0; NS_IMETHOD SetRect(nsIPresContext* aPresContext, const nsRect& aRect) = 0; NS_IMETHOD MoveTo(nsIPresContext* aPresContext, nscoord aX, nscoord aY) = 0; NS_IMETHOD SizeTo(nsIPresContext* aPresContext, nscoord aWidth, nscoord aHeight) = 0; /** * Used to iterate the list of additional child list names. Returns the atom * name for the additional child list at the specified 0-based index, or a * NULL pointer if there are no more named child lists. * * Note that the list is only the additional named child lists and does not * include the unnamed principal child list. * * @return NS_ERROR_INVALID_ARG if the index is < 0 and NS_OK otherwise */ NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex, nsIAtom** aListName) const = 0; /** * Get the first child frame from the specified child list. * * @param aListName the name of the child list. A NULL pointer for the atom * name means the unnamed principal child list * @return NS_ERROR_INVALID_ARG if there is no child list with the specified name * @see #GetAdditionalListName() */ NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const = 0; /** * Child frames are linked together in a singly-linked */ NS_IMETHOD GetNextSibling(nsIFrame** aNextSibling) const = 0; NS_IMETHOD SetNextSibling(nsIFrame* aNextSibling) = 0; /** * Paint is responsible for painting the a frame. The aWhichLayer * argument indicates which layer of painting should be done during * the call. */ NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) = 0; /** * Event handling of GUI events. * * @param aEvent event structure describing the type of event and rge widget * where the event originated * @param aEventStatus a return value indicating whether the event was handled * and whether default processing should be done * * XXX From a frame's perspective it's unclear what the effect of the event status * is. Does it cause the event to continue propagating through the frame hierarchy * or is it just returned to the widgets? * * @see nsGUIEvent * @see nsEventStatus */ NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus) = 0; NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX, const nsPoint& aPoint, nsIContent ** aNewContent, PRInt32& aContentOffset, PRInt32& aContentOffsetEnd, PRBool& aBeginFrameContent) = 0; /** * Get the cursor for a given frame. */ NS_IMETHOD GetCursor(nsIPresContext& aPresContext, nsPoint& aPoint, PRInt32& aCursor) = 0; NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, const nsPoint& aPoint, nsIFrame** aFrame) = 0; /** * Get a point (in the frame's coordinate space) given an offset into * the content. This point should be on the baseline of text with * the correct horizontal offset */ NS_IMETHOD GetPointFromOffset(nsIPresContext* inPresContext, nsIRenderingContext* inRendContext, PRInt32 inOffset, nsPoint* outPoint) = 0; /** * Get the child frame of this frame which contains the given * content offset. outChildFrame may be this frame, or nsnull on return. * outContentOffset returns the content offset relative to the start * of the returned node. You can also pass a hint which tells the method * to stick to the end of the first found frame or the beginning of the * next in case the offset falls on a boundary. */ NS_IMETHOD GetChildFrameContainingOffset(PRInt32 inContentOffset, PRBool inHint,//false stick left PRInt32* outFrameContentOffset, nsIFrame* *outChildFrame) = 0; /** * Get the current frame-state value for this frame. aResult is * filled in with the state bits. The return value has no * meaning. */ NS_IMETHOD GetFrameState(nsFrameState* aResult) = 0; /** * Set the current frame-state value for this frame. The return * value has no meaning. */ NS_IMETHOD SetFrameState(nsFrameState aNewState) = 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 * change by generating an incremental reflow command. * * @param aIndexInParent the index in the content container where * the new content was deleted. */ NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, nsISupports* aSubContent) = 0; /** * This call is invoked when the value of a content objects's attribute * is changed. * The first frame that maps that content is asked to deal * with the change by doing whatever is appropriate. * * @param aChild the content object * @param aAttribute the attribute whose value changed * @param aHint the level of change that has already been dealt with */ NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aHint) = 0; /** * This call is invoked when the value of a content object's state * is changed. * The first frame that maps that content is asked to deal * with the change by doing whatever is appropriate. * * @param aChild the content object * @param aHint the level of change that has already been dealt with */ NS_IMETHOD ContentStateChanged(nsIPresContext* aPresContext, nsIContent* aChild, PRInt32 aHint) = 0; /** * Return how your frame can be split. */ NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const = 0; /** * Flow member functions */ NS_IMETHOD GetPrevInFlow(nsIFrame** aPrevInFlow) const = 0; NS_IMETHOD SetPrevInFlow(nsIFrame*) = 0; NS_IMETHOD GetNextInFlow(nsIFrame** aNextInFlow) const = 0; NS_IMETHOD SetNextInFlow(nsIFrame*) = 0; /** * Pre-reflow hook. Before a frame is reflowed this method will be called. * This call will always be invoked at least once before a subsequent Reflow * and DidReflow call. It may be called more than once, In general you will * receive on WillReflow notification before each Reflow request. * * XXX Is this really the semantics we want? Because we have the NS_FRAME_IN_REFLOW * bit we can ensure we don't call it more than once... */ 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. * * For an incremental reflow you are responsible for invalidating * any area within your frame that needs repainting (including * borders). If your new desired size is different than your current * size, then your parent frame is responsible for making sure that * the difference between the two rects is repainted * * @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 * * @param aStatus a return value indicating whether the frame is complete * and whether the next-in-flow is dirty and needs to be reflowed */ NS_IMETHOD Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aReflowMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) = 0; /** * Post-reflow hook. After a frame is reflowed this method will be called * informing the frame that this reflow process is complete, and telling the * frame the status returned by the Reflow member function. * * 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. * * XXX This doesn't make sense. If the frame is reflowed but not complete, then * the status should be NS_FRAME_NOT_COMPLETE and not NS_FRAME_COMPLETE * XXX Don't we want the semantics to dictate that we only call this once for * a given reflow? */ NS_IMETHOD DidReflow(nsIPresContext& aPresContext, nsDidReflowStatus aStatus) = 0; // XXX Maybe these three should be a separate interface? // Helper method used by block reflow to identify runs of text so that // proper word-breaking can be done. NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout) = 0; // Justification helper method used to distribute extra space in a // line to leaf frames. aUsedSpace is filled in with the amount of // space actually used. NS_IMETHOD AdjustFrameSize(nscoord aExtraSpace, nscoord& aUsedSpace) = 0; // Justification helper method that is used to remove trailing // whitespace before justification. NS_IMETHOD TrimTrailingWhiteSpace(nsIPresContext* aPresContext, nsIRenderingContext& aRC, nscoord& aDeltaWidth) = 0; /** * Accessor functions to get/set the associated view object */ NS_IMETHOD GetView(nsIPresContext* aPresContext, nsIView** aView) const = 0; // may be null NS_IMETHOD SetView(nsIPresContext* aPresContext, nsIView* aView) = 0; /** * Find the first geometric parent that has a view */ NS_IMETHOD GetParentWithView(nsIPresContext* aPresContext, nsIFrame** aParent) const = 0; /** * Returns the offset from this frame to the closest geometric parent that * has a view. Also returns the containing view or null in case of error */ NS_IMETHOD GetOffsetFromView(nsIPresContext* aPresContext, nsPoint& aOffset, nsIView** aView) const = 0; /** * Returns the window that contains this frame. If this frame has a * view and the view has a window, then this frames window is * returned, otherwise this frame's geometric parent is checked * recursively upwards. */ NS_IMETHOD GetWindow(nsIPresContext* aPresContext, nsIWidget** aWidget) const = 0; /** * Get the "type" of the frame. May return a NULL atom pointer * * @see nsLayoutAtoms */ NS_IMETHOD GetFrameType(nsIAtom** aType) const = 0; /** * Is this frame a "containing block"? */ NS_IMETHOD IsPercentageBase(PRBool& aBase) const = 0; /** * called when the frame has been scrolled to a new * position. only called for frames with views. */ NS_IMETHOD Scrolled(nsIView *aView) = 0; /** Selection related calls */ /** * Called to set the selection of the frame based on frame offsets. you can FORCE the frame * to redraw event if aSelected == the frame selection with the last parameter. * data in struct may be changed when passed in. * @param aRange is the range that will dictate if the frames need to be redrawn null means the whole content needs to be redrawn * @param aSelected is it selected * @param aSpread should is spread selection to flow elements around it? or go down to its children? */ NS_IMETHOD SetSelected(nsIPresContext* aPresContext, nsIDOMRange* aRange, PRBool aSelected, nsSpread aSpread) = 0; NS_IMETHOD GetSelected(PRBool *aSelected) const = 0; /** EndSelection related calls */ /** * called to find the previous/next character, word, or line returns the actual * nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE * uses frame's begin selection state to start. if no selection on this frame will * return NS_ERROR_FAILURE * @param aPOS is defined in nsIFrameSelection */ NS_IMETHOD PeekOffset(nsIPresContext* aPresContext, nsPeekOffsetStruct *aPos) = 0; private: NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; NS_IMETHOD_(nsrefcnt) Release(void) = 0; }; #endif /* nsIFrame_h___ */