Work-in-progress for making relatively positioned inline-level elements a

container for absolutely positioned child elements
This commit is contained in:
troy%netscape.com 1999-04-19 19:10:15 +00:00
parent d724778c32
commit bfd8240682
6 changed files with 304 additions and 14 deletions

View File

@ -2918,12 +2918,18 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPresCo
floaterList.childList);
}
}
// See if it's a relatively positioned block
else if ((NS_STYLE_POSITION_RELATIVE == position->mPosition) &&
((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay))) {
// See if it's relatively positioned
else if (NS_STYLE_POSITION_RELATIVE == position->mPosition) {
// Is it block-level or inline-level?
if (NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) {
// Create an area frame. No space manager, though
NS_NewAreaFrame(newFrame, NS_AREA_NO_SPACE_MGR);
} else {
// Create a positioned inline frame
NS_NewPositionedInlineFrame(newFrame);
}
// Create an area frame. No space manager, though
NS_NewAreaFrame(newFrame, NS_AREA_NO_SPACE_MGR);
// Initialize the frame
newFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext, nsnull);
// Create a view
@ -2935,8 +2941,15 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPresCo
nsAbsoluteItems absoluteItems(newFrame);
nsAbsoluteItems floaterList(newFrame);
nsFrameItems childItems;
ProcessChildren(aPresContext, aContent, newFrame, absoluteItems,
childItems, aFixedItems, floaterList, PR_TRUE);
if (NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) {
ProcessChildren(aPresContext, aContent, newFrame, absoluteItems,
childItems, aFixedItems, floaterList, PR_TRUE);
} else {
ProcessChildren(aPresContext, aContent, newFrame, absoluteItems,
childItems, aFixedItems, aFloatingItems, PR_TRUE);
}
// Set the frame's initial child list
newFrame->SetInitialChildList(*aPresContext, nsnull, childItems.childList);

View File

@ -258,6 +258,7 @@ extern nsresult NS_NewViewportFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewRootFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewImageFrame(nsIFrame*& aFrameResult);
extern nsresult NS_NewInlineFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewPositionedInlineFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewObjectFrame(nsIFrame*& aFrameResult);
extern nsresult NS_NewSpacerFrame(nsIFrame*& aResult);
extern nsresult NS_NewTextFrame(nsIFrame*& aResult);

View File

@ -29,6 +29,8 @@
#include "nsIPresContext.h"
#include "nsIRenderingContext.h"
#include "nsIFontMetrics.h"
#include "nsAbsoluteContainingBlock.h"
#include "nsLayoutAtoms.h"
// XXX TODO:
// append/insert/remove floater testing
@ -190,6 +192,135 @@ protected:
nsReflowStatus& aStatus);
};
//////////////////////////////////////////////////////////////////////
// Derived class created for relatively positioned inline-level elements
// that acts as a containing block for child absolutely positioned
// elements
class nsPositionedInlineFrame : public nsInlineFrame
{
public:
NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const;
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
protected:
nsAbsoluteContainingBlock mAbsoluteContainer;
};
nsresult
NS_NewPositionedInlineFrame(nsIFrame*& aNewFrame)
{
nsPositionedInlineFrame* it = new nsPositionedInlineFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
aNewFrame = it;
return NS_OK;
}
NS_IMETHODIMP
nsPositionedInlineFrame::DeleteFrame(nsIPresContext& aPresContext)
{
mAbsoluteContainer.DeleteFrames(aPresContext);
return nsInlineFrame::DeleteFrame(aPresContext);
}
NS_IMETHODIMP
nsPositionedInlineFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult rv;
if (nsLayoutAtoms::absoluteList == aListName) {
rv = mAbsoluteContainer.SetInitialChildList(aPresContext, aListName, aChildList);
} else {
rv = nsInlineFrame::SetInitialChildList(aPresContext, aListName, aChildList);
}
return rv;
}
NS_IMETHODIMP
nsPositionedInlineFrame::GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const
{
NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer");
*aListName = nsnull;
if (0 == aIndex) {
*aListName = nsLayoutAtoms::absoluteList;
NS_ADDREF(*aListName);
}
return NS_OK;
}
NS_IMETHODIMP
nsPositionedInlineFrame::FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const
{
NS_PRECONDITION(nsnull != aFirstChild, "null OUT parameter pointer");
if (aListName == nsLayoutAtoms::absoluteList) {
return mAbsoluteContainer.FirstChild(aListName, aFirstChild);
}
return nsInlineFrame::FirstChild(aListName, aFirstChild);
}
NS_IMETHODIMP
nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
// See if it's an incremental reflow command
if (eReflowReason_Incremental == aReflowState.reason) {
// Give the absolute positioning code a chance to handle it
PRBool handled;
mAbsoluteContainer.IncrementalReflow(aPresContext, aReflowState, handled);
// If the incremental reflow command was handled by the absolute positioning
// code, then we're all done
if (handled) {
// Just return our current size as our desired size
aDesiredSize.width = mRect.width;
aDesiredSize.height = mRect.height;
// XXX This isn't correct...
aDesiredSize.ascent = mRect.height;
aDesiredSize.descent = 0;
// Whether or not we're complete hasn't changed
aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
return rv;
}
}
// Let the inline frame do its reflow first
rv = nsInlineFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
// Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed
if (NS_SUCCEEDED(rv)) {
rv = mAbsoluteContainer.Reflow(aPresContext, aReflowState);
}
return rv;
}
//////////////////////////////////////////////////////////////////////
// SectionData implementation

View File

@ -258,6 +258,7 @@ extern nsresult NS_NewViewportFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewRootFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewImageFrame(nsIFrame*& aFrameResult);
extern nsresult NS_NewInlineFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewPositionedInlineFrame(nsIFrame*& aNewFrame);
extern nsresult NS_NewObjectFrame(nsIFrame*& aFrameResult);
extern nsresult NS_NewSpacerFrame(nsIFrame*& aResult);
extern nsresult NS_NewTextFrame(nsIFrame*& aResult);

View File

@ -29,6 +29,8 @@
#include "nsIPresContext.h"
#include "nsIRenderingContext.h"
#include "nsIFontMetrics.h"
#include "nsAbsoluteContainingBlock.h"
#include "nsLayoutAtoms.h"
// XXX TODO:
// append/insert/remove floater testing
@ -190,6 +192,135 @@ protected:
nsReflowStatus& aStatus);
};
//////////////////////////////////////////////////////////////////////
// Derived class created for relatively positioned inline-level elements
// that acts as a containing block for child absolutely positioned
// elements
class nsPositionedInlineFrame : public nsInlineFrame
{
public:
NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const;
NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const;
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
protected:
nsAbsoluteContainingBlock mAbsoluteContainer;
};
nsresult
NS_NewPositionedInlineFrame(nsIFrame*& aNewFrame)
{
nsPositionedInlineFrame* it = new nsPositionedInlineFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
aNewFrame = it;
return NS_OK;
}
NS_IMETHODIMP
nsPositionedInlineFrame::DeleteFrame(nsIPresContext& aPresContext)
{
mAbsoluteContainer.DeleteFrames(aPresContext);
return nsInlineFrame::DeleteFrame(aPresContext);
}
NS_IMETHODIMP
nsPositionedInlineFrame::SetInitialChildList(nsIPresContext& aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult rv;
if (nsLayoutAtoms::absoluteList == aListName) {
rv = mAbsoluteContainer.SetInitialChildList(aPresContext, aListName, aChildList);
} else {
rv = nsInlineFrame::SetInitialChildList(aPresContext, aListName, aChildList);
}
return rv;
}
NS_IMETHODIMP
nsPositionedInlineFrame::GetAdditionalChildListName(PRInt32 aIndex,
nsIAtom** aListName) const
{
NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer");
*aListName = nsnull;
if (0 == aIndex) {
*aListName = nsLayoutAtoms::absoluteList;
NS_ADDREF(*aListName);
}
return NS_OK;
}
NS_IMETHODIMP
nsPositionedInlineFrame::FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const
{
NS_PRECONDITION(nsnull != aFirstChild, "null OUT parameter pointer");
if (aListName == nsLayoutAtoms::absoluteList) {
return mAbsoluteContainer.FirstChild(aListName, aFirstChild);
}
return nsInlineFrame::FirstChild(aListName, aFirstChild);
}
NS_IMETHODIMP
nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
// See if it's an incremental reflow command
if (eReflowReason_Incremental == aReflowState.reason) {
// Give the absolute positioning code a chance to handle it
PRBool handled;
mAbsoluteContainer.IncrementalReflow(aPresContext, aReflowState, handled);
// If the incremental reflow command was handled by the absolute positioning
// code, then we're all done
if (handled) {
// Just return our current size as our desired size
aDesiredSize.width = mRect.width;
aDesiredSize.height = mRect.height;
// XXX This isn't correct...
aDesiredSize.ascent = mRect.height;
aDesiredSize.descent = 0;
// Whether or not we're complete hasn't changed
aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
return rv;
}
}
// Let the inline frame do its reflow first
rv = nsInlineFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
// Let the absolutely positioned container reflow any absolutely positioned
// child frames that need to be reflowed
if (NS_SUCCEEDED(rv)) {
rv = mAbsoluteContainer.Reflow(aPresContext, aReflowState);
}
return rv;
}
//////////////////////////////////////////////////////////////////////
// SectionData implementation

View File

@ -2918,12 +2918,18 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPresCo
floaterList.childList);
}
}
// See if it's a relatively positioned block
else if ((NS_STYLE_POSITION_RELATIVE == position->mPosition) &&
((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay))) {
// See if it's relatively positioned
else if (NS_STYLE_POSITION_RELATIVE == position->mPosition) {
// Is it block-level or inline-level?
if (NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) {
// Create an area frame. No space manager, though
NS_NewAreaFrame(newFrame, NS_AREA_NO_SPACE_MGR);
} else {
// Create a positioned inline frame
NS_NewPositionedInlineFrame(newFrame);
}
// Create an area frame. No space manager, though
NS_NewAreaFrame(newFrame, NS_AREA_NO_SPACE_MGR);
// Initialize the frame
newFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext, nsnull);
// Create a view
@ -2935,8 +2941,15 @@ nsCSSFrameConstructor::ConstructFrameByDisplayType(nsIPresContext* aPresCo
nsAbsoluteItems absoluteItems(newFrame);
nsAbsoluteItems floaterList(newFrame);
nsFrameItems childItems;
ProcessChildren(aPresContext, aContent, newFrame, absoluteItems,
childItems, aFixedItems, floaterList, PR_TRUE);
if (NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) {
ProcessChildren(aPresContext, aContent, newFrame, absoluteItems,
childItems, aFixedItems, floaterList, PR_TRUE);
} else {
ProcessChildren(aPresContext, aContent, newFrame, absoluteItems,
childItems, aFixedItems, aFloatingItems, PR_TRUE);
}
// Set the frame's initial child list
newFrame->SetInitialChildList(*aPresContext, nsnull, childItems.childList);