mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-31 21:21:08 +00:00
Changed absolutely positioned elements to have the body as their
geometric parent
This commit is contained in:
parent
427ffec39f
commit
09eaa8f230
@ -16,20 +16,12 @@
|
||||
* Reserved.
|
||||
*/
|
||||
#include "nsAbsoluteFrame.h"
|
||||
#include "nsIContentDelegate.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIPtr.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsBodyFrame.h"
|
||||
#include "nsIAbsoluteItems.h"
|
||||
#include "nsIContentDelegate.h"
|
||||
#include "nsIStyleContext.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsViewsCID.h"
|
||||
|
||||
static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
|
||||
NS_DEF_PTR(nsIStyleContext);
|
||||
#include "nsHTMLIIDs.h"
|
||||
|
||||
nsresult
|
||||
nsAbsoluteFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
@ -49,7 +41,7 @@ nsAbsoluteFrame::NewFrame(nsIFrame** aInstancePtrResult,
|
||||
}
|
||||
|
||||
nsAbsoluteFrame::nsAbsoluteFrame(nsIContent* aContent, nsIFrame* aParent)
|
||||
: nsContainerFrame(aContent, aParent)
|
||||
: nsFrame(aContent, aParent)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,198 +49,54 @@ nsAbsoluteFrame::~nsAbsoluteFrame()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbsoluteFrame::IsSplittable(nsSplittableType& aIsSplittable) const
|
||||
NS_METHOD nsAbsoluteFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
aIsSplittable = NS_FRAME_NOT_SPLITTABLE;
|
||||
return NS_OK;
|
||||
}
|
||||
// Have we created the absolutely positioned item yet?
|
||||
if (nsnull == mFrame) {
|
||||
// If the content object is a container then wrap it in a body pseudo-frame
|
||||
if (mContent->CanContainChildren()) {
|
||||
nsBodyFrame::NewFrame(&mFrame, mContent, this);
|
||||
|
||||
nsIView* nsAbsoluteFrame::CreateView(nsIView* aContainingView,
|
||||
const nsRect& aRect,
|
||||
const nsStylePosition* aPosition,
|
||||
const nsStyleDisplay* aDisplay) const
|
||||
{
|
||||
nsIView* view;
|
||||
// Use our style context for the pseudo-frame
|
||||
mFrame->SetStyleContext(aPresContext, mStyleContext);
|
||||
|
||||
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
|
||||
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
|
||||
|
||||
nsresult result = NSRepository::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void **)&view);
|
||||
if (NS_OK == result) {
|
||||
nsIViewManager* viewManager = aContainingView->GetViewManager();
|
||||
|
||||
// Initialize the view
|
||||
NS_ASSERTION(nsnull != viewManager, "null view manager");
|
||||
|
||||
// See if the containing view is a scroll view
|
||||
nsIScrollableView* scrollView = nsnull;
|
||||
nsresult result;
|
||||
nsViewClip clip = {0, 0, 0, 0};
|
||||
PRUint8 clipType = (aDisplay->mClipFlags & NS_STYLE_CLIP_TYPE_MASK);
|
||||
nsViewClip* pClip = nsnull;
|
||||
|
||||
// Is there a clip rect specified?
|
||||
if (NS_STYLE_CLIP_RECT == clipType) {
|
||||
if ((NS_STYLE_CLIP_LEFT_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mLeft = aDisplay->mClip.left;
|
||||
}
|
||||
if ((NS_STYLE_CLIP_RIGHT_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mRight = aDisplay->mClip.right;
|
||||
}
|
||||
if ((NS_STYLE_CLIP_TOP_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mTop = aDisplay->mClip.top;
|
||||
}
|
||||
if ((NS_STYLE_CLIP_BOTTOM_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mBottom = aDisplay->mClip.bottom;
|
||||
}
|
||||
pClip = &clip;
|
||||
}
|
||||
else if (NS_STYLE_CLIP_INHERIT == clipType) {
|
||||
// XXX need to handle clip inherit (get from parent style context)
|
||||
NS_NOTYETIMPLEMENTED("clip inherit");
|
||||
}
|
||||
|
||||
PRInt32 zIndex = 0;
|
||||
if (aPosition->mZIndex.GetUnit() == eStyleUnit_Integer) {
|
||||
zIndex = aPosition->mZIndex.GetIntValue();
|
||||
} else if (aPosition->mZIndex.GetUnit() == eStyleUnit_Auto) {
|
||||
zIndex = 0;
|
||||
} else if (aPosition->mZIndex.GetUnit() == eStyleUnit_Inherit) {
|
||||
// XXX need to handle z-index "inherit"
|
||||
NS_NOTYETIMPLEMENTED("zIndex: inherit");
|
||||
}
|
||||
|
||||
result = aContainingView->QueryInterface(kIScrollableViewIID, (void**)&scrollView);
|
||||
if (NS_OK == result) {
|
||||
nsIView* scrolledView = scrollView->GetScrolledView();
|
||||
|
||||
view->Init(viewManager, aRect, scrolledView, nsnull, nsnull, nsnull,
|
||||
zIndex, pClip);
|
||||
viewManager->InsertChild(scrolledView, view, 0);
|
||||
NS_RELEASE(scrolledView);
|
||||
NS_RELEASE(scrollView);
|
||||
} else {
|
||||
view->Init(viewManager, aRect, aContainingView, nsnull, nsnull, nsnull,
|
||||
zIndex, pClip);
|
||||
viewManager->InsertChild(aContainingView, view, 0);
|
||||
}
|
||||
// Ask the content delegate to create the frame
|
||||
nsIContentDelegate* delegate = mContent->GetDelegate(aPresContext);
|
||||
|
||||
NS_RELEASE(viewManager);
|
||||
nsresult rv = delegate->CreateFrame(aPresContext, mContent, this,
|
||||
mStyleContext, mFrame);
|
||||
NS_RELEASE(delegate);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the containing block
|
||||
nsIFrame* containingBlock = GetContainingBlock();
|
||||
NS_ASSERTION(nsnull != containingBlock, "no initial containing block");
|
||||
|
||||
// Query for its nsIAbsoluteItems interface
|
||||
nsIAbsoluteItems* absoluteItemContainer;
|
||||
containingBlock->QueryInterface(kIAbsoluteItemsIID, (void**)&absoluteItemContainer);
|
||||
|
||||
// Notify it that there's a new absolutely positioned frame, passing it the
|
||||
// anchor frame
|
||||
NS_ASSERTION(nsnull != absoluteItemContainer, "no nsIAbsoluteItems support");
|
||||
absoluteItemContainer->AddAbsoluteItem(this);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
// Returns the offset from this frame to aFrameTo
|
||||
void nsAbsoluteFrame::GetOffsetFromFrame(nsIFrame* aFrameTo, nsPoint& aOffset) const
|
||||
{
|
||||
nsIFrame* frame = (nsIFrame*)this;
|
||||
|
||||
aOffset.MoveTo(0, 0);
|
||||
do {
|
||||
nsPoint origin;
|
||||
|
||||
frame->GetOrigin(origin);
|
||||
aOffset += origin;
|
||||
frame->GetGeometricParent(frame);
|
||||
} while ((nsnull != frame) && (frame != aFrameTo));
|
||||
}
|
||||
|
||||
void nsAbsoluteFrame::ComputeViewBounds(nsIFrame* aContainingBlock,
|
||||
const nsStylePosition* aPosition,
|
||||
nsRect& aRect) const
|
||||
{
|
||||
nsRect containingRect;
|
||||
|
||||
// XXX We should be using the inner rect, and not just the bounding rect.
|
||||
// Because of the way the frame sizing protocol works (it's top-down, and
|
||||
// the size of a container is set after reflowing its children), get the
|
||||
// rect from the containing block's view
|
||||
nsIView* containingView;
|
||||
aContainingBlock->GetView(containingView);
|
||||
containingView->GetBounds(containingRect);
|
||||
NS_RELEASE(containingView);
|
||||
containingRect.x = containingRect.y = 0;
|
||||
|
||||
// Compute the offset and size of the view based on the position properties
|
||||
// and the inner rect of the containing block
|
||||
const nsStylePosition* position = (const nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
|
||||
|
||||
// If either the left or top are 'auto' then get the offset of our frame from
|
||||
// the containing block
|
||||
nsPoint offset; // offset from containing block
|
||||
if ((eStyleUnit_Auto == position->mLeftOffset.GetUnit()) ||
|
||||
(eStyleUnit_Auto == position->mTopOffset.GetUnit())) {
|
||||
GetOffsetFromFrame(aContainingBlock, offset);
|
||||
}
|
||||
|
||||
// x-offset
|
||||
if (eStyleUnit_Auto == position->mLeftOffset.GetUnit()) {
|
||||
// Use the current x-offset of our frame translated into the coordinate space
|
||||
// of the containing block
|
||||
aRect.x = offset.x;
|
||||
} else if (eStyleUnit_Coord == position->mLeftOffset.GetUnit()) {
|
||||
aRect.x = position->mLeftOffset.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == position->mLeftOffset.GetUnit(),
|
||||
"unexpected offset type");
|
||||
// Percentage values refer to the width of the containing block
|
||||
aRect.x = containingRect.x +
|
||||
(nscoord)((float)containingRect.width *
|
||||
position->mLeftOffset.GetPercentValue());
|
||||
}
|
||||
|
||||
// y-offset
|
||||
if (eStyleUnit_Auto == position->mTopOffset.GetUnit()) {
|
||||
// Use the current y-offset of our frame translated into the coordinate space
|
||||
// of the containing block
|
||||
aRect.y = offset.y;
|
||||
} else if (eStyleUnit_Coord == position->mTopOffset.GetUnit()) {
|
||||
aRect.y = position->mTopOffset.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == position->mTopOffset.GetUnit(),
|
||||
"unexpected offset type");
|
||||
// Percentage values refer to the height of the containing block
|
||||
aRect.y = containingRect.y +
|
||||
(nscoord)((float)containingRect.height *
|
||||
position->mTopOffset.GetPercentValue());
|
||||
}
|
||||
|
||||
// width
|
||||
if (eStyleUnit_Auto == position->mWidth.GetUnit()) {
|
||||
// Use the right-edge of the containing block
|
||||
aRect.width = containingRect.width - aRect.x;
|
||||
} else if (eStyleUnit_Coord == position->mWidth.GetUnit()) {
|
||||
aRect.width = position->mWidth.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == position->mWidth.GetUnit(),
|
||||
"unexpected width type");
|
||||
aRect.width = (nscoord)((float)containingRect.width *
|
||||
position->mWidth.GetPercentValue());
|
||||
}
|
||||
|
||||
// height
|
||||
if (eStyleUnit_Auto == position->mHeight.GetUnit()) {
|
||||
// Allow it to be as high as it wants
|
||||
aRect.height = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (eStyleUnit_Coord == position->mHeight.GetUnit()) {
|
||||
aRect.height = position->mHeight.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == position->mHeight.GetUnit(),
|
||||
"unexpected height type");
|
||||
aRect.height = (nscoord)((float)containingRect.height *
|
||||
position->mHeight.GetPercentValue());
|
||||
}
|
||||
// Return our desired size as (0, 0)
|
||||
return nsFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
}
|
||||
|
||||
nsIFrame* nsAbsoluteFrame::GetContainingBlock() const
|
||||
{
|
||||
// Look for a containing frame that is absolutely positioned. If we don't
|
||||
// find one then use the initial containg block which is the root frame
|
||||
// find one then use the initial containg block which is the BODY
|
||||
nsIFrame* lastFrame = (nsIFrame*)this;
|
||||
nsIFrame* result;
|
||||
|
||||
@ -269,91 +117,24 @@ nsIFrame* nsAbsoluteFrame::GetContainingBlock() const
|
||||
}
|
||||
|
||||
if (nsnull == result) {
|
||||
result = lastFrame;
|
||||
// Walk back down the tree until we find a frame that supports nsIAnchoredItems
|
||||
// XXX This is pretty yucky, but there isn't currently a better way to do
|
||||
// this...
|
||||
lastFrame->FirstChild(result);
|
||||
|
||||
while (nsnull != result) {
|
||||
nsIAbsoluteItems* interface;
|
||||
if (NS_OK == result->QueryInterface(kIAbsoluteItemsIID, (void**)&interface)) {
|
||||
break;
|
||||
}
|
||||
|
||||
result->FirstChild(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_METHOD nsAbsoluteFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
// Have we created the absolutely positioned item yet?
|
||||
if (nsnull == mFirstChild) {
|
||||
// If the content object is a container then wrap it in a body pseudo-frame
|
||||
if (mContent->CanContainChildren()) {
|
||||
nsBodyFrame::NewFrame(&mFirstChild, mContent, this);
|
||||
|
||||
// Use our style context for the pseudo-frame
|
||||
mFirstChild->SetStyleContext(aPresContext, mStyleContext);
|
||||
|
||||
} else {
|
||||
// Create the absolutely positioned item as a pseudo-frame child. We'll
|
||||
// also create a view
|
||||
nsIContentDelegate* delegate = mContent->GetDelegate(aPresContext);
|
||||
|
||||
nsresult rv = delegate->CreateFrame(aPresContext, mContent, this,
|
||||
mStyleContext, mFirstChild);
|
||||
NS_RELEASE(delegate);
|
||||
if (NS_OK != rv) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the containing block, and its associated view
|
||||
nsIFrame* containingBlock = GetContainingBlock();
|
||||
|
||||
// Use the position properties to determine the offset and size
|
||||
const nsStylePosition* position = (const nsStylePosition*)mStyleContext->GetStyleData(eStyleStruct_Position);
|
||||
nsRect rect;
|
||||
|
||||
ComputeViewBounds(containingBlock, position, rect);
|
||||
|
||||
// Create a view for the frame
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
|
||||
nsIView* containingView;
|
||||
containingBlock->GetView(containingView);
|
||||
nsIView* view = CreateView(containingView, rect, position, display);
|
||||
NS_RELEASE(containingView);
|
||||
|
||||
mFirstChild->SetView(view);
|
||||
NS_RELEASE(view);
|
||||
|
||||
// Resize reflow the absolutely positioned element
|
||||
nsSize availSize(rect.width, rect.height);
|
||||
|
||||
if (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow) {
|
||||
// Don't constrain the height since the container should be enlarged to
|
||||
// contain overflowing frames
|
||||
availSize.height = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
|
||||
nsReflowMetrics desiredSize(nsnull);
|
||||
nsReflowState reflowState(mFirstChild, aReflowState, availSize, eReflowReason_Initial);
|
||||
mFirstChild->WillReflow(*aPresContext);
|
||||
mFirstChild->Reflow(aPresContext, desiredSize, reflowState, aStatus);
|
||||
|
||||
// Figure out what size to actually use. If the position style is 'auto' or
|
||||
// the container should be enlarged to contain overflowing frames then use
|
||||
// the desired size
|
||||
if ((eStyleUnit_Auto == position->mWidth.GetUnit()) ||
|
||||
((desiredSize.width > availSize.width) &&
|
||||
(NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow))) {
|
||||
rect.width = desiredSize.width;
|
||||
}
|
||||
if (eStyleUnit_Auto == position->mHeight.GetUnit()) {
|
||||
rect.height = desiredSize.height;
|
||||
}
|
||||
mFirstChild->SetRect(rect);
|
||||
mFirstChild->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
}
|
||||
|
||||
// Return our desired size as (0, 0)
|
||||
return nsFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
}
|
||||
|
||||
NS_METHOD nsAbsoluteFrame::ListTag(FILE* out) const
|
||||
{
|
||||
fputs("*absolute", out);
|
||||
|
@ -18,23 +18,26 @@
|
||||
#ifndef nsAbsoluteFrame_h___
|
||||
#define nsAbsoluteFrame_h___
|
||||
|
||||
#include "nsContainerFrame.h"
|
||||
struct nsStylePosition;
|
||||
struct nsStyleDisplay;
|
||||
#include "nsFrame.h"
|
||||
|
||||
// Implementation of a frame that's used as a placeholder for an absolutely
|
||||
// positioned frame
|
||||
class nsAbsoluteFrame : public nsContainerFrame {
|
||||
class nsAbsoluteFrame : public nsFrame {
|
||||
public:
|
||||
/**
|
||||
* Create a new absolutely positioned frame
|
||||
* Create a placeholder for an absolutely positioned frame. Also creates
|
||||
* the absolutely positioned frame itself
|
||||
*
|
||||
* @see #GetAbsoluteFrame()
|
||||
*/
|
||||
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent);
|
||||
|
||||
// Returns the associated anchored item
|
||||
nsIFrame* GetAbsoluteFrame() const {return mFrame;}
|
||||
|
||||
// nsIFrame overrides
|
||||
NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
|
||||
NS_IMETHOD Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
const nsReflowState& aReflowState,
|
||||
@ -42,21 +45,15 @@ public:
|
||||
NS_IMETHOD ListTag(FILE* out = stdout) const;
|
||||
|
||||
protected:
|
||||
nsIFrame* mFrame; // the absolutely positioned frame
|
||||
|
||||
// Constructor. Takes as arguments the content object, the index in parent,
|
||||
// and the Frame for the content parent
|
||||
nsAbsoluteFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
|
||||
virtual ~nsAbsoluteFrame();
|
||||
|
||||
nsIView* CreateView(nsIView* aContainingView,
|
||||
const nsRect& aRect,
|
||||
const nsStylePosition* aPosition,
|
||||
const nsStyleDisplay* aDisplay) const;
|
||||
nsIFrame* GetContainingBlock() const;
|
||||
void ComputeViewBounds(nsIFrame* aContainingBlock,
|
||||
const nsStylePosition* aPosition,
|
||||
nsRect& aRect) const;
|
||||
void GetOffsetFromFrame(nsIFrame* aFrameTo, nsPoint& aOffset) const;
|
||||
};
|
||||
|
||||
#endif /* nsAbsoluteFrame_h___ */
|
||||
|
@ -28,6 +28,9 @@
|
||||
#include "nsIRunaround.h"
|
||||
#include "nsSpaceManager.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsViewsCID.h"
|
||||
#include "nsAbsoluteFrame.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsCSSBlockFrame.h"
|
||||
|
||||
@ -60,6 +63,9 @@ nsBodyFrame::~nsBodyFrame()
|
||||
NS_RELEASE(mSpaceManager);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIUnknown
|
||||
|
||||
nsresult
|
||||
nsBodyFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
@ -71,63 +77,15 @@ nsBodyFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
*aInstancePtr = (void*) ((nsIAnchoredItems*) this);
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kIAbsoluteItemsIID)) {
|
||||
*aInstancePtr = (void*) ((nsIAbsoluteItems*) this);
|
||||
return NS_OK;
|
||||
}
|
||||
return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
void nsBodyFrame::CreateColumnFrame(nsIPresContext* aPresContext)
|
||||
{
|
||||
nsIStyleContext* styleContext =
|
||||
aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, this);
|
||||
|
||||
// Do we have a prev-in-flow?
|
||||
if (nsnull == mPrevInFlow) {
|
||||
// No, create a column pseudo frame
|
||||
NS_NewCSSBlockFrame(&mFirstChild, mContent, this);
|
||||
mChildCount = 1;
|
||||
mFirstChild->SetStyleContext(aPresContext,styleContext);
|
||||
} else {
|
||||
// Create a continuing column
|
||||
nsBodyFrame* prevBody = (nsBodyFrame*)mPrevInFlow;
|
||||
nsIFrame* prevColumn = prevBody->mFirstChild;
|
||||
NS_ASSERTION(prevBody->ChildIsPseudoFrame(prevColumn),
|
||||
"bad previous column");
|
||||
|
||||
prevColumn->CreateContinuingFrame(aPresContext, this, styleContext,
|
||||
mFirstChild);
|
||||
mChildCount = 1;
|
||||
}
|
||||
|
||||
NS_RELEASE(styleContext);
|
||||
}
|
||||
|
||||
nsSize nsBodyFrame::GetColumnAvailSpace(nsIPresContext* aPresContext,
|
||||
const nsMargin& aBorderPadding,
|
||||
const nsSize& aMaxSize)
|
||||
{
|
||||
nsSize result(aMaxSize);
|
||||
|
||||
// If we're not being used as a pseudo frame then make adjustments
|
||||
// for border/padding and a vertical scrollbar
|
||||
if (!mIsPseudoFrame) {
|
||||
// If our width is constrained then subtract for the border/padding
|
||||
if (aMaxSize.width != NS_UNCONSTRAINEDSIZE) {
|
||||
result.width -= aBorderPadding.left +
|
||||
aBorderPadding.right;
|
||||
if (! aPresContext->IsPaginated()) {
|
||||
nsIDeviceContext* dc = aPresContext->GetDeviceContext();
|
||||
result.width -= NS_TO_INT_ROUND(dc->GetScrollBarWidth());
|
||||
NS_RELEASE(dc);
|
||||
}
|
||||
}
|
||||
// If our height is constrained then subtract for the border/padding
|
||||
if (aMaxSize.height != NS_UNCONSTRAINEDSIZE) {
|
||||
result.height -= aBorderPadding.top +
|
||||
aBorderPadding.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIFrame
|
||||
|
||||
NS_METHOD nsBodyFrame::Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
@ -249,6 +207,9 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext* aPresContext,
|
||||
mLastContentIsComplete = blockPseudoFrame->GetLastContentIsComplete();
|
||||
#endif
|
||||
|
||||
// Reflow any absolutely positioned frames that need reflowing
|
||||
ReflowAbsoluteItems(aPresContext, aReflowState);
|
||||
|
||||
// Return our desired size
|
||||
ComputeDesiredSize(desiredRect, aReflowState.maxSize, borderPadding, aDesiredSize);
|
||||
}
|
||||
@ -269,6 +230,508 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsBodyFrame::ContentAppended(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer)
|
||||
{
|
||||
NS_ASSERTION(mContent == aContainer, "bad content-appended target");
|
||||
|
||||
// Pass along the notification to our pseudo frame. It will generate a
|
||||
// reflow command
|
||||
return mFirstChild->ContentAppended(aShell, aPresContext, aContainer);
|
||||
}
|
||||
|
||||
NS_METHOD nsBodyFrame::ContentInserted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent)
|
||||
{
|
||||
NS_ASSERTION(mContent == aContainer, "bad content-inserted target");
|
||||
|
||||
// Pass along the notification to our pseudo frame that maps all the content
|
||||
return mFirstChild->ContentInserted(aShell, aPresContext, aContainer,
|
||||
aChild, aIndexInParent);
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsBodyFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aStyleContext,
|
||||
nsIFrame*& aContinuingFrame)
|
||||
{
|
||||
nsBodyFrame* cf = new nsBodyFrame(mContent, aParent);
|
||||
if (nsnull == cf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Helper functions
|
||||
|
||||
void nsBodyFrame::CreateColumnFrame(nsIPresContext* aPresContext)
|
||||
{
|
||||
nsIStyleContext* styleContext =
|
||||
aPresContext->ResolvePseudoStyleContextFor(nsHTMLAtoms::columnPseudo, this);
|
||||
|
||||
// Do we have a prev-in-flow?
|
||||
if (nsnull == mPrevInFlow) {
|
||||
// No, create a column pseudo frame
|
||||
NS_NewCSSBlockFrame(&mFirstChild, mContent, this);
|
||||
mChildCount = 1;
|
||||
mFirstChild->SetStyleContext(aPresContext,styleContext);
|
||||
} else {
|
||||
// Create a continuing column
|
||||
nsBodyFrame* prevBody = (nsBodyFrame*)mPrevInFlow;
|
||||
nsIFrame* prevColumn = prevBody->mFirstChild;
|
||||
NS_ASSERTION(prevBody->ChildIsPseudoFrame(prevColumn),
|
||||
"bad previous column");
|
||||
|
||||
prevColumn->CreateContinuingFrame(aPresContext, this, styleContext,
|
||||
mFirstChild);
|
||||
mChildCount = 1;
|
||||
}
|
||||
|
||||
NS_RELEASE(styleContext);
|
||||
}
|
||||
|
||||
nsSize nsBodyFrame::GetColumnAvailSpace(nsIPresContext* aPresContext,
|
||||
const nsMargin& aBorderPadding,
|
||||
const nsSize& aMaxSize)
|
||||
{
|
||||
nsSize result(aMaxSize);
|
||||
|
||||
// If we're not being used as a pseudo frame then make adjustments
|
||||
// for border/padding and a vertical scrollbar
|
||||
if (!mIsPseudoFrame) {
|
||||
// If our width is constrained then subtract for the border/padding
|
||||
if (aMaxSize.width != NS_UNCONSTRAINEDSIZE) {
|
||||
result.width -= aBorderPadding.left +
|
||||
aBorderPadding.right;
|
||||
if (! aPresContext->IsPaginated()) {
|
||||
nsIDeviceContext* dc = aPresContext->GetDeviceContext();
|
||||
result.width -= NS_TO_INT_ROUND(dc->GetScrollBarWidth());
|
||||
NS_RELEASE(dc);
|
||||
}
|
||||
}
|
||||
// If our height is constrained then subtract for the border/padding
|
||||
if (aMaxSize.height != NS_UNCONSTRAINEDSIZE) {
|
||||
result.height -= aBorderPadding.top +
|
||||
aBorderPadding.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsBodyFrame::ComputeDesiredSize(const nsRect& aDesiredRect,
|
||||
const nsSize& aMaxSize,
|
||||
const nsMargin& aBorderPadding,
|
||||
nsReflowMetrics& aDesiredSize)
|
||||
{
|
||||
// Note: Body used as a pseudo-frame shrink wraps
|
||||
aDesiredSize.height = PR_MAX(aDesiredRect.YMost(), mSpaceManager->YMost());
|
||||
aDesiredSize.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);
|
||||
if (rect.XMost() > aDesiredSize.width) {
|
||||
aDesiredSize.width = rect.XMost();
|
||||
}
|
||||
if (rect.YMost() > aDesiredSize.height) {
|
||||
aDesiredSize.height = rect.YMost();
|
||||
}
|
||||
}
|
||||
|
||||
if (!mIsPseudoFrame) {
|
||||
// Make sure we're at least as wide as our available width
|
||||
aDesiredSize.width = PR_MAX(aDesiredSize.width, aMaxSize.width);
|
||||
aDesiredSize.height += aBorderPadding.top +
|
||||
aBorderPadding.bottom;
|
||||
}
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
}
|
||||
|
||||
// Add the frame to the end of the child list
|
||||
void nsBodyFrame::AddFrame(nsIFrame* aFrame)
|
||||
{
|
||||
nsIFrame* lastChild;
|
||||
|
||||
LastChild(lastChild);
|
||||
lastChild->SetNextSibling(aFrame);
|
||||
aFrame->SetNextSibling(nsnull);
|
||||
mChildCount++;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAnchoredItems
|
||||
|
||||
void nsBodyFrame::AddAnchoredItem(nsIFrame* aAnchoredItem,
|
||||
AnchoringPosition aPosition,
|
||||
nsIFrame* aContainer)
|
||||
{
|
||||
// Set the geometric parent and add the anchored frame to the child list
|
||||
aAnchoredItem->SetGeometricParent(this);
|
||||
AddFrame(aAnchoredItem);
|
||||
}
|
||||
|
||||
void nsBodyFrame::RemoveAnchoredItem(nsIFrame* aAnchoredItem)
|
||||
{
|
||||
NS_PRECONDITION(IsChild(aAnchoredItem), "bad anchored item");
|
||||
NS_ASSERTION(aAnchoredItem != mFirstChild, "unexpected anchored item");
|
||||
// Remove the anchored item from the child list
|
||||
// XXX Implement me
|
||||
mChildCount--;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAbsoluteItems
|
||||
|
||||
NS_METHOD nsBodyFrame::AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame)
|
||||
{
|
||||
// Add the absolute anchor frame to our list of absolutely positioned
|
||||
// items.
|
||||
mAbsoluteItems.AppendElement(aAnchorFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_METHOD nsBodyFrame::RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("removing an absolutely positioned frame");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Called at the end of the Reflow() member function so we can process
|
||||
// any abolutely positioned items that need to be reflowed
|
||||
void nsBodyFrame::ReflowAbsoluteItems(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState)
|
||||
{
|
||||
for (PRInt32 i = 0; i < mAbsoluteItems.Count(); i++) {
|
||||
// Get the anchor frame and its absolutely positioned frame
|
||||
nsAbsoluteFrame* anchorFrame = (nsAbsoluteFrame*)mAbsoluteItems[i];
|
||||
nsIFrame* absoluteFrame = anchorFrame->GetAbsoluteFrame();
|
||||
PRBool placeFrame = PR_FALSE;
|
||||
PRBool reflowFrame = PR_FALSE;
|
||||
nsReflowReason reflowReason = eReflowReason_Resize;
|
||||
|
||||
// Get its style information
|
||||
const nsStyleDisplay* display;
|
||||
const nsStylePosition* position;
|
||||
|
||||
absoluteFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct*&)display);
|
||||
absoluteFrame->GetStyleData(eStyleStruct_Position, (nsStyleStruct*&)position);
|
||||
|
||||
// See whether the frame is a newly added frame
|
||||
nsIFrame* parent;
|
||||
absoluteFrame->GetGeometricParent(parent);
|
||||
if (parent != this) {
|
||||
// The absolutely position item hasn't yet been added to our child list
|
||||
absoluteFrame->SetGeometricParent(this);
|
||||
|
||||
// Add the absolutely positioned frame to the end of the child list
|
||||
AddFrame(absoluteFrame);
|
||||
|
||||
// Make sure the frame has a view
|
||||
nsIView* view;
|
||||
absoluteFrame->GetView(view);
|
||||
if (nsnull == view) {
|
||||
view = CreateAbsoluteView(position, display);
|
||||
absoluteFrame->SetView(view);
|
||||
}
|
||||
NS_RELEASE(view);
|
||||
|
||||
// See whether this is the frame's initial reflow
|
||||
nsFrameState frameState;
|
||||
absoluteFrame->GetFrameState(frameState);
|
||||
if (frameState & NS_FRAME_FIRST_REFLOW) {
|
||||
reflowReason = eReflowReason_Initial;
|
||||
}
|
||||
|
||||
// We need to place and reflow the absolutely positioned frame
|
||||
placeFrame = reflowFrame = PR_TRUE;
|
||||
|
||||
} else {
|
||||
// We need to place the frame if the left-offset or the top-offset are
|
||||
// auto or a percentage
|
||||
if ((eStyleUnit_Coord != position->mLeftOffset.GetUnit()) ||
|
||||
(eStyleUnit_Coord != position->mTopOffset.GetUnit())) {
|
||||
placeFrame = PR_TRUE;
|
||||
}
|
||||
|
||||
// We need to reflow the frame if its width or its height is auto or
|
||||
// a percentage
|
||||
if ((eStyleUnit_Coord != position->mWidth.GetUnit()) ||
|
||||
(eStyleUnit_Coord != position->mHeight.GetUnit())) {
|
||||
reflowFrame = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (placeFrame || reflowFrame) {
|
||||
// Get the rect for the absolutely positioned element
|
||||
nsRect rect;
|
||||
ComputeAbsoluteFrameBounds(anchorFrame, aReflowState, position, rect);
|
||||
|
||||
absoluteFrame->WillReflow(*aPresContext);
|
||||
absoluteFrame->MoveTo(rect.x, rect.y);
|
||||
|
||||
if (reflowFrame) {
|
||||
// Resize reflow the absolutely positioned element
|
||||
nsSize availSize(rect.width, rect.height);
|
||||
|
||||
if (NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow) {
|
||||
// Don't constrain the height since the container should be enlarged
|
||||
// to contain overflowing frames
|
||||
availSize.height = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
|
||||
nsReflowMetrics desiredSize(nsnull);
|
||||
nsReflowState reflowState(absoluteFrame, aReflowState, availSize,
|
||||
reflowReason);
|
||||
nsReflowStatus status;
|
||||
absoluteFrame->Reflow(aPresContext, desiredSize, reflowState, status);
|
||||
|
||||
// Figure out what size to actually use. If we let the child choose its
|
||||
// size, then use what the child requested. Otherwise, use the value
|
||||
// specified in the style information
|
||||
if ((eStyleUnit_Auto == position->mWidth.GetUnit()) ||
|
||||
((desiredSize.width > availSize.width) &&
|
||||
(NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow))) {
|
||||
rect.width = desiredSize.width;
|
||||
}
|
||||
if ((eStyleUnit_Auto == position->mHeight.GetUnit()) ||
|
||||
(NS_UNCONSTRAINEDSIZE == rect.height) ||
|
||||
((desiredSize.height > rect.height) &&
|
||||
(NS_STYLE_OVERFLOW_VISIBLE == display->mOverflow))) {
|
||||
rect.height = desiredSize.height;
|
||||
}
|
||||
absoluteFrame->SetRect(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsIView* nsBodyFrame::CreateAbsoluteView(const nsStylePosition* aPosition,
|
||||
const nsStyleDisplay* aDisplay) const
|
||||
{
|
||||
nsIView* view;
|
||||
|
||||
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
|
||||
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
|
||||
|
||||
// Create the view
|
||||
nsresult result = NSRepository::CreateInstance(kViewCID,
|
||||
nsnull,
|
||||
kIViewIID,
|
||||
(void **)&view);
|
||||
if (NS_OK == result) {
|
||||
// XXX Even though since we're absolutely positioned we should have a view,
|
||||
// we might not...
|
||||
nsIView* containingView;
|
||||
GetView(containingView);
|
||||
if (nsnull == containingView) {
|
||||
nsPoint offset;
|
||||
GetOffsetFromView(offset, containingView);
|
||||
}
|
||||
|
||||
// Initialize the view
|
||||
nsIViewManager* viewManager = containingView->GetViewManager();
|
||||
NS_ASSERTION(nsnull != viewManager, "null view manager");
|
||||
|
||||
// Is there a clip rect specified?
|
||||
nsViewClip clip = {0, 0, 0, 0};
|
||||
PRUint8 clipType = (aDisplay->mClipFlags & NS_STYLE_CLIP_TYPE_MASK);
|
||||
nsViewClip* pClip = nsnull;
|
||||
|
||||
if (NS_STYLE_CLIP_RECT == clipType) {
|
||||
if ((NS_STYLE_CLIP_LEFT_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mLeft = aDisplay->mClip.left;
|
||||
}
|
||||
if ((NS_STYLE_CLIP_RIGHT_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mRight = aDisplay->mClip.right;
|
||||
}
|
||||
if ((NS_STYLE_CLIP_TOP_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mTop = aDisplay->mClip.top;
|
||||
}
|
||||
if ((NS_STYLE_CLIP_BOTTOM_AUTO & aDisplay->mClipFlags) == 0) {
|
||||
clip.mBottom = aDisplay->mClip.bottom;
|
||||
}
|
||||
pClip = &clip;
|
||||
}
|
||||
else if (NS_STYLE_CLIP_INHERIT == clipType) {
|
||||
// XXX need to handle clip inherit (get from parent style context)
|
||||
NS_NOTYETIMPLEMENTED("clip inherit");
|
||||
}
|
||||
|
||||
// Get the z-index to use
|
||||
PRInt32 zIndex = 0;
|
||||
if (aPosition->mZIndex.GetUnit() == eStyleUnit_Integer) {
|
||||
zIndex = aPosition->mZIndex.GetIntValue();
|
||||
} else if (aPosition->mZIndex.GetUnit() == eStyleUnit_Auto) {
|
||||
zIndex = 0;
|
||||
} else if (aPosition->mZIndex.GetUnit() == eStyleUnit_Inherit) {
|
||||
// XXX need to handle z-index "inherit"
|
||||
NS_NOTYETIMPLEMENTED("zIndex: inherit");
|
||||
}
|
||||
|
||||
// Initialize the view with a size of (0, 0). When we're done reflowing
|
||||
// the frame the view will be sized and positioned
|
||||
view->Init(viewManager, nsRect(0, 0, 0, 0), containingView, nsnull,
|
||||
nsnull, nsnull, zIndex, pClip);
|
||||
viewManager->InsertChild(containingView, view, 0);
|
||||
NS_RELEASE(viewManager);
|
||||
NS_RELEASE(containingView);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
// Translate aPoint from aFrameFrom's coordinate space to our coordinate space
|
||||
void nsBodyFrame::TranslatePoint(nsIFrame* aFrameFrom, nsPoint& aPoint) const
|
||||
{
|
||||
nsIFrame* parent;
|
||||
|
||||
aFrameFrom->GetGeometricParent(parent);
|
||||
while ((nsnull != parent) && (parent != (nsIFrame*)this)) {
|
||||
nsPoint origin;
|
||||
|
||||
parent->GetOrigin(origin);
|
||||
aPoint += origin;
|
||||
parent->GetGeometricParent(parent);
|
||||
}
|
||||
}
|
||||
|
||||
void nsBodyFrame::ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFrame,
|
||||
const nsReflowState& aReflowState,
|
||||
const nsStylePosition* aPosition,
|
||||
nsRect& aRect) const
|
||||
{
|
||||
// Compute the offset and size of the view based on the position properties,
|
||||
// and the inner rect of the containing block (which we get from the reflow
|
||||
// state)
|
||||
//
|
||||
// If either the left or top are 'auto' then get the offset of the anchor
|
||||
// frame from this frame
|
||||
nsPoint offset;
|
||||
if ((eStyleUnit_Auto == aPosition->mLeftOffset.GetUnit()) ||
|
||||
(eStyleUnit_Auto == aPosition->mTopOffset.GetUnit())) {
|
||||
aAnchorFrame->GetOrigin(offset);
|
||||
TranslatePoint(aAnchorFrame, offset);
|
||||
}
|
||||
|
||||
// left-offset
|
||||
if (eStyleUnit_Auto == aPosition->mLeftOffset.GetUnit()) {
|
||||
// Use the current x-offset of the anchor frame translated into our
|
||||
// coordinate space
|
||||
aRect.x = offset.x;
|
||||
} else if (eStyleUnit_Coord == aPosition->mLeftOffset.GetUnit()) {
|
||||
aRect.x = aPosition->mLeftOffset.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == aPosition->mLeftOffset.GetUnit(),
|
||||
"unexpected offset type");
|
||||
// Percentage values refer to the width of the containing block. If the
|
||||
// width is unconstrained then just use 0
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.maxSize.width) {
|
||||
aRect.x = 0;
|
||||
} else {
|
||||
aRect.x = (nscoord)((float)aReflowState.maxSize.width *
|
||||
aPosition->mLeftOffset.GetPercentValue());
|
||||
}
|
||||
}
|
||||
|
||||
// top-offset
|
||||
if (eStyleUnit_Auto == aPosition->mTopOffset.GetUnit()) {
|
||||
// Use the current y-offset of the anchor frame translated into our
|
||||
// coordinate space
|
||||
aRect.y = offset.y;
|
||||
} else if (eStyleUnit_Coord == aPosition->mTopOffset.GetUnit()) {
|
||||
aRect.y = aPosition->mTopOffset.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == aPosition->mTopOffset.GetUnit(),
|
||||
"unexpected offset type");
|
||||
// Percentage values refer to the height of the containing block. If the
|
||||
// height is unconstrained then interpret it like 'auto'
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.maxSize.height) {
|
||||
aRect.y = offset.y;
|
||||
} else {
|
||||
aRect.y = (nscoord)((float)aReflowState.maxSize.height *
|
||||
aPosition->mTopOffset.GetPercentValue());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX We aren't properly handling 'auto' width and height
|
||||
// XXX The width/height represent the size of the content area only, and not
|
||||
// the frame size...
|
||||
|
||||
// width
|
||||
if (eStyleUnit_Auto == aPosition->mWidth.GetUnit()) {
|
||||
// Use the right-edge of the containing block
|
||||
aRect.width = aReflowState.maxSize.width;
|
||||
} else if (eStyleUnit_Coord == aPosition->mWidth.GetUnit()) {
|
||||
aRect.width = aPosition->mWidth.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == aPosition->mWidth.GetUnit(),
|
||||
"unexpected width type");
|
||||
// Percentage values refer to the width of the containing block
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.maxSize.width) {
|
||||
aRect.width = NS_UNCONSTRAINEDSIZE;
|
||||
} else {
|
||||
aRect.width = (nscoord)((float)aReflowState.maxSize.width *
|
||||
aPosition->mWidth.GetPercentValue());
|
||||
}
|
||||
}
|
||||
|
||||
// height
|
||||
if (eStyleUnit_Auto == aPosition->mHeight.GetUnit()) {
|
||||
// Allow it to be as high as it wants
|
||||
aRect.height = NS_UNCONSTRAINEDSIZE;
|
||||
} else if (eStyleUnit_Coord == aPosition->mHeight.GetUnit()) {
|
||||
aRect.height = aPosition->mHeight.GetCoordValue();
|
||||
} else {
|
||||
NS_ASSERTION(eStyleUnit_Percent == aPosition->mHeight.GetUnit(),
|
||||
"unexpected height type");
|
||||
// Percentage values refer to the height of the containing block. If the
|
||||
// height is unconstrained, then interpret it like 'auto' and make the
|
||||
// height unconstrained
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.maxSize.height) {
|
||||
aRect.height = NS_UNCONSTRAINEDSIZE;
|
||||
} else {
|
||||
aRect.height = (nscoord)((float)aReflowState.maxSize.height *
|
||||
aPosition->mHeight.GetPercentValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
NS_METHOD nsBodyFrame::VerifyTree() const
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
@ -312,95 +775,3 @@ NS_METHOD nsBodyFrame::VerifyTree() const
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsBodyFrame::ComputeDesiredSize(const nsRect& aDesiredRect,
|
||||
const nsSize& aMaxSize,
|
||||
const nsMargin& aBorderPadding,
|
||||
nsReflowMetrics& aDesiredSize)
|
||||
{
|
||||
// Note: Body used as a pseudo-frame shrink wraps
|
||||
aDesiredSize.height = PR_MAX(aDesiredRect.YMost(), mSpaceManager->YMost());
|
||||
aDesiredSize.width = aDesiredRect.XMost();
|
||||
if (!mIsPseudoFrame) {
|
||||
aDesiredSize.width = PR_MAX(aDesiredSize.width, aMaxSize.width);
|
||||
aDesiredSize.height += aBorderPadding.top +
|
||||
aBorderPadding.bottom;
|
||||
}
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
}
|
||||
|
||||
NS_METHOD nsBodyFrame::ContentAppended(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer)
|
||||
{
|
||||
NS_ASSERTION(mContent == aContainer, "bad content-appended target");
|
||||
|
||||
// Pass along the notification to our pseudo frame. It will generate a
|
||||
// reflow command
|
||||
return mFirstChild->ContentAppended(aShell, aPresContext, aContainer);
|
||||
}
|
||||
|
||||
NS_METHOD nsBodyFrame::ContentInserted(nsIPresShell* aShell,
|
||||
nsIPresContext* aPresContext,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInParent)
|
||||
{
|
||||
NS_ASSERTION(mContent == aContainer, "bad content-inserted target");
|
||||
|
||||
// Pass along the notification to our pseudo frame that maps all the content
|
||||
return mFirstChild->ContentInserted(aShell, aPresContext, aContainer,
|
||||
aChild, aIndexInParent);
|
||||
}
|
||||
|
||||
void nsBodyFrame::AddAnchoredItem(nsIFrame* aAnchoredItem,
|
||||
AnchoringPosition aPosition,
|
||||
nsIFrame* aContainer)
|
||||
{
|
||||
aAnchoredItem->SetGeometricParent(this);
|
||||
// Add the item to the end of the child list
|
||||
nsIFrame* lastChild;
|
||||
|
||||
LastChild(lastChild);
|
||||
lastChild->SetNextSibling(aAnchoredItem);
|
||||
aAnchoredItem->SetNextSibling(nsnull);
|
||||
mChildCount++;
|
||||
}
|
||||
|
||||
void nsBodyFrame::RemoveAnchoredItem(nsIFrame* aAnchoredItem)
|
||||
{
|
||||
NS_PRECONDITION(IsChild(aAnchoredItem), "bad anchored item");
|
||||
NS_ASSERTION(aAnchoredItem != mFirstChild, "unexpected anchored item");
|
||||
// Remove the anchored item from the child list
|
||||
// XXX Implement me
|
||||
mChildCount--;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsBodyFrame::CreateContinuingFrame(nsIPresContext* aPresContext,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aStyleContext,
|
||||
nsIFrame*& aContinuingFrame)
|
||||
{
|
||||
nsBodyFrame* cf = new nsBodyFrame(mContent, aParent);
|
||||
if (nsnull == cf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PrepareContinuingFrame(aPresContext, aParent, aStyleContext, cf);
|
||||
aContinuingFrame = cf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
@ -20,11 +20,17 @@
|
||||
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsIAnchoredItems.h"
|
||||
#include "nsIAbsoluteItems.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
struct nsBodyReflowState;
|
||||
class nsSpaceManager;
|
||||
|
||||
class nsBodyFrame : public nsHTMLContainerFrame, public nsIAnchoredItems {
|
||||
struct nsStyleDisplay;
|
||||
struct nsStylePosition;
|
||||
|
||||
class nsBodyFrame : public nsHTMLContainerFrame,
|
||||
public nsIAnchoredItems,
|
||||
public nsIAbsoluteItems {
|
||||
public:
|
||||
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
@ -56,9 +62,12 @@ public:
|
||||
virtual void AddAnchoredItem(nsIFrame* aAnchoredItem,
|
||||
AnchoringPosition aPosition,
|
||||
nsIFrame* aContainer);
|
||||
|
||||
virtual void RemoveAnchoredItem(nsIFrame* aAnchoredItem);
|
||||
|
||||
// nsIAbsoluteItems
|
||||
NS_IMETHOD AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame);
|
||||
NS_IMETHOD RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame);
|
||||
|
||||
NS_IMETHOD VerifyTree() const;
|
||||
|
||||
protected:
|
||||
@ -75,8 +84,24 @@ protected:
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
||||
void ReflowAbsoluteItems(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState);
|
||||
|
||||
nsIView* CreateAbsoluteView(const nsStylePosition* aPosition,
|
||||
const nsStyleDisplay* aDisplay) const;
|
||||
|
||||
void TranslatePoint(nsIFrame* aFrameFrom, nsPoint& aPoint) const;
|
||||
|
||||
void ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFrame,
|
||||
const nsReflowState& aState,
|
||||
const nsStylePosition* aPosition,
|
||||
nsRect& aRect) const;
|
||||
|
||||
void AddFrame(nsIFrame* aFrame);
|
||||
|
||||
private:
|
||||
nsSpaceManager* mSpaceManager;
|
||||
nsVoidArray mAbsoluteItems;
|
||||
|
||||
void CreateColumnFrame(nsIPresContext* aPresContext);
|
||||
nsSize GetColumnAvailSpace(nsIPresContext* aPresContext,
|
||||
|
@ -17,12 +17,14 @@
|
||||
*/
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIAbsoluteItems.h"
|
||||
#include "nsIAnchoredItems.h"
|
||||
#include "nsIFloaterContainer.h"
|
||||
#include "nsIRunaround.h"
|
||||
#include "nsIInlineReflow.h"
|
||||
#include "nsCSSBlockFrame.h"
|
||||
|
||||
const nsIID kIAbsoluteItemsIID = NS_IABSOLUTE_ITEMS_IID;
|
||||
const nsIID kIAnchoredItemsIID = NS_IANCHORED_ITEMS_IID;
|
||||
const nsIID kIFloaterContainerIID = NS_IFLOATER_CONTAINER_IID;
|
||||
const nsIID kIHTMLContentIID = NS_IHTMLCONTENT_IID;
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
extern const nsIID kBlockFrameCID; // XXX temporary
|
||||
|
||||
extern const nsIID kIAbsoluteItemsIID;
|
||||
extern const nsIID kIAnchoredItemsIID;
|
||||
extern const nsIID kIFloaterContainerIID;
|
||||
extern const nsIID kIHTMLContentIID;
|
||||
|
51
layout/html/base/src/nsIAbsoluteItems.h
Normal file
51
layout/html/base/src/nsIAbsoluteItems.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
#ifndef nsIAbsoluteItems_h___
|
||||
#define nsIAbsoluteItems_h___
|
||||
|
||||
class nsAbsoluteFrame;
|
||||
|
||||
// IID for the nsIAbsoluteItems interface {28E68A10-0BD4-11d2-85DD-00A02468FAB6}
|
||||
#define NS_IABSOLUTE_ITEMS_IID \
|
||||
{ 0x28e68a10, 0xbd4, 0x11d2, \
|
||||
{0x85, 0xdd, 0x0, 0xa0, 0x24, 0x68, 0xfa, 0xb6}}
|
||||
|
||||
/**
|
||||
* An interface for managing absolutely positioned items. Note that this interface
|
||||
* is not an nsISupports interface, and therefore you cannot QueryInterface() back
|
||||
*/
|
||||
class nsIAbsoluteItems
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Request to add an absolutely positioned item. The anchor for the
|
||||
* absolutely positioned item is passed as an argument
|
||||
*
|
||||
* @see nsAbsoluteFrame::GetAbsoluteFrame()
|
||||
*/
|
||||
NS_IMETHOD AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) = 0;
|
||||
|
||||
/**
|
||||
* Called to remove an absolutely positioned item, most likely because the
|
||||
* associated piece of content has been removed.
|
||||
**/
|
||||
NS_IMETHOD RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) = 0;
|
||||
};
|
||||
|
||||
#endif /* nsIAbsoluteItems_h___ */
|
Loading…
Reference in New Issue
Block a user