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:
troy%netscape.com 1999-01-18 17:27:27 +00:00
parent 46eb195775
commit 64fcc4cfa2
5 changed files with 229 additions and 46 deletions

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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();

View File

@ -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