Putting back code that was backed out last week.

-a leaf
This commit is contained in:
evaughan%netscape.com 2000-04-18 00:17:00 +00:00
parent 8cdd6bce1b
commit a794898863
15 changed files with 469 additions and 272 deletions

View File

@ -44,7 +44,7 @@
#include "nsHTMLAtoms.h"
#include "nsXULAtoms.h"
nsBox::nsBox(nsIPresShell* aShell):mParentBox(nsnull),mNextChild(nsnull),mMouseThrough(sometimes)
nsBox::nsBox(nsIPresShell* aShell):mParentBox(nsnull),mNextChild(nsnull),mMouseThrough(unset)
{
//mX = 0;
//mY = 0;
@ -96,36 +96,69 @@ nsBox::MarkDirty(nsBoxLayoutState& aState)
state |= NS_FRAME_IS_DIRTY;
frame->SetFrameState(state);
nsIFrame* parent = nsnull;
frame->GetParent(&parent);
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
nsCOMPtr<nsIBoxLayout> layout;
GetLayoutManager(getter_AddRefs(layout));
if (layout)
layout->BecameDirty(this, aState);
return parent->ReflowDirtyChild(shell, frame);
if (state & NS_FRAME_HAS_DIRTY_CHILDREN)
return NS_OK;
nsIBox* parent = nsnull;
GetParentBox(&parent);
if (parent)
return parent->RelayoutDirtyChild(aState, this);
else {
nsIFrame* parent = nsnull;
frame->GetParent(&parent);
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
return parent->ReflowDirtyChild(shell, frame);
}
}
NS_IMETHODIMP
nsBox::MarkDirtyChildren(nsBoxLayoutState& aState)
{
nsFrameState state;
nsIFrame* frame;
GetFrame(&frame);
frame->GetFrameState(&state);
return RelayoutDirtyChild(aState, nsnull);
}
// only reflow if we aren't already dirty.
if (state & NS_FRAME_HAS_DIRTY_CHILDREN)
return NS_OK;
NS_IMETHODIMP
nsBox::RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild)
{
nsFrameState state;
nsIFrame* frame;
GetFrame(&frame);
frame->GetFrameState(&state);
state |= NS_FRAME_HAS_DIRTY_CHILDREN;
frame->SetFrameState(state);
// if we are not dirty mark ourselves dirty and tell our parent we are dirty too.
if (!(state & NS_FRAME_HAS_DIRTY_CHILDREN)) {
// Mark yourself as dirty and needing to be recalculated
state |= NS_FRAME_HAS_DIRTY_CHILDREN;
frame->SetFrameState(state);
NeedsRecalc();
NeedsRecalc();
nsIFrame* parent = nsnull;
frame->GetParent(&parent);
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
if (aChild != nsnull) {
nsCOMPtr<nsIBoxLayout> layout;
GetLayoutManager(getter_AddRefs(layout));
if (layout)
layout->ChildBecameDirty(this, aState, aChild);
}
return parent->ReflowDirtyChild(shell, frame);
nsIBox* parent = nsnull;
GetParentBox(&parent);
if (parent)
return parent->RelayoutDirtyChild(aState, this);
else {
nsIFrame* parent = nsnull;
frame->GetParent(&parent);
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
return parent->ReflowDirtyChild(shell, frame);
}
}
return NS_OK;
}
NS_IMETHODIMP
@ -547,6 +580,7 @@ NS_IMETHODIMP
nsBox::GetFlex(nsBoxLayoutState& aState, nscoord& aFlex)
{
aFlex = 0;
GetDefaultFlex(aFlex);
PRBool collapsed = PR_FALSE;
nsIBox::AddCSSFlex(aState, this, aFlex);
@ -1011,6 +1045,40 @@ nsBox::GetDebug(PRBool& aDebug)
return NS_OK;
}
NS_IMETHODIMP
nsBox::GetMouseThrough(PRBool& aMouseThrough)
{
switch(mMouseThrough)
{
case always:
aMouseThrough = PR_TRUE;
return NS_OK;
case never:
aMouseThrough = PR_FALSE;
return NS_OK;
case unset:
{
nsIBox* parent = nsnull;
GetParentBox(&parent);
if (parent)
return parent->GetMouseThrough(aMouseThrough);
else {
aMouseThrough = PR_FALSE;
return NS_OK;
}
}
}
return NS_ERROR_FAILURE;
}
PRBool
nsBox::GetDefaultFlex(PRInt32& aFlex)
{
aFlex = 0;
return PR_TRUE;
}
// nsISupports
NS_IMETHODIMP_(nsrefcnt)
nsBox::AddRef(void)

View File

@ -73,6 +73,8 @@ public:
NS_IMETHOD NeedsRecalc();
NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIBox** aBox);
NS_IMETHOD GetDebug(PRBool& aDebug);
NS_IMETHOD RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild);
NS_IMETHOD GetMouseThrough(PRBool& aMouseThrough);
// XXX Eventually these will move into nsIFrame.
// These methods are used for XBL <children>.
@ -105,10 +107,11 @@ public:
protected:
virtual PRBool GetWasCollapsed(nsBoxLayoutState& aState);
virtual void SetWasCollapsed(nsBoxLayoutState& aState, PRBool aWas);
virtual PRBool GetDefaultFlex(PRInt32& aFlex);
enum eMouseThrough {
unset,
never,
sometimes,
always
};

View File

@ -153,6 +153,8 @@ public:
void DrawLine(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x1, nscoord y1, nscoord x2, nscoord y2);
void FillRect(nsIRenderingContext& aRenderingContext, PRBool aHorizontal, nscoord x, nscoord y, nscoord width, nscoord height);
nsIBox* GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor);
nsBoxFrame::Halignment GetHAlign();
nsBoxFrame::Valignment GetVAlign();
@ -253,7 +255,6 @@ nsBoxFrame::~nsBoxFrame()
NS_ASSERTION(mInner == nsnull,"Error Destroy was never called on this Frame!!!");
}
NS_IMETHODIMP
nsBoxFrame::GetVAlign(Valignment& aAlign)
{
@ -281,7 +282,8 @@ nsBoxFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsresult r = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
if (r == NS_OK) {
// initialize our list of infos.
InitChildren(shell, aChildList);
nsBoxLayoutState state(shell);
InitChildren(state, aChildList);
} else {
printf("Warning add child failed!!\n");
}
@ -355,7 +357,7 @@ nsBoxFrame::Init(nsIPresContext* aPresContext,
mInner->GetDebugPref(aPresContext);
mMouseThrough = always;
mMouseThrough = unset;
if (mContent) {
nsAutoString value;
@ -579,15 +581,10 @@ nsBoxFrame::GetInitialAutoStretch(PRBool& aStretch)
NS_IMETHODIMP
nsBoxFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
{
// if we are not dirty mark ourselves dirty and tell our parent we are dirty too.
if (!(mState & NS_FRAME_HAS_DIRTY_CHILDREN)) {
// Mark yourself as dirty and needing to be recalculated
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
NeedsRecalc();
return mParent->ReflowDirtyChild(aPresShell, this);
}
return NS_OK;
nsCOMPtr<nsIPresContext> context;
aPresShell->GetPresContext(getter_AddRefs(context));
nsBoxLayoutState state(context);
return RelayoutDirtyChild(state, this);
}
NS_IMETHODIMP
@ -851,7 +848,9 @@ nsBoxFrame::Destroy(nsIPresContext* aPresContext)
// if we are root remove 1 from the debug count.
if (mState & NS_STATE_IS_ROOT)
mInner->GetDebugPref(aPresContext);
SetLayoutManager(nsnull);
// recycle the Inner via the shell's arena.
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
@ -888,11 +887,13 @@ nsBoxFrame::SetDebug(nsBoxLayoutState& aState, PRBool aDebug)
NS_IMETHODIMP
nsBoxFrame::NeedsRecalc()
{
SizeNeedsRecalc(mInner->mPrefSize);
SizeNeedsRecalc(mInner->mMinSize);
SizeNeedsRecalc(mInner->mMaxSize);
CoordNeedsRecalc(mInner->mFlex);
CoordNeedsRecalc(mInner->mAscent);
if (mInner) {
SizeNeedsRecalc(mInner->mPrefSize);
SizeNeedsRecalc(mInner->mMinSize);
SizeNeedsRecalc(mInner->mMaxSize);
CoordNeedsRecalc(mInner->mFlex);
CoordNeedsRecalc(mInner->mAscent);
}
return NS_OK;
}
@ -910,7 +911,8 @@ nsBoxFrame::RemoveFrame(nsIPresContext* aPresContext,
SanityCheck(mFrames);
// remove child from our info list
Remove(&aPresShell, aOldFrame);
nsBoxLayoutState state(aPresContext);
Remove(state, aOldFrame);
// remove the child frame
mFrames.DestroyFrame(aPresContext, aOldFrame);
@ -918,7 +920,6 @@ nsBoxFrame::RemoveFrame(nsIPresContext* aPresContext,
SanityCheck(mFrames);
// mark us dirty and generate a reflow command
nsBoxLayoutState state(aPresContext);
MarkDirtyChildren(state);
MarkDirty(state);
return NS_OK;
@ -945,13 +946,12 @@ nsBoxFrame::InsertFrames(nsIPresContext* aPresContext,
}
// insert the frames to our info list
Insert(&aPresShell, aPrevFrame, aFrameList);
nsBoxLayoutState state(aPresContext);
Insert(state, aPrevFrame, aFrameList);
// insert the frames in out regular frame list
mFrames.InsertFrames(this, aPrevFrame, aFrameList);
nsBoxLayoutState state(aPresContext);
// if we are in debug make sure our children are in debug as well.
if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
SetDebugOnChildList(state, mFirstChild, PR_TRUE);
@ -979,13 +979,12 @@ nsBoxFrame::AppendFrames(nsIPresContext* aPresContext,
SanityCheck(mFrames);
// append them after
Append(&aPresShell,aFrameList);
nsBoxLayoutState state(aPresContext);
Append(state,aFrameList);
// append in regular frames
mFrames.AppendFrames(this, aFrameList);
nsBoxLayoutState state(aPresContext);
// if we are in debug make sure our children are in debug as well.
if (mState & NS_STATE_CURRENTLY_IN_DEBUG)
SetDebugOnChildList(state, mFirstChild, PR_TRUE);
@ -1429,99 +1428,132 @@ nsBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext,
}
}
nsIFrame *kid, *hit = nsnull;
nsPoint tmp;
if (mMouseThrough == never)
{
*aFrame = this;
return NS_OK;
FirstChild(aPresContext, nsnull, &kid);
*aFrame = nsnull;
tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
while (nsnull != kid) {
// have we hit a child before
PRBool haveKid = (hit != nsnull);
nsresult rv = kid->GetFrameForPoint(aPresContext, tmp, aWhichLayer, &hit);
if (NS_SUCCEEDED(rv) && hit) {
if (!haveKid)
*aFrame = hit;
else
{
// if the kid had a child before see if this child has mouse
// though.
nsresult rv = NS_OK;
PRBool isAdaptor = PR_FALSE;
nsCOMPtr<nsIBox> box = mInner->GetBoxForFrame(hit, isAdaptor);
if (box) {
PRBool mouseThrough = PR_FALSE;
box->GetMouseThrough(mouseThrough);
// if the child says it can never mouse though ignore it.
if (!mouseThrough)
*aFrame = hit;
else {
/*
// otherwise see if it has an opaque parent.
nsIFrame* child = hit;
while(child) {
if (child == this)
break;
const nsStyleColor* color = nsnull;
child->GetStyleData(eStyleStruct_Color, (const nsStyleStruct*&)color);
PRBool transparentBG = (!color || NS_STYLE_BG_COLOR_TRANSPARENT ==
(color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT));
if (!transparentBG) {
*aFrame = hit;
break;
}
child->GetParent(&child);
}
*/
}
}
}
}
kid->GetNextSibling(&kid);
}
// This won't work.
nsresult rv = GetFrameForPointUsing(aPresContext, aPoint, nsnull, aWhichLayer, PR_FALSE, aFrame);
/*
nsRect r(0,0,mRect.width, mRect.height);
// if it is not inside us fail
if (!r.Contains(aPoint)) {
return NS_ERROR_FAILURE;
if (*aFrame) {
return NS_OK;
}
// is it inside our border, padding, and debugborder or insets?
nsMargin im(0,0,0,0);
nsBoxLayoutState state(aPresContext);
GetInset(im);
nsMargin border(0,0,0,0);
GetBorderAndPadding(border);
r.Deflate(im);
r.Deflate(border);
// no? Then it must be in our border so return us.
if (!r.Contains(aPoint)) {
// if no kids were hit then select us
const nsStyleDisplay* disp = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
if (disp->IsVisible()) {
*aFrame = this;
return NS_OK;
}
// ok lets look throught the children
*aFrame = nsnull;
nsIBox* child = nsnull;
GetChildBox(&child);
nsPoint tmp;
nsIFrame *frame = nsnull, *hit = nsnull;
tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
while(child)
{
child->GetFrame(&frame);
nsresult rv = frame->GetFrameForPoint(aPresContext, tmp, aWhichLayer, &hit);
if (NS_SUCCEEDED(rv) && hit) {
*aFrame = hit;
}
child->GetNextBox(&child);
}
// found it.
if (hit)
return NS_OK;
*/
if (rv != NS_ERROR_FAILURE)
return rv;
// see if it is in our border, padding, or inset
nsRect r(mRect);
nsMargin m;
GetInset(m);
r.Deflate(m);
GetBorderAndPadding(m);
r.Deflate(m);
if (!r.Contains(aPoint)) {
*aFrame = this;
return NS_OK;
}
if (mMouseThrough == sometimes)
{
*aFrame = this;
return NS_OK;
}
const nsStyleColor* color = (const nsStyleColor*)
mStyleContext->GetStyleData(eStyleStruct_Color);
PRBool transparentBG = NS_STYLE_BG_COLOR_TRANSPARENT ==
(color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT);
if (!transparentBG)
{
*aFrame = this;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsIBox*
nsBoxFrameInner::GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor)
{
if (aFrame == nsnull)
return nsnull;
nsIBox* ibox = nsnull;
if (NS_FAILED(aFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox))) {
aIsAdaptor = PR_TRUE;
// if we hit a non box. Find the box in out last container
// and clear its cache.
nsIFrame* parent = nsnull;
aFrame->GetParent(&parent);
nsIBox* parentBox = nsnull;
if (NS_FAILED(parent->QueryInterface(NS_GET_IID(nsIBox), (void**)&parentBox)))
return nsnull;
if (parentBox) {
nsIBox* start = nsnull;
parentBox->GetChildBox(&start);
while (start) {
nsIFrame* frame = nsnull;
start->GetFrame(&frame);
if (frame == aFrame) {
ibox = start;
break;
}
start->GetNextBox(&start);
}
}
}
return ibox;
}
/*
NS_IMETHODIMP
nsBoxFrame::GetMouseThrough(PRBool& aMouseThrough)
{
const nsStyleColor* color = (const nsStyleColor*)
mStyleContext->GetStyleData(eStyleStruct_Color);
PRBool transparentBG = NS_STYLE_BG_COLOR_TRANSPARENT ==
(color->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT);
if (!transparentBG)
aMouseThrough = never;
else
return nsBox::GetMouseThrough(aMouseThrough);
return NS_OK;
}
*/
NS_IMETHODIMP
@ -1619,7 +1651,8 @@ nsBoxFrameInner::operator new(size_t sz, nsIPresShell* aPresShell)
void
nsBoxFrameInner::Recycle(nsIPresShell* aPresShell)
{
mOuter->ClearChildren(aPresShell);
nsBoxLayoutState state(aPresShell);
mOuter->ClearChildren(state);
delete this;
nsBoxLayoutState::RecycleFreedMemory(aPresShell, this);

View File

@ -90,6 +90,7 @@ public:
NS_IMETHOD GetInset(nsMargin& aInset);
NS_IMETHOD Layout(nsBoxLayoutState& aBoxLayoutState);
NS_IMETHOD GetDebug(PRBool& aDebug);
//NS_IMETHOD GetMouseThrough(PRBool& aMouseThrough);
// ----- child and sibling operations ---
@ -160,7 +161,6 @@ public:
virtual PRBool IsHorizontal() const;
virtual ~nsBoxFrame();
virtual nsresult GetContentOf(nsIContent** aContent);

View File

@ -49,6 +49,11 @@ nsBoxLayoutState::nsBoxLayoutState(const nsBoxLayoutState& aState)
mMaxElementSize = aState.mMaxElementSize;
}
nsBoxLayoutState::nsBoxLayoutState(nsIPresShell* aShell):mReflowState(nsnull), mMaxElementSize(nsnull)
{
aShell->GetPresContext(getter_AddRefs(mPresContext));
}
nsBoxLayoutState::nsBoxLayoutState(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize):mReflowState(&aReflowState),mPresContext(aPresContext),mType(Dirty)
{
mMaxElementSize = aDesiredSize.maxElementSize;
@ -73,27 +78,6 @@ nsBoxLayoutState::HandleReflow(nsIBox* aRootBox, PRBool aCoelesce)
nsIReflowCommand::ReflowType type;
mReflowState->reflowCommand->GetType(type);
// atempt to coelesce style changes and reflows
// see if the target is a box
/*
PRBool isAdaptor = PR_FALSE;
nsIBox* box = GetTargetBox(mReflowState->reflowCommand, isAdaptor);
// if it is mark it dirty. Generating a dirty reflow targeted at us unless on is already
// done.
if (box && box != aRootBox) {
if (type == nsIReflowCommand::StyleChanged) {
// could be a visiblity change need to dirty
// parent so it gets redrawn.
nsIBox* parent;
box->GetParentBox(&parent);
parent->MarkDirty(*this);
DirtyAllChildren(*this, box);
} else
box->MarkDirty(*this);
return PR_TRUE;
}
*/
// ok if the target was not a box. Then unwind it down
if (UnWind(mReflowState->reflowCommand, aRootBox, aCoelesce)) {
mType = Dirty;
@ -118,6 +102,11 @@ nsBoxLayoutState::HandleReflow(nsIBox* aRootBox, PRBool aCoelesce)
mType = Initial;
break;
case eReflowReason_StyleChange:
printf("STYLE CHANGE REFLOW. Blowing away all box caches!!\n");
DirtyAllChildren(*this, aRootBox);
// fall through to dirty
default:
mType = Dirty;
}
@ -174,11 +163,25 @@ nsBoxLayoutState::UnWind(nsIReflowCommand* aCommand, nsIBox* aBox, PRBool aCoele
ibox->MarkDirty(*this);
if (type == nsIReflowCommand::StyleChanged) {
// could be a visiblity change need to dirty
// parent so it gets redrawn.
// could be a visiblity change. Like collapse so we need to dirty
// parent so it gets redrawn. But be carefull we
// don't want to just mark dirty that would notify the
// box and it would notify its layout manager. This would
// be really bad for grid because it would blow away
// all is cached infomation for is colums and rows. Because the
// our parent is most likely a rows or columns and it will think
// its child is getting bigger or something.
nsIBox* parent;
ibox->GetParentBox(&parent);
parent->MarkDirty(*this);
if (parent) {
nsFrameState parentState;
nsIFrame* parentFrame;
parent->GetFrame(&parentFrame);
parentFrame->GetFrameState(&parentState);
parentState |= NS_FRAME_IS_DIRTY;
parentFrame->SetFrameState(parentState);
}
DirtyAllChildren(*this, ibox);
}

View File

@ -53,11 +53,12 @@ public:
nsBoxLayoutState(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize);
nsBoxLayoutState(nsIPresContext* aPresContext);
nsBoxLayoutState(nsIPresShell* aShell);
nsBoxLayoutState(const nsBoxLayoutState& aState);
virtual PRBool HandleReflow(nsIBox* aRootBox, PRBool aCoalesce);
virtual nsIPresContext* GetPresContext() { return mPresContext; }
virtual nsIPresContext* GetPresContext() { return mPresContext.get(); }
virtual nsresult GetPresShell(nsIPresShell** aShell);
virtual void GetMaxElementSize(nsSize** aMaxElementSize);
@ -79,7 +80,7 @@ private:
nsIBox* GetTargetBox(nsIReflowCommand* mCommand, PRBool& aIsAdaptor);
nsIBox* GetBoxForFrame(nsIFrame* aFrame, PRBool& aIsAdaptor);
nsIPresContext* mPresContext;
nsCOMPtr<nsIPresContext> mPresContext;
const nsHTMLReflowState* mReflowState;
eBoxLayoutReason mType;
nsSize* mMaxElementSize;

View File

@ -59,6 +59,7 @@ nsBoxToBlockAdaptor::nsBoxToBlockAdaptor(nsIPresShell* aPresShell, nsIFrame* aFr
mFrame = aFrame;
mSpaceManager = nsnull;
mWasCollapsed = PR_FALSE;
mCachedMaxElementHeight = 0;
NeedsRecalc();
}
@ -165,11 +166,16 @@ nsBoxToBlockAdaptor::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize)
NS_INTRINSICSIZE,
PR_FALSE);
if (currentSize) {
if (currentSize) {
desiredSize.maxElementSize = nsnull;
if (size.width > currentSize->width)
currentSize->width = size.width;
if (size.height > currentSize->height)
currentSize->height = size.height;
mCachedMaxElementHeight = size.height;
}
nsFrameState frameState = 0;
@ -310,9 +316,14 @@ nsBoxToBlockAdaptor::Layout(nsBoxLayoutState& aState)
desiredSize.maxElementSize = nsnull;
if (size.width > currentSize->width)
currentSize->width = size.width;
currentSize->width = size.width;
if (mCachedMaxElementHeight > currentSize->height) {
currentSize->height = mCachedMaxElementHeight;
}
}
mAscent = desiredSize.ascent;
mFrame->SizeTo(presContext, desiredSize.width, desiredSize.height);
}

View File

@ -82,7 +82,7 @@ protected:
nsSize mLastSize;
nscoord mMinWidth;
PRBool mWasCollapsed;
nscoord mCachedMaxElementHeight;
};
#endif

View File

@ -89,15 +89,18 @@ nsContainerBox::GetChildCount()
}
PRInt32
nsContainerBox::CreateBoxList(nsIPresShell* aPresShell, nsIFrame* aFrameList, nsIBox*& aFirst, nsIBox*& aLast)
nsContainerBox::CreateBoxList(nsBoxLayoutState& aState, nsIFrame* aFrameList, nsIBox*& aFirst, nsIBox*& aLast)
{
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
PRInt32 count = 0;
if (aFrameList) {
nsIBox* ibox = nsnull;
if (NS_SUCCEEDED(aFrameList->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox)
aFirst = ibox;
else
aFirst = new (aPresShell) nsBoxToBlockAdaptor(aPresShell, aFrameList);
aFirst = new (shell) nsBoxToBlockAdaptor(shell, aFrameList);
aFirst->SetParentBox(this);
@ -111,7 +114,7 @@ nsContainerBox::CreateBoxList(nsIPresShell* aPresShell, nsIFrame* aFrameList, ns
if (NS_SUCCEEDED(aFrameList->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox)
aLast = ibox;
else
aLast = new (aPresShell) nsBoxToBlockAdaptor(aPresShell, aFrameList);
aLast = new (shell) nsBoxToBlockAdaptor(shell, aFrameList);
aLast->SetParentBox(this);
@ -217,15 +220,15 @@ nsContainerBox::GetIndexOf(nsIBox* aBox)
}
void
nsContainerBox::Remove(nsIPresShell* aShell, nsIFrame* aFrame)
nsContainerBox::Remove(nsBoxLayoutState& aState, nsIFrame* aFrame)
{
// get the info before the frame
nsIBox* prevBox = GetPrevious(aFrame);
RemoveAfter(aShell, prevBox);
RemoveAfter(aState, prevBox);
}
void
nsContainerBox::Insert(nsIPresShell* aShell, nsIFrame* aPrevFrame, nsIFrame* aFrameList)
nsContainerBox::Insert(nsBoxLayoutState& aState, nsIFrame* aPrevFrame, nsIFrame* aFrameList)
{
nsIBox* prevBox = GetBox(aPrevFrame);
//NS_ASSERTION(aPrevFrame == nsnull || prevBox,"Error! The previous frame given is not in our list!");
@ -234,15 +237,15 @@ nsContainerBox::Insert(nsIPresShell* aShell, nsIFrame* aPrevFrame, nsIFrame* aFr
// if no previous frame then we are inserting in front
if (prevBox == nsnull) {
// prepend them
Prepend(aShell, aFrameList);
Prepend(aState, aFrameList);
} else {
// insert insert after previous info
InsertAfter(aShell, prevBox, aFrameList);
InsertAfter(aState, prevBox, aFrameList);
}
}
void
nsContainerBox::RemoveAfter(nsIPresShell* aPresShell, nsIBox* aPrevious)
nsContainerBox::RemoveAfter(nsBoxLayoutState& aState, nsIBox* aPrevious)
{
nsIBox* toDelete = nsnull;
@ -271,15 +274,24 @@ nsContainerBox::RemoveAfter(nsIPresShell* aPresShell, nsIBox* aPrevious)
// recycle adaptors
nsIBoxToBlockAdaptor* adaptor = nsnull;
if (NS_SUCCEEDED(toDelete->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor)) && adaptor)
adaptor->Recycle(aPresShell);
if (NS_SUCCEEDED(toDelete->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor)) && adaptor) {
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
adaptor->Recycle(shell);
}
mChildCount--;
if (mLayoutManager)
mLayoutManager->ChildrenRemoved(this, aState, toDelete);
}
void
nsContainerBox::ClearChildren(nsIPresShell* aShell)
nsContainerBox::ClearChildren(nsBoxLayoutState& aState)
{
if (mFirstChild && mLayoutManager)
mLayoutManager->ChildrenRemoved(this, aState, mFirstChild);
nsIBox* box = mFirstChild;
while(box) {
nsIBox* it = box;
@ -287,8 +299,11 @@ nsContainerBox::ClearChildren(nsIPresShell* aShell)
// recycle adaptors
nsIBoxToBlockAdaptor* adaptor = nsnull;
if (NS_SUCCEEDED(it->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor)) && adaptor)
adaptor->Recycle(aShell);
if (NS_SUCCEEDED(it->QueryInterface(NS_GET_IID(nsIBoxToBlockAdaptor), (void**)&adaptor)) && adaptor) {
nsCOMPtr<nsIPresShell> shell;
aState.GetPresShell(getter_AddRefs(shell));
adaptor->Recycle(shell);
}
}
mFirstChild= nsnull;
@ -297,52 +312,68 @@ nsContainerBox::ClearChildren(nsIPresShell* aShell)
}
void
nsContainerBox::Prepend(nsIPresShell* aPresShell, nsIFrame* aList)
nsContainerBox::Prepend(nsBoxLayoutState& aState, nsIFrame* aList)
{
nsIBox* first;
nsIBox* last;
mChildCount += CreateBoxList(aPresShell, aList, first, last);
mChildCount += CreateBoxList(aState, aList, first, last);
if (!mFirstChild)
mFirstChild= mLastChild= first;
else {
last->SetNextBox(mFirstChild);
mFirstChild= first;
}
if (mLayoutManager)
mLayoutManager->ChildrenInserted(this, aState, nsnull, first);
}
void
nsContainerBox::Append(nsIPresShell* aPresShell, nsIFrame* aList)
nsContainerBox::Append(nsBoxLayoutState& aState, nsIFrame* aList)
{
nsIBox* first;
nsIBox* last;
mChildCount += CreateBoxList(aPresShell, aList, first, last);
mChildCount += CreateBoxList(aState, aList, first, last);
if (!mFirstChild)
mFirstChild= first;
else
mLastChild->SetNextBox(first);
mLastChild= last;
if (mLayoutManager)
mLayoutManager->ChildrenAppended(this, aState, first);
}
void
nsContainerBox::InsertAfter(nsIPresShell* aPresShell, nsIBox* aPrev, nsIFrame* aList)
nsContainerBox::InsertAfter(nsBoxLayoutState& aState, nsIBox* aPrev, nsIFrame* aList)
{
nsIBox* first = nsnull;
nsIBox* last = nsnull;
mChildCount += CreateBoxList(aPresShell, aList, first, last);
mChildCount += CreateBoxList(aState, aList, first, last);
nsIBox* next = nsnull;
aPrev->GetNextBox(&next);
last->SetNextBox(next);
aPrev->SetNextBox(first);
if (aPrev == mLastChild)
mLastChild = last;
if (mLayoutManager) {
mLayoutManager->ChildrenInserted(this, aState, aPrev, first);
}
}
void
nsContainerBox::InitChildren(nsIPresShell* aPresShell, nsIFrame* aList)
nsContainerBox::InitChildren(nsBoxLayoutState& aState, nsIFrame* aList)
{
ClearChildren(aPresShell);
mChildCount += CreateBoxList(aPresShell, aList, mFirstChild, mLastChild);
ClearChildren(aState);
mChildCount += CreateBoxList(aState, aList, mFirstChild, mLastChild);
if (mLayoutManager)
mLayoutManager->ChildrenAppended(this, aState, mFirstChild);
}
void

View File

@ -50,15 +50,15 @@ public:
virtual nsIBox* GetBox(nsIFrame* aFrame);
virtual PRInt32 GetIndexOf(nsIBox* aBox);
virtual PRInt32 GetChildCount();
virtual void ClearChildren(nsIPresShell* aShell);
virtual PRInt32 CreateBoxList(nsIPresShell* aShell, nsIFrame* aList, nsIBox*& first, nsIBox*& last);
virtual void RemoveAfter(nsIPresShell* aShell, nsIBox* aPrev);
virtual void Remove(nsIPresShell* aShell, nsIFrame* aChild);
virtual void Prepend(nsIPresShell* aShell, nsIFrame* aList);
virtual void Append(nsIPresShell* aShell, nsIFrame* aList);
virtual void Insert(nsIPresShell* aShell, nsIFrame* aPrevFrame, nsIFrame* aList);
virtual void InsertAfter(nsIPresShell* aShell, nsIBox* aPrev, nsIFrame* aList);
virtual void InitChildren(nsIPresShell* aShell, nsIFrame* aList);
virtual void ClearChildren(nsBoxLayoutState& aState);
virtual PRInt32 CreateBoxList(nsBoxLayoutState& aState, nsIFrame* aList, nsIBox*& first, nsIBox*& last);
virtual void RemoveAfter(nsBoxLayoutState& aState, nsIBox* aPrev);
virtual void Remove(nsBoxLayoutState& aState, nsIFrame* aChild);
virtual void Prepend(nsBoxLayoutState& aState, nsIFrame* aList);
virtual void Append(nsBoxLayoutState& aState, nsIFrame* aList);
virtual void Insert(nsBoxLayoutState& aState, nsIFrame* aPrevFrame, nsIFrame* aList);
virtual void InsertAfter(nsBoxLayoutState& aState, nsIBox* aPrev, nsIFrame* aList);
virtual void InitChildren(nsBoxLayoutState& aState, nsIFrame* aList);
virtual nsIBox* GetPrevious(nsIFrame* aChild);
virtual void SanityCheck(nsFrameList& aFrameList);
virtual void SetDebugOnChildList(nsBoxLayoutState& aState, nsIBox* aChild, PRBool aDebug);

View File

@ -98,6 +98,8 @@ public:
NS_IMETHOD Redraw(nsBoxLayoutState& aState, const nsRect* aRect = nsnull, PRBool aImmediate = PR_FALSE)=0;
NS_IMETHOD NeedsRecalc()=0;
NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIBox** aBox)=0;
NS_IMETHOD RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild)=0;
NS_IMETHOD GetMouseThrough(PRBool& aMouseThrough)=0;
// XXX Eventually these will move into nsIFrame.
// These methods are used for XBL <children>.

View File

@ -79,7 +79,7 @@ nsLeafBoxFrame::Init(nsIPresContext* aPresContext,
{
nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mMouseThrough = sometimes;
mMouseThrough = unset;
if (mContent) {
nsAutoString value;
@ -104,13 +104,8 @@ nsLeafBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext,
if (!mRect.Contains(aPoint))
return NS_ERROR_FAILURE;
if (mMouseThrough != never)
{
*aFrame = this;
return NS_OK;
}
return NS_ERROR_FAILURE;
*aFrame = this;
return NS_OK;
}
NS_IMETHODIMP

View File

@ -240,11 +240,12 @@ nsObeliskLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxS
nsBoxSize* last = nsnull;
temple->BuildBoxSizeList(aTempleBox, aState, first, last);
aBoxSizes = first;
} else {
}/* else { */
nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aComputedBoxSizes, aMinSize, aMaxSize, aFlexes);
return;
}
// return;
// }
/*
aMinSize = 0;
aMaxSize = NS_INTRINSICSIZE;
@ -254,6 +255,12 @@ nsObeliskLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxS
nsIBox* child = nsnull;
aBox->GetChildBox(&child);
if (child && !aBoxSizes)
aBoxSizes = new (aState) nsBoxSize();
nsBoxSize* childSize = aBoxSizes;
while(child)
{
nscoord flex = 0;
@ -296,7 +303,14 @@ nsObeliskLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxS
child->GetNextBox(&child);
if (child && !childSize->next)
{
childSize->next = new (aState) nsBoxSize();
childSize = childSize->next;
}
}
*/
}
void

View File

@ -576,109 +576,141 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
PRInt32 count = 0;
aFlexes = 0;
nsBoxSize* currentBox = nsnull;
//nsComputedBoxSize* currentComputed = nsnull;
nsBoxSize* currentBox = nsnull;
/*
nsBoxSize* start = aBoxSizes;
while(child)
{
if (!currentBox) {
aBoxSizes = new (aState) nsBoxSize();
//aComputedBoxSizes = new (aState) nsComputedBoxSizeSpecial();
currentBox = aBoxSizes;
//currentComputed = aComputedBoxSizes;
} else {
currentBox->next = new (aState) nsBoxSize();
//currentComputed->next = new (aState) nsComputedBoxSizeSpecial();
currentBox = currentBox->next;
//currentComputed = currentComputed->next;
}
// ok if we started with a list move down the list
// until we reach the end. Then start looking at childen.
// This feature is used extensively for Grid.
nscoord flex = 0;
child->GetFlex(aState, flex);
PRBool collapsed = PR_FALSE;
child->IsCollapsed(aState, collapsed);
currentBox->flex = flex;
currentBox->collapsed = collapsed;
//currentComputed->resized = PR_FALSE;
//currentComputed->size = 0;
if (!start) {
if (!currentBox) {
aBoxSizes = new (aState) nsBoxSize();
currentBox = aBoxSizes;
} else {
currentBox->next = new (aState) nsBoxSize();
currentBox = currentBox->next;
}
child->GetFlex(aState, flex);
PRBool collapsed = PR_FALSE;
child->IsCollapsed(aState, collapsed);
currentBox->flex = flex;
currentBox->collapsed = collapsed;
} else {
flex = start->flex;
start = start->next;
}
if (flex > 0)
aFlexes++;
child->GetNextBox(&child);
}
*/
// get pref, min, max
aBox->GetChildBox(&child);
currentBox = aBoxSizes;
nsBoxSize* last = nsnull;
while(child)
{
nsSize pref(0,0);
nsSize min(0,0);
nsSize max(0,0);
nsSize max(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
// only one flexible child? Cool we will just make its preferred size
// 0 then and not even have to ask for it.
//if (flexes != 1) {
child->GetPrefSize(aState, pref);
child->GetAscent(aState, currentBox->ascent);
nsMargin margin;
child->GetMargin(margin);
currentBox->ascent += margin.top + margin.bottom;
//}
// only one flexible child? Cool we will just make its preferred size
// 0 then and not even have to ask for it.
//if (flexes != 1) {
nscoord ascent = 0;
child->GetPrefSize(aState, pref);
child->GetMinSize(aState, min);
child->GetMaxSize(aState, max);
child->GetAscent(aState, ascent);
nsMargin margin;
child->GetMargin(margin);
ascent += margin.top + margin.bottom;
//}
child->GetMinSize(aState, min);
child->GetMaxSize(aState, max);
nsBox::BoundsCheck(min, pref, max);
nsBox::BoundsCheck(min, pref, max);
AddMargin(child, pref);
AddMargin(child, min);
AddMargin(child, max);
nscoord minWidth = min.width;
nscoord maxWidth = max.width;
nscoord prefWidth = pref.width;
if (!isHorizontal) {
minWidth = min.height;
maxWidth = max.height;
prefWidth = pref.height;
if (min.width > aMinSize)
aMinSize = min.width;
if (max.width < aMaxSize)
aMaxSize = max.width;
AddMargin(child, pref);
AddMargin(child, min);
AddMargin(child, max);
if (!currentBox) {
// create one.
currentBox = new (aState) nsBoxSize();
if (!aBoxSizes) {
aBoxSizes = currentBox;
last = aBoxSizes;
} else {
if (min.height > aMinSize)
aMinSize = min.height;
if (max.height < aMaxSize)
aMaxSize = max.height;
last->next = currentBox;
last = currentBox;
}
nscoord minWidth;
nscoord maxWidth;
nscoord prefWidth;
// get sizes from child
if (isHorizontal) {
minWidth = min.width;
maxWidth = max.width;
prefWidth = pref.width;
} else {
minWidth = min.height;
maxWidth = max.height;
prefWidth = pref.height;
}
nscoord flex = 0;
child->GetFlex(aState, flex);
PRBool collapsed = PR_FALSE;
child->IsCollapsed(aState, collapsed);
// set them
currentBox->flex = flex;
currentBox->collapsed = collapsed;
currentBox->pref = prefWidth;
currentBox->min = minWidth;
currentBox->max = maxWidth;
NS_ASSERTION(minWidth <= prefWidth && prefWidth <= maxWidth,"Bad min, pref, max widths!");
/*
if (minWidth > maxWidth)
minWidth = maxWidth;
}
if (prefWidth > maxWidth)
prefWidth = maxWidth;
if (!isHorizontal) {
if (min.width > aMinSize)
aMinSize = min.width;
if (prefWidth < minWidth)
prefWidth = minWidth;
*/
if (max.width < aMaxSize)
aMaxSize = max.width;
currentBox->pref = prefWidth;
currentBox->min = minWidth;
currentBox->max = maxWidth;
} else {
if (min.height > aMinSize)
aMinSize = min.height;
if (max.height < aMaxSize)
aMaxSize = max.height;
}
currentBox->ascent = ascent;
aFlexes += currentBox->flex;
child->GetNextBox(&child);
last = currentBox;
currentBox = currentBox->next;
}
}

View File

@ -221,6 +221,8 @@ nsStackLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
nsIBox* child = nsnull;
PRBool grow;
PRInt32 passes = 0;
do {
aBox->GetChildBox(&child);
grow = PR_FALSE;
@ -248,6 +250,8 @@ nsStackLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
child->GetNextBox(&child);
}
NS_ASSERTION(passes < 10,"Infinite loop! Someone won't stop growing!!");
passes++;
} while(grow);
// if some HTML inside us got bigger we need to force ourselves to