Changed the body to be a subclass of nsBlockFrame rather than contain a

block frame
This commit is contained in:
troy%netscape.com 1998-11-17 16:37:39 +00:00
Родитель d14f0035d3
Коммит f350be91c1
2 изменённых файлов: 166 добавлений и 445 удалений

Просмотреть файл

@ -41,6 +41,8 @@
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID); static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
nsIAtom* nsBodyFrame::gAbsoluteAtom;
nsresult nsresult
NS_NewBodyFrame(nsIContent* aContent, nsIFrame* aParent, nsIFrame*& aResult, NS_NewBodyFrame(nsIContent* aContent, nsIFrame* aParent, nsIFrame*& aResult,
PRUint32 aFlags) PRUint32 aFlags)
@ -55,10 +57,14 @@ NS_NewBodyFrame(nsIContent* aContent, nsIFrame* aParent, nsIFrame*& aResult,
} }
nsBodyFrame::nsBodyFrame(nsIContent* aContent, nsIFrame* aParentFrame) nsBodyFrame::nsBodyFrame(nsIContent* aContent, nsIFrame* aParentFrame)
: nsHTMLContainerFrame(aContent, aParentFrame) : nsBlockFrame(aContent, aParentFrame)
{ {
mSpaceManager = new nsSpaceManager(this); mSpaceManager = new nsSpaceManager(this);
NS_ADDREF(mSpaceManager); NS_ADDREF(mSpaceManager);
// XXX for now this is a memory leak
if (nsnull == gAbsoluteAtom) {
gAbsoluteAtom = NS_NewAtom("Absolute-list");
}
} }
nsBodyFrame::~nsBodyFrame() nsBodyFrame::~nsBodyFrame()
@ -88,42 +94,37 @@ nsBodyFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
// nsIFrame // nsIFrame
NS_IMETHODIMP NS_IMETHODIMP
nsBodyFrame::SetInitialChildList(nsIPresContext& aPresContext, nsBodyFrame::DeleteFrame(nsIPresContext& aPresContext)
nsIAtom* aListName,
nsIFrame* aChildList)
{ {
if (nsnull == mPrevInFlow) { DeleteFrameList(aPresContext, &mAbsoluteFrames);
// Create a block frame and set its style context return nsBlockFrame::DeleteFrame(aPresContext);
nsresult rv = NS_NewBlockFrame(mContent, this, mFirstChild, mFlags); }
if (NS_OK != rv) {
return rv;
}
mChildCount = 1;
nsIStyleContext* pseudoStyleContext =
aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::columnPseudo, mStyleContext);
mFirstChild->SetStyleContext(&aPresContext, pseudoStyleContext);
NS_RELEASE(pseudoStyleContext);
// Set the geometric and content parent for each of the child frames NS_IMETHODIMP
for (nsIFrame* frame = aChildList; nsnull != frame; frame->GetNextSibling(frame)) { nsBodyFrame::GetAdditionalChildListName(PRInt32 aIndex,
frame->SetGeometricParent(mFirstChild); nsIAtom*& aListName) const
frame->SetContentParent(mFirstChild); {
} if (aIndex < 0) {
return NS_ERROR_INVALID_ARG;
// Queue up the frames for the block frame
return mFirstChild->SetInitialChildList(aPresContext, nsnull, aChildList);
} else {
// We have a prev-in-flow, so create a continuing block frame
nsBodyFrame* prevBodyFrame = (nsBodyFrame*)mPrevInFlow;
nsIStyleContext* blockStyleContext;
prevBodyFrame->mFirstChild->GetStyleContext(blockStyleContext);
prevBodyFrame->mFirstChild->CreateContinuingFrame(aPresContext, this,
blockStyleContext, mFirstChild);
NS_RELEASE(blockStyleContext);
return mFirstChild->SetInitialChildList(aPresContext, nsnull, nsnull);
} }
nsIAtom* atom = nsnull;
if (0 == aIndex) {
atom = gAbsoluteAtom;
NS_ADDREF(atom);
}
aListName = atom;
return NS_OK;
}
NS_IMETHODIMP
nsBodyFrame::FirstChild(nsIAtom* aListName, nsIFrame*& aFirstChild) const
{
if (aListName == gAbsoluteAtom) {
aFirstChild = mAbsoluteFrames;
return NS_OK;
}
return nsBlockFrame::FirstChild(aListName, aFirstChild);
} }
#ifdef NS_DEBUG #ifdef NS_DEBUG
@ -191,15 +192,17 @@ nsBodyFrame::BandData::ComputeAvailSpaceRect()
} }
#endif #endif
#ifdef NS_DEBUG
NS_IMETHODIMP NS_IMETHODIMP
nsBodyFrame::Paint(nsIPresContext& aPresContext, nsBodyFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext, nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect) const nsRect& aDirtyRect)
{ {
nsresult rv = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, // Note: all absolutely positioned elements have views so we don't
aDirtyRect); // need to worry about painting them
nsresult rv = nsBlockFrame::Paint(aPresContext, aRenderingContext,
aDirtyRect);
#ifdef NS_DEBUG
if (nsIFrame::GetShowFrameBorders()) { if (nsIFrame::GetShowFrameBorders()) {
// Render the bands in the spacemanager // Render the bands in the spacemanager
BandData band; BandData band;
@ -237,10 +240,10 @@ nsBodyFrame::Paint(nsIPresContext& aPresContext,
y = band.availSpace.YMost(); y = band.availSpace.YMost();
} }
} }
#endif
return rv; return rv;
} }
#endif
NS_IMETHODIMP NS_IMETHODIMP
nsBodyFrame::Reflow(nsIPresContext& aPresContext, nsBodyFrame::Reflow(nsIPresContext& aPresContext,
@ -254,229 +257,94 @@ nsBodyFrame::Reflow(nsIPresContext& aPresContext,
aReflowState.maxSize.height, aReflowState.maxSize.height,
aReflowState.reason)); aReflowState.reason));
const nsHTMLReflowState* rsp = &aReflowState; // Make a copy of the reflow state so we can set the space manager
nsHTMLReflowState resizeReflowState(aReflowState); nsHTMLReflowState reflowState(aReflowState);
resizeReflowState.spaceManager = mSpaceManager; reflowState.spaceManager = mSpaceManager;
aStatus = NS_FRAME_COMPLETE; // initialize out parameter if (eReflowReason_Resize == reflowState.reason) {
// Clear any regions that are marked as unavailable
#if 0 // XXX Temporary hack until everything is incremental...
else { mSpaceManager->ClearRegions();
NS_ASSERTION(eReflowReason_Initial != aReflowState.reason, "bad reason");
} }
#endif
nsIFrame* reflowCmdTarget; // XXX We need to peek at incremental reflow commands and see if the next
nsIReflowCommand::ReflowType reflowCmdType; // frame is one of the absolutely positioned frames...
nsresult rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus);
if (eReflowReason_Incremental == aReflowState.reason) { // Reflow any absolutely positioned frames that need reflowing
NS_ASSERTION(nsnull != aReflowState.reflowCommand, "null reflow command"); // XXX We shouldn't really be doing this for all incremental reflow commands
ReflowAbsoluteItems(aPresContext, reflowState);
// Get the target and the type of reflow command // Compute our desired size. Take into account any floaters when computing the
aReflowState.reflowCommand->GetTarget(reflowCmdTarget); // height
aReflowState.reflowCommand->GetType(reflowCmdType); if (mSpaceManager->YMost() > aDesiredSize.height) {
aDesiredSize.height = mSpaceManager->YMost();
}
if (this == reflowCmdTarget) { // Also take into account absolutely positioned elements
NS_ASSERTION(nsIReflowCommand::FrameAppended == reflowCmdType, const nsStyleDisplay* display= (const nsStyleDisplay*)
"unexpected reflow command"); mStyleContext->GetStyleData(eStyleStruct_Display);
// Append reflow commands will be targeted at us. Reset the target and if (NS_STYLE_OVERFLOW_HIDDEN != display->mOverflow) {
// send the reflow command. for (PRInt32 i = 0; i < mAbsoluteItems.Count(); i++) {
// XXX Would it be better to have the frame generate the reflow command // Get the anchor frame
// that way it could correctly set the target? nsAbsoluteFrame* anchorFrame = (nsAbsoluteFrame*)mAbsoluteItems[i];
reflowCmdTarget = mFirstChild; nsIFrame* absoluteFrame = anchorFrame->GetAbsoluteFrame();
aReflowState.reflowCommand->SetTarget(mFirstChild); nsRect rect;
// Reset the geometric and content parent for each of the child frames absoluteFrame->GetRect(rect);
nsIFrame* childList; nscoord xmost = rect.XMost();
aReflowState.reflowCommand->GetChildFrame(childList); nscoord ymost = rect.YMost();
for (nsIFrame* frame = childList; nsnull != frame; frame->GetNextSibling(frame)) { if (xmost > aDesiredSize.width) {
frame->SetGeometricParent(mFirstChild); aDesiredSize.width = xmost;
frame->SetContentParent(mFirstChild);
} }
} if (ymost > aDesiredSize.height) {
aDesiredSize.height = ymost;
// The reflow command should never be target for us
#ifdef NS_DEBUG
NS_ASSERTION(this != reflowCmdTarget, "bad reflow command target");
#endif
// Is the next frame in the reflow chain the pseudo block-frame or an
// absolutely positioned frame?
//
// If the next frame is the pseudo block-frame then fall thru to the main
// code below. The only thing that should be handled below is absolutely
// positioned elements...
nsIFrame* nextFrame;
aReflowState.reflowCommand->GetNext(nextFrame);
if ((nsnull != nextFrame) && (mFirstChild != nextFrame)) {
NS_ASSERTION(this != nextFrame, "huh?");
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
("nsBodyFrame::Reflow: reflowing frame=%p",
nextFrame));
// It's an absolutely positioned frame that's the target.
// XXX FIX ME. For an absolutely positioned item we need to properly
// compute the available space and compute the origin...
nsIHTMLReflow* reflow;
if (NS_OK == nextFrame->QueryInterface(kIHTMLReflowIID, (void**)&reflow)) {
nsHTMLReflowState reflowState(aPresContext, nextFrame, aReflowState,
aReflowState.maxSize);
reflowState.spaceManager = mSpaceManager;
reflow->WillReflow(aPresContext);
nsresult rv = reflow->Reflow(aPresContext, aDesiredSize, reflowState, aStatus);
if (NS_OK != rv) {
return rv;
}
nextFrame->SizeTo(aDesiredSize.width, aDesiredSize.height);
} }
// XXX Commented this out because the absolute positioning code
// above doesn't check if it needs to position the absolute frame.
#if 0
// XXX Temporary code: if the frame we just reflowed is a
// floating frame then fall through into the main reflow pathway
// after clearing out our incremental reflow status. This forces
// our child to adjust to the new size of the floater.
//
// XXXX We shouldn't be here at all for floating frames, just for absolutely
// positioned frames. What's happening is that if a child of the body is
// floated then the reflow state path isn't getting set up correctly. The
// body's block pseudo-frame isn't getting included in the reflow path like
// it shoudld and that's why we end up here
const nsStyleDisplay* display;
nextFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) display);
if (NS_STYLE_FLOAT_NONE == display->mFloats) {
return NS_OK;
}
#endif
// Switch over to a reflow-state that is called resize instead
// of an incremental reflow state like we were passed in.
resizeReflowState.reason = eReflowReason_Resize;
resizeReflowState.reflowCommand = nsnull;
rsp = &resizeReflowState;
// XXX End temporary code
} }
} }
// The area that needs to be repainted. Depends on the reflow type. // XXX This code is really temporary; the lower level frame
// classes need to contribute to the area that needs damage
// repair. This class should only worry about damage repairing
// it's border+padding area.
nsRect damageArea(0, 0, 0, 0); nsRect damageArea(0, 0, 0, 0);
// Reflow the child frame // Decide how much to repaint based on the reflow type.
if (nsnull != mFirstChild) { // Note: we don't have to handle the initial reflow case and the
// Get our border/padding info // resize reflow case, because they're handled by the scroll frame
const nsStyleSpacing* mySpacing = if (eReflowReason_Incremental == aReflowState.reason) {
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); nsIReflowCommand::ReflowType reflowType;
nsMargin borderPadding; aReflowState.reflowCommand->GetType(reflowType);
mySpacing->CalcBorderPaddingFor(this, borderPadding);
// Compute the child frame's max size // For append reflow commands that target the flowed frames just
nsSize kidMaxSize = GetColumnAvailSpace(aPresContext, borderPadding, // repaint the newly added part of the frame.
*rsp); if (nsIReflowCommand::FrameAppended == reflowType) {
mSpaceManager->Translate(borderPadding.left, borderPadding.top); // It's an append reflow command
damageArea.y = mRect.YMost();
if (eReflowReason_Resize == rsp->reason) { damageArea.width = aDesiredSize.width;
// Clear any regions that are marked as unavailable damageArea.height = aDesiredSize.height - mRect.height;
// XXX Temporary hack until everything is incremental... if (aDesiredSize.height == mRect.height) {
mSpaceManager->ClearRegions(); // Since we don't know what changed, assume it all changed.
} damageArea.y = 0;
// Get the child's current rect
nsRect kidOldRect;
mFirstChild->GetRect(kidOldRect);
// Get the column's desired size
nsHTMLReflowState reflowState(aPresContext, mFirstChild, *rsp, kidMaxSize);
reflowState.spaceManager = mSpaceManager;
nsIHTMLReflow* htmlReflow;
if (NS_OK == mFirstChild->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
htmlReflow->WillReflow(aPresContext);
htmlReflow->Reflow(aPresContext, aDesiredSize, reflowState, aStatus);
}
// If the frame is complete, then check whether there's a next-in-flow that
// needs to be deleted
if (NS_FRAME_IS_COMPLETE(aStatus)) {
nsIFrame* kidNextInFlow;
mFirstChild->GetNextInFlow(kidNextInFlow);
if (nsnull != kidNextInFlow) {
// Remove all of the childs next-in-flows
DeleteChildsNextInFlow(aPresContext, mFirstChild);
}
}
mSpaceManager->Translate(-borderPadding.left, -borderPadding.top);
// Place and size the frame
nsRect desiredRect(borderPadding.left, borderPadding.top,
aDesiredSize.width, aDesiredSize.height);
mFirstChild->SetRect(desiredRect);
// Reflow any absolutely positioned frames that need reflowing
ReflowAbsoluteItems(aPresContext, *rsp);
// Return our desired size
ComputeDesiredSize(aPresContext, aReflowState, desiredRect,
rsp->maxSize, borderPadding, aDesiredSize);
// XXX This code is really temporary; the lower level frame
// classes need to contribute to the area that needs damage
// repair. This class should only worry about damage repairing
// it's border+padding area.
// Decide how much to repaint based on the reflow type.
// Note: we don't have to handle the initial reflow case and the
// resize reflow case, because they're handled by the root content
// frame
if (eReflowReason_Incremental == rsp->reason) {
// For append reflow commands that target the body just repaint the newly
// added part of the frame.
if ((nsIReflowCommand::FrameAppended == reflowCmdType) &&
(reflowCmdTarget == mFirstChild)) {
// It's an append reflow command targeted at us
damageArea.y = kidOldRect.YMost();
damageArea.width = aDesiredSize.width;
damageArea.height = aDesiredSize.height - kidOldRect.height;
if (desiredRect.height == kidOldRect.height) {
// Since we don't know what changed, assume it all changed.
damageArea.y = 0;
damageArea.height = aDesiredSize.height;
}
} else {
// Ideally the frame that is the target of the reflow command
// (or its parent frame) would generate a damage rect, but
// since none of the frame classes know how to do this then
// for the time being just repaint the entire frame
damageArea.width = aDesiredSize.width;
damageArea.height = aDesiredSize.height; damageArea.height = aDesiredSize.height;
} }
} } else {
// Ideally the frame that is the target of the reflow command
} // (or its parent frame) would generate a damage rect, but
else { // since none of the frame classes know how to do this then
aDesiredSize.width = 0; // for the time being just repaint the entire frame
aDesiredSize.height = 0; damageArea.width = aDesiredSize.width;
aDesiredSize.ascent = 0; damageArea.height = aDesiredSize.height;
aDesiredSize.descent = 0;
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = 0;
aDesiredSize.maxElementSize->height = 0;
} }
} }
// If this is really The Body, we force a repaint of the damage area // If this is really the body, force a repaint of the damage area
if ((NS_BODY_THE_BODY & mFlags) && !damageArea.IsEmpty()) { if ((NS_BODY_THE_BODY & mFlags) && !damageArea.IsEmpty()) {
Invalidate(damageArea); Invalidate(damageArea);
} }
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, return rv;
("exit nsBodyFrame::Reflow: status=%d width=%d height=%d",
aStatus, aDesiredSize.width, aDesiredSize.height));
return NS_OK;
} }
NS_METHOD NS_METHOD
@ -490,7 +358,6 @@ nsBodyFrame::CreateContinuingFrame(nsIPresContext& aPresContext,
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf); PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
cf->SetInitialChildList(aPresContext, nsnull, nsnull);
aContinuingFrame = cf; aContinuingFrame = cf;
return NS_OK; return NS_OK;
} }
@ -609,115 +476,18 @@ nsBodyFrame::DidSetStyleContext(nsIPresContext* aPresContext)
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Helper functions // Helper functions
nsSize
nsBodyFrame::GetColumnAvailSpace(nsIPresContext& aPresContext,
const nsMargin& aBorderPadding,
const nsHTMLReflowState& aReflowState)
{
nsSize result(aReflowState.maxSize);
// If we are being used as a top-level frame then make adjustments
// for border/padding and a vertical scrollbar
if (NS_BODY_THE_BODY & mFlags) {
// If our width is constrained then subtract for the border/padding
if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) {
result.width -= aBorderPadding.left + aBorderPadding.right;
}
// If our height is constrained then subtract for the border/padding
if (aReflowState.maxSize.height != NS_UNCONSTRAINEDSIZE) {
result.height -= aBorderPadding.top + aBorderPadding.bottom;
}
}
else {
if (aReflowState.HaveFixedContentWidth()) {
result.width = aReflowState.minWidth +
aBorderPadding.left + aBorderPadding.right;
}
if (aReflowState.HaveFixedContentHeight()) {
result.height -= aBorderPadding.top + aBorderPadding.bottom;
}
}
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
(": nsBodyFrame: columnAvailSpace=%d,%d [%s,%s]\n",
result.width, result.height,
eHTMLFrameConstraint_Unconstrained == aReflowState.widthConstraint
? "not-constrained" : "constrained",
eHTMLFrameConstraint_Unconstrained == aReflowState.heightConstraint
? "not-constrained" : "constrained"));
return result;
}
void
nsBodyFrame::ComputeDesiredSize(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
const nsRect& aDesiredRect,
const nsSize& aMaxSize,
const nsMargin& aBorderPadding,
nsHTMLReflowMetrics& aMetrics)
{
// Note: Body used as a pseudo-frame shrink wraps (unless of course
// style says otherwise)
nscoord height = PR_MAX(aDesiredRect.YMost(), mSpaceManager->YMost());
nscoord width = aDesiredRect.XMost();
// Take into account absolutely positioned elements when computing the
// desired size
for (PRInt32 i = 0; i < mAbsoluteItems.Count(); i++) {
// Get the anchor frame
nsAbsoluteFrame* anchorFrame = (nsAbsoluteFrame*)mAbsoluteItems[i];
nsIFrame* absoluteFrame = anchorFrame->GetAbsoluteFrame();
nsRect rect;
absoluteFrame->GetRect(rect);
nscoord xmost = rect.XMost();
nscoord ymost = rect.YMost();
if (xmost > width) {
width = xmost;
}
if (ymost > height) {
height = ymost;
}
}
// Apply style size if present; XXX note the inner value (style-size -
// border+padding) should be given to the child as a max-size
if (aReflowState.HaveFixedContentWidth()) {
width = aReflowState.minWidth + aBorderPadding.left + aBorderPadding.right;
}
else {
if ((0 == (NS_BODY_SHRINK_WRAP & mFlags)) &&
(NS_UNCONSTRAINEDSIZE != aMaxSize.width)) {
// Make sure we're at least as wide as our available width
if (aMaxSize.width > width) {
width = aMaxSize.width;
}
}
}
if (aReflowState.HaveFixedContentHeight()) {
height = aReflowState.minHeight +
aBorderPadding.top + aBorderPadding.bottom;
}
else {
// aBorderPadding.top is already reflected in the
// aDesiredRect.YMost() value.
height += aBorderPadding.bottom;
}
aMetrics.width = width;
aMetrics.height = height;
aMetrics.ascent = height;
aMetrics.descent = 0;
}
// Add the frame to the end of the child list // Add the frame to the end of the child list
void nsBodyFrame::AddAbsoluteFrame(nsIFrame* aFrame) void nsBodyFrame::AddAbsoluteFrame(nsIFrame* aFrame)
{ {
nsIFrame* lastChild = LastFrame(mFirstChild); if (nsnull == mAbsoluteFrames) {
mAbsoluteFrames = aFrame;
} else {
nsIFrame* lastChild = LastFrame(mAbsoluteFrames);
lastChild->SetNextSibling(aFrame); lastChild->SetNextSibling(aFrame);
aFrame->SetNextSibling(nsnull); aFrame->SetNextSibling(nsnull);
mChildCount++; // XXX Eliminate mChildCount...
}
} }
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@ -728,33 +498,7 @@ nsBodyFrame::HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent, nsGUIEvent* aEvent,
nsEventStatus& aEventStatus) nsEventStatus& aEventStatus)
{ {
aEventStatus = nsEventStatus_eIgnore; nsBlockFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
// Pass event down to our children. Give it to the children after
// our first-child first (children after the first-child are either
// absolute positioned frames or are floating frames, both of which
// are on top (in the z order) of the first-child).
/*XXX Commenting event dispatch to BodyFrame's absolutely positioned
* children. They already get the event through the view hierarchy.
*/
/*PRInt32 n = mChildCount;*/
nsIFrame* kid = mFirstChild;
/*kid->GetNextSibling(kid);
while (--n >= 0) {
if (nsnull == kid) {
kid = mFirstChild;
}*/
nsRect kidRect;
kid->GetRect(kidRect);
if (kidRect.Contains(aEvent->point)) {
aEvent->point.MoveBy(-kidRect.x, -kidRect.y);
kid->HandleEvent(aPresContext, aEvent, aEventStatus);
aEvent->point.MoveBy(kidRect.x, kidRect.y);
/*break;*/
}
/*kid->GetNextSibling(kid);
}*/
// XXX Hack mouse enter/exit and cursor code. THIS DOESN'T BELONG HERE! // XXX Hack mouse enter/exit and cursor code. THIS DOESN'T BELONG HERE!
#if 1 #if 1
@ -857,36 +601,6 @@ nsBodyFrame::HandleEvent(nsIPresContext& aPresContext,
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsBodyFrame::GetCursorAndContentAt(nsIPresContext& aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame,
nsIContent** aContent,
PRInt32& aCursor)
{
aCursor = NS_STYLE_CURSOR_INHERIT;
*aContent = mContent;
nsPoint tmp;
PRInt32 n = mChildCount;
nsIFrame* kid = mFirstChild;
kid->GetNextSibling(kid);
while (--n >= 0) {
if (nsnull == kid) {
kid = mFirstChild;
}
nsRect kidRect;
kid->GetRect(kidRect);
if (kidRect.Contains(aPoint)) {
tmp.MoveTo(aPoint.x - kidRect.x, aPoint.y - kidRect.y);
kid->GetCursorAndContentAt(aPresContext, tmp, aFrame, aContent, aCursor);
break;
}
kid->GetNextSibling(kid);
}
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// nsIAbsoluteItems // nsIAbsoluteItems
@ -898,6 +612,19 @@ NS_METHOD nsBodyFrame::AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame)
return NS_OK; return NS_OK;
} }
PRBool
nsBodyFrame::IsAbsoluteFrame(nsIFrame* aFrame)
{
// Check whether the frame is in our list of absolutely positioned frames
for (nsIFrame* f = mAbsoluteFrames; nsnull != f; f->GetNextSibling(f)) {
if (f == aFrame) {
return PR_TRUE;
}
}
return PR_FALSE;
}
NS_METHOD nsBodyFrame::RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) NS_METHOD nsBodyFrame::RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame)
{ {
NS_NOTYETIMPLEMENTED("removing an absolutely positioned frame"); NS_NOTYETIMPLEMENTED("removing an absolutely positioned frame");
@ -926,9 +653,7 @@ nsBodyFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext,
absoluteFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)position); absoluteFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)position);
// See whether the frame is a newly added frame // See whether the frame is a newly added frame
nsIFrame* parent; if (!IsAbsoluteFrame(absoluteFrame)) {
absoluteFrame->GetGeometricParent(parent);
if (parent != this) {
// The absolutely position item hasn't yet been added to our child list // The absolutely position item hasn't yet been added to our child list
absoluteFrame->SetGeometricParent(this); absoluteFrame->SetGeometricParent(this);
@ -1227,22 +952,6 @@ void nsBodyFrame::ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFra
} }
} }
/////////////////////////////////////////////////////////////////////////////
// nsHTMLContainerFrame
// XXX use same logic as block frame?
PRIntn nsBodyFrame::GetSkipSides() const
{
PRIntn skip = 0;
if (nsnull != mPrevInFlow) {
skip |= 1 << NS_SIDE_TOP;
}
if (nsnull != mNextInFlow) {
skip |= 1 << NS_SIDE_BOTTOM;
}
return skip;
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Diagnostics // Diagnostics
@ -1263,6 +972,27 @@ nsBodyFrame::ListTag(FILE* out) const
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsBodyFrame::List(FILE* out, PRInt32 aIndent, nsIListFilter* aFilter) const
{
nsresult rv = nsBlockFrame::List(out, aIndent, aFilter);
// Output absolutely positioned frames
if (nsnull != mAbsoluteFrames) {
for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
fprintf(out, "absolute-items <\n");
}
nsIFrame* f = mAbsoluteFrames;
while (nsnull != f) {
f->List(out, aIndent+1, aFilter);
f->GetNextSibling(f);
}
for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out);
fputs(">\n", out);
return rv;
}
NS_METHOD nsBodyFrame::VerifyTree() const NS_METHOD nsBodyFrame::VerifyTree() const
{ {
#ifdef NS_DEBUG #ifdef NS_DEBUG

Просмотреть файл

@ -18,7 +18,7 @@
#ifndef nsBodyFrame_h___ #ifndef nsBodyFrame_h___
#define nsBodyFrame_h___ #define nsBodyFrame_h___
#include "nsHTMLContainerFrame.h" #include "nsBlockFrame.h"
#include "nsIAbsoluteItems.h" #include "nsIAbsoluteItems.h"
#include "nsISpaceManager.h" #include "nsISpaceManager.h"
#include "nsVoidArray.h" #include "nsVoidArray.h"
@ -28,7 +28,7 @@ class nsSpaceManager;
struct nsStyleDisplay; struct nsStyleDisplay;
struct nsStylePosition; struct nsStylePosition;
class nsBodyFrame : public nsHTMLContainerFrame, class nsBodyFrame : public nsBlockFrame,
public nsIAbsoluteItems public nsIAbsoluteItems
{ {
public: public:
@ -37,34 +37,35 @@ public:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, NS_IMETHOD DeleteFrame(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, NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize, nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus); nsReflowStatus& aStatus);
#ifdef NS_DEBUG
NS_IMETHOD Paint(nsIPresContext& aPresContext, NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext, nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect); const nsRect& aDirtyRect);
#endif
NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext, NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
nsIFrame* aParent, nsIFrame* aParent,
nsIStyleContext* aStyleContext, nsIStyleContext* aStyleContext,
nsIFrame*& aContinuingFrame); nsIFrame*& aContinuingFrame);
NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, NS_IMETHOD HandleEvent(nsIPresContext& aPresContext,
nsGUIEvent* aEvent, nsGUIEvent* aEvent,
nsEventStatus& aEventStatus); nsEventStatus& aEventStatus);
NS_IMETHOD GetCursorAndContentAt(nsIPresContext& aPresContext,
const nsPoint& aPoint,
nsIFrame** aFrame,
nsIContent** aContent,
PRInt32& aCursor);
NS_IMETHOD DidSetStyleContext(nsIPresContext* aPresContext); NS_IMETHOD DidSetStyleContext(nsIPresContext* aPresContext);
NS_METHOD List(FILE* out, PRInt32 aIndent, nsIListFilter* aFilter) const;
NS_IMETHOD ListTag(FILE* out) const; NS_IMETHOD ListTag(FILE* out) const;
// nsIAbsoluteItems // nsIAbsoluteItems
@ -75,6 +76,7 @@ public:
protected: protected:
PRUint32 mFlags; PRUint32 mFlags;
static nsIAtom* gAbsoluteAtom;
void SetFlags(PRUint32 aFlags) { void SetFlags(PRUint32 aFlags) {
mFlags = aFlags; mFlags = aFlags;
@ -84,15 +86,6 @@ protected:
~nsBodyFrame(); ~nsBodyFrame();
void ComputeDesiredSize(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
const nsRect& aDesiredRect,
const nsSize& aMaxSize,
const nsMargin& aBorderPadding,
nsHTMLReflowMetrics& aDesiredSize);
virtual PRIntn GetSkipSides() const;
void ReflowAbsoluteItems(nsIPresContext& aPresContext, void ReflowAbsoluteItems(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState); const nsHTMLReflowState& aReflowState);
@ -106,16 +99,14 @@ protected:
nsRect& aRect) const; nsRect& aRect) const;
void AddAbsoluteFrame(nsIFrame* aFrame); void AddAbsoluteFrame(nsIFrame* aFrame);
PRBool IsAbsoluteFrame(nsIFrame* aFrame);
private: private:
nsSpaceManager* mSpaceManager; nsSpaceManager* mSpaceManager;
nsVoidArray mAbsoluteItems; nsVoidArray mAbsoluteItems;
nsIFrame* mAbsoluteFrames; // additional named child list
PRInt32 mChildCount; PRInt32 mChildCount;
nsSize GetColumnAvailSpace(nsIPresContext& aPresContext,
const nsMargin& aBorderPadding,
const nsHTMLReflowState& aReflowState);
#ifdef NS_DEBUG #ifdef NS_DEBUG
struct BandData : public nsBandData { struct BandData : public nsBandData {
// Trapezoids used during band processing // Trapezoids used during band processing