Improvements to absolute positioning code
git-svn-id: svn://10.0.0.236/trunk@17952 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
46eb195775
commit
64fcc4cfa2
@ -36,6 +36,7 @@
|
||||
#include "nsLayoutAtoms.h"
|
||||
|
||||
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
|
||||
static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID);
|
||||
|
||||
nsresult
|
||||
NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags)
|
||||
@ -51,6 +52,7 @@ NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags)
|
||||
|
||||
nsAreaFrame::nsAreaFrame()
|
||||
{
|
||||
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; // let us handle it
|
||||
}
|
||||
|
||||
nsAreaFrame::~nsAreaFrame()
|
||||
@ -58,6 +60,23 @@ nsAreaFrame::~nsAreaFrame()
|
||||
NS_IF_RELEASE(mSpaceManager);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kAreaFrameIID)) {
|
||||
nsIAreaFrame* tmp = (nsIAreaFrame*)this;
|
||||
*aInstancePtr = (void*)tmp;
|
||||
return NS_OK;
|
||||
}
|
||||
return nsBlockFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIFrame
|
||||
|
||||
@ -248,6 +267,82 @@ nsAreaFrame::Paint(nsIPresContext& aPresContext,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return the x-most and y-most for the child absolutely positioned
|
||||
// elements
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const
|
||||
{
|
||||
aXMost = aYMost = 0;
|
||||
for (nsIFrame* f = mAbsoluteFrames.FirstChild(); nsnull != f; f->GetNextSibling(f)) {
|
||||
// Get the frame's x-most and y-most. This is for its flowed content only
|
||||
nsRect rect;
|
||||
f->GetRect(rect);
|
||||
|
||||
if (rect.XMost() > aXMost) {
|
||||
aXMost = rect.XMost();
|
||||
}
|
||||
if (rect.YMost() > aYMost) {
|
||||
aYMost = rect.YMost();
|
||||
}
|
||||
|
||||
// If the child frame is also an area frame, then take into account its child
|
||||
// absolutely positioned elements
|
||||
nsIAreaFrame* areaFrame;
|
||||
if (NS_SUCCEEDED(f->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) {
|
||||
nscoord xMost, yMost;
|
||||
|
||||
areaFrame->GetPositionedInfo(xMost, yMost);
|
||||
// Convert to our coordinate space
|
||||
xMost += rect.x;
|
||||
yMost += rect.y;
|
||||
|
||||
if (xMost > aXMost) {
|
||||
aXMost = xMost;
|
||||
}
|
||||
if (yMost > aYMost) {
|
||||
aYMost = yMost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Temporary until the view code allows positioned child views to extend
|
||||
// outside their parent without being clipped...
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::DidReflow(nsIPresContext& aPresContext,
|
||||
nsDidReflowStatus aStatus)
|
||||
{
|
||||
nsresult rv = nsBlockFrame::DidReflow(aPresContext, aStatus);
|
||||
|
||||
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
|
||||
nsIView* view;
|
||||
GetView(view);
|
||||
|
||||
// Size and position the view if requested
|
||||
if (nsnull != view) {
|
||||
// Position and size view relative to its parent, not relative to our
|
||||
// parent frame (our parent frame may not have a view).
|
||||
nsIView* parentWithView;
|
||||
nsPoint origin;
|
||||
GetOffsetFromView(origin, parentWithView);
|
||||
nsIViewManager *vm;
|
||||
view->GetViewManager(vm);
|
||||
|
||||
// Take into account any absolutely positioned children
|
||||
nscoord xMost, yMost;
|
||||
GetPositionedInfo(xMost, yMost);
|
||||
|
||||
vm->ResizeView(view, PR_MAX(mRect.width, xMost), PR_MAX(mRect.height, yMost));
|
||||
vm->MoveViewTo(view, origin.x, origin.y);
|
||||
NS_RELEASE(vm);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -366,28 +461,6 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
// Also take into account absolutely positioned elements depending on
|
||||
// the overflow policy
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
mStyleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_OVERFLOW_HIDDEN != display->mOverflow) {
|
||||
for (nsIFrame* f = mAbsoluteFrames.FirstChild(); nsnull != f;
|
||||
f->GetNextSibling(f)) {
|
||||
nsRect rect;
|
||||
|
||||
f->GetRect(rect);
|
||||
nscoord xmost = rect.XMost();
|
||||
nscoord ymost = rect.YMost();
|
||||
if (xmost > aDesiredSize.width) {
|
||||
aDesiredSize.width = xmost;
|
||||
}
|
||||
if (ymost > aDesiredSize.height) {
|
||||
aDesiredSize.height = ymost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsISpaceManager.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIAreaFrame.h"
|
||||
|
||||
class nsSpaceManager;
|
||||
|
||||
@ -39,11 +40,14 @@ struct nsStylePosition;
|
||||
*
|
||||
* @see nsLayoutAtoms::absoluteList
|
||||
*/
|
||||
class nsAreaFrame : public nsBlockFrame
|
||||
class nsAreaFrame : public nsBlockFrame, public nsIAreaFrame
|
||||
{
|
||||
public:
|
||||
friend nsresult NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags);
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
||||
// nsIFrame
|
||||
NS_IMETHOD Init(nsIPresContext& aPresContext,
|
||||
nsIContent* aContent,
|
||||
@ -73,12 +77,18 @@ public:
|
||||
nsFramePaintLayer aWhichLayer);
|
||||
#endif
|
||||
|
||||
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
|
||||
nsDidReflowStatus aStatus);
|
||||
|
||||
NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aStyleContext,
|
||||
nsIFrame*& aContinuingFrame);
|
||||
NS_IMETHOD GetFrameName(nsString& aResult) const;
|
||||
|
||||
// nsIAreaFrame
|
||||
NS_IMETHOD GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const;
|
||||
|
||||
protected:
|
||||
nsAreaFrame();
|
||||
virtual ~nsAreaFrame();
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "nsLayoutAtoms.h"
|
||||
|
||||
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
|
||||
static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID);
|
||||
|
||||
nsresult
|
||||
NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags)
|
||||
@ -51,6 +52,7 @@ NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags)
|
||||
|
||||
nsAreaFrame::nsAreaFrame()
|
||||
{
|
||||
mState &= ~NS_FRAME_SYNC_FRAME_AND_VIEW; // let us handle it
|
||||
}
|
||||
|
||||
nsAreaFrame::~nsAreaFrame()
|
||||
@ -58,6 +60,23 @@ nsAreaFrame::~nsAreaFrame()
|
||||
NS_IF_RELEASE(mSpaceManager);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kAreaFrameIID)) {
|
||||
nsIAreaFrame* tmp = (nsIAreaFrame*)this;
|
||||
*aInstancePtr = (void*)tmp;
|
||||
return NS_OK;
|
||||
}
|
||||
return nsBlockFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// nsIFrame
|
||||
|
||||
@ -248,6 +267,82 @@ nsAreaFrame::Paint(nsIPresContext& aPresContext,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return the x-most and y-most for the child absolutely positioned
|
||||
// elements
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const
|
||||
{
|
||||
aXMost = aYMost = 0;
|
||||
for (nsIFrame* f = mAbsoluteFrames.FirstChild(); nsnull != f; f->GetNextSibling(f)) {
|
||||
// Get the frame's x-most and y-most. This is for its flowed content only
|
||||
nsRect rect;
|
||||
f->GetRect(rect);
|
||||
|
||||
if (rect.XMost() > aXMost) {
|
||||
aXMost = rect.XMost();
|
||||
}
|
||||
if (rect.YMost() > aYMost) {
|
||||
aYMost = rect.YMost();
|
||||
}
|
||||
|
||||
// If the child frame is also an area frame, then take into account its child
|
||||
// absolutely positioned elements
|
||||
nsIAreaFrame* areaFrame;
|
||||
if (NS_SUCCEEDED(f->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) {
|
||||
nscoord xMost, yMost;
|
||||
|
||||
areaFrame->GetPositionedInfo(xMost, yMost);
|
||||
// Convert to our coordinate space
|
||||
xMost += rect.x;
|
||||
yMost += rect.y;
|
||||
|
||||
if (xMost > aXMost) {
|
||||
aXMost = xMost;
|
||||
}
|
||||
if (yMost > aYMost) {
|
||||
aYMost = yMost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Temporary until the view code allows positioned child views to extend
|
||||
// outside their parent without being clipped...
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::DidReflow(nsIPresContext& aPresContext,
|
||||
nsDidReflowStatus aStatus)
|
||||
{
|
||||
nsresult rv = nsBlockFrame::DidReflow(aPresContext, aStatus);
|
||||
|
||||
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
|
||||
nsIView* view;
|
||||
GetView(view);
|
||||
|
||||
// Size and position the view if requested
|
||||
if (nsnull != view) {
|
||||
// Position and size view relative to its parent, not relative to our
|
||||
// parent frame (our parent frame may not have a view).
|
||||
nsIView* parentWithView;
|
||||
nsPoint origin;
|
||||
GetOffsetFromView(origin, parentWithView);
|
||||
nsIViewManager *vm;
|
||||
view->GetViewManager(vm);
|
||||
|
||||
// Take into account any absolutely positioned children
|
||||
nscoord xMost, yMost;
|
||||
GetPositionedInfo(xMost, yMost);
|
||||
|
||||
vm->ResizeView(view, PR_MAX(mRect.width, xMost), PR_MAX(mRect.height, yMost));
|
||||
vm->MoveViewTo(view, origin.x, origin.y);
|
||||
NS_RELEASE(vm);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAreaFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -366,28 +461,6 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
// Also take into account absolutely positioned elements depending on
|
||||
// the overflow policy
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
mStyleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_OVERFLOW_HIDDEN != display->mOverflow) {
|
||||
for (nsIFrame* f = mAbsoluteFrames.FirstChild(); nsnull != f;
|
||||
f->GetNextSibling(f)) {
|
||||
nsRect rect;
|
||||
|
||||
f->GetRect(rect);
|
||||
nscoord xmost = rect.XMost();
|
||||
nscoord ymost = rect.YMost();
|
||||
if (xmost > aDesiredSize.width) {
|
||||
aDesiredSize.width = xmost;
|
||||
}
|
||||
if (ymost > aDesiredSize.height) {
|
||||
aDesiredSize.height = ymost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsISpaceManager.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIAreaFrame.h"
|
||||
|
||||
class nsSpaceManager;
|
||||
|
||||
@ -39,11 +40,14 @@ struct nsStylePosition;
|
||||
*
|
||||
* @see nsLayoutAtoms::absoluteList
|
||||
*/
|
||||
class nsAreaFrame : public nsBlockFrame
|
||||
class nsAreaFrame : public nsBlockFrame, public nsIAreaFrame
|
||||
{
|
||||
public:
|
||||
friend nsresult NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags);
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
||||
// nsIFrame
|
||||
NS_IMETHOD Init(nsIPresContext& aPresContext,
|
||||
nsIContent* aContent,
|
||||
@ -73,12 +77,18 @@ public:
|
||||
nsFramePaintLayer aWhichLayer);
|
||||
#endif
|
||||
|
||||
NS_IMETHOD DidReflow(nsIPresContext& aPresContext,
|
||||
nsDidReflowStatus aStatus);
|
||||
|
||||
NS_IMETHOD CreateContinuingFrame(nsIPresContext& aPresContext,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aStyleContext,
|
||||
nsIFrame*& aContinuingFrame);
|
||||
NS_IMETHOD GetFrameName(nsString& aResult) const;
|
||||
|
||||
// nsIAreaFrame
|
||||
NS_IMETHOD GetPositionedInfo(nscoord& aXMost, nscoord& aYMost) const;
|
||||
|
||||
protected:
|
||||
nsAreaFrame();
|
||||
virtual ~nsAreaFrame();
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsIAreaFrame.h"
|
||||
|
||||
static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID);
|
||||
static NS_DEFINE_IID(kScrollingViewCID, NS_SCROLLING_VIEW_CID);
|
||||
@ -36,6 +37,7 @@ static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
|
||||
|
||||
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
|
||||
static NS_DEFINE_IID(kScrollViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
static NS_DEFINE_IID(kAreaFrameIID, NS_IAREAFRAME_IID);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
@ -340,6 +342,21 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext,
|
||||
ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
|
||||
aStatus);
|
||||
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
|
||||
|
||||
// If it's an area frame then get the total size, which includes the
|
||||
// space taken up by absolutely positioned child elements
|
||||
nsIAreaFrame* areaFrame;
|
||||
if (NS_SUCCEEDED(kidFrame->QueryInterface(kAreaFrameIID, (void**)&areaFrame))) {
|
||||
nscoord xMost, yMost;
|
||||
|
||||
areaFrame->GetPositionedInfo(xMost, yMost);
|
||||
if (xMost > kidDesiredSize.width) {
|
||||
kidDesiredSize.width = xMost;
|
||||
}
|
||||
if (yMost > kidDesiredSize.height) {
|
||||
kidDesiredSize.height = yMost;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the height of the scrolled frame fills the entire scroll area,
|
||||
// unless we're shrink wrapping
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user