From a268db39c4ef7b01e58b4f4dec43aa011ce1044e Mon Sep 17 00:00:00 2001 From: "evaughan%netscape.com" Date: Wed, 9 Feb 2000 22:02:40 +0000 Subject: [PATCH] 1) implememted box reflow coelescing. 2) implemented gfx scrollbars for list boxes 3) fixed progess meter to be an animated gif 4) fixed bugs 23521, 24721, 19114, 20546, 24385, 24457, 23156, 20226, 22543 -r hyatt, troy, rod git-svn-id: svn://10.0.0.236/trunk@60253 18797224-902f-48f8-a5cc-f745e15eee43 --- .../content/shared/public/nsLayoutAtomList.h | 1 + mozilla/content/shared/public/nsXULAtomList.h | 1 + mozilla/layout/base/nsCSSFrameConstructor.cpp | 52 +- mozilla/layout/base/nsLayoutAtomList.h | 1 + mozilla/layout/base/public/nsLayoutAtomList.h | 1 + mozilla/layout/forms/nsFieldSetFrame.cpp | 591 ++----- mozilla/layout/generic/nsGfxScrollFrame.cpp | 593 ++++--- mozilla/layout/generic/nsGfxScrollFrame.h | 4 +- mozilla/layout/generic/nsLeafFrame.cpp | 6 + .../layout/html/base/src/nsGfxScrollFrame.cpp | 593 ++++--- .../layout/html/base/src/nsGfxScrollFrame.h | 4 +- mozilla/layout/html/base/src/nsLeafFrame.cpp | 6 + .../html/base/src/nsScrollPortFrame.cpp | 159 +- .../layout/html/base/src/nsScrollPortFrame.h | 4 +- mozilla/layout/html/document/src/html.css | 6 + .../layout/html/forms/src/nsFieldSetFrame.cpp | 591 ++----- .../html/forms/src/nsGfxListControlFrame.cpp | 246 +++ .../html/style/src/nsCSSFrameConstructor.cpp | 52 +- mozilla/layout/style/html.css | 6 + mozilla/layout/xul/base/src/nsBoxFrame.cpp | 1566 +++++++++++++---- mozilla/layout/xul/base/src/nsBoxFrame.h | 41 +- mozilla/layout/xul/base/src/nsDeckFrame.cpp | 11 + mozilla/layout/xul/base/src/nsDeckFrame.h | 8 +- mozilla/layout/xul/base/src/nsIBox.h | 18 +- mozilla/layout/xul/base/src/nsMenuBarFrame.h | 7 + mozilla/layout/xul/base/src/nsMenuFrame.cpp | 125 +- mozilla/layout/xul/base/src/nsMenuFrame.h | 9 +- .../layout/xul/base/src/nsMenuPopupFrame.cpp | 10 +- .../layout/xul/base/src/nsMenuPopupFrame.h | 7 + .../layout/xul/base/src/nsPopupSetFrame.cpp | 121 +- mozilla/layout/xul/base/src/nsPopupSetFrame.h | 9 +- .../xul/base/src/nsProgressMeterFrame.cpp | 585 +----- .../xul/base/src/nsProgressMeterFrame.h | 36 +- .../layout/xul/base/src/nsRepeatService.cpp | 10 +- .../xul/base/src/nsScrollbarButtonFrame.cpp | 3 +- mozilla/layout/xul/base/src/nsSliderFrame.cpp | 67 +- mozilla/layout/xul/base/src/nsSliderFrame.h | 5 +- .../layout/xul/base/src/nsSplitterFrame.cpp | 275 +-- mozilla/layout/xul/base/src/nsSplitterFrame.h | 7 +- .../xul/base/src/nsTitledButtonFrame.cpp | 198 ++- .../layout/xul/base/src/nsTitledButtonFrame.h | 11 +- mozilla/layout/xul/base/src/nsToolbarFrame.h | 7 + mozilla/layout/xul/base/src/nsToolboxFrame.h | 6 + mozilla/layout/xul/base/src/nsTreeFrame.cpp | 4 +- .../layout/xul/base/src/nsTreeOuterFrame.cpp | 61 +- .../layout/xul/base/src/nsTreeOuterFrame.h | 5 +- .../layout/xul/content/src/nsXULAtomList.h | 1 + .../base/resources/skin/messenger.css | 9 + .../browser/resources/content/navigator.xul | 2 +- mozilla/xpfe/global/resources/skin/MANIFEST | 1 + .../xpfe/global/resources/skin/Makefile.in | 1 + mozilla/xpfe/global/resources/skin/global.css | 6 +- .../xpfe/global/resources/skin/makefile.win | 1 + .../resources/skin/progressmeter-busy.gif | Bin 0 -> 3068 bytes 54 files changed, 3341 insertions(+), 2809 deletions(-) create mode 100644 mozilla/xpfe/global/resources/skin/progressmeter-busy.gif diff --git a/mozilla/content/shared/public/nsLayoutAtomList.h b/mozilla/content/shared/public/nsLayoutAtomList.h index 6c416edadba..8be6148b196 100644 --- a/mozilla/content/shared/public/nsLayoutAtomList.h +++ b/mozilla/content/shared/public/nsLayoutAtomList.h @@ -79,6 +79,7 @@ LAYOUT_ATOM(processingInstructionTagName, "__moz_pi") LAYOUT_ATOM(scrolledContentPseudo, ":scrolled-content") LAYOUT_ATOM(viewportPseudo, ":viewport") LAYOUT_ATOM(viewportScrollPseudo, ":viewport-scroll") +LAYOUT_ATOM(selectScrolledContentPseudo, ":-moz-select-scrolled-content") // Alphabetical list of frame types LAYOUT_ATOM(areaFrame, "AreaFrame") diff --git a/mozilla/content/shared/public/nsXULAtomList.h b/mozilla/content/shared/public/nsXULAtomList.h index d5d01cec2eb..fae78a9f6db 100644 --- a/mozilla/content/shared/public/nsXULAtomList.h +++ b/mozilla/content/shared/public/nsXULAtomList.h @@ -97,6 +97,7 @@ XUL_ATOM(mode, "mode") XUL_ATOM(box, "box") XUL_ATOM(flex, "flex") XUL_ATOM(spring, "spring") +XUL_ATOM(orient, "orient") XUL_ATOM(deck, "deck") XUL_ATOM(tabcontrol, "tabcontrol") diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 16257c4c4ad..a4f2a410162 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -111,7 +111,8 @@ static PRBool gReallyNoisyContentUpdates = PR_FALSE; static PRBool gNoisyInlineConstruction = PR_FALSE; #endif -//#define NEWGFX_LIST +#define NEWGFX_LIST +#define NEWGFX_LIST_SCROLLFRAME #ifdef NEWGFX_LIST nsresult @@ -140,7 +141,7 @@ nsresult NS_NewTitledButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult -NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags ); +NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame); nsresult NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -3042,9 +3043,9 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, } } else { #ifdef NEWGFX_LIST - // Construct a frame-based list box + // Construct a frame-based list box nsIFrame * listFrame; - rv = NS_NewGfxListControlFrame(&listFrame); + rv = NS_NewGfxListControlFrame(aPresShell, &listFrame); // initialize the list control InitAndRestoreFrame(aPresContext, aState, aContent, @@ -3053,33 +3054,37 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, // create the area frame we are scrolling PRUint32 flags = NS_BLOCK_SHRINK_WRAP | (aIsAbsolutelyPositioned?NS_BLOCK_SPACE_MGR:0); nsIFrame* scrolledFrame = nsnull; - NS_NewSelectsAreaFrame(&scrolledFrame, flags); - - nsCOMPtr listControlframe(do_QueryInterface(listFrame)); - if (listControlframe) { - listControlframe->SetMainChildFrame(scrolledFrame); - } + NS_NewSelectsAreaFrame(aPresShell, &scrolledFrame, flags); // resolve a style for our gfx scrollframe based on the list frames style - /*nsCOMPtr scrollFrameStyle; + nsCOMPtr scrollFrameStyle; aPresContext->ResolvePseudoStyleContextFor(aContent, - nsLayoutAtoms::scrolledContentPseudo,// (this will probably work but you might want to set up you own), + nsLayoutAtoms::selectScrolledContentPseudo, aStyleContext, PR_FALSE, getter_AddRefs(scrollFrameStyle)); - */ + + InitAndRestoreFrame(aPresContext, aState, aContent, + listFrame, scrollFrameStyle, nsnull, scrolledFrame); + // this is what is returned when the scrollframe is created. // newScrollFrame - Either a gfx scrollframe or a native scrollframe that was created // scrolledFrameStyleContext - The resolved style context of the scrolledframe you passed in. // this is not the style of the scrollFrame. nsIFrame* newScrollFrame = nsnull; + + /* scroll frame */ + +#ifdef NEWGFX_LIST_SCROLLFRAME nsIStyleContext * scrolledFrameStyleContext = nsnull; // ok take the style context, the Select area frame to scroll,the listFrame, and its parent // and build the scrollframe. - BuildScrollFrame(aPresContext, aState, aContent, aStyleContext, scrolledFrame, + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, scrollFrameStyle, scrolledFrame, listFrame, newScrollFrame, scrolledFrameStyleContext); - +#else + newScrollFrame = scrolledFrame; +#endif // The area frame is a floater container PRBool haveFirstLetterStyle, haveFirstLineStyle; @@ -3108,7 +3113,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, nsIStyleContext* styleContext = nsnull; nsIFrame* generatedFrame = nsnull; scrolledFrame->GetStyleContext(&styleContext); - if (CreateGeneratedContentFrame(aPresContext, aState, scrolledFrame, aContent, + if (CreateGeneratedContentFrame(aPresShell, aPresContext, aState, scrolledFrame, aContent, styleContext, nsLayoutAtoms::dummyOptionPseudo, PR_FALSE, &generatedFrame)) { // Add the generated frame to the child list @@ -7310,7 +7315,9 @@ StyleChangeReflow(nsIPresContext* aPresContext, { nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); - + + + nsIReflowCommand* reflowCmd; nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, aFrame, nsIReflowCommand::StyleChanged, @@ -7320,6 +7327,17 @@ StyleChangeReflow(nsIPresContext* aPresContext, shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + /* + + nsFrameState state; + aFrame->GetFrameState(&state); + state |= NS_FRAME_IS_DIRTY; + aFrame->SetFrameState(state); + nsIFrame* parent; + aFrame->GetParent(&parent); + parent->ReflowDirtyChild(shell, aFrame); +*/ } NS_IMETHODIMP diff --git a/mozilla/layout/base/nsLayoutAtomList.h b/mozilla/layout/base/nsLayoutAtomList.h index 6c416edadba..8be6148b196 100644 --- a/mozilla/layout/base/nsLayoutAtomList.h +++ b/mozilla/layout/base/nsLayoutAtomList.h @@ -79,6 +79,7 @@ LAYOUT_ATOM(processingInstructionTagName, "__moz_pi") LAYOUT_ATOM(scrolledContentPseudo, ":scrolled-content") LAYOUT_ATOM(viewportPseudo, ":viewport") LAYOUT_ATOM(viewportScrollPseudo, ":viewport-scroll") +LAYOUT_ATOM(selectScrolledContentPseudo, ":-moz-select-scrolled-content") // Alphabetical list of frame types LAYOUT_ATOM(areaFrame, "AreaFrame") diff --git a/mozilla/layout/base/public/nsLayoutAtomList.h b/mozilla/layout/base/public/nsLayoutAtomList.h index 6c416edadba..8be6148b196 100644 --- a/mozilla/layout/base/public/nsLayoutAtomList.h +++ b/mozilla/layout/base/public/nsLayoutAtomList.h @@ -79,6 +79,7 @@ LAYOUT_ATOM(processingInstructionTagName, "__moz_pi") LAYOUT_ATOM(scrolledContentPseudo, ":scrolled-content") LAYOUT_ATOM(viewportPseudo, ":viewport") LAYOUT_ATOM(viewportScrollPseudo, ":viewport-scroll") +LAYOUT_ATOM(selectScrolledContentPseudo, ":-moz-select-scrolled-content") // Alphabetical list of frame types LAYOUT_ATOM(areaFrame, "AreaFrame") diff --git a/mozilla/layout/forms/nsFieldSetFrame.cpp b/mozilla/layout/forms/nsFieldSetFrame.cpp index 3d0aefa398b..d3b7ccb09bc 100644 --- a/mozilla/layout/forms/nsFieldSetFrame.cpp +++ b/mozilla/layout/forms/nsFieldSetFrame.cpp @@ -51,8 +51,6 @@ static NS_DEFINE_IID(kIDOMHTMLLegendElementIID, NS_IDOMHTMLLEGENDELEMENT_IID); class nsLegendFrame; -//#define DO_NEWFIELDSET - class nsFieldSetFrame : public nsHTMLContainerFrame { public: @@ -124,116 +122,13 @@ nsFieldSetFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { -#ifdef DO_NEWFIELDSET - nsIFrame* newChildList = aChildList; - // Set the geometric and content parent for each of the child frames - // that will go into the area frame's child list. - // The legend frame does not go into the list - nsIFrame* lastNewFrame = nsnull; - for (nsIFrame* frame = aChildList; nsnull != frame;) { - nsIFrame* legendFrame = nsnull; - nsresult result = frame->QueryInterface(kLegendFrameCID, (void**)&legendFrame); - if (NS_SUCCEEDED(result) && legendFrame) { - if (mLegendFrame) { // we already have a legend, destroy it - frame->GetNextSibling(&frame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(frame); - } - else { - aChildList = frame; - } - legendFrame->Destroy(aPresContext); - } else { - /*nsIFrame* nextFrame; - frame->GetNextSibling(&nextFrame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(nextFrame); - } else { - newChildList = nextFrame; - } - mFrames.FirstChild()->SetNextSibling(frame); - */ - mLegendFrame = frame; - break; - //mLegendFrame->SetNextSibling(nsnull); - //frame = nextFrame; - } - } else { - lastNewFrame = frame; - frame->GetNextSibling(&frame); - } - } + + // get the content and legend frames. + mContentFrame = aChildList; + mContentFrame->GetNextSibling(&mLegendFrame); + // Queue up the frames for the content frame - return nsHTMLContainerFrame::SetInitialChildList(aPresContext, nsnull, newChildList); -#else - // cache our display type - const nsStyleDisplay* styleDisplay; - GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); - - PRUint32 flags = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay) ? NS_BLOCK_SHRINK_WRAP : 0; - - // add in the parent state (we need it to be inherited) - PRUint32 parentState; - GetFrameState( &parentState ); - flags |= parentState; - - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - NS_NewAreaFrame(shell, &mContentFrame, flags); - mFrames.SetFrames(mContentFrame); - - // Resolve style and initialize the frame - nsIStyleContext* styleContext; - aPresContext->ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::fieldsetContentPseudo, - mStyleContext, PR_FALSE, &styleContext); - mFrames.FirstChild()->Init(aPresContext, mContent, this, styleContext, nsnull); - mFrames.FirstChild()->SetNextSibling(nsnull); - NS_RELEASE(styleContext); - - nsIFrame* newChildList = aChildList; - - // Set the geometric and content parent for each of the child frames - // that will go into the area frame's child list. - // The legend frame does not go into the list - nsIFrame* lastNewFrame = nsnull; - for (nsIFrame* frame = aChildList; nsnull != frame;) { - nsIFrame* legendFrame = nsnull; - nsresult result = frame->QueryInterface(kLegendFrameCID, (void**)&legendFrame); - if (NS_SUCCEEDED(result) && legendFrame) { - if (mLegendFrame) { // we already have a legend, destroy it - frame->GetNextSibling(&frame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(frame); - } - else { - aChildList = frame; - } - legendFrame->Destroy(aPresContext); - } - else { - nsIFrame* nextFrame; - frame->GetNextSibling(&nextFrame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(nextFrame); - } else { - newChildList = nextFrame; - } - frame->SetParent(this); - mFrames.FirstChild()->SetNextSibling(frame); - mLegendFrame = frame; - mLegendFrame->SetNextSibling(nsnull); - frame = nextFrame; - } - } else { - frame->SetParent(mFrames.FirstChild()); - lastNewFrame = frame; - frame->GetNextSibling(&frame); - } - } - // Queue up the frames for the content frame - return mFrames.FirstChild()->SetInitialChildList(aPresContext, nsnull, newChildList); - -#endif + return nsHTMLContainerFrame::SetInitialChildList(aPresContext, nsnull, aChildList); } // this is identical to nsHTMLContainerFrame::Paint except for the background and border. @@ -353,73 +248,72 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { -#ifdef DO_NEWFIELDSET // Initialize OUT parameter - aStatus = NS_FRAME_COMPLETE; + aStatus = NS_FRAME_COMPLETE; - PRBool isStyleChange = PR_FALSE; - PRBool isDirtyChildReflow = PR_FALSE; - PRBool needResizeReflow = PR_FALSE; - nsIFrame * lastReflowFrame = nsnull; + //------------ Handle Incremental Reflow ----------------- + nsIFrame* incrementalChild = nsnull; + PRBool reflowContent = PR_TRUE; + PRBool reflowLegend = PR_TRUE; + nsReflowReason reason = aReflowState.reason; - // Check for an incremental reflow - if (eReflowReason_Incremental == aReflowState.reason) { - // See if we're the target frame - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); - if (this == targetFrame) { - // Get the reflow type - nsIReflowCommand::ReflowType reflowType; - aReflowState.reflowCommand->GetType(reflowType); + if ( aReflowState.reason == eReflowReason_Incremental ) { + nsIReflowCommand::ReflowType reflowType; + aReflowState.reflowCommand->GetType(reflowType); - switch (reflowType) { - case nsIReflowCommand::ReflowDirty: - isDirtyChildReflow = PR_TRUE; - break; + // See if it's targeted at us + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); - case nsIReflowCommand::StyleChanged: - // Remember it's a style change so we can set the reflow reason below - isStyleChange = PR_TRUE; - break; + if (this == targetFrame) { + switch (reflowType) { - default: - NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); - } + case nsIReflowCommand::StyleChanged: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_StyleChange; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; - } else { - nsIFrame* nextFrame; - // Get the next frame in the reflow chain - aReflowState.reflowCommand->GetNext(nextFrame); - //NS_ASSERTION(nextFrame == mFrames.FirstChild(), "unexpected next reflow command frame"); + // if its a dirty type then reflow us with a dirty reflow + case nsIReflowCommand::ReflowDirty: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_Dirty; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + } + } else { + aReflowState.reflowCommand->GetNext(incrementalChild); - nsSize availSize(aReflowState.mComputedWidth, aReflowState.availableHeight); - nsRect currentRect; - nextFrame->GetRect(currentRect); + reflowContent = PR_FALSE; + reflowLegend = PR_FALSE; - // We must specify an unconstrained available height, because constrained - // is only for when we're paginated... - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, nextFrame, - availSize); - // Reflow the frame - ReflowChild(nextFrame, aPresContext, aDesiredSize, kidReflowState, - kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, - 0, aStatus); - if (currentRect.width != aDesiredSize.width || - currentRect.height != aDesiredSize.height) { - needResizeReflow = PR_TRUE; - } - lastReflowFrame = nextFrame; - nextFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + if (incrementalChild == mLegendFrame) + reflowLegend = PR_TRUE; + else if (incrementalChild == mContentFrame) + reflowContent = PR_TRUE; + } } - } - // XXX NOT OPTIMIZED - This code always reflows the legend and the area frame - if (mFrames.IsEmpty()) { - // We have no child frame, so return an empty size - aDesiredSize.width = aDesiredSize.height = 0; - aDesiredSize.ascent = aDesiredSize.descent = 0; + // if dirty then check dirty flags + if (reason == eReflowReason_Dirty) + { + if (reflowContent) { + nsFrameState state; + mContentFrame->GetFrameState(&state); + reflowContent = (state & NS_FRAME_IS_DIRTY) || (state & NS_FRAME_HAS_DIRTY_CHILDREN); + } + + if (reflowLegend) { + nsFrameState state; + mLegendFrame->GetFrameState(&state); + reflowLegend = (state & NS_FRAME_IS_DIRTY) || (state & NS_FRAME_HAS_DIRTY_CHILDREN); + } + } - } else { // availSize could have unconstrained values, don't perform any addition on them nsSize availSize(aReflowState.mComputedWidth, aReflowState.availableHeight); @@ -431,116 +325,136 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, // Figure out how big the legend is if there is one. nsMargin legendMargin(0,0,0,0); - // if there is a legend frame flow it. + // reflow the legend only if needed if (mLegendFrame) { - nsHTMLReflowState legendReflowState(aPresContext, aReflowState, - mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE)); + if (reflowLegend) { + nsHTMLReflowState legendReflowState(aPresContext, aReflowState, + mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE)); - // always give the legend as much size as it needs - legendReflowState.mComputedWidth = NS_INTRINSICSIZE; - legendReflowState.mComputedHeight = NS_INTRINSICSIZE; - legendReflowState.reason = eReflowReason_Resize; + // always give the legend as much size as it needs + legendReflowState.mComputedWidth = NS_INTRINSICSIZE; + legendReflowState.mComputedHeight = NS_INTRINSICSIZE; + legendReflowState.reason = reason; - ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); - // get the legend's margin - nsIStyleContext* legendSC = nsnull; - mLegendFrame->GetStyleContext(&legendSC); - if (legendSC) { - const nsStyleSpacing* legendSpacing = - (const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing); - legendSpacing->GetMargin(legendMargin); - NS_RELEASE(legendSC); - } + // get the legend's margin + const nsStyleSpacing* legendSpacing; + mLegendFrame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) legendSpacing); - // figure out the legend's rectangle - mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right; - mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom; - mLegendRect.x = borderPadding.left; - mLegendRect.y = 0; - mLegendSpace = 0; - if (mLegendRect.height > border.top) { - // center the border on the legend - mLegendSpace = mLegendRect.height - borderPadding.top; - } else { - mLegendRect.y = (border.top - mLegendRect.height)/2; - } + legendSpacing->GetMargin(legendMargin); - // if we are contrained then remove the legend from our available height. - if (NS_INTRINSICSIZE != availSize.height) { - if (availSize.height >= mLegendSpace) - availSize.height -= mLegendSpace; - } + // figure out the legend's rectangle + mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right; + mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom; + mLegendRect.x = borderPadding.left; + mLegendRect.y = 0; + + nscoord oldSpace = mLegendSpace; + mLegendSpace = 0; + if (mLegendRect.height > border.top) { + // center the border on the legend + mLegendSpace = mLegendRect.height - borderPadding.top; + } else { + mLegendRect.y = (border.top - mLegendRect.height)/2; + } + + // if the legend space changes then we need to reflow the + // content area as well. + if (mLegendSpace != oldSpace) { + if (reflowContent == PR_FALSE || reason == eReflowReason_Dirty) { + reflowContent = PR_TRUE; + reason = eReflowReason_Resize; + } + } + + // if we are contrained then remove the legend from our available height. + if (NS_INTRINSICSIZE != availSize.height) { + if (availSize.height >= mLegendSpace) + availSize.height -= mLegendSpace; + } - // don't get any smaller than the legend - if (NS_INTRINSICSIZE != availSize.width) { - if (availSize.width < mLegendRect.width) - availSize.width = mLegendRect.width; - } + // don't get any smaller than the legend + if (NS_INTRINSICSIZE != availSize.width) { + if (availSize.width < mLegendRect.width) + availSize.width = mLegendRect.width; + } - // Tell the legend we're done with the reflow. We'll size and place it later on - mLegendFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + FinishReflowChild(mLegendFrame, aPresContext, aDesiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME); + } } - nsIFrame* kidFrame = mFrames.FirstChild(); + nsRect contentRect; + + // reflow the content frame only if needed + if (mContentFrame) { + if (reflowContent) { + availSize.width = aReflowState.mComputedWidth; #if 0 - availSize.width = aReflowState.mComputedWidth; - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) { - availSize.height = aReflowState.mComputedHeight - mLegendSpace; - } else { - availSize.height = NS_INTRINSICSIZE; - } + if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) { + availSize.height = aReflowState.mComputedHeight - mLegendSpace; + } else { + availSize.height = NS_INTRINSICSIZE; + } #endif - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, - availSize); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, mContentFrame, + availSize); - if (isDirtyChildReflow) { - // Note: the only reason the frame would be dirty would be if it had - // just been inserted or appended - kidReflowState.reason = eReflowReason_Initial; - kidReflowState.reflowCommand = nsnull; - } else if (isStyleChange) { - kidReflowState.reason = eReflowReason_StyleChange; - kidReflowState.reflowCommand = nsnull; - } else { - kidReflowState.reason = eReflowReason_Resize; + kidReflowState.reason = reason; + + // Reflow the frame + ReflowChild(mContentFrame, aPresContext, aDesiredSize, kidReflowState, + kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, + 0, aStatus); + + printf("*** %p computedHgt: %d ", this, aReflowState.mComputedHeight); + printf("Reason: "); + switch (aReflowState.reason) { + case eReflowReason_Initial:printf("Initil");break; + case eReflowReason_Incremental:printf("Increm");break; + case eReflowReason_Resize: printf("Resize"); break; + case eReflowReason_StyleChange:printf("eReflowReason_StyleChange");break; + } + + // set the rect. make sure we add the margin back in. + contentRect.SetRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); + if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && + borderPadding.top + mLegendSpace+aDesiredSize.height > aReflowState.mComputedHeight) { + aDesiredSize.height = aReflowState.mComputedHeight-(borderPadding.top + mLegendSpace); + printf(" areaHgt: %d", aDesiredSize.height); + } + + FinishReflowChild(mContentFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); + + nsFrameState kidState; + mContentFrame->GetFrameState(&kidState); + + // printf("width: %d, height: %d\n", desiredSize.mCombinedArea.width, desiredSize.mCombinedArea.height); + + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + aDesiredSize.mOverflowArea.width += borderPadding.left + borderPadding.right; + aDesiredSize.mOverflowArea.height += borderPadding.top + borderPadding.bottom + mLegendSpace; + } + + NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); + + } else { + // if we don't need to reflow just get the old size + mContentFrame->GetRect(contentRect); + const nsStyleSpacing* spacing; + mContentFrame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + nsMargin m(0,0,0,0); + spacing->GetMargin(m); + contentRect.Inflate(m); + } } - // Reflow the frame - ReflowChild(kidFrame, aPresContext, aDesiredSize, kidReflowState, - kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, - 0, aStatus); - -printf("*** %p computedHgt: %d ", this, aReflowState.mComputedHeight); - printf("Reason: "); - switch (aReflowState.reason) { - case eReflowReason_Initial:printf("Initil");break; - case eReflowReason_Incremental:printf("Increm");break; - case eReflowReason_Resize: printf("Resize"); break; - case eReflowReason_StyleChange:printf("eReflowReason_StyleChange");break; - } - - // set the rect. make sure we add the margin back in. - nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && - borderPadding.top + mLegendSpace+aDesiredSize.height > aReflowState.mComputedHeight) { - aDesiredSize.height = aReflowState.mComputedHeight-(borderPadding.top + mLegendSpace); -printf(" areaHgt: %d", aDesiredSize.height); - } - - FinishReflowChild(kidFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); - - // If the child frame was just inserted, then we're responsible for making sure - // it repaints - //if (isDirtyChildReflow) { - // Damage the area occupied by the deleted frame - // Invalidate(aPresContext, rect, PR_FALSE); - //} - - NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); - if (mLegendFrame) { if (contentRect.width > mLegendRect.width) { PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign(); @@ -560,9 +474,24 @@ printf(" areaHgt: %d", aDesiredSize.height); // place the legend nsRect actualLegendRect(mLegendRect); actualLegendRect.Deflate(legendMargin); - mLegendFrame->SetRect(aPresContext, actualLegendRect); + + nsPoint curOrigin; + mLegendFrame->GetOrigin(curOrigin); + + // only if the origin changed + if ((curOrigin.x != mLegendRect.x) || (curOrigin.y != mLegendRect.y)) { + + mLegendFrame->MoveTo(aPresContext, actualLegendRect.x , actualLegendRect.y); + + nsIView* view; + mLegendFrame->GetView(aPresContext, &view); + if (view) + nsContainerFrame::PositionFrameView(aPresContext, mLegendFrame, view); + else + nsContainerFrame::PositionChildViews(aPresContext, mLegendFrame); + } } - + // Return our size and our result if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) { aDesiredSize.height = mLegendSpace + @@ -601,145 +530,7 @@ printf(" areaHgt: %d", aDesiredSize.height); // height is border + legend aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom + mLegendRect.height; } - } -printf(" desiredHgt: %d\n", aDesiredSize.height); -#else - // availSize could have unconstrained values, don't perform any addition on them - nsSize availSize(aReflowState.mComputedWidth, aReflowState.availableHeight); - - // get our border and padding - const nsMargin &borderPadding = aReflowState.mComputedBorderPadding; - const nsMargin &padding = aReflowState.mComputedPadding; - nsMargin border = borderPadding - padding; - // Figure out how big the legend is if there is one. - nsMargin legendMargin(0,0,0,0); - - // if there is a legend frame flow it. - if (mLegendFrame) { - nsHTMLReflowState legendReflowState(aPresContext, aReflowState, - mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE)); - - // always give the legend as much size as it needs - legendReflowState.mComputedWidth = NS_INTRINSICSIZE; - legendReflowState.mComputedHeight = NS_INTRINSICSIZE; - - ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); - - // get the legend's margin - nsIStyleContext* legendSC = nsnull; - mLegendFrame->GetStyleContext(&legendSC); - if (legendSC) { - const nsStyleSpacing* legendSpacing = - (const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing); - legendSpacing->GetMargin(legendMargin); - NS_RELEASE(legendSC); - } - - // figure out the legend's rectangle - mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right; - mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom; - mLegendRect.x = borderPadding.left; - mLegendRect.y = 0; - mLegendSpace = 0; - if (mLegendRect.height > border.top) { - // center the border on the legend - mLegendSpace = mLegendRect.height - borderPadding.top; - } else { - mLegendRect.y = (border.top - mLegendRect.height)/2; - } - - // if we are contrained then remove the legend from our available height. - if (NS_INTRINSICSIZE != availSize.height) { - if (availSize.height >= mLegendSpace) - availSize.height -= mLegendSpace; - } - - // don't get any smaller than the legend - if (NS_INTRINSICSIZE != availSize.width) { - if (availSize.width < mLegendRect.width) - availSize.width = mLegendRect.width; - } - - // Tell the legend we're done with the reflow. We'll size and place it later on - mLegendFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - } - - mContentFrame = mFrames.FirstChild(); - - // Try to reflow the area frame into the available space. - nsHTMLReflowState contentReflowState(aPresContext, aReflowState, - mContentFrame, availSize); - - ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, - borderPadding.left, borderPadding.top + mLegendSpace, 0, aStatus); - - // set the rect. make sure we add the margin back in. - nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); - - // Place the content area frame. - FinishReflowChild(mContentFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); - - if (mLegendFrame) - { - PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign(); - - switch(align) { - case NS_STYLE_TEXT_ALIGN_RIGHT: - mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left; - break; - case NS_STYLE_TEXT_ALIGN_CENTER: - mLegendRect.x = contentRect.width/2 - mLegendRect.width/2 + borderPadding.left; - } - - // place the legend - nsRect actualLegendRect(mLegendRect); - actualLegendRect.Deflate(legendMargin); - mLegendFrame->SetRect(aPresContext, actualLegendRect); - } - - // Return our size and our result - if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) { - aDesiredSize.height = mLegendSpace + - borderPadding.top + - aDesiredSize.height + - borderPadding.bottom; - } else { - nscoord min = borderPadding.top + borderPadding.bottom + mLegendRect.height; - aDesiredSize.height = aReflowState.mComputedHeight + borderPadding.top + borderPadding.bottom; - if (aDesiredSize.height < min) - aDesiredSize.height = min; - } - - if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) { - aDesiredSize.width = borderPadding.left + - aDesiredSize.width + - borderPadding.right; - } else { - nscoord min = borderPadding.left + borderPadding.right + mLegendRect.width; - aDesiredSize.width = aReflowState.mComputedWidth + borderPadding.left + borderPadding.right; - if (aDesiredSize.width < min) - aDesiredSize.width = min; - } - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - - if (nsnull != aDesiredSize.maxElementSize) { - // if the legend it wider use it - if (aDesiredSize.maxElementSize->width < mLegendRect.width) - aDesiredSize.maxElementSize->width = mLegendRect.width; - - // add in padding. - aDesiredSize.maxElementSize->width += borderPadding.left + borderPadding.right; - - // height is border + legend - aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom + mLegendRect.height; - } - - aStatus = NS_FRAME_COMPLETE; -#endif return NS_OK; } diff --git a/mozilla/layout/generic/nsGfxScrollFrame.cpp b/mozilla/layout/generic/nsGfxScrollFrame.cpp index a4c46513905..ed1f1b29a8b 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.cpp +++ b/mozilla/layout/generic/nsGfxScrollFrame.cpp @@ -47,6 +47,7 @@ #include "nsIDocumentObserver.h" #include "nsIDocument.h" #include "nsIScrollPositionListener.h" +//#include "nsBoxFrame.h" #include "nsIElementFactory.h" static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID); @@ -132,7 +133,7 @@ public: NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument) { mDocument = nsnull; return NS_OK; } - void SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize); + PRBool SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); PRInt32 GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRInt32 defaultValue); nsresult CalculateChildTotalSize(nsIFrame* aKidFrame, @@ -153,21 +154,10 @@ public: void SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisible); - void DetermineReflowNeed(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, - nsIFrame*& aIncrementalChild); void ReflowScrollbars( nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollBarResized, nsIFrame*& aIncrementalChild); void ReflowScrollbar( nsIPresContext* aPresContext, @@ -192,9 +182,6 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, nsIFrame*& aIncrementalChild); void LayoutChildren(nsIPresContext* aPresContext, @@ -209,6 +196,25 @@ public: void AddVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize); void RemoveVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); + + /* + PRBool IsDirty(nsIFrame* aFrame) { + nsFrameState frameState; + aFrame->GetFrameState(&frameState); + if (frameState & NS_FRAME_IS_DIRTY) + return PR_TRUE; + else + return PR_FALSE; + } + + void MarkDirty(nsIFrame* aFrame) { + nsFrameState frameState; + aFrame->GetFrameState(&frameState); + frameState |= NS_FRAME_IS_DIRTY; + aFrame->SetFrameState(frameState); + } + */ + nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext); void GetScrolledContentSize(nsIPresContext* aPresContext, nsSize& aSize); @@ -219,15 +225,16 @@ public: nsIFrame* mHScrollbarFrame; nsIFrame* mVScrollbarFrame; nsIFrame* mScrollAreaFrame; - PRBool mHasVerticalScrollbar; - PRBool mHasHorizontalScrollbar; - PRBool mHscrollbarNeedsReflow; - PRBool mVscrollbarNeedsReflow; - PRBool mScrollAreaNeedsReflow; nscoord mOnePixel; nsCOMPtr mDocument; nsGfxScrollFrame* mOuter; nsIScrollableView* mScrollableView; + nsSize mMaxElementSize; + + PRBool mHasVerticalScrollbar; + PRBool mHasHorizontalScrollbar; + PRBool mFirstPass; + PRBool mIsRoot; }; NS_IMPL_ISUPPORTS2(nsGfxScrollFrameInner, nsIDocumentObserver, nsIScrollPositionListener) @@ -253,6 +260,7 @@ nsGfxScrollFrame::nsGfxScrollFrame(nsIDocument* aDocument) mInner->AddRef(); mInner->mDocument = aDocument; mPresContext = nsnull; + mInner->mIsRoot = PR_FALSE; } nsGfxScrollFrame::~nsGfxScrollFrame() @@ -447,45 +455,110 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, aReflowState.availableWidth, aReflowState.availableHeight)); - // scroll frames can't have padding. So lets remove their padding from the reflow state - // and move it to their computed size. - nsMargin padding = aReflowState.mComputedPadding; + // if we have any padding then ignore it. It is inherited down to our scrolled frame + if (aReflowState.mComputedPadding.left != 0 || + aReflowState.mComputedPadding.right != 0 || + aReflowState.mComputedPadding.top != 0 || + aReflowState.mComputedPadding.bottom != 0) + { + nsHTMLReflowState newState(aReflowState); - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedWidth) += padding.left + padding.right; - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedHeight) += padding.top + padding.bottom; + // get the padding to remove + nscoord pwidth = (newState.mComputedPadding.left + newState.mComputedPadding.right); + nscoord pheight = (newState.mComputedPadding.top + newState.mComputedPadding.bottom); + + // adjust our computed size to add in the padding we are removing. Make sure + // the computed size doesn't go negative or anything. + if (newState.mComputedWidth != NS_INTRINSICSIZE) + newState.mComputedWidth += pwidth; + + if (newState.mComputedHeight != NS_INTRINSICSIZE) + newState.mComputedHeight += pheight; + + // fix up the borderpadding + ((nsMargin&)newState.mComputedBorderPadding) -= newState.mComputedPadding; + + // remove the padding + ((nsMargin&)newState.mComputedPadding) = nsMargin(0,0,0,0); + + // reflow us again with the correct values. + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + + mInner->mFirstPass = PR_TRUE; - ((nsMargin&)aReflowState.mComputedPadding) = nsMargin(0,0,0,0); - ((nsMargin&)aReflowState.mComputedBorderPadding) -= padding; - - // assume we need to reflow nothing - PRBool hscrollbarNeedsReflow = mInner->mHscrollbarNeedsReflow; - PRBool vscrollbarNeedsReflow = mInner->mVscrollbarNeedsReflow; - PRBool scrollAreaNeedsReflow = mInner->mScrollAreaNeedsReflow; - + // Handle Incremental Reflow nsIFrame* incrementalChild = nsnull; - // see what things need reflow - mInner->DetermineReflowNeed(aPresContext, - aDesiredSize, - aReflowState, - aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, - incrementalChild); + if ( aReflowState.reason == eReflowReason_Initial) { + // on the initial reflow see if we are the root box. + // the root box. + mInner->mIsRoot = PR_TRUE; + + // see if we are the root box + nsIFrame* parent = mParent; + while (parent) { + nsIBox* ibox = nsnull; + if (NS_SUCCEEDED(parent->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox) { + mInner->mIsRoot = PR_FALSE; + break; + } + + parent->GetParent(&parent); + } + } else if ( aReflowState.reason == eReflowReason_Incremental ) { + + nsIReflowCommand::ReflowType reflowType; + aReflowState.reflowCommand->GetType(reflowType); + + // See if it's targeted at us + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); + + if (this == targetFrame) { + // if we are the target see what the type was + // and generate a normal non incremental reflow. + switch (reflowType) { + + case nsIReflowCommand::StyleChanged: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_StyleChange; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + // if its a dirty type then reflow us with a dirty reflow + case nsIReflowCommand::ReflowDirty: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_Dirty; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + default: + NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); + } + } + + if (mInner->mIsRoot) + nsIBox::HandleRootBoxReflow(aPresContext, this, aReflowState); + + // then get the child we need to flow incrementally + aReflowState.reflowCommand->GetNext(incrementalChild); + + } + + + // next reflow the scrollbars so we will at least know their size. If they are bigger or smaller than // we thought we will have to reflow the scroll area as well. mInner->ReflowScrollbars( aPresContext, aReflowState, aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, incrementalChild); // then reflow the scroll area. If it gets bigger it could signal the scrollbars need @@ -494,18 +567,14 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize, aReflowState, aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, incrementalChild); + mInner->mFirstPass = PR_FALSE; + // reflow the scrollbars again but only the ones that need it. mInner->ReflowScrollbars( aPresContext, aReflowState, aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, incrementalChild); // layout all the children. @@ -513,15 +582,6 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize, aReflowState); - // redraw anything that needs it. - if ( aReflowState.reason == eReflowReason_Incremental ) - if (hscrollbarNeedsReflow && vscrollbarNeedsReflow && scrollAreaNeedsReflow) - Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); - - - mInner->mHscrollbarNeedsReflow = PR_FALSE; - mInner->mVscrollbarNeedsReflow = PR_FALSE; - mInner->mScrollAreaNeedsReflow = PR_FALSE; /* if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) @@ -713,9 +773,9 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsGfxScrollFrame* aOuter):mHScrollb { mOuter = aOuter; mRefCnt = 0; - mHscrollbarNeedsReflow = PR_FALSE; - mVscrollbarNeedsReflow = PR_FALSE; - mScrollAreaNeedsReflow = PR_FALSE; + mMaxElementSize.width = 0; + mMaxElementSize.height = 0; + mFirstPass = PR_FALSE; } NS_IMETHODIMP @@ -897,6 +957,19 @@ nsGfxScrollFrameInner::CalculateScrollAreaSize(nsIPresContext* aPresCon aScrollAreaSize.width = aReflowState.mComputedWidth; aScrollAreaSize.height = aReflowState.mComputedHeight; + if (aScrollAreaSize.width != NS_INTRINSICSIZE) { + aScrollAreaSize.width -= aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + if (aScrollAreaSize.width < 0) + aScrollAreaSize.width = 0; + } + + if (aScrollAreaSize.height != NS_INTRINSICSIZE) { + aScrollAreaSize.height -= aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + if (aScrollAreaSize.height < 0) + aScrollAreaSize.height = 0; + + } + // get the current state PRBool vert = mHasVerticalScrollbar; PRBool horiz = mHasHorizontalScrollbar; @@ -976,61 +1049,6 @@ nsGfxScrollFrameInner::SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisi child->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, newStyle, PR_TRUE); } -/** - * Determine which of our children need reflow. It also return the child that is being - * incrementally reflowed if there is one. - */ -void -nsGfxScrollFrameInner::DetermineReflowNeed(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, - nsIFrame*& aIncrementalChild) -{ - nsIFrame* targetFrame; - - // Special handling for incremental reflow - if (eReflowReason_Incremental == aReflowState.reason) { - // See whether we're the target of the reflow command - aReflowState.reflowCommand->GetTarget(targetFrame); - if (mOuter == targetFrame) { - nsIReflowCommand::ReflowType type; - - // The only type of reflow command we expect to get is a style - // change reflow command - aReflowState.reflowCommand->GetType(type); - NS_ASSERTION(nsIReflowCommand::StyleChanged == type, "unexpected reflow type"); - - // Make a copy of the reflow state (with a different reflow reason) and - // then recurse - nsHTMLReflowState reflowState(aReflowState); - reflowState.reason = eReflowReason_StyleChange; - reflowState.reflowCommand = nsnull; - mOuter->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); - } - - // Get the next frame in the reflow chain this will be one of the scrollbars. - aReflowState.reflowCommand->GetNext(aIncrementalChild); - - // see which scrollbar it is and signal that is needs reflow - if (aIncrementalChild == mHScrollbarFrame) - aHscrollbarNeedsReflow = PR_TRUE; - else if (aIncrementalChild == mVScrollbarFrame) - aVscrollbarNeedsReflow = PR_TRUE; - else if (aIncrementalChild == mScrollAreaFrame) - aScrollAreaNeedsReflow = PR_TRUE; - - } else { - // if not incremental reflow then reflow everyone one. - aHscrollbarNeedsReflow = PR_TRUE; - aVscrollbarNeedsReflow = PR_TRUE; - aScrollAreaNeedsReflow = PR_TRUE; - } -} - /** * Reflows the visible scrollbars to fit in our content area. If the scrollbars change size @@ -1041,40 +1059,30 @@ void nsGfxScrollFrameInner::ReflowScrollbars( nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollBarResized, nsIFrame*& aIncrementalChild) { // if we have gfx scrollbars reflow them. If they changed size then signal that // we need to reflow the content area. This could happen if there is a style rule set // up on them that changed there size. Like an image on the thumb gets big. - if (aHscrollbarNeedsReflow) - { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - aScrollBarResized, - mHScrollbarFrame, - aIncrementalChild); - - if (aScrollBarResized) - aVscrollbarNeedsReflow = PR_TRUE; - - } - if (aVscrollbarNeedsReflow) - { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - aScrollBarResized, - mVScrollbarFrame, - aIncrementalChild); - if (aScrollBarResized) - aHscrollbarNeedsReflow = PR_TRUE; + PRBool resized = PR_TRUE; + if (mHasHorizontalScrollbar || aReflowState.reason == eReflowReason_Initial) { + ReflowScrollbar(aPresContext, + aReflowState, + aStatus, + resized, + mHScrollbarFrame, + aIncrementalChild); + } - } + if (mHasVerticalScrollbar || aReflowState.reason == eReflowReason_Initial) { + ReflowScrollbar(aPresContext, + aReflowState, + aStatus, + resized, + mVScrollbarFrame, + aIncrementalChild); + } SetScrollbarVisibility(mHScrollbarFrame, mHasHorizontalScrollbar); SetScrollbarVisibility(mVScrollbarFrame, mHasVerticalScrollbar); @@ -1090,7 +1098,11 @@ nsGfxScrollFrameInner::ReflowScrollbar( nsIPresContext* aPresContext { nsSize scrollArea; GetFrameSize(mScrollAreaFrame, scrollArea); - + + // add the padding to it. + scrollArea.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + scrollArea.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + // is it the horizontal scrollbar? if (aScrollbarFrame == mHScrollbarFrame) { @@ -1120,9 +1132,8 @@ nsGfxScrollFrameInner::ReflowScrollbar( nsIPresContext* aPresContext nsSize(NS_INTRINSICSIZE, height), aScrollbarResized, aIncrementalChild); - - } + } } void @@ -1189,9 +1200,57 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, PRBool& aResized, nsIFrame*& aIncrementalChild) { - // get the current size - nsSize oldSize; - GetFrameSize(aFrame, oldSize); + PRBool needsReflow = PR_FALSE; + nsReflowReason reason = aReflowState.reason; + + switch(reason) + { + case eReflowReason_Incremental: + if (aIncrementalChild == aFrame) { + needsReflow = PR_TRUE; + aIncrementalChild = nsnull; + } else { + reason = eReflowReason_Resize; + needsReflow = PR_FALSE; + } + break; + + // if its dirty then see if the child we want to reflow is dirty. If it is then + // mark it as needing to be reflowed. + case eReflowReason_Dirty: + // get the frame state to see if it needs reflow + nsFrameState state; + aFrame->GetFrameState(&state); + needsReflow = (state & NS_FRAME_IS_DIRTY) || (state & NS_FRAME_HAS_DIRTY_CHILDREN); + break; + + // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different + // from the new size would we actually do a reflow + case eReflowReason_Resize: + needsReflow = PR_FALSE; + break; + + default: + needsReflow = PR_TRUE; + + } + + nsSize currentSize; + GetFrameSize(aFrame, currentSize); + + // if we do not need reflow then + // see if the size it what we already want. If it is then we are done. + if (!needsReflow) { + // get the current size + + // if the size is not changing and the frame is not dirty then there + // is nothing to do. + if (currentSize.width == aComputed.width && currentSize.height == aComputed.height) { + aDesiredSize.width = currentSize.width; + aDesiredSize.height = currentSize.height; + return NS_OK; + } + } aDesiredSize.width = 0; aDesiredSize.height = 0; @@ -1199,14 +1258,7 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, nsHTMLReflowState childReflowState(aPresContext, aReflowState, aFrame, aAvailable); - // handle incremental reflow - if (aReflowState.reason == eReflowReason_Incremental) { - if (aFrame == aIncrementalChild) - aIncrementalChild = nsnull; - else - childReflowState.reason = eReflowReason_Resize; - } - + childReflowState.reason = reason; childReflowState.mComputedWidth = aComputed.width; childReflowState.mComputedHeight = aComputed.height; @@ -1219,42 +1271,33 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, if (NS_FAILED(rv)) return rv; - // this basically sucks. Sometime it fails to get the border and padding - // because one or the other is not set. So we are forced to go out and get - // the border and padding separately and add them together. - /* - nsMargin border; - if (!spacing->GetBorderPadding(border)) { - if (!spacing->GetBorder(border)) - border.SizeTo(0,0,0,0); - - - border += padding; - } - */ - + // get the margin nsMargin margin(0,0,0,0); spacing->GetMargin(margin); - - /* - if (aFrame == mScrollAreaFrame) { - childReflowState.mComputedBorderPadding -= childReflowState.mComputedPadding; - childReflowState.mComputedPadding = nsMargin(0,0,0,0); - } - - if (childReflowState.mComputedWidth != NS_INTRINSICSIZE) + + // subtract out the border and padding + if (childReflowState.mComputedWidth != NS_INTRINSICSIZE) { childReflowState.mComputedWidth -= childReflowState.mComputedBorderPadding.left + childReflowState.mComputedBorderPadding.right; + childReflowState.mComputedWidth -= margin.left + margin.right; + if (childReflowState.mComputedWidth < 0) + childReflowState.mComputedWidth = 0; + } - if (childReflowState.mComputedHeight != NS_INTRINSICSIZE) + if (childReflowState.mComputedHeight != NS_INTRINSICSIZE) { childReflowState.mComputedHeight -= childReflowState.mComputedBorderPadding.top + childReflowState.mComputedBorderPadding.bottom; - */ + childReflowState.mComputedWidth -= margin.top + margin.bottom; + if (childReflowState.mComputedHeight < 0) + childReflowState.mComputedHeight = 0; + } mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + NS_ASSERTION(aDesiredSize.width >= 0 && aDesiredSize.height >= 0,"Error child's size is less than 0!"); + // if the frame size change then mark the flag - if (oldSize.width != aDesiredSize.width || oldSize.height != aDesiredSize.height) { + if (currentSize.width != aDesiredSize.width || currentSize.height != aDesiredSize.height) { aFrame->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height); aResized = PR_TRUE; } @@ -1271,31 +1314,25 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, * cause any of the scrollbars to need to be reflowed. */ void -nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext, +nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, nsIFrame*& aIncrementalChild) { - - aVscrollbarNeedsReflow = PR_FALSE; - aHscrollbarNeedsReflow = PR_FALSE; - - nsSize scrollAreaSize; - - if (!aScrollAreaNeedsReflow) { - // if we don't need to reflow the content area then just use its old size. - GetFrameSize(mScrollAreaFrame, scrollAreaSize); - } else { + nsSize scrollAreaSize; // get the current scrollarea size nsSize oldScrollAreaSize; GetFrameSize(mScrollAreaFrame, oldScrollAreaSize); + /* + // add our padding + oldScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + oldScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + */ + // get the width of the vertical scrollbar and the height of the horizontal scrollbar nsSize sbSize; GetScrollbarDimensions(aPresContext, sbSize); @@ -1307,6 +1344,9 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext CalculateScrollAreaSize(aPresContext, aReflowState, sbSize, scrollAreaSize); + // if the frame is not changing size and its not dirty then do nothing + //if (oldScrollAreaSize == scrollAreaSize && !IsDirty(mScrollAreaFrame)) + // return; // -------- flow the scroll area ----------- nsSize scrollAreaReflowSize(scrollAreaSize.width, scrollAreaSize.height); @@ -1318,6 +1358,12 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext resized, aIncrementalChild); + // ------- set up max size ------- + if (nsnull != aDesiredSize.maxElementSize) { + *aDesiredSize.maxElementSize = *scrollAreaDesiredSize.maxElementSize; + mMaxElementSize = *aDesiredSize.maxElementSize; + } + // make sure we take into account any children outside our bounds CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); @@ -1344,6 +1390,7 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext } } else { // if we are not shrink wrapping + PRBool mustReflow = PR_FALSE; // if we have 'auto' scrollbars if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL @@ -1370,7 +1417,6 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext // out we needed it AddVerticalScrollbar(sbSize, scrollAreaSize); mustReflow = PR_TRUE; - aVscrollbarNeedsReflow = PR_TRUE; } } @@ -1388,7 +1434,6 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); - //scrollAreaSize.height = scrollAreaDesiredSize.height; } } } @@ -1440,18 +1485,13 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext break; } - - // if the scroll area changed size - if (oldScrollAreaSize != scrollAreaSize) - { - // if the scroll area changed height then signal for reflow of the vertical scrollbar - if (oldScrollAreaSize.height != scrollAreaSize.height) - aVscrollbarNeedsReflow = PR_TRUE; - - // if the scroll area changed width then signal for reflow of the horizontal scrollbar - if (oldScrollAreaSize.width != scrollAreaSize.width) - aHscrollbarNeedsReflow = PR_TRUE; - } + /* + // the old scroll area includes our margin. If our margin changed it will cause the + // scrollbars to be recalculated as well. + nsSize marginedScrollAreaSize = scrollAreaSize; + marginedScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + marginedScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + */ nsSize size; GetScrolledContentSize(aPresContext, size); @@ -1467,37 +1507,29 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext nscoord fontHeight = 1; fm->GetHeight(fontHeight); - //nscoord curX = GetIntegerAttribute(mHScrollbarFrame, nsXULAtoms::curpos, 0); - //nscoord curY = GetIntegerAttribute(mVScrollbarFrame, nsXULAtoms::curpos, 0); nscoord maxX = size.width - scrollAreaSize.width; nscoord maxY = size.height - scrollAreaSize.height; - //if (curX > maxX) - // curX = maxX; - - //if (curY > maxY) - // curY = maxY; - - //SetAttribute(mVScrollbarFrame, nsXULAtoms::curpos, curY); - //SetAttribute(mHScrollbarFrame, nsXULAtoms::curpos, curX); - SetAttribute(mVScrollbarFrame, nsXULAtoms::maxpos, maxY); - SetAttribute(mHScrollbarFrame, nsXULAtoms::maxpos, maxX); - SetAttribute(mVScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.height - fontHeight)); - SetAttribute(mHScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.width - 10*mOnePixel)); - - SetAttribute(mVScrollbarFrame, nsXULAtoms::increment, fontHeight); nsIScrollableView* scrollable = GetScrollableView(aPresContext); scrollable->SetLineHeight(fontHeight); - SetAttribute(mHScrollbarFrame, nsXULAtoms::increment, 10*mOnePixel); + // set the scrollbars properties. Mark the scrollbars for reflow if there values change. + if (mHasVerticalScrollbar) { + SetAttribute(mVScrollbarFrame, nsXULAtoms::maxpos, maxY); + SetAttribute(mVScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.height - fontHeight)); + SetAttribute(mVScrollbarFrame, nsXULAtoms::increment, fontHeight, PR_FALSE); + } + if (mHasHorizontalScrollbar) { + SetAttribute(mHScrollbarFrame, nsXULAtoms::maxpos, maxX, PR_FALSE); + SetAttribute(mHScrollbarFrame, nsXULAtoms::pageincrement, nscoord(float(scrollAreaSize.width)*0.8)); + SetAttribute(mHScrollbarFrame, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); + } // size the scroll area // even if it is different from the old size. This is because ReflowFrame set the child's // frame so we have to make sure our final size is scrollAreaSize SetFrameSize(aPresContext, mScrollAreaFrame, scrollAreaSize); - - } } @@ -1513,22 +1545,26 @@ nsGfxScrollFrameInner::LayoutChildren(nsIPresContext* aPresContext, nsSize scrollAreaSize; GetFrameSize(mScrollAreaFrame, scrollAreaSize); + // add the padding to it. + scrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + scrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + nsSize sbSize; GetScrollbarDimensions(aPresContext, sbSize); - // only move by the border not the padding. The padding will end up on our child instead - const nsMargin& border = aReflowState.mComputedBorderPadding; + const nsMargin& borderPadding = aReflowState.mComputedBorderPadding; + nsMargin border = borderPadding - aReflowState.mComputedPadding; // Place scroll area nsIView* view; - mScrollAreaFrame->MoveTo(aPresContext, border.left, border.top); + mScrollAreaFrame->MoveTo(aPresContext, borderPadding.left, borderPadding.top); mScrollAreaFrame->GetView(aPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mScrollAreaFrame, view, nsnull); } - // place vertical scrollbar + // place vertical scrollbar move by the border because the scrollbars are outside our padding mVScrollbarFrame->MoveTo(aPresContext, border.left + scrollAreaSize.width, border.top); mVScrollbarFrame->GetView(aPresContext, &view); if (view) { @@ -1579,16 +1615,6 @@ nsGfxScrollFrameInner::LayoutChildren(nsIPresContext* aPresContext, aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; - - // ------- set up max size ------- - if (nsnull != aDesiredSize.maxElementSize) { - nscoord maxWidth = aDesiredSize.maxElementSize->width; - maxWidth += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right + sbSize.width; - nscoord maxHeight = aDesiredSize.maxElementSize->height; - maxHeight += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - aDesiredSize.maxElementSize->width = maxWidth; - aDesiredSize.maxElementSize->height = maxHeight; - } } void @@ -1607,13 +1633,15 @@ nsGfxScrollFrameInner::~nsGfxScrollFrameInner() } } -void -nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize) +/** + * Returns whether it actually needed to change the attribute + */ +PRBool +nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow) { // convert to pixels aSize /= mOnePixel; - // only set the attribute if it changed. PRInt32 current = GetIntegerAttribute(aFrame, aAtom, -1); @@ -1624,8 +1652,11 @@ nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aS char ch[100]; sprintf(ch,"%d", aSize); nsString newValue(ch); - content->SetAttribute(kNameSpaceID_None, aAtom, newValue, PR_TRUE); + content->SetAttribute(kNameSpaceID_None, aAtom, newValue, aReflow); + return PR_TRUE; } + + return PR_FALSE; } PRInt32 @@ -1646,6 +1677,13 @@ nsGfxScrollFrameInner::GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRIn return defaultValue; } +NS_IMETHODIMP +nsGfxScrollFrame::InvalidateCache(nsIFrame* aChild) +{ + // we don't cache any layout information. So do nothing. + return NS_OK; +} + NS_IMETHODIMP nsGfxScrollFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) @@ -1748,46 +1786,27 @@ nsBoxFrame::GetRedefinedMinPrefMax(nsIFrame* aFrame, nsBoxInfo& aSize) } */ + NS_IMETHODIMP -nsGfxScrollFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) +nsGfxScrollFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) { - incrementalChild = nsnull; - nsresult rv = NS_OK; - - // Dirty any children that need it. - nsIFrame* frame; - aReflowState.reflowCommand->GetNext(frame); - - nscoord count = 0; - nsIFrame* childFrame = mFrames.FirstChild(); - while (nsnull != childFrame) - { - if (childFrame == frame) { - if (frame == mInner->mVScrollbarFrame) - mInner->mVscrollbarNeedsReflow = PR_TRUE; - else if (frame == mInner->mHScrollbarFrame) - mInner->mHscrollbarNeedsReflow = PR_TRUE; - else if (frame == mInner->mScrollAreaFrame) - mInner->mScrollAreaNeedsReflow = PR_TRUE; - - nsCOMPtr ibox ( do_QueryInterface(childFrame, &rv) ); - NS_ASSERTION(NS_SUCCEEDED(rv),"We have a child that is not a box!!!!"); - if (NS_FAILED(rv)) - return rv; - - if (ibox) ibox->Dirty(aPresContext, aReflowState, incrementalChild); - break; + // if the frame is a vertical or horizontal scrollbar and we are about + // to reflow the scrollbars then don't propagate up + if (aChild == mInner->mHScrollbarFrame || aChild == mInner->mVScrollbarFrame) { + + // First pass means we will be checking to see if children should be reflowed + // if (mInner->mFirstPass) + // return NS_OK; } - rv = childFrame->GetNextSibling(&childFrame); - NS_ASSERTION(rv == NS_OK,"failed to get next child"); - if (NS_FAILED(rv)) - return rv; + // if we aren't dirty dirty us + if (!(mState & NS_FRAME_IS_DIRTY)) { + mState |= NS_FRAME_IS_DIRTY; + // if out parent is a box ask it to post a reflow for us and mark us as dirty + return mParent->ReflowDirtyChild(aPresShell,this); + } - count++; - } - - return NS_OK; + return NS_OK; } nsresult diff --git a/mozilla/layout/generic/nsGfxScrollFrame.h b/mozilla/layout/generic/nsGfxScrollFrame.h index 94793cd408b..b512e066532 100644 --- a/mozilla/layout/generic/nsGfxScrollFrame.h +++ b/mozilla/layout/generic/nsGfxScrollFrame.h @@ -103,16 +103,18 @@ public: PRInt32& aContentOffsetEnd, PRBool& aBeginFrameContent); + NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); + // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); // nsIBox methods NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& aIncrementalChild); NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } + NS_IMETHOD InvalidateCache(nsIFrame* aChild); // nsIScrollableFrame NS_IMETHOD SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScrolledFrame); diff --git a/mozilla/layout/generic/nsLeafFrame.cpp b/mozilla/layout/generic/nsLeafFrame.cpp index 649a76e684d..34f3966eb6d 100644 --- a/mozilla/layout/generic/nsLeafFrame.cpp +++ b/mozilla/layout/generic/nsLeafFrame.cpp @@ -113,6 +113,7 @@ nsLeafFrame::ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, nsISupports* aSubContent) { + /* // Generate a reflow command with this frame as the target frame nsIReflowCommand* cmd; nsresult rv; @@ -128,6 +129,11 @@ nsLeafFrame::ContentChanged(nsIPresContext* aPresContext, } return rv; + */ + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + return mParent->ReflowDirtyChild(shell, this); } #ifdef DEBUG diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp index a4c46513905..ed1f1b29a8b 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.cpp @@ -47,6 +47,7 @@ #include "nsIDocumentObserver.h" #include "nsIDocument.h" #include "nsIScrollPositionListener.h" +//#include "nsBoxFrame.h" #include "nsIElementFactory.h" static NS_DEFINE_IID(kWidgetCID, NS_CHILD_CID); @@ -132,7 +133,7 @@ public: NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument) { mDocument = nsnull; return NS_OK; } - void SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize); + PRBool SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow=PR_TRUE); PRInt32 GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRInt32 defaultValue); nsresult CalculateChildTotalSize(nsIFrame* aKidFrame, @@ -153,21 +154,10 @@ public: void SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisible); - void DetermineReflowNeed(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, - nsIFrame*& aIncrementalChild); void ReflowScrollbars( nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollBarResized, nsIFrame*& aIncrementalChild); void ReflowScrollbar( nsIPresContext* aPresContext, @@ -192,9 +182,6 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, nsIFrame*& aIncrementalChild); void LayoutChildren(nsIPresContext* aPresContext, @@ -209,6 +196,25 @@ public: void AddVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); void RemoveHorizontalScrollbar(const nsSize& aSbSize, nsSize& aScrollAreaSize); void RemoveVerticalScrollbar (const nsSize& aSbSize, nsSize& aScrollAreaSize); + + /* + PRBool IsDirty(nsIFrame* aFrame) { + nsFrameState frameState; + aFrame->GetFrameState(&frameState); + if (frameState & NS_FRAME_IS_DIRTY) + return PR_TRUE; + else + return PR_FALSE; + } + + void MarkDirty(nsIFrame* aFrame) { + nsFrameState frameState; + aFrame->GetFrameState(&frameState); + frameState |= NS_FRAME_IS_DIRTY; + aFrame->SetFrameState(frameState); + } + */ + nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext); void GetScrolledContentSize(nsIPresContext* aPresContext, nsSize& aSize); @@ -219,15 +225,16 @@ public: nsIFrame* mHScrollbarFrame; nsIFrame* mVScrollbarFrame; nsIFrame* mScrollAreaFrame; - PRBool mHasVerticalScrollbar; - PRBool mHasHorizontalScrollbar; - PRBool mHscrollbarNeedsReflow; - PRBool mVscrollbarNeedsReflow; - PRBool mScrollAreaNeedsReflow; nscoord mOnePixel; nsCOMPtr mDocument; nsGfxScrollFrame* mOuter; nsIScrollableView* mScrollableView; + nsSize mMaxElementSize; + + PRBool mHasVerticalScrollbar; + PRBool mHasHorizontalScrollbar; + PRBool mFirstPass; + PRBool mIsRoot; }; NS_IMPL_ISUPPORTS2(nsGfxScrollFrameInner, nsIDocumentObserver, nsIScrollPositionListener) @@ -253,6 +260,7 @@ nsGfxScrollFrame::nsGfxScrollFrame(nsIDocument* aDocument) mInner->AddRef(); mInner->mDocument = aDocument; mPresContext = nsnull; + mInner->mIsRoot = PR_FALSE; } nsGfxScrollFrame::~nsGfxScrollFrame() @@ -447,45 +455,110 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, aReflowState.availableWidth, aReflowState.availableHeight)); - // scroll frames can't have padding. So lets remove their padding from the reflow state - // and move it to their computed size. - nsMargin padding = aReflowState.mComputedPadding; + // if we have any padding then ignore it. It is inherited down to our scrolled frame + if (aReflowState.mComputedPadding.left != 0 || + aReflowState.mComputedPadding.right != 0 || + aReflowState.mComputedPadding.top != 0 || + aReflowState.mComputedPadding.bottom != 0) + { + nsHTMLReflowState newState(aReflowState); - if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedWidth) += padding.left + padding.right; - - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - ((nscoord&)aReflowState.mComputedHeight) += padding.top + padding.bottom; + // get the padding to remove + nscoord pwidth = (newState.mComputedPadding.left + newState.mComputedPadding.right); + nscoord pheight = (newState.mComputedPadding.top + newState.mComputedPadding.bottom); + + // adjust our computed size to add in the padding we are removing. Make sure + // the computed size doesn't go negative or anything. + if (newState.mComputedWidth != NS_INTRINSICSIZE) + newState.mComputedWidth += pwidth; + + if (newState.mComputedHeight != NS_INTRINSICSIZE) + newState.mComputedHeight += pheight; + + // fix up the borderpadding + ((nsMargin&)newState.mComputedBorderPadding) -= newState.mComputedPadding; + + // remove the padding + ((nsMargin&)newState.mComputedPadding) = nsMargin(0,0,0,0); + + // reflow us again with the correct values. + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + + mInner->mFirstPass = PR_TRUE; - ((nsMargin&)aReflowState.mComputedPadding) = nsMargin(0,0,0,0); - ((nsMargin&)aReflowState.mComputedBorderPadding) -= padding; - - // assume we need to reflow nothing - PRBool hscrollbarNeedsReflow = mInner->mHscrollbarNeedsReflow; - PRBool vscrollbarNeedsReflow = mInner->mVscrollbarNeedsReflow; - PRBool scrollAreaNeedsReflow = mInner->mScrollAreaNeedsReflow; - + // Handle Incremental Reflow nsIFrame* incrementalChild = nsnull; - // see what things need reflow - mInner->DetermineReflowNeed(aPresContext, - aDesiredSize, - aReflowState, - aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, - incrementalChild); + if ( aReflowState.reason == eReflowReason_Initial) { + // on the initial reflow see if we are the root box. + // the root box. + mInner->mIsRoot = PR_TRUE; + + // see if we are the root box + nsIFrame* parent = mParent; + while (parent) { + nsIBox* ibox = nsnull; + if (NS_SUCCEEDED(parent->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox) { + mInner->mIsRoot = PR_FALSE; + break; + } + + parent->GetParent(&parent); + } + } else if ( aReflowState.reason == eReflowReason_Incremental ) { + + nsIReflowCommand::ReflowType reflowType; + aReflowState.reflowCommand->GetType(reflowType); + + // See if it's targeted at us + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); + + if (this == targetFrame) { + // if we are the target see what the type was + // and generate a normal non incremental reflow. + switch (reflowType) { + + case nsIReflowCommand::StyleChanged: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_StyleChange; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + // if its a dirty type then reflow us with a dirty reflow + case nsIReflowCommand::ReflowDirty: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_Dirty; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + default: + NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); + } + } + + if (mInner->mIsRoot) + nsIBox::HandleRootBoxReflow(aPresContext, this, aReflowState); + + // then get the child we need to flow incrementally + aReflowState.reflowCommand->GetNext(incrementalChild); + + } + + + // next reflow the scrollbars so we will at least know their size. If they are bigger or smaller than // we thought we will have to reflow the scroll area as well. mInner->ReflowScrollbars( aPresContext, aReflowState, aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, incrementalChild); // then reflow the scroll area. If it gets bigger it could signal the scrollbars need @@ -494,18 +567,14 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize, aReflowState, aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, incrementalChild); + mInner->mFirstPass = PR_FALSE; + // reflow the scrollbars again but only the ones that need it. mInner->ReflowScrollbars( aPresContext, aReflowState, aStatus, - hscrollbarNeedsReflow, - vscrollbarNeedsReflow, - scrollAreaNeedsReflow, incrementalChild); // layout all the children. @@ -513,15 +582,6 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, aDesiredSize, aReflowState); - // redraw anything that needs it. - if ( aReflowState.reason == eReflowReason_Incremental ) - if (hscrollbarNeedsReflow && vscrollbarNeedsReflow && scrollAreaNeedsReflow) - Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); - - - mInner->mHscrollbarNeedsReflow = PR_FALSE; - mInner->mVscrollbarNeedsReflow = PR_FALSE; - mInner->mScrollAreaNeedsReflow = PR_FALSE; /* if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) @@ -713,9 +773,9 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsGfxScrollFrame* aOuter):mHScrollb { mOuter = aOuter; mRefCnt = 0; - mHscrollbarNeedsReflow = PR_FALSE; - mVscrollbarNeedsReflow = PR_FALSE; - mScrollAreaNeedsReflow = PR_FALSE; + mMaxElementSize.width = 0; + mMaxElementSize.height = 0; + mFirstPass = PR_FALSE; } NS_IMETHODIMP @@ -897,6 +957,19 @@ nsGfxScrollFrameInner::CalculateScrollAreaSize(nsIPresContext* aPresCon aScrollAreaSize.width = aReflowState.mComputedWidth; aScrollAreaSize.height = aReflowState.mComputedHeight; + if (aScrollAreaSize.width != NS_INTRINSICSIZE) { + aScrollAreaSize.width -= aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + if (aScrollAreaSize.width < 0) + aScrollAreaSize.width = 0; + } + + if (aScrollAreaSize.height != NS_INTRINSICSIZE) { + aScrollAreaSize.height -= aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + if (aScrollAreaSize.height < 0) + aScrollAreaSize.height = 0; + + } + // get the current state PRBool vert = mHasVerticalScrollbar; PRBool horiz = mHasHorizontalScrollbar; @@ -976,61 +1049,6 @@ nsGfxScrollFrameInner::SetScrollbarVisibility(nsIFrame* aScrollbar, PRBool aVisi child->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, newStyle, PR_TRUE); } -/** - * Determine which of our children need reflow. It also return the child that is being - * incrementally reflowed if there is one. - */ -void -nsGfxScrollFrameInner::DetermineReflowNeed(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, - nsIFrame*& aIncrementalChild) -{ - nsIFrame* targetFrame; - - // Special handling for incremental reflow - if (eReflowReason_Incremental == aReflowState.reason) { - // See whether we're the target of the reflow command - aReflowState.reflowCommand->GetTarget(targetFrame); - if (mOuter == targetFrame) { - nsIReflowCommand::ReflowType type; - - // The only type of reflow command we expect to get is a style - // change reflow command - aReflowState.reflowCommand->GetType(type); - NS_ASSERTION(nsIReflowCommand::StyleChanged == type, "unexpected reflow type"); - - // Make a copy of the reflow state (with a different reflow reason) and - // then recurse - nsHTMLReflowState reflowState(aReflowState); - reflowState.reason = eReflowReason_StyleChange; - reflowState.reflowCommand = nsnull; - mOuter->Reflow(aPresContext, aDesiredSize, reflowState, aStatus); - } - - // Get the next frame in the reflow chain this will be one of the scrollbars. - aReflowState.reflowCommand->GetNext(aIncrementalChild); - - // see which scrollbar it is and signal that is needs reflow - if (aIncrementalChild == mHScrollbarFrame) - aHscrollbarNeedsReflow = PR_TRUE; - else if (aIncrementalChild == mVScrollbarFrame) - aVscrollbarNeedsReflow = PR_TRUE; - else if (aIncrementalChild == mScrollAreaFrame) - aScrollAreaNeedsReflow = PR_TRUE; - - } else { - // if not incremental reflow then reflow everyone one. - aHscrollbarNeedsReflow = PR_TRUE; - aVscrollbarNeedsReflow = PR_TRUE; - aScrollAreaNeedsReflow = PR_TRUE; - } -} - /** * Reflows the visible scrollbars to fit in our content area. If the scrollbars change size @@ -1041,40 +1059,30 @@ void nsGfxScrollFrameInner::ReflowScrollbars( nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollBarResized, nsIFrame*& aIncrementalChild) { // if we have gfx scrollbars reflow them. If they changed size then signal that // we need to reflow the content area. This could happen if there is a style rule set // up on them that changed there size. Like an image on the thumb gets big. - if (aHscrollbarNeedsReflow) - { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - aScrollBarResized, - mHScrollbarFrame, - aIncrementalChild); - - if (aScrollBarResized) - aVscrollbarNeedsReflow = PR_TRUE; - - } - if (aVscrollbarNeedsReflow) - { - ReflowScrollbar(aPresContext, - aReflowState, - aStatus, - aScrollBarResized, - mVScrollbarFrame, - aIncrementalChild); - if (aScrollBarResized) - aHscrollbarNeedsReflow = PR_TRUE; + PRBool resized = PR_TRUE; + if (mHasHorizontalScrollbar || aReflowState.reason == eReflowReason_Initial) { + ReflowScrollbar(aPresContext, + aReflowState, + aStatus, + resized, + mHScrollbarFrame, + aIncrementalChild); + } - } + if (mHasVerticalScrollbar || aReflowState.reason == eReflowReason_Initial) { + ReflowScrollbar(aPresContext, + aReflowState, + aStatus, + resized, + mVScrollbarFrame, + aIncrementalChild); + } SetScrollbarVisibility(mHScrollbarFrame, mHasHorizontalScrollbar); SetScrollbarVisibility(mVScrollbarFrame, mHasVerticalScrollbar); @@ -1090,7 +1098,11 @@ nsGfxScrollFrameInner::ReflowScrollbar( nsIPresContext* aPresContext { nsSize scrollArea; GetFrameSize(mScrollAreaFrame, scrollArea); - + + // add the padding to it. + scrollArea.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + scrollArea.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + // is it the horizontal scrollbar? if (aScrollbarFrame == mHScrollbarFrame) { @@ -1120,9 +1132,8 @@ nsGfxScrollFrameInner::ReflowScrollbar( nsIPresContext* aPresContext nsSize(NS_INTRINSICSIZE, height), aScrollbarResized, aIncrementalChild); - - } + } } void @@ -1189,9 +1200,57 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, PRBool& aResized, nsIFrame*& aIncrementalChild) { - // get the current size - nsSize oldSize; - GetFrameSize(aFrame, oldSize); + PRBool needsReflow = PR_FALSE; + nsReflowReason reason = aReflowState.reason; + + switch(reason) + { + case eReflowReason_Incremental: + if (aIncrementalChild == aFrame) { + needsReflow = PR_TRUE; + aIncrementalChild = nsnull; + } else { + reason = eReflowReason_Resize; + needsReflow = PR_FALSE; + } + break; + + // if its dirty then see if the child we want to reflow is dirty. If it is then + // mark it as needing to be reflowed. + case eReflowReason_Dirty: + // get the frame state to see if it needs reflow + nsFrameState state; + aFrame->GetFrameState(&state); + needsReflow = (state & NS_FRAME_IS_DIRTY) || (state & NS_FRAME_HAS_DIRTY_CHILDREN); + break; + + // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different + // from the new size would we actually do a reflow + case eReflowReason_Resize: + needsReflow = PR_FALSE; + break; + + default: + needsReflow = PR_TRUE; + + } + + nsSize currentSize; + GetFrameSize(aFrame, currentSize); + + // if we do not need reflow then + // see if the size it what we already want. If it is then we are done. + if (!needsReflow) { + // get the current size + + // if the size is not changing and the frame is not dirty then there + // is nothing to do. + if (currentSize.width == aComputed.width && currentSize.height == aComputed.height) { + aDesiredSize.width = currentSize.width; + aDesiredSize.height = currentSize.height; + return NS_OK; + } + } aDesiredSize.width = 0; aDesiredSize.height = 0; @@ -1199,14 +1258,7 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, nsHTMLReflowState childReflowState(aPresContext, aReflowState, aFrame, aAvailable); - // handle incremental reflow - if (aReflowState.reason == eReflowReason_Incremental) { - if (aFrame == aIncrementalChild) - aIncrementalChild = nsnull; - else - childReflowState.reason = eReflowReason_Resize; - } - + childReflowState.reason = reason; childReflowState.mComputedWidth = aComputed.width; childReflowState.mComputedHeight = aComputed.height; @@ -1219,42 +1271,33 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, if (NS_FAILED(rv)) return rv; - // this basically sucks. Sometime it fails to get the border and padding - // because one or the other is not set. So we are forced to go out and get - // the border and padding separately and add them together. - /* - nsMargin border; - if (!spacing->GetBorderPadding(border)) { - if (!spacing->GetBorder(border)) - border.SizeTo(0,0,0,0); - - - border += padding; - } - */ - + // get the margin nsMargin margin(0,0,0,0); spacing->GetMargin(margin); - - /* - if (aFrame == mScrollAreaFrame) { - childReflowState.mComputedBorderPadding -= childReflowState.mComputedPadding; - childReflowState.mComputedPadding = nsMargin(0,0,0,0); - } - - if (childReflowState.mComputedWidth != NS_INTRINSICSIZE) + + // subtract out the border and padding + if (childReflowState.mComputedWidth != NS_INTRINSICSIZE) { childReflowState.mComputedWidth -= childReflowState.mComputedBorderPadding.left + childReflowState.mComputedBorderPadding.right; + childReflowState.mComputedWidth -= margin.left + margin.right; + if (childReflowState.mComputedWidth < 0) + childReflowState.mComputedWidth = 0; + } - if (childReflowState.mComputedHeight != NS_INTRINSICSIZE) + if (childReflowState.mComputedHeight != NS_INTRINSICSIZE) { childReflowState.mComputedHeight -= childReflowState.mComputedBorderPadding.top + childReflowState.mComputedBorderPadding.bottom; - */ + childReflowState.mComputedWidth -= margin.top + margin.bottom; + if (childReflowState.mComputedHeight < 0) + childReflowState.mComputedHeight = 0; + } mOuter->ReflowChild(aFrame, aPresContext, aDesiredSize, childReflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + NS_ASSERTION(aDesiredSize.width >= 0 && aDesiredSize.height >= 0,"Error child's size is less than 0!"); + // if the frame size change then mark the flag - if (oldSize.width != aDesiredSize.width || oldSize.height != aDesiredSize.height) { + if (currentSize.width != aDesiredSize.width || currentSize.height != aDesiredSize.height) { aFrame->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height); aResized = PR_TRUE; } @@ -1271,31 +1314,25 @@ nsGfxScrollFrameInner::ReflowFrame( nsIPresContext* aPresContext, * cause any of the scrollbars to need to be reflowed. */ void -nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext, +nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - PRBool& aHscrollbarNeedsReflow, - PRBool& aVscrollbarNeedsReflow, - PRBool& aScrollAreaNeedsReflow, nsIFrame*& aIncrementalChild) { - - aVscrollbarNeedsReflow = PR_FALSE; - aHscrollbarNeedsReflow = PR_FALSE; - - nsSize scrollAreaSize; - - if (!aScrollAreaNeedsReflow) { - // if we don't need to reflow the content area then just use its old size. - GetFrameSize(mScrollAreaFrame, scrollAreaSize); - } else { + nsSize scrollAreaSize; // get the current scrollarea size nsSize oldScrollAreaSize; GetFrameSize(mScrollAreaFrame, oldScrollAreaSize); + /* + // add our padding + oldScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + oldScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + */ + // get the width of the vertical scrollbar and the height of the horizontal scrollbar nsSize sbSize; GetScrollbarDimensions(aPresContext, sbSize); @@ -1307,6 +1344,9 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext CalculateScrollAreaSize(aPresContext, aReflowState, sbSize, scrollAreaSize); + // if the frame is not changing size and its not dirty then do nothing + //if (oldScrollAreaSize == scrollAreaSize && !IsDirty(mScrollAreaFrame)) + // return; // -------- flow the scroll area ----------- nsSize scrollAreaReflowSize(scrollAreaSize.width, scrollAreaSize.height); @@ -1318,6 +1358,12 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext resized, aIncrementalChild); + // ------- set up max size ------- + if (nsnull != aDesiredSize.maxElementSize) { + *aDesiredSize.maxElementSize = *scrollAreaDesiredSize.maxElementSize; + mMaxElementSize = *aDesiredSize.maxElementSize; + } + // make sure we take into account any children outside our bounds CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); @@ -1344,6 +1390,7 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext } } else { // if we are not shrink wrapping + PRBool mustReflow = PR_FALSE; // if we have 'auto' scrollbars if (aReflowState.mStyleDisplay->mOverflow != NS_STYLE_OVERFLOW_SCROLL @@ -1370,7 +1417,6 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext // out we needed it AddVerticalScrollbar(sbSize, scrollAreaSize); mustReflow = PR_TRUE; - aVscrollbarNeedsReflow = PR_TRUE; } } @@ -1388,7 +1434,6 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext CalculateChildTotalSize(mScrollAreaFrame, scrollAreaDesiredSize); - //scrollAreaSize.height = scrollAreaDesiredSize.height; } } } @@ -1440,18 +1485,13 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext break; } - - // if the scroll area changed size - if (oldScrollAreaSize != scrollAreaSize) - { - // if the scroll area changed height then signal for reflow of the vertical scrollbar - if (oldScrollAreaSize.height != scrollAreaSize.height) - aVscrollbarNeedsReflow = PR_TRUE; - - // if the scroll area changed width then signal for reflow of the horizontal scrollbar - if (oldScrollAreaSize.width != scrollAreaSize.width) - aHscrollbarNeedsReflow = PR_TRUE; - } + /* + // the old scroll area includes our margin. If our margin changed it will cause the + // scrollbars to be recalculated as well. + nsSize marginedScrollAreaSize = scrollAreaSize; + marginedScrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + marginedScrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + */ nsSize size; GetScrolledContentSize(aPresContext, size); @@ -1467,37 +1507,29 @@ nsGfxScrollFrameInner::ReflowScrollArea( nsIPresContext* aPresContext nscoord fontHeight = 1; fm->GetHeight(fontHeight); - //nscoord curX = GetIntegerAttribute(mHScrollbarFrame, nsXULAtoms::curpos, 0); - //nscoord curY = GetIntegerAttribute(mVScrollbarFrame, nsXULAtoms::curpos, 0); nscoord maxX = size.width - scrollAreaSize.width; nscoord maxY = size.height - scrollAreaSize.height; - //if (curX > maxX) - // curX = maxX; - - //if (curY > maxY) - // curY = maxY; - - //SetAttribute(mVScrollbarFrame, nsXULAtoms::curpos, curY); - //SetAttribute(mHScrollbarFrame, nsXULAtoms::curpos, curX); - SetAttribute(mVScrollbarFrame, nsXULAtoms::maxpos, maxY); - SetAttribute(mHScrollbarFrame, nsXULAtoms::maxpos, maxX); - SetAttribute(mVScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.height - fontHeight)); - SetAttribute(mHScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.width - 10*mOnePixel)); - - SetAttribute(mVScrollbarFrame, nsXULAtoms::increment, fontHeight); nsIScrollableView* scrollable = GetScrollableView(aPresContext); scrollable->SetLineHeight(fontHeight); - SetAttribute(mHScrollbarFrame, nsXULAtoms::increment, 10*mOnePixel); + // set the scrollbars properties. Mark the scrollbars for reflow if there values change. + if (mHasVerticalScrollbar) { + SetAttribute(mVScrollbarFrame, nsXULAtoms::maxpos, maxY); + SetAttribute(mVScrollbarFrame, nsXULAtoms::pageincrement, nscoord(scrollAreaSize.height - fontHeight)); + SetAttribute(mVScrollbarFrame, nsXULAtoms::increment, fontHeight, PR_FALSE); + } + if (mHasHorizontalScrollbar) { + SetAttribute(mHScrollbarFrame, nsXULAtoms::maxpos, maxX, PR_FALSE); + SetAttribute(mHScrollbarFrame, nsXULAtoms::pageincrement, nscoord(float(scrollAreaSize.width)*0.8)); + SetAttribute(mHScrollbarFrame, nsXULAtoms::increment, 10*mOnePixel, PR_FALSE); + } // size the scroll area // even if it is different from the old size. This is because ReflowFrame set the child's // frame so we have to make sure our final size is scrollAreaSize SetFrameSize(aPresContext, mScrollAreaFrame, scrollAreaSize); - - } } @@ -1513,22 +1545,26 @@ nsGfxScrollFrameInner::LayoutChildren(nsIPresContext* aPresContext, nsSize scrollAreaSize; GetFrameSize(mScrollAreaFrame, scrollAreaSize); + // add the padding to it. + scrollAreaSize.width += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + scrollAreaSize.height += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + nsSize sbSize; GetScrollbarDimensions(aPresContext, sbSize); - // only move by the border not the padding. The padding will end up on our child instead - const nsMargin& border = aReflowState.mComputedBorderPadding; + const nsMargin& borderPadding = aReflowState.mComputedBorderPadding; + nsMargin border = borderPadding - aReflowState.mComputedPadding; // Place scroll area nsIView* view; - mScrollAreaFrame->MoveTo(aPresContext, border.left, border.top); + mScrollAreaFrame->MoveTo(aPresContext, borderPadding.left, borderPadding.top); mScrollAreaFrame->GetView(aPresContext, &view); if (view) { nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, mScrollAreaFrame, view, nsnull); } - // place vertical scrollbar + // place vertical scrollbar move by the border because the scrollbars are outside our padding mVScrollbarFrame->MoveTo(aPresContext, border.left + scrollAreaSize.width, border.top); mVScrollbarFrame->GetView(aPresContext, &view); if (view) { @@ -1579,16 +1615,6 @@ nsGfxScrollFrameInner::LayoutChildren(nsIPresContext* aPresContext, aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; - - // ------- set up max size ------- - if (nsnull != aDesiredSize.maxElementSize) { - nscoord maxWidth = aDesiredSize.maxElementSize->width; - maxWidth += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right + sbSize.width; - nscoord maxHeight = aDesiredSize.maxElementSize->height; - maxHeight += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - aDesiredSize.maxElementSize->width = maxWidth; - aDesiredSize.maxElementSize->height = maxHeight; - } } void @@ -1607,13 +1633,15 @@ nsGfxScrollFrameInner::~nsGfxScrollFrameInner() } } -void -nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize) +/** + * Returns whether it actually needed to change the attribute + */ +PRBool +nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aSize, PRBool aReflow) { // convert to pixels aSize /= mOnePixel; - // only set the attribute if it changed. PRInt32 current = GetIntegerAttribute(aFrame, aAtom, -1); @@ -1624,8 +1652,11 @@ nsGfxScrollFrameInner::SetAttribute(nsIFrame* aFrame, nsIAtom* aAtom, nscoord aS char ch[100]; sprintf(ch,"%d", aSize); nsString newValue(ch); - content->SetAttribute(kNameSpaceID_None, aAtom, newValue, PR_TRUE); + content->SetAttribute(kNameSpaceID_None, aAtom, newValue, aReflow); + return PR_TRUE; } + + return PR_FALSE; } PRInt32 @@ -1646,6 +1677,13 @@ nsGfxScrollFrameInner::GetIntegerAttribute(nsIFrame* aFrame, nsIAtom* atom, PRIn return defaultValue; } +NS_IMETHODIMP +nsGfxScrollFrame::InvalidateCache(nsIFrame* aChild) +{ + // we don't cache any layout information. So do nothing. + return NS_OK; +} + NS_IMETHODIMP nsGfxScrollFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) @@ -1748,46 +1786,27 @@ nsBoxFrame::GetRedefinedMinPrefMax(nsIFrame* aFrame, nsBoxInfo& aSize) } */ + NS_IMETHODIMP -nsGfxScrollFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) +nsGfxScrollFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) { - incrementalChild = nsnull; - nsresult rv = NS_OK; - - // Dirty any children that need it. - nsIFrame* frame; - aReflowState.reflowCommand->GetNext(frame); - - nscoord count = 0; - nsIFrame* childFrame = mFrames.FirstChild(); - while (nsnull != childFrame) - { - if (childFrame == frame) { - if (frame == mInner->mVScrollbarFrame) - mInner->mVscrollbarNeedsReflow = PR_TRUE; - else if (frame == mInner->mHScrollbarFrame) - mInner->mHscrollbarNeedsReflow = PR_TRUE; - else if (frame == mInner->mScrollAreaFrame) - mInner->mScrollAreaNeedsReflow = PR_TRUE; - - nsCOMPtr ibox ( do_QueryInterface(childFrame, &rv) ); - NS_ASSERTION(NS_SUCCEEDED(rv),"We have a child that is not a box!!!!"); - if (NS_FAILED(rv)) - return rv; - - if (ibox) ibox->Dirty(aPresContext, aReflowState, incrementalChild); - break; + // if the frame is a vertical or horizontal scrollbar and we are about + // to reflow the scrollbars then don't propagate up + if (aChild == mInner->mHScrollbarFrame || aChild == mInner->mVScrollbarFrame) { + + // First pass means we will be checking to see if children should be reflowed + // if (mInner->mFirstPass) + // return NS_OK; } - rv = childFrame->GetNextSibling(&childFrame); - NS_ASSERTION(rv == NS_OK,"failed to get next child"); - if (NS_FAILED(rv)) - return rv; + // if we aren't dirty dirty us + if (!(mState & NS_FRAME_IS_DIRTY)) { + mState |= NS_FRAME_IS_DIRTY; + // if out parent is a box ask it to post a reflow for us and mark us as dirty + return mParent->ReflowDirtyChild(aPresShell,this); + } - count++; - } - - return NS_OK; + return NS_OK; } nsresult diff --git a/mozilla/layout/html/base/src/nsGfxScrollFrame.h b/mozilla/layout/html/base/src/nsGfxScrollFrame.h index 94793cd408b..b512e066532 100644 --- a/mozilla/layout/html/base/src/nsGfxScrollFrame.h +++ b/mozilla/layout/html/base/src/nsGfxScrollFrame.h @@ -103,16 +103,18 @@ public: PRInt32& aContentOffsetEnd, PRBool& aBeginFrameContent); + NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); + // nsIAnonymousContentCreator NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aAnonymousItems); // nsIBox methods NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& aIncrementalChild); NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } + NS_IMETHOD InvalidateCache(nsIFrame* aChild); // nsIScrollableFrame NS_IMETHOD SetScrolledFrame(nsIPresContext* aPresContext, nsIFrame *aScrolledFrame); diff --git a/mozilla/layout/html/base/src/nsLeafFrame.cpp b/mozilla/layout/html/base/src/nsLeafFrame.cpp index 649a76e684d..34f3966eb6d 100644 --- a/mozilla/layout/html/base/src/nsLeafFrame.cpp +++ b/mozilla/layout/html/base/src/nsLeafFrame.cpp @@ -113,6 +113,7 @@ nsLeafFrame::ContentChanged(nsIPresContext* aPresContext, nsIContent* aChild, nsISupports* aSubContent) { + /* // Generate a reflow command with this frame as the target frame nsIReflowCommand* cmd; nsresult rv; @@ -128,6 +129,11 @@ nsLeafFrame::ContentChanged(nsIPresContext* aPresContext, } return rv; + */ + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + return mParent->ReflowDirtyChild(shell, this); } #ifdef DEBUG diff --git a/mozilla/layout/html/base/src/nsScrollPortFrame.cpp b/mozilla/layout/html/base/src/nsScrollPortFrame.cpp index 86d7d97d774..870f4968671 100644 --- a/mozilla/layout/html/base/src/nsScrollPortFrame.cpp +++ b/mozilla/layout/html/base/src/nsScrollPortFrame.cpp @@ -78,7 +78,7 @@ NS_NewScrollPortFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) nsScrollPortFrame::nsScrollPortFrame() { - mIncremental = PR_FALSE; + //mIncremental = PR_FALSE; mNeedsRecalc = PR_TRUE; } @@ -328,41 +328,85 @@ nsScrollPortFrame::Reflow(nsIPresContext* aPresContext, aReflowState.availableWidth, aReflowState.availableHeight)); - nsIFrame* kidFrame = mFrames.FirstChild(); - nsIFrame* targetFrame; - nsIFrame* nextFrame; + // if we have any padding then ignore it. It is inherited down to our scrolled frame + if (aReflowState.mComputedPadding.left != 0 || + aReflowState.mComputedPadding.right != 0 || + aReflowState.mComputedPadding.top != 0 || + aReflowState.mComputedPadding.bottom != 0) + { + nsHTMLReflowState newState(aReflowState); - // Special handling for incremental reflow - if (eReflowReason_Incremental == aReflowState.reason) { - // See whether we're the target of the reflow command - aReflowState.reflowCommand->GetTarget(targetFrame); - if (this == targetFrame) { - nsIReflowCommand::ReflowType type; + // get the padding to remove + nscoord pwidth = (newState.mComputedPadding.left + newState.mComputedPadding.right); + nscoord pheight = (newState.mComputedPadding.top + newState.mComputedPadding.bottom); - // The only type of reflow command we expect to get is a style - // change reflow command - aReflowState.reflowCommand->GetType(type); - NS_ASSERTION(nsIReflowCommand::StyleChanged == type, "unexpected reflow type"); + // adjust our computed size to add in the padding we are removing. Make sure + // the computed size doesn't go negative or anything. + if (newState.mComputedWidth != NS_INTRINSICSIZE) + newState.mComputedWidth += pwidth; - // Make a copy of the reflow state (with a different reflow reason) and - // then recurse - nsHTMLReflowState reflowState(aReflowState); - reflowState.reason = eReflowReason_StyleChange; - reflowState.reflowCommand = nsnull; - return Reflow(aPresContext, aDesiredSize, reflowState, aStatus); - } + if (newState.mComputedHeight != NS_INTRINSICSIZE) + newState.mComputedHeight += pheight; - // Get the next frame in the reflow chain, and verify that it's our - // child frame - aReflowState.reflowCommand->GetNext(nextFrame); - NS_ASSERTION(nextFrame == kidFrame, "unexpected reflow command next-frame"); + // fix up the borderpadding + ((nsMargin&)newState.mComputedBorderPadding) -= newState.mComputedPadding; + + // remove the padding + ((nsMargin&)newState.mComputedPadding) = nsMargin(0,0,0,0); + + // reflow us again with the correct values. + return Reflow(aPresContext, aDesiredSize, newState, aStatus); } + // Handle Incremental Reflow + nsIFrame* incrementalChild = nsnull; + if ( aReflowState.reason == eReflowReason_Incremental ) { + nsIReflowCommand::ReflowType reflowType; + aReflowState.reflowCommand->GetType(reflowType); + + // See if it's targeted at us + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); + + if (this == targetFrame) { + // if we are the target see what the type was + // and generate a normal non incremental reflow. + switch (reflowType) { + + case nsIReflowCommand::StyleChanged: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_StyleChange; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + // if its a dirty type then reflow us with a dirty reflow + case nsIReflowCommand::ReflowDirty: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_Dirty; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + default: + NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); + } + + } + + // then get the child we need to flow incrementally + aReflowState.reflowCommand->GetNext(incrementalChild); + + } + nsIFrame* kidFrame = mFrames.FirstChild(); // Reflow the child and get its desired size. Let it be as high as it // wants const nsMargin& border = aReflowState.mComputedBorderPadding; + /* // we only worry about our border. Out scrolled frame worries about the padding. // so lets remove the padding and add it to our computed size. nsMargin padding = aReflowState.mComputedPadding; @@ -376,7 +420,8 @@ nsScrollPortFrame::Reflow(nsIPresContext* aPresContext, ((nsMargin&)aReflowState.mComputedPadding) = nsMargin(0,0,0,0); ((nsMargin&)aReflowState.mComputedBorderPadding) -= padding; - + */ + nscoord theHeight; nsIBox* box; nsresult result = kidFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&box); @@ -390,15 +435,20 @@ nsScrollPortFrame::Reflow(nsIPresContext* aPresContext, kidFrame, kidReflowSize); nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.maxElementSize); - if (mIncremental) { - kidReflowState.reason = eReflowReason_Incremental; - mIncremental = PR_FALSE; - } - kidReflowState.mComputedWidth = aReflowState.mComputedWidth; kidReflowState.mComputedHeight = theHeight; + + nscoord pwidth = (kidReflowState.mComputedBorderPadding.left + kidReflowState.mComputedBorderPadding.right); + nscoord pheight = (kidReflowState.mComputedBorderPadding.top + kidReflowState.mComputedBorderPadding.bottom); + + // child's size is our computed size minus its border and padding. + if (kidReflowState.mComputedWidth != NS_INTRINSICSIZE && kidReflowState.mComputedWidth >= pwidth) + kidReflowState.mComputedWidth -= pwidth; + if (kidReflowState.mComputedHeight != NS_INTRINSICSIZE && kidReflowState.mComputedHeight >= pheight) + kidReflowState.mComputedHeight -= pheight; + // reflow and place the child. ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState, border.left, border.top, NS_FRAME_NO_MOVE_VIEW, aStatus); @@ -436,14 +486,17 @@ nsScrollPortFrame::Reflow(nsIPresContext* aPresContext, if (nsnull != aDesiredSize.maxElementSize) { - nscoord maxWidth = aDesiredSize.maxElementSize->width; - maxWidth += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; - nscoord maxHeight = aDesiredSize.maxElementSize->height; - maxHeight += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; - aDesiredSize.maxElementSize->width = maxWidth; - aDesiredSize.maxElementSize->height = maxHeight; + // nscoord maxWidth = aDesiredSize.maxElementSize->width; + // maxWidth += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + // nscoord maxHeight = aDesiredSize.maxElementSize->height; + // maxHeight += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + // aDesiredSize.maxElementSize->width = maxWidth; + // aDesiredSize.maxElementSize->height = maxHeight; + *aDesiredSize.maxElementSize = *kidDesiredSize.maxElementSize; } + //mIncremental = PR_FALSE; + aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; @@ -516,6 +569,13 @@ nsScrollPortFrame::GetFrameName(nsString& aResult) const } #endif +NS_IMETHODIMP +nsScrollPortFrame::InvalidateCache(nsIFrame* aChild) +{ + mNeedsRecalc = PR_TRUE; + return NS_OK; +} + /** * Goes though each child asking for its size to determine our size. Returns our box size minus our border. * This method is defined in nsIBox interface. @@ -654,26 +714,13 @@ nsScrollPortFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) } NS_IMETHODIMP -nsScrollPortFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) +nsScrollPortFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) { - mIncremental = PR_FALSE; - incrementalChild = nsnull; + if (! (mState & NS_FRAME_IS_DIRTY)) { + mState |= NS_FRAME_IS_DIRTY; + return mParent->ReflowDirtyChild(aPresShell, aChild); + } - nsIFrame* frame; - aReflowState.reflowCommand->GetNext(frame); - - nsIFrame* childFrame = mFrames.FirstChild(); - - nsIBox* ibox; - if (NS_SUCCEEDED(childFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) - ibox->Dirty(aPresContext, aReflowState, incrementalChild); - else { - incrementalChild = frame; - // if we found a leaf that is not a box. Then mark it as being incremental. So if we are ever - // flowed incremental then we will flow our child incrementally. - mIncremental = PR_TRUE; - } - - return NS_OK; + return NS_OK; } diff --git a/mozilla/layout/html/base/src/nsScrollPortFrame.h b/mozilla/layout/html/base/src/nsScrollPortFrame.h index 352175b7f63..572a7a54599 100644 --- a/mozilla/layout/html/base/src/nsScrollPortFrame.h +++ b/mozilla/layout/html/base/src/nsScrollPortFrame.h @@ -82,6 +82,8 @@ public: const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); + NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); + /** * Get the "type" of the frame * @@ -95,10 +97,10 @@ public: // nsIBox methods NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& aIncrementalChild); NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } + NS_IMETHOD InvalidateCache(nsIFrame* aChild); protected: nsScrollPortFrame(); diff --git a/mozilla/layout/html/document/src/html.css b/mozilla/layout/html/document/src/html.css index 4298843244e..10b15a233f7 100644 --- a/mozilla/layout/html/document/src/html.css +++ b/mozilla/layout/html/document/src/html.css @@ -1386,6 +1386,12 @@ sourcetext { /* XXX should not be in HTML namespace */ border: 2px outset #c0c0c0; } +:-moz-select-scrolled-content { + background: inherit; + display: inherit; + padding: inherit; +} + :scrolled-content { background: inherit; padding: inherit; diff --git a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp index 3d0aefa398b..d3b7ccb09bc 100644 --- a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp @@ -51,8 +51,6 @@ static NS_DEFINE_IID(kIDOMHTMLLegendElementIID, NS_IDOMHTMLLEGENDELEMENT_IID); class nsLegendFrame; -//#define DO_NEWFIELDSET - class nsFieldSetFrame : public nsHTMLContainerFrame { public: @@ -124,116 +122,13 @@ nsFieldSetFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { -#ifdef DO_NEWFIELDSET - nsIFrame* newChildList = aChildList; - // Set the geometric and content parent for each of the child frames - // that will go into the area frame's child list. - // The legend frame does not go into the list - nsIFrame* lastNewFrame = nsnull; - for (nsIFrame* frame = aChildList; nsnull != frame;) { - nsIFrame* legendFrame = nsnull; - nsresult result = frame->QueryInterface(kLegendFrameCID, (void**)&legendFrame); - if (NS_SUCCEEDED(result) && legendFrame) { - if (mLegendFrame) { // we already have a legend, destroy it - frame->GetNextSibling(&frame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(frame); - } - else { - aChildList = frame; - } - legendFrame->Destroy(aPresContext); - } else { - /*nsIFrame* nextFrame; - frame->GetNextSibling(&nextFrame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(nextFrame); - } else { - newChildList = nextFrame; - } - mFrames.FirstChild()->SetNextSibling(frame); - */ - mLegendFrame = frame; - break; - //mLegendFrame->SetNextSibling(nsnull); - //frame = nextFrame; - } - } else { - lastNewFrame = frame; - frame->GetNextSibling(&frame); - } - } + + // get the content and legend frames. + mContentFrame = aChildList; + mContentFrame->GetNextSibling(&mLegendFrame); + // Queue up the frames for the content frame - return nsHTMLContainerFrame::SetInitialChildList(aPresContext, nsnull, newChildList); -#else - // cache our display type - const nsStyleDisplay* styleDisplay; - GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); - - PRUint32 flags = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay) ? NS_BLOCK_SHRINK_WRAP : 0; - - // add in the parent state (we need it to be inherited) - PRUint32 parentState; - GetFrameState( &parentState ); - flags |= parentState; - - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - NS_NewAreaFrame(shell, &mContentFrame, flags); - mFrames.SetFrames(mContentFrame); - - // Resolve style and initialize the frame - nsIStyleContext* styleContext; - aPresContext->ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::fieldsetContentPseudo, - mStyleContext, PR_FALSE, &styleContext); - mFrames.FirstChild()->Init(aPresContext, mContent, this, styleContext, nsnull); - mFrames.FirstChild()->SetNextSibling(nsnull); - NS_RELEASE(styleContext); - - nsIFrame* newChildList = aChildList; - - // Set the geometric and content parent for each of the child frames - // that will go into the area frame's child list. - // The legend frame does not go into the list - nsIFrame* lastNewFrame = nsnull; - for (nsIFrame* frame = aChildList; nsnull != frame;) { - nsIFrame* legendFrame = nsnull; - nsresult result = frame->QueryInterface(kLegendFrameCID, (void**)&legendFrame); - if (NS_SUCCEEDED(result) && legendFrame) { - if (mLegendFrame) { // we already have a legend, destroy it - frame->GetNextSibling(&frame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(frame); - } - else { - aChildList = frame; - } - legendFrame->Destroy(aPresContext); - } - else { - nsIFrame* nextFrame; - frame->GetNextSibling(&nextFrame); - if (lastNewFrame) { - lastNewFrame->SetNextSibling(nextFrame); - } else { - newChildList = nextFrame; - } - frame->SetParent(this); - mFrames.FirstChild()->SetNextSibling(frame); - mLegendFrame = frame; - mLegendFrame->SetNextSibling(nsnull); - frame = nextFrame; - } - } else { - frame->SetParent(mFrames.FirstChild()); - lastNewFrame = frame; - frame->GetNextSibling(&frame); - } - } - // Queue up the frames for the content frame - return mFrames.FirstChild()->SetInitialChildList(aPresContext, nsnull, newChildList); - -#endif + return nsHTMLContainerFrame::SetInitialChildList(aPresContext, nsnull, aChildList); } // this is identical to nsHTMLContainerFrame::Paint except for the background and border. @@ -353,73 +248,72 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { -#ifdef DO_NEWFIELDSET // Initialize OUT parameter - aStatus = NS_FRAME_COMPLETE; + aStatus = NS_FRAME_COMPLETE; - PRBool isStyleChange = PR_FALSE; - PRBool isDirtyChildReflow = PR_FALSE; - PRBool needResizeReflow = PR_FALSE; - nsIFrame * lastReflowFrame = nsnull; + //------------ Handle Incremental Reflow ----------------- + nsIFrame* incrementalChild = nsnull; + PRBool reflowContent = PR_TRUE; + PRBool reflowLegend = PR_TRUE; + nsReflowReason reason = aReflowState.reason; - // Check for an incremental reflow - if (eReflowReason_Incremental == aReflowState.reason) { - // See if we're the target frame - nsIFrame* targetFrame; - aReflowState.reflowCommand->GetTarget(targetFrame); - if (this == targetFrame) { - // Get the reflow type - nsIReflowCommand::ReflowType reflowType; - aReflowState.reflowCommand->GetType(reflowType); + if ( aReflowState.reason == eReflowReason_Incremental ) { + nsIReflowCommand::ReflowType reflowType; + aReflowState.reflowCommand->GetType(reflowType); - switch (reflowType) { - case nsIReflowCommand::ReflowDirty: - isDirtyChildReflow = PR_TRUE; - break; + // See if it's targeted at us + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); - case nsIReflowCommand::StyleChanged: - // Remember it's a style change so we can set the reflow reason below - isStyleChange = PR_TRUE; - break; + if (this == targetFrame) { + switch (reflowType) { - default: - NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); - } + case nsIReflowCommand::StyleChanged: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_StyleChange; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; - } else { - nsIFrame* nextFrame; - // Get the next frame in the reflow chain - aReflowState.reflowCommand->GetNext(nextFrame); - //NS_ASSERTION(nextFrame == mFrames.FirstChild(), "unexpected next reflow command frame"); + // if its a dirty type then reflow us with a dirty reflow + case nsIReflowCommand::ReflowDirty: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_Dirty; + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + } + } else { + aReflowState.reflowCommand->GetNext(incrementalChild); - nsSize availSize(aReflowState.mComputedWidth, aReflowState.availableHeight); - nsRect currentRect; - nextFrame->GetRect(currentRect); + reflowContent = PR_FALSE; + reflowLegend = PR_FALSE; - // We must specify an unconstrained available height, because constrained - // is only for when we're paginated... - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, nextFrame, - availSize); - // Reflow the frame - ReflowChild(nextFrame, aPresContext, aDesiredSize, kidReflowState, - kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, - 0, aStatus); - if (currentRect.width != aDesiredSize.width || - currentRect.height != aDesiredSize.height) { - needResizeReflow = PR_TRUE; - } - lastReflowFrame = nextFrame; - nextFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + if (incrementalChild == mLegendFrame) + reflowLegend = PR_TRUE; + else if (incrementalChild == mContentFrame) + reflowContent = PR_TRUE; + } } - } - // XXX NOT OPTIMIZED - This code always reflows the legend and the area frame - if (mFrames.IsEmpty()) { - // We have no child frame, so return an empty size - aDesiredSize.width = aDesiredSize.height = 0; - aDesiredSize.ascent = aDesiredSize.descent = 0; + // if dirty then check dirty flags + if (reason == eReflowReason_Dirty) + { + if (reflowContent) { + nsFrameState state; + mContentFrame->GetFrameState(&state); + reflowContent = (state & NS_FRAME_IS_DIRTY) || (state & NS_FRAME_HAS_DIRTY_CHILDREN); + } + + if (reflowLegend) { + nsFrameState state; + mLegendFrame->GetFrameState(&state); + reflowLegend = (state & NS_FRAME_IS_DIRTY) || (state & NS_FRAME_HAS_DIRTY_CHILDREN); + } + } - } else { // availSize could have unconstrained values, don't perform any addition on them nsSize availSize(aReflowState.mComputedWidth, aReflowState.availableHeight); @@ -431,116 +325,136 @@ nsFieldSetFrame::Reflow(nsIPresContext* aPresContext, // Figure out how big the legend is if there is one. nsMargin legendMargin(0,0,0,0); - // if there is a legend frame flow it. + // reflow the legend only if needed if (mLegendFrame) { - nsHTMLReflowState legendReflowState(aPresContext, aReflowState, - mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE)); + if (reflowLegend) { + nsHTMLReflowState legendReflowState(aPresContext, aReflowState, + mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE)); - // always give the legend as much size as it needs - legendReflowState.mComputedWidth = NS_INTRINSICSIZE; - legendReflowState.mComputedHeight = NS_INTRINSICSIZE; - legendReflowState.reason = eReflowReason_Resize; + // always give the legend as much size as it needs + legendReflowState.mComputedWidth = NS_INTRINSICSIZE; + legendReflowState.mComputedHeight = NS_INTRINSICSIZE; + legendReflowState.reason = reason; - ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); + ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); - // get the legend's margin - nsIStyleContext* legendSC = nsnull; - mLegendFrame->GetStyleContext(&legendSC); - if (legendSC) { - const nsStyleSpacing* legendSpacing = - (const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing); - legendSpacing->GetMargin(legendMargin); - NS_RELEASE(legendSC); - } + // get the legend's margin + const nsStyleSpacing* legendSpacing; + mLegendFrame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) legendSpacing); - // figure out the legend's rectangle - mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right; - mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom; - mLegendRect.x = borderPadding.left; - mLegendRect.y = 0; - mLegendSpace = 0; - if (mLegendRect.height > border.top) { - // center the border on the legend - mLegendSpace = mLegendRect.height - borderPadding.top; - } else { - mLegendRect.y = (border.top - mLegendRect.height)/2; - } + legendSpacing->GetMargin(legendMargin); - // if we are contrained then remove the legend from our available height. - if (NS_INTRINSICSIZE != availSize.height) { - if (availSize.height >= mLegendSpace) - availSize.height -= mLegendSpace; - } + // figure out the legend's rectangle + mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right; + mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom; + mLegendRect.x = borderPadding.left; + mLegendRect.y = 0; + + nscoord oldSpace = mLegendSpace; + mLegendSpace = 0; + if (mLegendRect.height > border.top) { + // center the border on the legend + mLegendSpace = mLegendRect.height - borderPadding.top; + } else { + mLegendRect.y = (border.top - mLegendRect.height)/2; + } + + // if the legend space changes then we need to reflow the + // content area as well. + if (mLegendSpace != oldSpace) { + if (reflowContent == PR_FALSE || reason == eReflowReason_Dirty) { + reflowContent = PR_TRUE; + reason = eReflowReason_Resize; + } + } + + // if we are contrained then remove the legend from our available height. + if (NS_INTRINSICSIZE != availSize.height) { + if (availSize.height >= mLegendSpace) + availSize.height -= mLegendSpace; + } - // don't get any smaller than the legend - if (NS_INTRINSICSIZE != availSize.width) { - if (availSize.width < mLegendRect.width) - availSize.width = mLegendRect.width; - } + // don't get any smaller than the legend + if (NS_INTRINSICSIZE != availSize.width) { + if (availSize.width < mLegendRect.width) + availSize.width = mLegendRect.width; + } - // Tell the legend we're done with the reflow. We'll size and place it later on - mLegendFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + FinishReflowChild(mLegendFrame, aPresContext, aDesiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME); + } } - nsIFrame* kidFrame = mFrames.FirstChild(); + nsRect contentRect; + + // reflow the content frame only if needed + if (mContentFrame) { + if (reflowContent) { + availSize.width = aReflowState.mComputedWidth; #if 0 - availSize.width = aReflowState.mComputedWidth; - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) { - availSize.height = aReflowState.mComputedHeight - mLegendSpace; - } else { - availSize.height = NS_INTRINSICSIZE; - } + if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) { + availSize.height = aReflowState.mComputedHeight - mLegendSpace; + } else { + availSize.height = NS_INTRINSICSIZE; + } #endif - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, - availSize); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, mContentFrame, + availSize); - if (isDirtyChildReflow) { - // Note: the only reason the frame would be dirty would be if it had - // just been inserted or appended - kidReflowState.reason = eReflowReason_Initial; - kidReflowState.reflowCommand = nsnull; - } else if (isStyleChange) { - kidReflowState.reason = eReflowReason_StyleChange; - kidReflowState.reflowCommand = nsnull; - } else { - kidReflowState.reason = eReflowReason_Resize; + kidReflowState.reason = reason; + + // Reflow the frame + ReflowChild(mContentFrame, aPresContext, aDesiredSize, kidReflowState, + kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, + 0, aStatus); + + printf("*** %p computedHgt: %d ", this, aReflowState.mComputedHeight); + printf("Reason: "); + switch (aReflowState.reason) { + case eReflowReason_Initial:printf("Initil");break; + case eReflowReason_Incremental:printf("Increm");break; + case eReflowReason_Resize: printf("Resize"); break; + case eReflowReason_StyleChange:printf("eReflowReason_StyleChange");break; + } + + // set the rect. make sure we add the margin back in. + contentRect.SetRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); + if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && + borderPadding.top + mLegendSpace+aDesiredSize.height > aReflowState.mComputedHeight) { + aDesiredSize.height = aReflowState.mComputedHeight-(borderPadding.top + mLegendSpace); + printf(" areaHgt: %d", aDesiredSize.height); + } + + FinishReflowChild(mContentFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); + + nsFrameState kidState; + mContentFrame->GetFrameState(&kidState); + + // printf("width: %d, height: %d\n", desiredSize.mCombinedArea.width, desiredSize.mCombinedArea.height); + + if (kidState & NS_FRAME_OUTSIDE_CHILDREN) { + mState |= NS_FRAME_OUTSIDE_CHILDREN; + aDesiredSize.mOverflowArea.width += borderPadding.left + borderPadding.right; + aDesiredSize.mOverflowArea.height += borderPadding.top + borderPadding.bottom + mLegendSpace; + } + + NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); + + } else { + // if we don't need to reflow just get the old size + mContentFrame->GetRect(contentRect); + const nsStyleSpacing* spacing; + mContentFrame->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + nsMargin m(0,0,0,0); + spacing->GetMargin(m); + contentRect.Inflate(m); + } } - // Reflow the frame - ReflowChild(kidFrame, aPresContext, aDesiredSize, kidReflowState, - kidReflowState.mComputedMargin.left, kidReflowState.mComputedMargin.top, - 0, aStatus); - -printf("*** %p computedHgt: %d ", this, aReflowState.mComputedHeight); - printf("Reason: "); - switch (aReflowState.reason) { - case eReflowReason_Initial:printf("Initil");break; - case eReflowReason_Incremental:printf("Increm");break; - case eReflowReason_Resize: printf("Resize"); break; - case eReflowReason_StyleChange:printf("eReflowReason_StyleChange");break; - } - - // set the rect. make sure we add the margin back in. - nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); - if (aReflowState.mComputedHeight != NS_INTRINSICSIZE && - borderPadding.top + mLegendSpace+aDesiredSize.height > aReflowState.mComputedHeight) { - aDesiredSize.height = aReflowState.mComputedHeight-(borderPadding.top + mLegendSpace); -printf(" areaHgt: %d", aDesiredSize.height); - } - - FinishReflowChild(kidFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); - - // If the child frame was just inserted, then we're responsible for making sure - // it repaints - //if (isDirtyChildReflow) { - // Damage the area occupied by the deleted frame - // Invalidate(aPresContext, rect, PR_FALSE); - //} - - NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus); - if (mLegendFrame) { if (contentRect.width > mLegendRect.width) { PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign(); @@ -560,9 +474,24 @@ printf(" areaHgt: %d", aDesiredSize.height); // place the legend nsRect actualLegendRect(mLegendRect); actualLegendRect.Deflate(legendMargin); - mLegendFrame->SetRect(aPresContext, actualLegendRect); + + nsPoint curOrigin; + mLegendFrame->GetOrigin(curOrigin); + + // only if the origin changed + if ((curOrigin.x != mLegendRect.x) || (curOrigin.y != mLegendRect.y)) { + + mLegendFrame->MoveTo(aPresContext, actualLegendRect.x , actualLegendRect.y); + + nsIView* view; + mLegendFrame->GetView(aPresContext, &view); + if (view) + nsContainerFrame::PositionFrameView(aPresContext, mLegendFrame, view); + else + nsContainerFrame::PositionChildViews(aPresContext, mLegendFrame); + } } - + // Return our size and our result if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) { aDesiredSize.height = mLegendSpace + @@ -601,145 +530,7 @@ printf(" areaHgt: %d", aDesiredSize.height); // height is border + legend aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom + mLegendRect.height; } - } -printf(" desiredHgt: %d\n", aDesiredSize.height); -#else - // availSize could have unconstrained values, don't perform any addition on them - nsSize availSize(aReflowState.mComputedWidth, aReflowState.availableHeight); - - // get our border and padding - const nsMargin &borderPadding = aReflowState.mComputedBorderPadding; - const nsMargin &padding = aReflowState.mComputedPadding; - nsMargin border = borderPadding - padding; - // Figure out how big the legend is if there is one. - nsMargin legendMargin(0,0,0,0); - - // if there is a legend frame flow it. - if (mLegendFrame) { - nsHTMLReflowState legendReflowState(aPresContext, aReflowState, - mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE)); - - // always give the legend as much size as it needs - legendReflowState.mComputedWidth = NS_INTRINSICSIZE; - legendReflowState.mComputedHeight = NS_INTRINSICSIZE; - - ReflowChild(mLegendFrame, aPresContext, aDesiredSize, legendReflowState, - 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus); - - // get the legend's margin - nsIStyleContext* legendSC = nsnull; - mLegendFrame->GetStyleContext(&legendSC); - if (legendSC) { - const nsStyleSpacing* legendSpacing = - (const nsStyleSpacing*)legendSC->GetStyleData(eStyleStruct_Spacing); - legendSpacing->GetMargin(legendMargin); - NS_RELEASE(legendSC); - } - - // figure out the legend's rectangle - mLegendRect.width = aDesiredSize.width + legendMargin.left + legendMargin.right; - mLegendRect.height = aDesiredSize.height + legendMargin.top + legendMargin.bottom; - mLegendRect.x = borderPadding.left; - mLegendRect.y = 0; - mLegendSpace = 0; - if (mLegendRect.height > border.top) { - // center the border on the legend - mLegendSpace = mLegendRect.height - borderPadding.top; - } else { - mLegendRect.y = (border.top - mLegendRect.height)/2; - } - - // if we are contrained then remove the legend from our available height. - if (NS_INTRINSICSIZE != availSize.height) { - if (availSize.height >= mLegendSpace) - availSize.height -= mLegendSpace; - } - - // don't get any smaller than the legend - if (NS_INTRINSICSIZE != availSize.width) { - if (availSize.width < mLegendRect.width) - availSize.width = mLegendRect.width; - } - - // Tell the legend we're done with the reflow. We'll size and place it later on - mLegendFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - } - - mContentFrame = mFrames.FirstChild(); - - // Try to reflow the area frame into the available space. - nsHTMLReflowState contentReflowState(aPresContext, aReflowState, - mContentFrame, availSize); - - ReflowChild(mContentFrame, aPresContext, aDesiredSize, contentReflowState, - borderPadding.left, borderPadding.top + mLegendSpace, 0, aStatus); - - // set the rect. make sure we add the margin back in. - nsRect contentRect(borderPadding.left,borderPadding.top + mLegendSpace,aDesiredSize.width ,aDesiredSize.height); - - // Place the content area frame. - FinishReflowChild(mContentFrame, aPresContext, aDesiredSize, contentRect.x, contentRect.y, 0); - - if (mLegendFrame) - { - PRInt32 align = ((nsLegendFrame*)mLegendFrame)->GetAlign(); - - switch(align) { - case NS_STYLE_TEXT_ALIGN_RIGHT: - mLegendRect.x = contentRect.width - mLegendRect.width + borderPadding.left; - break; - case NS_STYLE_TEXT_ALIGN_CENTER: - mLegendRect.x = contentRect.width/2 - mLegendRect.width/2 + borderPadding.left; - } - - // place the legend - nsRect actualLegendRect(mLegendRect); - actualLegendRect.Deflate(legendMargin); - mLegendFrame->SetRect(aPresContext, actualLegendRect); - } - - // Return our size and our result - if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) { - aDesiredSize.height = mLegendSpace + - borderPadding.top + - aDesiredSize.height + - borderPadding.bottom; - } else { - nscoord min = borderPadding.top + borderPadding.bottom + mLegendRect.height; - aDesiredSize.height = aReflowState.mComputedHeight + borderPadding.top + borderPadding.bottom; - if (aDesiredSize.height < min) - aDesiredSize.height = min; - } - - if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) { - aDesiredSize.width = borderPadding.left + - aDesiredSize.width + - borderPadding.right; - } else { - nscoord min = borderPadding.left + borderPadding.right + mLegendRect.width; - aDesiredSize.width = aReflowState.mComputedWidth + borderPadding.left + borderPadding.right; - if (aDesiredSize.width < min) - aDesiredSize.width = min; - } - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - - if (nsnull != aDesiredSize.maxElementSize) { - // if the legend it wider use it - if (aDesiredSize.maxElementSize->width < mLegendRect.width) - aDesiredSize.maxElementSize->width = mLegendRect.width; - - // add in padding. - aDesiredSize.maxElementSize->width += borderPadding.left + borderPadding.right; - - // height is border + legend - aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom + mLegendRect.height; - } - - aStatus = NS_FRAME_COMPLETE; -#endif return NS_OK; } diff --git a/mozilla/layout/html/forms/src/nsGfxListControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxListControlFrame.cpp index 3c044ce848c..a551b857d69 100644 --- a/mozilla/layout/html/forms/src/nsGfxListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxListControlFrame.cpp @@ -295,6 +295,251 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, } #endif // DEBUG_rodsXXX +#if 0 + // reflow optimization - why reflow if all the contents + // and frames aren't there yet + if (!mIsAllContentHere || !mIsAllFramesHere) { + aDesiredSize.width = 30*15; + aDesiredSize.height = 30*15; + if (nsnull != aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = aDesiredSize.width; + aDesiredSize.maxElementSize->height = aDesiredSize.height; + } + aStatus = NS_FRAME_COMPLETE; + printf("--------------------------> Skipping reflow\n"); + return NS_OK; + } +#endif + + // If all the content and frames are here + // then initialize it before reflow + if (mIsAllContentHere && !mHasBeenInitialized) { + if (PR_FALSE == mIsAllFramesHere) { + CheckIfAllFramesHere(); + } + if (mIsAllFramesHere && !mHasBeenInitialized) { + mHasBeenInitialized = PR_TRUE; + InitSelectionCache(-1); // Reset sel cache so as not to send event + Reset(mPresContext); + // reflow if initialized in reflow + nsCOMPtr cmd; + nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(cmd), this, nsIReflowCommand::StyleChanged); + if (NS_FAILED(rv)) { return rv; } + if (!cmd) { return NS_ERROR_NULL_POINTER; } + nsCOMPtr shell; + rv = mPresContext->GetShell(getter_AddRefs(shell)); + if (NS_FAILED(rv)) { return rv; } + if (!shell) { return NS_ERROR_NULL_POINTER; } + rv = shell->EnterReflowLock(); + if (NS_FAILED(rv)) { return rv; } + rv = shell->AppendReflowCommand(cmd); + // must do this next line regardless of result of AppendReflowCommand + shell->ExitReflowLock(PR_TRUE); + } + } + +#if 1 + nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementSize, aPresContext, + aDesiredSize, aReflowState, aStatus); + if (NS_SUCCEEDED(skiprv)) { + return skiprv; + } +#endif + // XXX So this may do it too often + // the side effect of this is if the user has scrolled to some other place in the list and + // an incremental reflow comes through the list gets scrolled to the first selected item + // I haven't been able to make it do it, but it will do it + // basically the real solution is to know when all the reframes are there. + if (aReflowState.reason == eReflowReason_Incremental) { + nsCOMPtr content = getter_AddRefs(GetOptionContent(mSelectedIndex)); + if (content) { + ScrollToFrame(content); + } + } + + nsIFrame * firstChildFrame = nsnull; + FirstChild(aPresContext, nsnull, &firstChildFrame); + + // Strategy: Let the inherited reflow happen as though the width and height of the + // ScrollFrame are big enough to allow the listbox to + // shrink to fit the longest option element line in the list. + // The desired width and height returned by the inherited reflow is returned, + // unless one of the following has been specified. + // 1. A css width has been specified. + // 2. The size has been specified. + // 3. The css height has been specified, but the number of rows has not. + // The size attribute overrides the height setting but the height setting + // should be honored if there isn't a size specified. + + // Determine the desired width + height for the listbox + + aDesiredSize.width = 0; + aDesiredSize.height = 0; + + PRBool isInDropDownMode = IsInDropDownMode(); + + // Add the list frame as a child of the form + if (isInDropDownMode == PR_FALSE && !mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { + nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); + } + + nsHTMLReflowState childReflowState(aPresContext, aReflowState, firstChildFrame, nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE)); + + // Get the size of option elements inside the listbox + // Compute the width based on the longest line in the listbox. + + childReflowState.mComputedWidth = aReflowState.mComputedWidth; + childReflowState.mComputedHeight = aReflowState.mComputedHeight; + + // remove our padding from the childs computed size. + nsMargin cb = aReflowState.mComputedPadding; + + if (childReflowState.mComputedWidth != NS_INTRINSICSIZE) { + childReflowState.mComputedWidth += aReflowState.mComputedPadding.left + aReflowState.mComputedPadding.right; + + if (childReflowState.mComputedWidth >= (cb.left + cb.right)) + childReflowState.mComputedWidth -= (cb.left + cb.right); + else + childReflowState.mComputedWidth = 0; + } + + + if (childReflowState.mComputedHeight != NS_INTRINSICSIZE) { + childReflowState.mComputedHeight += aReflowState.mComputedPadding.top + aReflowState.mComputedPadding.bottom; + + if (childReflowState.mComputedHeight >= (cb.top + cb.bottom)) + childReflowState.mComputedHeight -= (cb.top + cb.bottom); + else + childReflowState.mComputedHeight = 0; + } + + // now reflow the child + nsSize scrolledAreaSize(0,0); + nsHTMLReflowMetrics scrolledAreaDesiredSize(&scrolledAreaSize); + + firstChildFrame->Reflow(aPresContext, + scrolledAreaDesiredSize, + childReflowState, + aStatus); + + if (childReflowState.mComputedHeight == NS_INTRINSICSIZE) { + PRInt32 numRows = 1; + GetSizeAttribute(&numRows); + + if (numRows == kNoSizeSpecified) { + nsIDOMNode* node; + nsresult rv = mContent->QueryInterface(nsCOMTypeInfo::GetIID(),(void**) &node); + if (node && NS_SUCCEEDED(rv)) { + numRows = 0; + CountAllChild(node, numRows); + NS_RELEASE(node); + } + } + + if (numRows > 1) { + PRInt32 heightOfARow = scrolledAreaDesiredSize.maxElementSize->height; + nscoord visibleHeight; + + if (isInDropDownMode) { + visibleHeight = childReflowState.mComputedHeight; + + if (visibleHeight > (kMaxDropDownRows * heightOfARow)) { + visibleHeight = (kMaxDropDownRows * heightOfARow); + } + } else { + visibleHeight = numRows * heightOfARow; + } + + //printf("Row height: %d\n", heightOfARow); + + nsHTMLReflowState pass2ReflowState(aPresContext, aReflowState, firstChildFrame, nsSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE)); + pass2ReflowState.mComputedHeight = visibleHeight; + pass2ReflowState.mComputedWidth = childReflowState.mComputedWidth; + + firstChildFrame->Reflow(aPresContext, + scrolledAreaDesiredSize, + pass2ReflowState, + aStatus); + } + } + + nsMargin b = aReflowState.mComputedBorderPadding - aReflowState.mComputedPadding; + + + // The visible height is zero, this could be a select with no options + // or a select with a single option that has no content or no label + // + // So this may not be the best solution, but we get the height of the font + // for the list frame and use that as the max/minimum size for the contents + /* + if (visibleHeight == 0) { + nsCOMPtr fontMet; + nsFormControlHelper::GetFrameFontFM(aPresContext, this, getter_AddRefs(fontMet)); + if (fontMet) { + aReflowState.rendContext->SetFont(fontMet); + fontMet->GetHeight(visibleHeight); + mMaxHeight = visibleHeight; + } + } + */ + + + nsRect r(b.left,b.top, scrolledAreaDesiredSize.width, scrolledAreaDesiredSize.height); + firstChildFrame->SetRect(aPresContext, r); + + // Set the max element size to be the same as the desired element size. + if (nsnull != aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = scrolledAreaDesiredSize.width; + aDesiredSize.maxElementSize->height = scrolledAreaDesiredSize.height; + } + + aDesiredSize.width = scrolledAreaDesiredSize.width + b.left + b.right; + aDesiredSize.height = scrolledAreaDesiredSize.height + b.top + b.bottom; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + + aStatus = NS_FRAME_COMPLETE; +#ifdef DEBUG_rodsXXX + if (!isInDropDownMode) { + PRInt32 numRows = 1; + GetSizeAttribute(&numRows); + printf("%d ", numRows); + if (numRows == 2) { + COMPARE_QUIRK_SIZE("nsGfxListControlFrame", 56, 38) + } if (numRows == 3) { + COMPARE_QUIRK_SIZE("nsGfxListControlFrame", 56, 54) + } if (numRows == 4) { + COMPARE_QUIRK_SIZE("nsGfxListControlFrame", 56, 70) + } + } +#endif + + nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedMaxElementSize, aDesiredSize); + + return NS_OK; +} + + +#if 0 +//--------------------------------------------------------- +// Reflow is overriden to constrain the listbox height to the number of rows and columns +// specified. + +NS_IMETHODIMP +nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ +#ifdef DEBUG_rodsXXX + printf("nsGfxListControlFrame::Reflow Reason: "); + switch (aReflowState.reason) { + case eReflowReason_Initial:printf("eReflowReason_Initial\n");break; + case eReflowReason_Incremental:printf("eReflowReason_Incremental\n");break; + case eReflowReason_Resize:printf("eReflowReason_Resize\n");break; + case eReflowReason_StyleChange:printf("eReflowReason_StyleChange\n");break; + } +#endif // DEBUG_rodsXXX + #if 0 // reflow optimization - why reflow if all the contents // and frames aren't there yet @@ -638,6 +883,7 @@ nsGfxListControlFrame::Reflow(nsIPresContext* aPresContext, return NS_OK; } +#endif //--------------------------------------------------------- NS_IMETHODIMP diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 16257c4c4ad..a4f2a410162 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -111,7 +111,8 @@ static PRBool gReallyNoisyContentUpdates = PR_FALSE; static PRBool gNoisyInlineConstruction = PR_FALSE; #endif -//#define NEWGFX_LIST +#define NEWGFX_LIST +#define NEWGFX_LIST_SCROLLFRAME #ifdef NEWGFX_LIST nsresult @@ -140,7 +141,7 @@ nsresult NS_NewTitledButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult -NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags ); +NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame); nsresult NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); @@ -3042,9 +3043,9 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, } } else { #ifdef NEWGFX_LIST - // Construct a frame-based list box + // Construct a frame-based list box nsIFrame * listFrame; - rv = NS_NewGfxListControlFrame(&listFrame); + rv = NS_NewGfxListControlFrame(aPresShell, &listFrame); // initialize the list control InitAndRestoreFrame(aPresContext, aState, aContent, @@ -3053,33 +3054,37 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, // create the area frame we are scrolling PRUint32 flags = NS_BLOCK_SHRINK_WRAP | (aIsAbsolutelyPositioned?NS_BLOCK_SPACE_MGR:0); nsIFrame* scrolledFrame = nsnull; - NS_NewSelectsAreaFrame(&scrolledFrame, flags); - - nsCOMPtr listControlframe(do_QueryInterface(listFrame)); - if (listControlframe) { - listControlframe->SetMainChildFrame(scrolledFrame); - } + NS_NewSelectsAreaFrame(aPresShell, &scrolledFrame, flags); // resolve a style for our gfx scrollframe based on the list frames style - /*nsCOMPtr scrollFrameStyle; + nsCOMPtr scrollFrameStyle; aPresContext->ResolvePseudoStyleContextFor(aContent, - nsLayoutAtoms::scrolledContentPseudo,// (this will probably work but you might want to set up you own), + nsLayoutAtoms::selectScrolledContentPseudo, aStyleContext, PR_FALSE, getter_AddRefs(scrollFrameStyle)); - */ + + InitAndRestoreFrame(aPresContext, aState, aContent, + listFrame, scrollFrameStyle, nsnull, scrolledFrame); + // this is what is returned when the scrollframe is created. // newScrollFrame - Either a gfx scrollframe or a native scrollframe that was created // scrolledFrameStyleContext - The resolved style context of the scrolledframe you passed in. // this is not the style of the scrollFrame. nsIFrame* newScrollFrame = nsnull; + + /* scroll frame */ + +#ifdef NEWGFX_LIST_SCROLLFRAME nsIStyleContext * scrolledFrameStyleContext = nsnull; // ok take the style context, the Select area frame to scroll,the listFrame, and its parent // and build the scrollframe. - BuildScrollFrame(aPresContext, aState, aContent, aStyleContext, scrolledFrame, + BuildScrollFrame(aPresShell, aPresContext, aState, aContent, scrollFrameStyle, scrolledFrame, listFrame, newScrollFrame, scrolledFrameStyleContext); - +#else + newScrollFrame = scrolledFrame; +#endif // The area frame is a floater container PRBool haveFirstLetterStyle, haveFirstLineStyle; @@ -3108,7 +3113,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsIPresShell* aPresShell, nsIStyleContext* styleContext = nsnull; nsIFrame* generatedFrame = nsnull; scrolledFrame->GetStyleContext(&styleContext); - if (CreateGeneratedContentFrame(aPresContext, aState, scrolledFrame, aContent, + if (CreateGeneratedContentFrame(aPresShell, aPresContext, aState, scrolledFrame, aContent, styleContext, nsLayoutAtoms::dummyOptionPseudo, PR_FALSE, &generatedFrame)) { // Add the generated frame to the child list @@ -7310,7 +7315,9 @@ StyleChangeReflow(nsIPresContext* aPresContext, { nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); - + + + nsIReflowCommand* reflowCmd; nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, aFrame, nsIReflowCommand::StyleChanged, @@ -7320,6 +7327,17 @@ StyleChangeReflow(nsIPresContext* aPresContext, shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + /* + + nsFrameState state; + aFrame->GetFrameState(&state); + state |= NS_FRAME_IS_DIRTY; + aFrame->SetFrameState(state); + nsIFrame* parent; + aFrame->GetParent(&parent); + parent->ReflowDirtyChild(shell, aFrame); +*/ } NS_IMETHODIMP diff --git a/mozilla/layout/style/html.css b/mozilla/layout/style/html.css index 4298843244e..10b15a233f7 100644 --- a/mozilla/layout/style/html.css +++ b/mozilla/layout/style/html.css @@ -1386,6 +1386,12 @@ sourcetext { /* XXX should not be in HTML namespace */ border: 2px outset #c0c0c0; } +:-moz-select-scrolled-content { + background: inherit; + display: inherit; + padding: inherit; +} + :scrolled-content { background: inherit; padding: inherit; diff --git a/mozilla/layout/xul/base/src/nsBoxFrame.cpp b/mozilla/layout/xul/base/src/nsBoxFrame.cpp index 138303721a4..b52e4c20631 100644 --- a/mozilla/layout/xul/base/src/nsBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsBoxFrame.cpp @@ -28,6 +28,27 @@ // See documentation in associated header file // +// How boxes layout +// ---------------- +// Boxes layout a bit differently than html. html does a bottom up layout. Where boxes do a top down. +// 1) First thing a box does it goes out and askes each child for its min, max, and preferred sizes. +// 2) It then adds them up to determine its size. +// 3) If the box was asked to layout it self intrinically it will layout its children at their preferred size +// otherwise it will layout the child at the size it was told to. It will squeeze or stretch its children if +// Necessary. +// +// However there is a catch. Some html components like block frames can not determine their preferred size. +// this is their size if they were layed out intrinsically. So the box will flow the child to determine this can +// cache the value. + +// Boxes and Incremental Reflow +// ---------------------------- +// Boxes layout out top down by adding up their childrens min, max, and preferred sizes. Only problem is if a incremental +// reflow occurs. The preferred size of a child deep in the hierarchy could change. And this could change +// any number of syblings around the box. Basically any children in the reflow chain must have their caches cleared +// so when asked for there current size they can relayout themselves. Thats where the Dirty method comes in. This +// moves down the reflow chain until it reaches something that is not a box marking each child as being dirty. + #include "nsBoxFrame.h" #include "nsIStyleContext.h" #include "nsIPresContext.h" @@ -50,8 +71,8 @@ #include "nsISelfScrollingFrame.h" #define CONSTANT 0 -#define DEBUG_REFLOW 0 -#define DEBUG_REDRAW 0 +//#define DEBUG_REFLOW +//#define DEBUG_REDRAW #define DEBUG_SPRING_SIZE 8 #define DEBUG_BORDER_SIZE 2 #define COIL_SIZE 8 @@ -85,10 +106,9 @@ public: void DrawLine(nsIRenderingContext& aRenderingContext, nscoord x1, nscoord y1, nscoord x2, nscoord y2); void FillRect(nsIRenderingContext& aRenderingContext, nscoord x, nscoord y, nscoord width, nscoord height); - nsresult DisplayDebugInfoFor(nsIPresContext* aPresContext, + PRBool DisplayDebugInfoFor(nsIPresContext* aPresContext, nsPoint& aPoint, PRInt32& aCursor); - }; class nsInfoListImpl: public nsInfoList @@ -154,25 +174,94 @@ public: nsresult GetContentOf(nsIFrame* aFrame, nsIContent** aContent); void SanityCheck(); + nsresult FlowChildren(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nsIFrame*& aIncrementalChild, + nsRect& availableSize); + + nsresult FlowChildAt(nsIFrame* frame, + nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nsCalculatedBoxInfo& aInfo, + nscoord aX, + nscoord aY, + PRBool aMoveFrame, + nsIFrame*& aIncrementalChild, + PRBool& needsRedraw, + const nsString& aReason); + + void TranslateEventCoords(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsPoint& aResult); + + static void InvalidateCachesTo(nsIFrame* aTargetFrame); + static void InvalidateAllCachesBelow(nsIPresContext* aPresContext, nsIFrame* aTargetFrame); + static PRBool AdjustTargetToScope(nsIFrame* aParent, nsIFrame*& aTargetFrame); + + enum Halignment { + hAlign_Left, + hAlign_Right, + hAlign_Center, + hAlign_Stretch, + hAlign_Default + }; + + enum Valignment { + vAlign_Top, + vAlign_Middle, + vAlign_BaseLine, + vAlign_Bottom, + vAlign_Stretch, + vAlign_Default + }; + + nsBoxFrameInner::Halignment nsBoxFrameInner::GetHAlign(); + nsBoxFrameInner::Valignment nsBoxFrameInner::GetVAlign(); + + +#ifdef DEBUG_REFLOW + void MakeReason(nsIFrame* aFrame, const nsString& aText, nsString& aReason); + void AddIndents(); +#endif + nsCOMPtr mSpaceManager; // We own this [OWNER]. - PRUint32 mFlags; nsBoxFrame* mOuter; nsBoxDebugInner* mDebugInner; nsInfoListImpl* mInfoList; + + // make these flags! PRBool mHorizontal; + PRBool mIsRoot; + + Valignment mValign; + Halignment mHalign; + +#ifdef DEBUG_REFLOW + PRInt32 reflowCount; +#endif }; +#define GET_WIDTH(size) (IsHorizontal() ? size.width : size.height) +#define GET_HEIGHT(size) (IsHorizontal() ? size.height : size.width) + +#define SET_WIDTH(size, coord) if (IsHorizontal()) { (size).width = (coord); } else { (size).height = (coord); } +#define SET_HEIGHT(size, coord) if (IsHorizontal()) { (size).height = (coord); } else { (size).width = (coord); } + nsIFrame* nsBoxDebugInner::mDebugChild = nsnull; nsresult -NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags ) +NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } - nsBoxFrame* it = new (aPresShell) nsBoxFrame(aFlags); + nsBoxFrame* it = new (aPresShell) nsBoxFrame(); if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -181,13 +270,19 @@ NS_NewBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags } // NS_NewBoxFrame -nsBoxFrame::nsBoxFrame(PRUint32 aFlags) +nsBoxFrame::nsBoxFrame() { mInner = new nsBoxFrameInner(this); // if not otherwise specified boxes by default are horizontal. mInner->mHorizontal = PR_TRUE; - mInner->mFlags = aFlags; + mInner->mIsRoot = PR_FALSE; + mInner->mValign = nsBoxFrameInner::vAlign_Default; + mInner->mHalign = nsBoxFrameInner::hAlign_Default; + +#ifdef DEBUG_REFLOW + mInner->reflowCount = 100; +#endif } nsBoxFrame::~nsBoxFrame() @@ -195,6 +290,33 @@ nsBoxFrame::~nsBoxFrame() delete mInner; } + +NS_IMETHODIMP +nsBoxFrame::InvalidateCache(nsIFrame* aChild) +{ + nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); + + // if the child is null then blow away all caches. Otherwise just blow away the + // specified kids cache. + if (aChild == nsnull) { + while(info != nsnull) { + info->needsRecalc = PR_TRUE; + info = info->next; + } + } else { + while(info != nsnull) { + if (info->frame == aChild) { + info->needsRecalc = PR_TRUE; + return NS_OK; + } + info = info->next; + } + } + + return NS_OK; +} + + NS_IMETHODIMP nsBoxFrame::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -245,6 +367,36 @@ nsBoxFrame::Init(nsIPresContext* aPresContext, #endif mInner->mHorizontal = GetInitialAlignment(); + + nsString value; + + nsCOMPtr content; + mInner->GetContentOf(this, getter_AddRefs(content)); + + // vertical align + mInner->mValign = nsBoxFrameInner::vAlign_Default; + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::valign, value)) { + if (value.EqualsIgnoreCase("top")) + mInner->mValign = nsBoxFrameInner::vAlign_Top; + else if (value.EqualsIgnoreCase("baseline")) + mInner->mValign = nsBoxFrameInner::vAlign_BaseLine; + else if (value.EqualsIgnoreCase("middle")) + mInner->mValign = nsBoxFrameInner::vAlign_Middle; + else if (value.EqualsIgnoreCase("bottom")) + mInner->mValign = nsBoxFrameInner::vAlign_Bottom; + } + + // horizontal align + mInner->mHalign = nsBoxFrameInner::hAlign_Default; + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, value)) { + if (value.EqualsIgnoreCase("left")) + mInner->mHalign = nsBoxFrameInner::hAlign_Left; + else if (value.EqualsIgnoreCase("center")) + mInner->mHalign = nsBoxFrameInner::hAlign_Center; + else if (value.EqualsIgnoreCase("right")) + mInner->mHalign = nsBoxFrameInner::hAlign_Right; + } + return rv; } @@ -259,11 +411,20 @@ nsBoxFrame::GetInitialAlignment() nsCOMPtr content; mInner->GetContentOf(this, getter_AddRefs(content)); - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, value); - if (value.EqualsIgnoreCase("vertical")) - return PR_FALSE; - else - return PR_TRUE; + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::orient, value)) + { + if (value.EqualsIgnoreCase("vertical")) + return PR_FALSE; + else + return PR_TRUE; + } else { + // depricated, use align + content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, value); + if (value.EqualsIgnoreCase("vertical")) + return PR_FALSE; + else + return PR_TRUE; + } } nsInfoList* @@ -303,7 +464,7 @@ nsBoxFrame::GetInnerRect(nsRect& aInner) void nsBoxFrame::GetRedefinedMinPrefMax(nsIPresContext* aPresContext, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize) { - // add in the css min, max, pref + // add in the css min, max, pref const nsStylePosition* position; aFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&) position); @@ -376,6 +537,27 @@ nsBoxFrame::GetRedefinedMinPrefMax(nsIPresContext* aPresContext, nsIFrame* aFra aSize.prefSize.height = NSIntPixelsToTwips(value.ToInteger(&error), p2t); } + + // make sure pref size is inside min and max values. + if (aSize.prefSize.width < aSize.minSize.width) + aSize.prefSize.width = aSize.minSize.width; + + if (aSize.prefSize.height < aSize.minSize.height) + aSize.prefSize.height = aSize.minSize.height; + + if (aSize.prefSize.width > aSize.maxSize.width) + aSize.prefSize.width = aSize.maxSize.width; + + if (aSize.prefSize.height > aSize.maxSize.height) + aSize.prefSize.height = aSize.maxSize.height; + + + // if we are not flexible then our min, max, and pref sizes are all the same. + // if (aSize.flex == 0) { + // SET_WIDTH(aSize.minSize, GET_WIDTH(aSize.prefSize)); + /// SET_WIDTH(aSize.maxSize, GET_WIDTH(aSize.prefSize)); + /// } + } /** @@ -391,8 +573,6 @@ nsBoxFrame::GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowStat // see if the frame Innerements IBox interface // since frames are not refCounted, don't use nsCOMPtr with them - //nsCOMPtr ibox = do_QueryInterface(aFrame); - // if it does ask it for its BoxSize and we are done nsIBox* ibox = nsnull; if (NS_SUCCEEDED(aFrame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) { @@ -402,6 +582,10 @@ nsBoxFrame::GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowStat return NS_OK; } + // so the child is not a box. So we will have to be creative. We need to get its min, max, and preferred + // sizes. Min and Max are easy you get them for CSS. But preferred size? First we will see if they are set in + // css. If not we will have to flow the child intrinically. + // start the preferred size as intrinsic aSize.prefSize.width = NS_INTRINSICSIZE; aSize.prefSize.height = NS_INTRINSICSIZE; @@ -435,15 +619,22 @@ nsBoxFrame::GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowStat if (aSize.prefSize.height != NS_INTRINSICSIZE) aSize.prefSize.height += (total.top + total.bottom); + // flow child at preferred size nsHTMLReflowMetrics desiredSize(nsnull); aSize.calculatedSize = aSize.prefSize; + nsReflowStatus status; PRBool redraw; nsString reason("To get pref size"); - FlowChildAt(aFrame, aPresContext, desiredSize, aReflowState, status, aSize, redraw, reason); + + nsHTMLReflowState state(aReflowState); + state.reason = eReflowReason_Initial; + nsIFrame* incrementalChild = nsnull; + + mInner->FlowChildAt(aFrame, aPresContext, desiredSize, state, status, aSize, 0, 0, PR_FALSE, incrementalChild, redraw, reason); // remove margin and border desiredSize.height -= (total.top + total.bottom); @@ -453,7 +644,9 @@ nsBoxFrame::GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowStat aSize.prefSize.width = desiredSize.width; aSize.prefSize.height = desiredSize.height; - + // aSize.prefSize.width = 0; + // aSize.prefSize.height = 0; + // redefine anything depending on css GetRedefinedMinPrefMax(aPresContext, aFrame, aSize); } @@ -461,6 +654,59 @@ nsBoxFrame::GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowStat return NS_OK; } +NS_IMETHODIMP +nsBoxFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) +{ + InvalidateCache(aChild); + + // if we are not dirty mark ourselves dirty and tell our parent we are dirty too. + if (!(mState & NS_FRAME_IS_DIRTY)) { + // Mark yourself as dirty + mState |= NS_FRAME_IS_DIRTY; + return mParent->ReflowDirtyChild(aPresShell, this); + } + + return NS_OK; +} + +#ifdef DEBUG_REFLOW + +PRInt32 gIndent = 0; +PRInt32 gReflows = 0; + +#endif + + + +void +nsIBox::HandleRootBoxReflow(nsIPresContext* aPresContext, + nsIFrame* aBox, + const nsHTMLReflowState& aReflowState) +{ + + // if its an incremental reflow + if ( aReflowState.reason == eReflowReason_Incremental ) { + + nsIReflowCommand::ReflowType reflowType; + aReflowState.reflowCommand->GetType(reflowType); + + // See if it's targeted at us + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); + + if (aBox != targetFrame) { + // clear the caches down the chain + nsBoxFrameInner::InvalidateCachesTo(targetFrame); + + // if the type is style changed then make sure we + // invalidate all caches under the target + if (reflowType == nsIReflowCommand::StyleChanged) + nsBoxFrameInner::InvalidateAllCachesBelow(aPresContext, targetFrame); + } + } +} + + /** * Ok what we want to do here is get all the children, figure out * their flexibility, preferred, min, max sizes and then stretch or @@ -478,6 +724,12 @@ nsBoxFrame::Reflow(nsIPresContext* aPresContext, nsReflowStatus& aStatus) { +#ifdef DEBUG_REFLOW + gIndent++; +#endif + + + mInner->SanityCheck(); // If we have a space manager, then set it in the reflow state @@ -505,22 +757,88 @@ nsBoxFrame::Reflow(nsIPresContext* aPresContext, //--------------------------------------------------------- //------- handle incremental reflow -------------------- //--------------------------------------------------------- + nsIFrame* incrementalChild = nsnull; - // if there is incremental we need to tell all the boxes below to blow away the - // cached values for the children in the reflow list - nsIFrame* incrementalChild = nsnull; - if ( aReflowState.reason == eReflowReason_Incremental ) { - nsIFrame* targetFrame; - // See if it's targeted at us - aReflowState.reflowCommand->GetTarget(targetFrame); - if (this == targetFrame) { - // if it has redraw us - Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); - } else { - // otherwise dirty our children - Dirty(aPresContext, aReflowState,incrementalChild); + if ( aReflowState.reason == eReflowReason_Initial) { + // on the initial reflow see if we are the root box. + // the root box. + mInner->mIsRoot = PR_TRUE; + + // see if we are the root box + nsIFrame* parent = mParent; + while (parent) { + nsIBox* ibox = nsnull; + if (NS_SUCCEEDED(parent->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox) { + mInner->mIsRoot = PR_FALSE; + break; + } + parent->GetParent(&parent); + } + if (mInner->mIsRoot) + printf("--------INITIAL REFLOW--------\n"); + + } else if ( aReflowState.reason == eReflowReason_Incremental ) { + nsIReflowCommand::ReflowType reflowType; + aReflowState.reflowCommand->GetType(reflowType); + + // See if it's targeted at us + nsIFrame* targetFrame; + aReflowState.reflowCommand->GetTarget(targetFrame); + + if (this == targetFrame) { + // if we are the target see what the type was + // and generate a normal non incremental reflow. + switch (reflowType) { + + case nsIReflowCommand::StyleChanged: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_StyleChange; + #ifdef DEBUG_REFLOW + gIndent--; + #endif + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + // if its a dirty type then reflow us with a dirty reflow + case nsIReflowCommand::ReflowDirty: + { + nsHTMLReflowState newState(aReflowState); + newState.reason = eReflowReason_Dirty; + #ifdef DEBUG_REFLOW + gIndent--; + #endif + return Reflow(aPresContext, aDesiredSize, newState, aStatus); + } + break; + + default: + NS_ASSERTION(PR_FALSE, "unexpected reflow command type"); + } + + } else { + // ok we are not the target, see if our parent is a box. If its not then we + // are the first box so its our responsibility + // to blow away the caches for each child in the incremental + // reflow chain. only mark those children whose parents are boxes + if (mInner->mIsRoot) { + HandleRootBoxReflow(aPresContext, this, aReflowState); + } + } + + // then get the child we need to flow incrementally + aReflowState.reflowCommand->GetNext(incrementalChild); } - } + +#ifdef DEBUG_REFLOW + if (mInner->mIsRoot) + printf("--------REFLOW %d--------\n", gReflows++); +#endif + + + + #if 0 ListTag(stdout); printf(": begin reflow reason=%s", @@ -571,15 +889,16 @@ printf("\n"); //----------------------------------------------------------------------------------- // flow each child at the new sizes we have calculated. - FlowChildren(aPresContext, aDesiredSize, aReflowState, aStatus, rect); + mInner->FlowChildren(aPresContext, aDesiredSize, aReflowState, aStatus, incrementalChild, rect); + /* //----------------------------------------------------------------------------------- //------------------------- Adjust each childs x, y location------------------------- //----------------------------------------------------------------------------------- // set the x,y locations of each of our children. Taking into acount their margins, our border, // and insets. PlaceChildren(aPresContext,rect); - +*/ //----------------------------------------------------------------------------------- //------------------------- Add our border and insets in ---------------------------- //----------------------------------------------------------------------------------- @@ -609,34 +928,120 @@ ListTag(stdout); printf(": reflow done\n"); mInner->SanityCheck(); + +#ifdef DEBUG_REFLOW + gIndent--; +#endif + return NS_OK; } +void +nsBoxFrameInner::InvalidateCachesTo(nsIFrame* aTargetFrame) +{ + // walk up the tree from the target frame to the root invalidating each childs cached layout infomation + + nsIFrame* parent; + aTargetFrame->GetParent(&parent); + if (parent == nsnull) + return; + + + InvalidateCachesTo(parent); + + // only mark those children whose parents are boxes + nsIBox* ibox = nsnull; + if (NS_SUCCEEDED(parent->QueryInterface(nsIBox::GetIID(), (void**)&ibox)) && ibox) { + ibox->InvalidateCache(aTargetFrame); + } +} + + +void +nsBoxFrameInner::InvalidateAllCachesBelow(nsIPresContext* aPresContext, nsIFrame* aTargetFrame) +{ + // walk the whole tree under the target frame and clear each childs cached layout information + // but make sure we only mark children whose parent is a box. + nsIBox* ibox = nsnull; + if (NS_FAILED(aTargetFrame->QueryInterface(nsIBox::GetIID(), (void**)&ibox))) { + return; + } + + ibox->InvalidateCache(nsnull); + + nsIFrame* child = nsnull; + aTargetFrame->FirstChild(aPresContext, nsnull, &child); + + while (nsnull != child) + { + InvalidateAllCachesBelow(aPresContext, child); + nsresult rv = child->GetNextSibling(&child); + NS_ASSERTION(rv == NS_OK,"failed to get next child"); + } +} + +void +nsBoxFrame::ComputeChildsNextPosition( nsIFrame* aChild, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect) +{ + if (mInner->mHorizontal) { + aNextX = aCurX + aCurrentChildSize.width; + switch (mInner->mValign) + { + case nsBoxFrameInner::vAlign_Top: + case nsBoxFrameInner::vAlign_BaseLine: + case nsBoxFrameInner::vAlign_Stretch: + case nsBoxFrameInner::vAlign_Default: + aCurY = aBoxRect.y; + break; + case nsBoxFrameInner::vAlign_Middle: + aCurY = aBoxRect.y + (aBoxRect.height/2 - aCurrentChildSize.height/2); + break; + case nsBoxFrameInner::vAlign_Bottom: + aCurY = aBoxRect.y + aBoxRect.height - aCurrentChildSize.height; + break; + } + } else { + aNextY = aCurY + aCurrentChildSize.height; + switch (mInner->mHalign) + { + case nsBoxFrameInner::hAlign_Left: + case nsBoxFrameInner::hAlign_Stretch: + case nsBoxFrameInner::hAlign_Default: + aCurX = aBoxRect.x; + break; + case nsBoxFrameInner::hAlign_Center: + aCurX = aBoxRect.x + (aBoxRect.width/2 - aCurrentChildSize.width/2); + break; + case nsBoxFrameInner::hAlign_Right: + aCurX = aBoxRect.x + aBoxRect.width - aCurrentChildSize.width; + break; + } + } +} /** * When all the childrens positions have been calculated and layed out. Flow each child * at its not size. */ nsresult -nsBoxFrame::FlowChildren(nsIPresContext* aPresContext, +nsBoxFrameInner::FlowChildren(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, - nsRect& rect) + nsIFrame*& aIncrementalChild, + nsRect& aRect) { - PRBool redraw = PR_FALSE; - //----------------------------------- - // first pass flow all fixed children - //----------------------------------- + // ------- set the childs positions --------- + + PRBool redraw = PR_FALSE; PRBool finished; nscoord passes = 0; nscoord changedIndex = -1; - //nscoord count = 0; - nsAutoString reason("initial"); - nsAutoString nextReason("initial"); - PRInt32 infoCount = mInner->mInfoList->GetCount(); + nsAutoString reason; + nsAutoString nextReason; + PRInt32 infoCount = mInfoList->GetCount(); PRBool* resized = new PRBool[infoCount]; for (int i=0; i < infoCount; i++) @@ -649,58 +1054,131 @@ nsBoxFrame::FlowChildren(nsIPresContext* aPresContext, // ok what we want to do if flow each child at the location given in the spring. // unfortunately after flowing a child it might get bigger. We have not control over this // so it the child gets bigger or smaller than we expected we will have to do a 2nd, 3rd, 4th pass to - // adjust. + // adjust. When we adjust make sure the new reason is resize. changedIndex = -1; - InvalidateChildren(); - LayoutChildrenInRect(rect); - + passes = 0; do - { + { + #ifdef DEBUG_REFLOW + if (passes > 0) { + AddIndents(); + printf("ChildResized doing pass: %d\n", passes); + } + #endif + finished = PR_TRUE; nscoord count = 0; - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); + nsCalculatedBoxInfo* info = mInfoList->GetFirst(); + + nscoord x = aRect.x; + nscoord y = aRect.y; + while (nsnull != info) { - nsIFrame* childFrame = info->frame; - NS_ASSERTION(info, "ERROR not info object!!"); + nsIFrame* childFrame = info->frame; + + NS_ASSERTION(info, "ERROR not info object!!"); // if we reached the index that changed we are done. - if (count == changedIndex) - break; + //if (count == changedIndex) + // break; - // We need to give our child at least the initial reflow. - // This is needed for iframes to create their webshell (bug 11762) - if (info->collapsed) - { - if (eReflowReason_Initial == aReflowState.reason) - { - FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, *info, redraw, reason); - } - } + // make collapsed children not show up + if (info->collapsed) { - else - { - // reflow if the child needs it or we are on a second pass - FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, *info, redraw, reason); + if (aReflowState.reason == eReflowReason_Initial) + { + FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, *info, x, y, PR_TRUE, aIncrementalChild, redraw, reason); + + // if the child got bigger then adjust our rect and all the children. + mOuter->ChildResized(childFrame, aDesiredSize, aRect, *info, resized, changedIndex, finished, count, nextReason); + } + + // ok if we are collapsed make sure the view and all its children + // are collapsed as well. + + nsRect rect(0,0,0,0); + childFrame->GetRect(rect); + if (rect.width > 0 || rect.height > 0) + { + childFrame->SizeTo(aPresContext, 0,0); + mOuter->CollapseChild(aPresContext, childFrame, PR_TRUE); + } + + /* + nsRect rect(0,0,0,0); + childFrame->GetRect(rect); + if (rect.width > 0 || rect.height > 0) { + nsIView* view; + childFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, childFrame, + view, nsnull); + } else { + // Re-position any child frame views + nsContainerFrame::PositionChildViews(aPresContext, childFrame); + } + } + */ + + } else { + + nscoord nextX = x; + nscoord nextY = y; + + mOuter->ComputeChildsNextPosition(childFrame, x, y, nextX, nextY, info->calculatedSize, aRect); + + // reflow if the child needs it or we are on a second pass + FlowChildAt(childFrame, aPresContext, aDesiredSize, aReflowState, aStatus, *info, x, y, PR_TRUE, aIncrementalChild, redraw, reason); // if the child got bigger then adjust our rect and all the children. - ChildResized(childFrame, aDesiredSize, rect, *info, resized, changedIndex, finished, count, nextReason); - } - + mOuter->ChildResized(childFrame, aDesiredSize, aRect, *info, resized, changedIndex, finished, count, nextReason); + + /* +#ifdef DEBUG_REFLOW + + if (!finished) { + AddIndents(); + printf("**** Child "); + nsFrame::ListTag(stdout, childFrame); + printf(" resized!******\n"); + AddIndents(); + char ch[100]; + nextReason.ToCString(ch,100); + printf("because (%s)\n", ch); + } +#endif + */ + + // always do 1 pass for now. + //finished = PR_TRUE; - info = info->next; - count++; - reason = nextReason; + // if the child resized then recompute it position. + if (!finished) { + mOuter->ComputeChildsNextPosition(childFrame, x, y, nextX, nextY, nsSize(aDesiredSize.width, aDesiredSize.height), aRect); + } + + x = nextX; + y = nextY; + + } + + info = info->next; + count++; } + // ok if something go bigger and we need to do another pass then + // the second pass will be reflow resize + reason = nextReason; + // if we get over 10 passes something probably when wrong. passes++; if (passes > 5) { - NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, - ("bug")); +// mOuter->NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, + // ("bug")); } //NS_ASSERTION(passes <= 10,"Error infinte loop too many passes"); @@ -713,11 +1191,11 @@ nsBoxFrame::FlowChildren(nsIPresContext* aPresContext, // redraw things if needed. if (redraw) { -#if DEBUG_REDRAW - ListTag(stdout); +#ifdef DEBUG_REDRAW + mInner->ListTag(stdout); printf("is being redrawn\n"); #endif - Invalidate(aPresContext, nsRect(0,0,mRect.width, mRect.height), PR_FALSE); + mOuter->Invalidate(aPresContext, nsRect(0,0,mOuter->mRect.width, mOuter->mRect.height), PR_FALSE); } delete[] resized; @@ -725,6 +1203,40 @@ nsBoxFrame::FlowChildren(nsIPresContext* aPresContext, return NS_OK; } +#ifdef DEBUG_REFLOW +void +nsBoxFrameInner::AddIndents() +{ + for(PRInt32 i=0; i < gIndent; i++) + { + printf(" "); + } +} +#endif + +#ifdef DEBUG_REFLOW +void +nsBoxFrameInner::MakeReason(nsIFrame* aFrame, const nsString& aText, nsString& aReason) +{ + nsAutoString type; + nsIFrameDebug* frameDebug; + + if (NS_SUCCEEDED(aFrame->QueryInterface(nsIFrameDebug::GetIID(), (void**)&frameDebug))) { + frameDebug->GetFrameName(type); + } + + char address[100]; + sprintf(address, "@%p", aFrame); + + aReason = "("; + aReason += type; + aReason += address; + aReason += " "; + aReason += aText; + aReason += ")"; +} +#endif + void nsBoxFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason) { @@ -747,7 +1259,10 @@ nsBoxFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, ns // relayout everything InvalidateChildren(); LayoutChildrenInRect(aRect); - aReason = "child's height got bigger"; +#ifdef DEBUG_REFLOW + mInner->MakeReason(aFrame, "height got bigger", aReason); +#endif + } else if (aDesiredSize.width > aInfo.calculatedSize.width) { // if the child is wider than we anticipated. This can happend for children that we were not able to get a // take on their min width. Like text, or tables. @@ -795,7 +1310,10 @@ nsBoxFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, ns LayoutChildrenInRect(aRect); aFinished = PR_FALSE; aChangedIndex = aIndex; - aReason = "child's width got bigger"; +#ifdef DEBUG_REFLOW + mInner->MakeReason(aFrame, "width got bigger", aReason); +#endif + } } else { if ( aDesiredSize.width > aRect.width) { @@ -834,7 +1352,10 @@ nsBoxFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, ns // relayout everything InvalidateChildren(); LayoutChildrenInRect(aRect); - aReason = "child's height got bigger"; +#ifdef DEBUG_REFLOW + mInner->MakeReason(aFrame, "width got bigger", aReason); +#endif + } else if (aDesiredSize.height > aInfo.calculatedSize.height) { // our width now becomes the new size aInfo.calculatedSize.height = aDesiredSize.height; @@ -856,7 +1377,10 @@ nsBoxFrame::ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, ns LayoutChildrenInRect(aRect); aFinished = PR_FALSE; aChangedIndex = aIndex; - aReason = "child's width got bigger"; +#ifdef DEBUG_REFLOW + mInner->MakeReason(aFrame, "height got bigger", aReason); +#endif + } } } @@ -913,18 +1437,24 @@ nsBoxFrame::DidReflow(nsIPresContext* aPresContext, nsresult rv = nsHTMLContainerFrame::DidReflow(aPresContext, aStatus); NS_ASSERTION(rv == NS_OK,"DidReflow failed"); + /* nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); while (info) { // make collapsed children not show up if (info->collapsed) { + nsRect rect(0,0,0,0); + info->frame->GetRect(rect); + if (rect.width == 0 && rect.height == 0) + return; + CollapseChild(aPresContext, info->frame, PR_TRUE); } info = info->next; } - + */ return rv; } @@ -953,6 +1483,7 @@ nsBoxFrame::PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect) childFrame->GetRect(rect); if (rect.width > 0 || rect.height > 0) { childFrame->SizeTo(aPresContext, 0,0); + CollapseChild(aPresContext, childFrame, PR_TRUE); } } else { const nsStyleSpacing* spacing; @@ -1019,26 +1550,64 @@ nsBoxFrame::PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect) */ nsresult -nsBoxFrame::FlowChildAt(nsIFrame* childFrame, - nsIPresContext* aPresContext, - nsHTMLReflowMetrics& desiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsCalculatedBoxInfo& aInfo, - PRBool& aRedraw, - nsString& aReason) +nsBoxFrameInner::FlowChildAt(nsIFrame* childFrame, + nsIPresContext* aPresContext, + nsHTMLReflowMetrics& desiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus, + nsCalculatedBoxInfo& aInfo, + nscoord aX, + nscoord aY, + PRBool aMoveFrame, + nsIFrame*& aIncrementalChild, + PRBool& aRedraw, + const nsString& aReason) { aStatus = NS_FRAME_COMPLETE; + PRBool needsReflow = PR_FALSE; nsReflowReason reason = aReflowState.reason; - PRBool shouldReflow = PR_TRUE; - // if the reason is incremental and the child is not marked as incremental. Then relow the child - // as a resize instead. - if (aInfo.isIncremental) - reason = eReflowReason_Incremental; - else if (reason == eReflowReason_Incremental) - reason = eReflowReason_Resize; - + switch(reason) + { + // if the child we are reflowing is the child we popped off the incremental + // reflow chain then we need to reflow it no matter what. + // if its not the child we got from the reflow chain then this child needs reflow + // because as a side effect of the incremental child changing aize andit needs to be resized. + // This will happen with a lot when a box that contains 2 children with different flexabilities + // if on child gets bigger the other is affected because it is proprotional to the first. + // so it might need to be resized. But we don't need to reflow it. If it is already the + // needed size then we will do nothing. + case eReflowReason_Incremental: + if (aIncrementalChild == aInfo.frame) { + needsReflow = PR_TRUE; + aIncrementalChild = nsnull; + } else { + reason = eReflowReason_Resize; + needsReflow = PR_FALSE; + } + + break; + + // if its dirty then see if the child we want to reflow is dirty. If it is then + // mark it as needing to be reflowed. + case eReflowReason_Dirty: + // get the frame state to see if it needs reflow + nsFrameState state; + aInfo.frame->GetFrameState(&state); + needsReflow = (state & NS_FRAME_IS_DIRTY) || (state & NS_FRAME_HAS_DIRTY_CHILDREN); + break; + + // if the a resize reflow then it doesn't need to be reflowed. Only if the size is different + // from the new size would we actually do a reflow + case eReflowReason_Resize: + needsReflow = PR_FALSE; + break; + + default: + needsReflow = PR_TRUE; + + } + // subtract out the childs margin and border const nsStyleSpacing* spacing; nsresult rv = childFrame->GetStyleData(eStyleStruct_Spacing, @@ -1053,11 +1622,11 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, // if we don't need a reflow then // lets see if we are already that size. Yes? then don't even reflow. We are done. - if (!aInfo.needsReflow && aInfo.calculatedSize.width != NS_INTRINSICSIZE && aInfo.calculatedSize.height != NS_INTRINSICSIZE) { - + if (!needsReflow && aInfo.calculatedSize.width != NS_INTRINSICSIZE && aInfo.calculatedSize.height != NS_INTRINSICSIZE) { + // if the new calculated size has a 0 width or a 0 height if ((currentRect.width == 0 || currentRect.height == 0) && (aInfo.calculatedSize.width == 0 || aInfo.calculatedSize.height == 0)) { - shouldReflow = PR_FALSE; + needsReflow = PR_FALSE; desiredSize.width = aInfo.calculatedSize.width - (margin.left + margin.right); desiredSize.height = aInfo.calculatedSize.height - (margin.top + margin.bottom); childFrame->SizeTo(aPresContext, desiredSize.width, desiredSize.height); @@ -1071,12 +1640,15 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, // don't reflow if we are already the right size if (currentRect.width == calcWidth && currentRect.height == calcHeight) - shouldReflow = PR_FALSE; + needsReflow = PR_FALSE; + else + needsReflow = PR_TRUE; + } } // ok now reflow the child into the springs calculated space - if (shouldReflow) { + if (needsReflow) { nsMargin border(0,0,0,0); spacing->GetBorderPadding(border); @@ -1127,7 +1699,7 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, // nsSize maxElementSize(0, 0); // desiredSize.maxElementSize = &maxElementSize; - + /* #if DEBUG_REFLOW ListTag(stdout); if (reason == eReflowReason_Incremental && aInfo.isIncremental) @@ -1140,11 +1712,56 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, aReason.ToCString(ch,100); printf("because (%s)\n", ch); #endif - // do the flow - // Note that we don't position the frame (or its view) now. If we knew - // where we were going to place the child, then it would be more - // efficient to position it now... + */ + +#ifdef DEBUG_REFLOW + + char* reflowReasonString; + + switch(reflowState.reason) + { + case eReflowReason_Initial: + reflowReasonString = "initial"; + break; + + case eReflowReason_Resize: + reflowReasonString = "resize"; + break; + case eReflowReason_Dirty: + reflowReasonString = "dirty"; + break; + case eReflowReason_StyleChange: + reflowReasonString = "stylechange"; + break; + case eReflowReason_Incremental: + reflowReasonString = "incremental"; + break; + default: + reflowReasonString = "unknown"; + break; + } + + AddIndents(); + nsFrame::ListTag(stdout, childFrame); + char ch[100]; + aReason.ToCString(ch,100); + + printf(" reason=%s %s\n",reflowReasonString,ch); +#endif + + // place the child and reflow childFrame->WillReflow(aPresContext); + + if (aMoveFrame) { + childFrame->MoveTo(aPresContext, aX + margin.left, aY + margin.top); + + nsIView* view; + childFrame->GetView(aPresContext, &view); + if (view) { + nsContainerFrame::PositionFrameView(aPresContext, childFrame, view); + } + } + childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); @@ -1193,9 +1810,11 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, if (min != 0) desiredSize.height = aInfo.calculatedSize.height - (margin.top + margin.bottom); } - } + + nsContainerFrame::FinishReflowChild(childFrame, aPresContext, desiredSize, aX + margin.left, aY + margin.top, NS_FRAME_NO_MOVE_FRAME); + /* // set the rect and size the view (if it has one).. Don't position the view // and sync its properties (like opacity) until later when we know its final // position @@ -1210,22 +1829,56 @@ nsBoxFrame::FlowChildAt(nsIFrame* childFrame, NS_RELEASE(vm); } childFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + */ // Stub out desiredSize.maxElementSize so that when go out of // scope, nothing bad happens! desiredSize.maxElementSize = nsnull; - - // clear out the incremental child, so that we don't flow it incrementally again - if (reason == eReflowReason_Incremental && aInfo.isIncremental) - aInfo.isIncremental = PR_FALSE; - } + } else { + if (aMoveFrame) { + nsPoint curOrigin; + childFrame->GetOrigin(curOrigin); + + // only if the origin changed + if ((curOrigin.x != aX) || (curOrigin.y != aY)) { + + childFrame->MoveTo(aPresContext, aX + margin.left, aY + margin.top); + + nsIView* view; + childFrame->GetView(aPresContext, &view); + if (view) + nsContainerFrame::PositionFrameView(aPresContext, childFrame, view); + else + nsContainerFrame::PositionChildViews(aPresContext, childFrame); + } + } + } + + // add the margin back in. The child should add its border automatically desiredSize.height += (margin.top + margin.bottom); desiredSize.width += (margin.left + margin.right); - aInfo.needsReflow = PR_FALSE; - +#ifdef DEBUG_REFLOW + if (aInfo.calculatedSize.height != NS_INTRINSICSIZE && desiredSize.height != aInfo.calculatedSize.height) + { + AddIndents(); + printf("**** Child "); + nsFrame::ListTag(stdout, childFrame); + printf(" got taller!******\n"); + + } + if (aInfo.calculatedSize.width != NS_INTRINSICSIZE && desiredSize.width != aInfo.calculatedSize.width) + { + AddIndents(); + printf("**** Child "); + nsFrame::ListTag(stdout, childFrame); + printf(" got wider!******\n"); + + } +#endif + return NS_OK; } @@ -1299,11 +1952,6 @@ nsBoxFrame::GetInset(nsMargin& margin) { } -#define GET_WIDTH(size) (IsHorizontal() ? size.width : size.height) -#define GET_HEIGHT(size) (IsHorizontal() ? size.height : size.width) - -#define SET_WIDTH(size, coord) if (IsHorizontal()) { (size).width = (coord); } else { (size).height = (coord); } -#define SET_HEIGHT(size, coord) if (IsHorizontal()) { (size).height = (coord); } else { (size).width = (coord); } void nsBoxFrame::InvalidateChildren() @@ -1315,9 +1963,57 @@ nsBoxFrame::InvalidateChildren() } } +nsBoxFrameInner::Valignment +nsBoxFrameInner::GetVAlign() +{ + /* + if (mValign == nsBoxFrameInner::vAlign_Default) { + // look at vertical alignment + const nsStyleText* textStyle = + (const nsStyleText*)mOuter->mStyleContext->GetStyleData(eStyleStruct_Text); + + if (textStyle->mVerticalAlign.GetUnit() == eStyleUnit_Enumerated) { + + PRInt32 value = textStyle->mVerticalAlign.GetIntValue(); + + switch (value) + { + case NS_STYLE_VERTICAL_ALIGN_BASELINE: + return nsBoxFrameInner::vAlign_BaseLine; + break; + + case NS_STYLE_VERTICAL_ALIGN_TOP: + return nsBoxFrameInner::vAlign_Top; + break; + + case NS_STYLE_VERTICAL_ALIGN_BOTTOM: + return nsBoxFrameInner::vAlign_Bottom; + break; + + case NS_STYLE_VERTICAL_ALIGN_MIDDLE: + return nsBoxFrameInner::vAlign_Middle; + break; + } + } + } +*/ + + return mValign; +} + +nsBoxFrameInner::Halignment +nsBoxFrameInner::GetHAlign() +{ + return mHalign; +} + + void nsBoxFrame::LayoutChildrenInRect(nsRect& size) { + nsBoxFrameInner::Valignment valign = mInner->GetVAlign(); + nsBoxFrameInner::Halignment halign = mInner->GetHAlign(); + nsCalculatedBoxInfo* first = mInner->mInfoList->GetFirst(); if (!first) @@ -1343,11 +2039,82 @@ nsBoxFrame::LayoutChildrenInRect(nsRect& size) // figure out the direction of the box and get the correct value either the width or height nscoord pref = GET_WIDTH(info->prefSize); - // nscoord& max = GET_WIDTH(spring.maxSize); // Not used. + nscoord min = GET_WIDTH(info->minSize); - SET_HEIGHT(info->calculatedSize, GET_HEIGHT(size)); - + PRBool hstretch = (halign == nsBoxFrameInner::hAlign_Stretch || halign == nsBoxFrameInner::hAlign_Default); + PRBool vstretch = (valign == nsBoxFrameInner::vAlign_Stretch || valign == nsBoxFrameInner::vAlign_Default); + + + if ((mInner->mHorizontal && vstretch) || (!mInner->mHorizontal && hstretch)) + { + // stretch + nscoord h = GET_HEIGHT(size); + nscoord max = GET_HEIGHT(info->maxSize); + nscoord min = GET_HEIGHT(info->minSize); + if (h < min) + h = min; + else if (h > max) + h = max; + + SET_HEIGHT(info->calculatedSize, h); + } else { + // go to preferred size + nscoord h = GET_HEIGHT(info->prefSize); + nscoord s = GET_HEIGHT(size); + if (h > s) + h = s; + + nscoord max = GET_HEIGHT(info->maxSize); + nscoord min = GET_HEIGHT(info->minSize); + if (h < min) + h = min; + else if (h > max) + h = max; + + SET_HEIGHT(info->calculatedSize, h); + } + + /* + switch (mInner->mValign) + { + case nsBoxFrameInner::Top: + case nsBoxFrameInner::Bottom: + case nsBoxFrameInner::Right: + { + nscoord h = GET_HEIGHT(info->prefSize); + nscoord s = GET_HEIGHT(size); + if (h > s) + h = s; + + nscoord max = GET_HEIGHT(info->maxSize); + nscoord min = GET_HEIGHT(info->minSize); + if (h < min) + h = min; + else if (h > max) + h = max; + + SET_HEIGHT(info->calculatedSize, h); + } + break; + + case nsBoxFrameInner::Stretch: + { + nscoord h = GET_HEIGHT(size); + nscoord max = GET_HEIGHT(info->maxSize); + nscoord min = GET_HEIGHT(info->minSize); + if (h < min) + h = min; + else if (h > max) + h = max; + + SET_HEIGHT(info->calculatedSize, h); + } + break; + } + } + */ + if (pref < min) { pref = min; SET_WIDTH(info->prefSize, min); @@ -1420,7 +2187,7 @@ nsBoxFrame::LayoutChildrenInRect(nsRect& size) SET_WIDTH(info->calculatedSize, min); springConstantsRemaining -= info->flex; sizeRemaining += pref; - sizeRemaining -= calculated; + sizeRemaining -= min; info->sizeValid = PR_TRUE; limit = PR_TRUE; @@ -1429,7 +2196,7 @@ nsBoxFrame::LayoutChildrenInRect(nsRect& size) SET_WIDTH(info->calculatedSize, max); springConstantsRemaining -= info->flex; sizeRemaining += pref; - sizeRemaining -= calculated; + sizeRemaining -= max; info->sizeValid = PR_TRUE; limit = PR_TRUE; } @@ -1438,8 +2205,6 @@ nsBoxFrame::LayoutChildrenInRect(nsRect& size) } } - //PRInt32 stretchFactor = (springConstantsRemaining == 0) ? 0 : sizeRemaining/springConstantsRemaining; - nscoord& s = GET_WIDTH(size); s = 0; info = first; @@ -1488,30 +2253,13 @@ nsBoxFrame::GetChildBoxInfo(PRInt32 aIndex, nsBoxInfo& aSize) aSize = *info; } -void -nsBoxFrame::SetChildNeedsRecalc(PRInt32 aIndex, PRBool aRecalc) -{ - PRInt32 infoCount = mInner->mInfoList->GetCount(); - - NS_ASSERTION(aIndex >= 0 && aIndex < infoCount,"Index out of bounds!!"); - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - - for (PRInt32 i=0; i< infoCount; i++) { - if (i == aIndex) - break; - info = info->next; - } - - info->needsRecalc = PR_TRUE; -} - - // Marks the frame as dirty and generates an incremental reflow // command targeted at this frame nsresult nsBoxFrame::GenerateDirtyReflowCommand(nsIPresContext* aPresContext, nsIPresShell& aPresShell) { +/* nsCOMPtr reflowCmd; nsresult rv; @@ -1524,6 +2272,11 @@ nsBoxFrame::GenerateDirtyReflowCommand(nsIPresContext* aPresContext, } return rv; + */ + + // ask out parent to dirty things. + mState |= NS_FRAME_IS_DIRTY; + return mParent->ReflowDirtyChild(&aPresShell, this); } NS_IMETHODIMP @@ -1696,65 +2449,38 @@ nsBoxFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aR aSize.minSize += in; aSize.prefSize += in; + // make sure we can see the debug info + if (aSize.maxSize.width < debugInset.left + debugInset.right) + aSize.maxSize.width = debugInset.left + debugInset.right; + + if (aSize.maxSize.height < debugInset.top + debugInset.bottom) + aSize.maxSize.height = debugInset.top + debugInset.bottom; + return rv; } void nsBoxFrame::AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo) { - // now that we know our child's min, max, pref sizes figure OUR size from them. - AddSize(aChildInfo.minSize, aInfo.minSize, PR_FALSE); - AddSize(aChildInfo.maxSize, aInfo.maxSize, PR_TRUE); - AddSize(aChildInfo.prefSize, aInfo.prefSize, PR_FALSE); -} + // if the child is not flexible then its min, max, is the same as its pref. + if (aChildInfo.flex == 0) { -/** - * Boxes work differently that regular HTML elements. Each box knows if it needs to be reflowed or not - * So when a box gets an incremental reflow. It runs down all the children and marks them for reflow. If it - * Reaches a child that is not a box then it marks that child as incremental so when it is flowed next it - * will be flowed incrementally. - */ -NS_IMETHODIMP -nsBoxFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) -{ - nsIFrame* targetFrame = nsnull; - aReflowState.reflowCommand->GetTarget(targetFrame); - if (this == targetFrame) { - // if it has redraw us if we are the target - Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); - } + nsSize min(aChildInfo.minSize); + nsSize max(aChildInfo.maxSize); + nsSize pref(aChildInfo.prefSize); - incrementalChild = nsnull; - nsresult rv = NS_OK; + SET_WIDTH(min, GET_WIDTH(pref)); + SET_WIDTH(max, GET_WIDTH(pref)); - // Dirty any children that need it. - nsIFrame* frame; - aReflowState.reflowCommand->GetNext(frame); - - nsCalculatedBoxInfo* info = mInner->mInfoList->GetFirst(); - - while (info) - { - if (info->frame == frame) { - // clear the spring so it is recalculated on the flow - info->Clear(); - // can't use nsCOMPtr on non-refcounted things like frames - nsIBox* ibox = nsnull; - if (NS_SUCCEEDED(info->frame->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) - ibox->Dirty(aPresContext, aReflowState, incrementalChild); - else - incrementalChild = frame; - - if (incrementalChild == info->frame) - info->isIncremental = PR_TRUE; - - break; + AddSize(min, aInfo.minSize, PR_FALSE); + AddSize(max, aInfo.maxSize, PR_TRUE); + AddSize(pref, aInfo.prefSize, PR_FALSE); + } else { + // now that we know our child's min, max, pref sizes figure OUR size from them. + AddSize(aChildInfo.minSize, aInfo.minSize, PR_FALSE); + AddSize(aChildInfo.maxSize, aInfo.maxSize, PR_TRUE); + AddSize(aChildInfo.prefSize, aInfo.prefSize, PR_FALSE); } - - info = info->next; - } - - return rv; } NS_IMETHODIMP @@ -1780,7 +2506,19 @@ nsBoxFrame :: Paint ( nsIPresContext* aPresContext, } } + + /* +#ifdef DEBUG_REFLOW + if (mInner->reflowCount == gViewPortReflowCount) { + if (!mInner->mResized) + aRenderingContext.SetColor(NS_RGB(255,0,0)); + else + aRenderingContext.SetColor(NS_RGB(0,255,0)); + aRenderingContext.DrawRect(nsRect(0,0,mRect.width, mRect.height)); + } +#endif + */ return r; } @@ -1875,6 +2613,18 @@ nsBoxDebugInner::PaintSprings(nsIPresContext* aPresContext, nsIRenderingContext& else borderSize = size.height; + /* + if (mDebugChild == info->frame) + { + aRenderingContext.SetColor(NS_RGB(0,255,0)); + if (mOuter->mInner->mHorizontal) + aRenderingContext.FillRect(x, inner.y, size.width, debugBorder.top); + else + aRenderingContext.FillRect(inner.x, x, size.height, debugBorder.left); + aRenderingContext.SetColor(debugColor->mColor); + } + */ + DrawSpring(aPresContext, aRenderingContext, info->flex, x, y, borderSize, springSize); x += borderSize; } @@ -2007,7 +2757,7 @@ nsBoxFrame::AddRef(void) return NS_OK; } -NS_IMETHODIMP_(nsrefcnt) +NS_IMETHODIMP_(nsrefcnt) nsBoxFrame::Release(void) { return NS_OK; @@ -2015,6 +2765,7 @@ nsBoxFrame::Release(void) NS_INTERFACE_MAP_BEGIN(nsBoxFrame) NS_INTERFACE_MAP_ENTRY(nsIBox) + NS_INTERFACE_MAP_ENTRY(nsIFrameDebug) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox) NS_INTERFACE_MAP_END_INHERITING(nsHTMLContainerFrame) @@ -2022,8 +2773,14 @@ NS_INTERFACE_MAP_END_INHERITING(nsHTMLContainerFrame) NS_IMETHODIMP nsBoxFrame::GetFrameName(nsString& aResult) const { - aResult = "Box"; - return NS_OK; + + nsString id; + mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); + + aResult = "Box[id="; + aResult.Append(id); + aResult.Append("]"); + return NS_OK; } //static PRInt32 gBoxInfoCount = 0; @@ -2034,13 +2791,10 @@ nsCalculatedBoxInfoImpl::nsCalculatedBoxInfoImpl(nsIFrame* aFrame) // printf("created Info=%d\n",gBoxInfoCount); next = nsnull; - needsReflow = PR_TRUE; - needsRecalc = PR_TRUE; collapsed = PR_FALSE; calculatedSize.width = 0; calculatedSize.height = 0; sizeValid = PR_FALSE; - isIncremental = PR_FALSE; frame = aFrame; prefWidthIntrinsic = PR_TRUE; prefHeightIntrinsic = PR_TRUE; @@ -2057,17 +2811,16 @@ nsCalculatedBoxInfoImpl::Clear() { nsBoxInfo::Clear(); - needsReflow = PR_TRUE; - needsRecalc = PR_TRUE; collapsed = PR_FALSE; + needsRecalc = PR_TRUE; calculatedSize.width = 0; calculatedSize.height = 0; sizeValid = PR_FALSE; - prefWidthIntrinsic = PR_TRUE; - prefHeightIntrinsic = PR_TRUE; + prefWidthIntrinsic = PR_TRUE; + prefHeightIntrinsic = PR_TRUE; } @@ -2108,7 +2861,7 @@ nsBoxDebugInner::GetValue(PRInt32 a, PRInt32 b, char* ch) sprintf(ch, "(%d)", a); } -nsresult +PRBool nsBoxDebugInner::DisplayDebugInfoFor(nsIPresContext* aPresContext, nsPoint& aPoint, PRInt32& aCursor) @@ -2116,198 +2869,223 @@ nsBoxDebugInner::DisplayDebugInfoFor(nsIPresContext* aPresContext, nscoord x = aPoint.x; nscoord y = aPoint.y; - /* - // get it into our coordintate system by subtracting our parents offsets. - nsIFrame* parent = mOuter; - while(parent != nsnull) - { - // if we hit a scrollable view make sure we take into account - // how much we are scrolled. - nsIScrollableView* scrollingView; - nsIView* view; - parent->GetView(aPresContext, &view); - if (view) { - nsresult result = view->QueryInterface(kScrollViewIID, (void**)&scrollingView); - if (NS_SUCCEEDED(result)) { - nscoord xoff = 0; - nscoord yoff = 0; - scrollingView->GetScrollPosition(xoff, yoff); - x += xoff; - y += yoff; - } - } + // get the area inside our border. + nsRect or(0,0,mOuter->mRect.width, mOuter->mRect.height); - nsRect cr; - parent->GetRect(cr); - x -= cr.x; - y -= cr.y; - parent->GetParent(&parent); - } - */ + const nsStyleSpacing* spacing; + nsresult rv = mOuter->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + NS_ASSERTION(rv == NS_OK,"failed to get spacing"); + if (NS_FAILED(rv)) + return rv; + + nsMargin border; + spacing->GetBorderPadding(border); + + or.Deflate(border); - nsRect r(0,0,mOuter->mRect.width, mOuter->mRect.height); PRBool isHorizontal = mOuter->mInner->mHorizontal; - if (!r.Contains(nsPoint(x,y))) + if (!or.Contains(nsPoint(x,y))) return NS_OK; + //printf("%%%%%% inside box %%%%%%%\n"); + int count = 0; nsCalculatedBoxInfo* info = mOuter->GetInfoList()->GetFirst(); - while (info) - { - nsIFrame* childFrame = info->frame; - childFrame->GetRect(r); + nsMargin m; + mOuter->mInner->GetDebugInset(m); - // if we are not in the child. But in the spring above the child. - if (((isHorizontal && x >= r.x && x < r.x + r.width && y < r.y) || - (!isHorizontal && y >= r.y && y < r.y + r.height && x < r.x))) { - //printf("y=%d, r.y=%d\n",y,r.y); - aCursor = NS_STYLE_CURSOR_POINTER; - // found it but we already showed it. - if (mDebugChild == childFrame) - return NS_OK; + if ((isHorizontal && y < or.y + m.top) || + (!isHorizontal && x < or.x + m.left)) { + //printf("**** inside debug border *******\n"); + while (info) + { + nsIFrame* childFrame = info->frame; + nsRect r; + childFrame->GetRect(r); - nsCOMPtr content; - mOuter->mInner->GetContentOf(childFrame, getter_AddRefs(content)); + // if we are not in the child. But in the spring above the child. + if ((isHorizontal && x >= r.x && x < r.x + r.width) || + (!isHorizontal && y >= r.y && y < r.y + r.height)) { + aCursor = NS_STYLE_CURSOR_POINTER; + // found it but we already showed it. + if (mDebugChild == childFrame) + return PR_TRUE; - nsString id; - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); - char idValue[100]; - id.ToCString(idValue,100); + nsCOMPtr content; + mOuter->mInner->GetContentOf(childFrame, getter_AddRefs(content)); + + nsString id; + mOuter->mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); + char idValue[100]; + id.ToCString(idValue,100); - nsString kClass; - content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, kClass); - char kClassValue[100]; - kClass.ToCString(kClassValue,100); + nsString kClass; + mOuter->mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, kClass); + char kClassValue[100]; + kClass.ToCString(kClassValue,100); - nsCOMPtr tag; - content->GetTag(*getter_AddRefs(tag)); - nsString tagString; - tag->ToString(tagString); - char tagValue[100]; - tagString.ToCString(tagValue,100); + nsCOMPtr tag; + mOuter->mContent->GetTag(*getter_AddRefs(tag)); + nsString tagString; + tag->ToString(tagString); + char tagValue[100]; + tagString.ToCString(tagValue,100); - printf("--------------------\n"); - printf("Tag='%s', id='%s' class='%s'\n", tagValue, idValue, kClassValue); + + printf("----- "); + nsFrame::ListTag(stdout, mOuter); + printf(" Tag='%s', id='%s' class='%s'---------------\n", tagValue, idValue, kClassValue); - mDebugChild = childFrame; - nsCalculatedBoxInfoImpl aSize(childFrame); - aSize.prefSize.width = NS_INTRINSICSIZE; - aSize.prefSize.height = NS_INTRINSICSIZE; + content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); + id.ToCString(idValue,100); + + content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, kClass); + kClass.ToCString(kClassValue,100); - aSize.minSize.width = NS_INTRINSICSIZE; - aSize.minSize.height = NS_INTRINSICSIZE; + content->GetTag(*getter_AddRefs(tag)); + tag->ToString(tagString); + tagString.ToCString(tagValue,100); - aSize.maxSize.width = NS_INTRINSICSIZE; - aSize.maxSize.height = NS_INTRINSICSIZE; + printf("child #%d: ", count); + nsFrame::ListTag(stdout, childFrame); + printf("Tag='%s', id='%s' class='%s'\n", tagValue, idValue, kClassValue); - aSize.calculatedSize.width = NS_INTRINSICSIZE; - aSize.calculatedSize.height = NS_INTRINSICSIZE; + mDebugChild = childFrame; + nsCalculatedBoxInfoImpl aSize(childFrame); + aSize.prefSize.width = NS_INTRINSICSIZE; + aSize.prefSize.height = NS_INTRINSICSIZE; - aSize.flex = -1; + aSize.minSize.width = NS_INTRINSICSIZE; + aSize.minSize.height = NS_INTRINSICSIZE; - // add in the css min, max, pref - const nsStylePosition* position; - nsresult rv = childFrame->GetStyleData(eStyleStruct_Position, - (const nsStyleStruct*&) position); + aSize.maxSize.width = NS_INTRINSICSIZE; + aSize.maxSize.height = NS_INTRINSICSIZE; - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get position"); - if (NS_FAILED(rv)) - return rv; + aSize.calculatedSize.width = NS_INTRINSICSIZE; + aSize.calculatedSize.height = NS_INTRINSICSIZE; - // see if the width or height was specifically set - if (position->mWidth.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.width = position->mWidth.GetCoordValue(); - } + aSize.flex = -1; - if (position->mHeight.GetUnit() == eStyleUnit_Coord) { - aSize.prefSize.height = position->mHeight.GetCoordValue(); - } + // add in the css min, max, pref + const nsStylePosition* position; + nsresult rv = childFrame->GetStyleData(eStyleStruct_Position, + (const nsStyleStruct*&) position); + + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get position"); + if (NS_FAILED(rv)) + return PR_TRUE; + + // see if the width or height was specifically set + if (position->mWidth.GetUnit() == eStyleUnit_Coord) { + aSize.prefSize.width = position->mWidth.GetCoordValue(); + } + + if (position->mHeight.GetUnit() == eStyleUnit_Coord) { + aSize.prefSize.height = position->mHeight.GetCoordValue(); + } - // same for min size. Unfortunately min size is always set to 0. So for now - // we will assume 0 means not set. - if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinWidth.GetCoordValue(); - if (min != 0) - aSize.minSize.width = min; - } + // same for min size. Unfortunately min size is always set to 0. So for now + // we will assume 0 means not set. + if (position->mMinWidth.GetUnit() == eStyleUnit_Coord) { + nscoord min = position->mMinWidth.GetCoordValue(); + if (min != 0) + aSize.minSize.width = min; + } - if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { - nscoord min = position->mMinHeight.GetCoordValue(); - if (min != 0) - aSize.minSize.height = min; - } + if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) { + nscoord min = position->mMinHeight.GetCoordValue(); + if (min != 0) + aSize.minSize.height = min; + } - // and max - if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxWidth.GetCoordValue(); - aSize.maxSize.width = max; - } + // and max + if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) { + nscoord max = position->mMaxWidth.GetCoordValue(); + aSize.maxSize.width = max; + } - if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) { - nscoord max = position->mMaxHeight.GetCoordValue(); - aSize.maxSize.height = max; - } + if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) { + nscoord max = position->mMaxHeight.GetCoordValue(); + aSize.maxSize.height = max; + } - PRInt32 error; - nsAutoString value; + PRInt32 error; + nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) - { - value.Trim("%"); - aSize.flex = value.ToInteger(&error); - } + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsXULAtoms::flex, value)) + { + value.Trim("%"); + aSize.flex = value.ToInteger(&error); + } - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, value)) - { - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::width, value)) + { + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); - value.Trim("%"); + value.Trim("%"); - aSize.prefSize.width = NSIntPixelsToTwips(value.ToInteger(&error), p2t); - } + aSize.prefSize.width = NSIntPixelsToTwips(value.ToInteger(&error), p2t); + } - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, value)) - { - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); + if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, value)) + { + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); - value.Trim("%"); + value.Trim("%"); - aSize.prefSize.height = NSIntPixelsToTwips(value.ToInteger(&error), p2t); - } + aSize.prefSize.height = NSIntPixelsToTwips(value.ToInteger(&error), p2t); + } - char min[100]; - char pref[100]; - char max[100]; - char calc[100]; - char flex[100]; + char min[100]; + char pref[100]; + char max[100]; + char calc[100]; + char flex[100]; - GetValue(info->minSize, aSize.minSize, min); - GetValue(info->prefSize, aSize.prefSize, pref); - GetValue(info->maxSize, aSize.maxSize, max); - GetValue(info->calculatedSize, aSize.calculatedSize, calc); - GetValue(info->flex, aSize.flex, flex); + /* + nsSize c(info->calculatedSize); + if (c.width != NS_INTRINSICSIZE) + c.width -= inset.left + inset.right; + + if (c.height != NS_INTRINSICSIZE) + c.height -= inset.left + inset.right; + + */ + + GetValue(info->minSize, aSize.minSize, min); + GetValue(info->prefSize, aSize.prefSize, pref); + GetValue(info->maxSize, aSize.maxSize, max); + GetValue(info->calculatedSize, aSize.calculatedSize, calc); + GetValue(info->flex, aSize.flex, flex); - printf("min%s, pref%s, max%s, actual%s, flex=%s\n", - min, - pref, - max, - calc, - flex - ); - break; + printf("min%s, pref%s, max%s, actual%s, flex=%s\n\n", + min, + pref, + max, + calc, + flex + ); + + return PR_TRUE; + } + + info = info->next; + count++; } - - info = info->next; - count++; + } else { + mDebugChild = nsnull; } - return NS_OK; + + return PR_FALSE; } NS_IMETHODIMP @@ -2315,14 +3093,82 @@ nsBoxFrame::GetCursor(nsIPresContext* aPresContext, nsPoint& aPoint, PRInt32& aCursor) { - nsresult rv = nsHTMLContainerFrame::GetCursor(aPresContext, aPoint, aCursor); + nsPoint newPoint; + mInner->TranslateEventCoords(aPresContext, aPoint, newPoint); - if (mInner->mDebugInner) - mInner->mDebugInner->DisplayDebugInfoFor(aPresContext, aPoint, aCursor); + nsString id; + mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, id); + char idValue[100]; + id.ToCString(idValue,100); - return rv; + nsRect or(0,0,mRect.width, mRect.height); + + /// printf("----------Box id = %s-----------\n", idValue); + // printf("x=%d, r.x=%d r.x + r.width=%d\n",newPoint.x, or.x, or.x + or.width); + // printf("y=%d, r.y=%d r.y + r.height=%d\n",newPoint.y, or.y, or.y + or.height); + + //aCursor = NS_STYLE_CURSOR_POINTER; + + + // if we are in debug and we are in the debug area + // return our own cursor and dump the debug information. + if (mInner->mDebugInner) + { + if (mInner->mDebugInner->DisplayDebugInfoFor(aPresContext, newPoint, aCursor)) + return NS_OK; + } + + return nsHTMLContainerFrame::GetCursor(aPresContext, aPoint, aCursor); } +//XXX the event come's in in view relative coords, but really should +//be in frame relative coords by the time it hits our frame. + +// Translate an point that is relative to our view (or a containing +// view) into a localized pixel coordinate that is relative to the +// content area of this frame (inside the border+padding). +void +nsBoxFrameInner::TranslateEventCoords(nsIPresContext* aPresContext, + const nsPoint& aPoint, + nsPoint& aResult) +{ + nscoord x = aPoint.x; + nscoord y = aPoint.y; + + // If we have a view then the event coordinates are already relative + // to this frame; otherwise we have to adjust the coordinates + // appropriately. + nsIView* view; + mOuter->GetView(aPresContext, &view); + if (nsnull == view) { + nsPoint offset; + mOuter->GetOffsetFromView(aPresContext, offset, &view); + if (nsnull != view) { + x -= offset.x; + y -= offset.y; + } + } + + /* + const nsStyleSpacing* spacing; + nsresult rv = mOuter->GetStyleData(eStyleStruct_Spacing, + (const nsStyleStruct*&) spacing); + + nsMargin m(0,0,0,0); + spacing->GetBorderPadding(m); + + // Subtract out border and padding here so that the coordinates are + // now relative to the content area of this frame. + x -= m.left + m.right; + y -= m.top + m.bottom; +*/ + + aResult.x = x; + aResult.y = y; + +} + + nsresult nsBoxFrameInner::GetContentOf(nsIFrame* aFrame, nsIContent** aContent) { diff --git a/mozilla/layout/xul/base/src/nsBoxFrame.h b/mozilla/layout/xul/base/src/nsBoxFrame.h index 7660d5cb6e7..04ee2e84752 100644 --- a/mozilla/layout/xul/base/src/nsBoxFrame.h +++ b/mozilla/layout/xul/base/src/nsBoxFrame.h @@ -45,11 +45,8 @@ class nsCalculatedBoxInfo : public nsBoxInfo { public: nsSize calculatedSize; PRBool sizeValid; - PRBool needsReflow; - PRBool needsRecalc; PRBool collapsed; - PRBool isIncremental; - nsHTMLInfo* htmlInfo; + PRBool needsRecalc; nsCalculatedBoxInfo* next; nsIFrame* frame; PRBool prefWidthIntrinsic; @@ -68,9 +65,10 @@ class nsBoxFrame : public nsHTMLContainerFrame, public nsIBox { public: - friend nsresult NS_NewBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags = 0); + friend nsresult NS_NewBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); // gets the rect inside our border and debug border. If you wish to paint inside a box // call this method to get the rect so you don't draw on the debug border or outer border. + virtual void GetInnerRect(nsRect& aInner); NS_IMETHOD GetFrameForPoint(nsIPresContext* aPresContext, @@ -82,16 +80,10 @@ public: PRInt32& aCursor); - - // nsIBox methods - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& aIncrementalChild); - - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); - NS_IMETHOD DidReflow(nsIPresContext* aPresContext, nsDidReflowStatus aStatus); + NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild); NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -148,7 +140,6 @@ public: virtual ~nsBoxFrame(); virtual void GetChildBoxInfo(PRInt32 aIndex, nsBoxInfo& aSize); - virtual void SetChildNeedsRecalc(PRInt32 aIndex, PRBool aRecalc); // Paint one child frame virtual void PaintChild(nsIPresContext* aPresContext, @@ -157,27 +148,19 @@ public: nsIFrame* aFrame, nsFramePaintLayer aWhichLayer); + // nsIBox methods + NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); + NS_IMETHOD InvalidateCache(nsIFrame* aChild); + protected: - nsBoxFrame(PRUint32 aFlags = 0); + nsBoxFrame(); + virtual void GetRedefinedMinPrefMax(nsIPresContext* aPresContext, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize); virtual nsresult GetChildBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame* aFrame, nsCalculatedBoxInfo& aSize); - virtual nsresult FlowChildren(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsRect& availableSize); - - virtual nsresult FlowChildAt(nsIFrame* frame, - nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus, - nsCalculatedBoxInfo& aInfo, - PRBool& needsRedraw, - nsString& aReason); - + virtual void ComputeChildsNextPosition( nsIFrame* aChild, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect); virtual nsresult PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect); virtual void ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason); virtual void LayoutChildrenInRect(nsRect& size); diff --git a/mozilla/layout/xul/base/src/nsDeckFrame.cpp b/mozilla/layout/xul/base/src/nsDeckFrame.cpp index 796368415af..daacf19e6e7 100644 --- a/mozilla/layout/xul/base/src/nsDeckFrame.cpp +++ b/mozilla/layout/xul/base/src/nsDeckFrame.cpp @@ -267,6 +267,16 @@ nsDeckFrame::AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo) aInfo.maxSize.height = aChildInfo.maxSize.height; } + +void +nsDeckFrame::ComputeChildsNextPosition( nsIFrame* aChild, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect) +{ + // let everything layout on top of each other. + aCurX = aNextX = aBoxRect.x; + aCurY = aNextY = aBoxRect.y; +} + +/* nsresult nsDeckFrame::PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect) { @@ -299,6 +309,7 @@ nsDeckFrame::PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect) return NS_OK; } +*/ NS_IMETHODIMP nsDeckFrame::DidReflow(nsIPresContext* aPresContext, diff --git a/mozilla/layout/xul/base/src/nsDeckFrame.h b/mozilla/layout/xul/base/src/nsDeckFrame.h index 2031c2b956b..348e2ffb4e2 100644 --- a/mozilla/layout/xul/base/src/nsDeckFrame.h +++ b/mozilla/layout/xul/base/src/nsDeckFrame.h @@ -74,10 +74,16 @@ public: virtual PRIntn GetSkipSides() const { return 0; } + NS_IMETHOD GetFrameName(nsString& aResult) const + { + aResult = "Deck"; + return NS_OK; + } + protected: virtual nsIFrame* GetSelectedFrame(); - virtual nsresult PlaceChildren(nsIPresContext* aPresContext, nsRect& boxRect); + virtual void ComputeChildsNextPosition( nsIFrame* aChild, nscoord& aCurX, nscoord& aCurY, nscoord& aNextX, nscoord& aNextY, const nsSize& aCurrentChildSize, const nsRect& aBoxRect); virtual void ChildResized(nsIFrame* aFrame, nsHTMLReflowMetrics& aDesiredSize, nsRect& aRect, nsCalculatedBoxInfo& aInfo, PRBool* aResized, nscoord& aChangedIndex, PRBool& aFinished, nscoord aIndex, nsString& aReason); virtual void LayoutChildrenInRect(nsRect& size); virtual void AddChildSize(nsBoxInfo& aInfo, nsBoxInfo& aChildInfo); diff --git a/mozilla/layout/xul/base/src/nsIBox.h b/mozilla/layout/xul/base/src/nsIBox.h index 4cacd7c172b..53b9d98c5e2 100644 --- a/mozilla/layout/xul/base/src/nsIBox.h +++ b/mozilla/layout/xul/base/src/nsIBox.h @@ -58,8 +58,24 @@ public: static const nsIID& GetIID() { static nsIID iid = NS_IBOX_IID; return iid; } + /** Get the layout information object for this box. It will contains things like flexiblity, + * preferred, min, max sizes. + */ NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize)=0; - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild)=0; + + /** clear any cached layout info about our children. If the child is specifically specified + * then only clear cached layout information for that specific child. If the child is not + * then clear all childrens cached information. + */ + NS_IMETHOD InvalidateCache(nsIFrame* aChild)=0; + + /** + * Helper method from doing box reflow + */ + static void HandleRootBoxReflow(nsIPresContext* aPresContext, + nsIFrame* aBox, + const nsHTMLReflowState& aReflowState); + }; #endif diff --git a/mozilla/layout/xul/base/src/nsMenuBarFrame.h b/mozilla/layout/xul/base/src/nsMenuBarFrame.h index b156db44bbb..32a2e40f087 100644 --- a/mozilla/layout/xul/base/src/nsMenuBarFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuBarFrame.h @@ -101,6 +101,13 @@ public: PRBool IsValidItem(nsIContent* aContent); PRBool IsDisabled(nsIContent* aContent); + NS_IMETHOD GetFrameName(nsString& aResult) const + { + aResult = "MenuBar"; + return NS_OK; + } + + protected: nsMenuBarListener* mMenuBarListener; // The listener that tells us about key and mouse events. nsMenuListener* mKeyboardNavigator; diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index 6b0cd38fdc0..42550fa49a3 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -635,40 +635,71 @@ nsMenuFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - nsIFrame* frame = mPopupFrames.FirstChild(); + //NS_ASSERTION(aReflowState.reason != eReflowReason_Incremental,"Incremental Reflow not supported!"); + + nsIFrame* popupChild = mPopupFrames.FirstChild(); + + nsHTMLReflowState boxState(aReflowState); + + if (aReflowState.reason == eReflowReason_Incremental) { + + nsIFrame* incrementalChild; + + // get the child but don't pull it off + aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); + + // see if it is in the mPopupFrames list + nsIFrame* child = mPopupFrames.FirstChild(); + popupChild = nsnull; + + while (nsnull != child) + { + // if it is then flow the popup incrementally then flow + // us with a resize just to get our correct desired size. + if (child == incrementalChild) { + // pull it off now + aReflowState.reflowCommand->GetNext(incrementalChild); + + // we know what child + popupChild = child; + + // relow the box with resize just to get the + // aDesiredSize set correctly + boxState.reason = eReflowReason_Resize; + break; + } + + nsresult rv = child->GetNextSibling(&child); + NS_ASSERTION(rv == NS_OK,"failed to get next child"); + } + } + + if (popupChild) + { + + // Constrain the child's width and height to aAvailableWidth and aAvailableHeight + nsSize availSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, popupChild, + availSize); + kidReflowState.mComputedWidth = NS_UNCONSTRAINEDSIZE; + kidReflowState.mComputedHeight = NS_UNCONSTRAINEDSIZE; + nsHTMLReflowMetrics kidDesiredSize(aDesiredSize); - if (!frame || (rv != NS_OK)) - return rv; + nsRect rect; + popupChild->GetRect(rect); + nsresult rv = ReflowChild(popupChild, aPresContext, kidDesiredSize, kidReflowState, + rect.x, rect.y, NS_FRAME_NO_MOVE_VIEW, aStatus); - // Constrain the child's width and height to aAvailableWidth and aAvailableHeight - nsSize availSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, - availSize); - kidReflowState.mComputedWidth = NS_UNCONSTRAINEDSIZE; - kidReflowState.mComputedHeight = NS_UNCONSTRAINEDSIZE; + // Set the child's width and height to its desired size + // Note: don't position or size the view now, we'll do that in the + // DidReflow() function + popupChild->SizeTo(aPresContext, kidDesiredSize.width, kidDesiredSize.height); + popupChild->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); + } + + nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, boxState, aStatus); - // Reflow child - nscoord w = aDesiredSize.width; - nscoord h = aDesiredSize.height; - if (kidReflowState.reason == eReflowReason_Incremental) - kidReflowState.reason = eReflowReason_Resize; - - nsRect rect; - frame->GetRect(rect); - rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, - rect.x, rect.y, NS_FRAME_NO_MOVE_VIEW, aStatus); - - // Set the child's width and height to its desired size - // Note: don't position or size the view now, we'll do that in the - // DidReflow() function - frame->SizeTo(aPresContext, aDesiredSize.width, aDesiredSize.height); - frame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED); - - // Don't let it affect our size. - aDesiredSize.width = w; - aDesiredSize.height = h; return rv; } @@ -715,40 +746,6 @@ nsMenuFrame::DidReflow(nsIPresContext* aPresContext, return rv; } -// Overridden Box method. -NS_IMETHODIMP -nsMenuFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) -{ - incrementalChild = nsnull; - nsresult rv = NS_OK; - - // Dirty any children that need it. - nsIFrame* frame; - aReflowState.reflowCommand->GetNext(frame, PR_FALSE); - if (frame == nsnull) { - incrementalChild = this; - return rv; - } - - // Now call our original box frame method - rv = nsBoxFrame::Dirty(aPresContext, aReflowState, incrementalChild); - if (rv != NS_OK || incrementalChild) - return rv; - - nsIFrame* popup = mPopupFrames.FirstChild(); - if (popup && (frame == popup)) { - // In order for the child box to know what it needs to reflow, we need - // to call its Dirty method... - nsIBox* ibox; - if (NS_SUCCEEDED(popup->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) - ibox->Dirty(aPresContext, aReflowState, incrementalChild); - else - incrementalChild = frame; - } - - return rv; -} - NS_IMETHODIMP nsMenuFrame::ShortcutNavigation(PRUint32 aLetter, PRBool& aHandledFlag) { diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.h b/mozilla/layout/xul/base/src/nsMenuFrame.h index 7cf223965ef..f50f06560d2 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuFrame.h @@ -102,8 +102,6 @@ public: NS_IMETHOD DidReflow(nsIPresContext* aPresContext, nsDidReflowStatus aStatus); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild); - NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, @@ -153,6 +151,13 @@ public: void SetIsMenu(PRBool aIsMenu) { mIsMenu = aIsMenu; }; + NS_IMETHOD GetFrameName(nsString& aResult) const + { + aResult = "Menu"; + return NS_OK; + } + + protected: static void UpdateDismissalListener(nsIMenuParent* aMenuParent); void UpdateMenuType(nsIPresContext* aPresContext); diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp index 2ca74984f29..d313f903215 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -399,10 +399,6 @@ nsMenuPopupFrame::SyncViewWithFrame(nsIPresContext* aPresContext, } } - // - // At this point, we should be positioned where we're told. Ensure that we fit - // on the screen. - // nsCOMPtr window(do_QueryInterface(scriptGlobalObject)); nsCOMPtr screen; window->GetScreen(getter_AddRefs(screen)); @@ -480,13 +476,17 @@ NS_IMETHODIMP nsMenuPopupFrame::DidReflow(nsIPresContext* aPresContext, nsDidReflowStatus aStatus) { + return nsFrame::DidReflow(aPresContext, aStatus); + + /* // Copied from nsContainerFrame reflow WITHOUT the call // nsFrame::DidReflow(). nsFrame::DidReflow() will move us to the // wrong place. - nsresult result = NS_OK; /* = nsFrame::DidReflow(aPresContext, aStatus) */ + nsresult result = NS_OK; /* = nsFrame::DidReflow(aPresContext, aStatus) NS_FRAME_TRACE_OUT("nsContainerFrame::DidReflow"); return result; + */ } NS_IMETHODIMP diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h index 4fc614c0788..959cc416dc3 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h @@ -115,6 +115,13 @@ public: PRBool IsValidItem(nsIContent* aContent); PRBool IsDisabled(nsIContent* aContent); + NS_IMETHOD GetFrameName(nsString& aResult) const + { + aResult = "MenuPopup"; + return NS_OK; + } + + protected: // return true if the alignment is horizontal false if vertical virtual PRBool GetInitialAlignment(); diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp index db711fd48fd..71204c55e9f 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp @@ -201,35 +201,65 @@ nsPopupSetFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - nsIFrame* frame = GetActiveChild(); - - if (!frame || (rv != NS_OK)) - return rv; + nsIFrame* popupChild = GetActiveChild(); - // Constrain the child's width and height to aAvailableWidth and aAvailableHeight - nsSize availSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, - availSize); - kidReflowState.mComputedWidth = NS_UNCONSTRAINEDSIZE; - kidReflowState.mComputedHeight = NS_UNCONSTRAINEDSIZE; - - // Reflow child - nscoord w = aDesiredSize.width; - nscoord h = aDesiredSize.height; - - nsRect rect; - frame->GetRect(rect); - rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, - rect.x, rect.y, 0, aStatus); + nsHTMLReflowState boxState(aReflowState); - // Set the child's width and height to its desired size - FinishReflowChild(frame, aPresContext, aDesiredSize, rect.x, rect.y, 0); + if (aReflowState.reason == eReflowReason_Incremental) { + + nsIFrame* incrementalChild; + + // get the child but don't pull it off + aReflowState.reflowCommand->GetNext(incrementalChild, PR_FALSE); + + // see if it is in the mPopupFrames list + nsIFrame* child = mPopupFrames.FirstChild(); + popupChild = nsnull; + + while (nsnull != child) + { + // if it is then flow the popup incrementally then flow + // us with a resize just to get our correct desired size. + if (child == incrementalChild) { + // pull it off now + aReflowState.reflowCommand->GetNext(incrementalChild); + + // we know what child + popupChild = child; + + // relow the box with resize just to get the + // aDesiredSize set correctly + boxState.reason = eReflowReason_Resize; + break; + } + + nsresult rv = child->GetNextSibling(&child); + NS_ASSERTION(rv == NS_OK,"failed to get next child"); + } + } + + if (popupChild) { + // Constrain the child's width and height to aAvailableWidth and aAvailableHeight + nsSize availSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, popupChild, + availSize); + kidReflowState.mComputedWidth = NS_UNCONSTRAINEDSIZE; + kidReflowState.mComputedHeight = NS_UNCONSTRAINEDSIZE; + + // Reflow child + nsHTMLReflowMetrics kidDesiredSize(aDesiredSize); + + nsRect rect; + popupChild->GetRect(rect); + nsresult rv = ReflowChild(popupChild, aPresContext, kidDesiredSize, kidReflowState, + rect.x, rect.y, 0, aStatus); + + // Set the child's width and height to its desired size + FinishReflowChild(popupChild, aPresContext, kidDesiredSize, rect.x, rect.y, 0); + } + + nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, boxState, aStatus); - // Don't let it affect our size. - aDesiredSize.width = w; - aDesiredSize.height = h; - return rv; } @@ -260,45 +290,6 @@ nsPopupSetFrame::DidReflow(nsIPresContext* aPresContext, return nsBoxFrame::DidReflow(aPresContext, aStatus); } -// Overridden Box method. -NS_IMETHODIMP -nsPopupSetFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) -{ - incrementalChild = nsnull; - nsresult rv = NS_OK; - - // Dirty any children that need it. - nsIFrame* frame; - aReflowState.reflowCommand->GetNext(frame, PR_FALSE); - if (frame == nsnull) { - incrementalChild = this; - return rv; - } - - // Now call our original box frame method - rv = nsBoxFrame::Dirty(aPresContext, aReflowState, incrementalChild); - if (rv != NS_OK || incrementalChild) - return rv; - - nsIFrame* popup = GetActiveChild(); - if (popup && (frame == popup)) { - // An incremental reflow command is targeting something inside our - // hidden popup view. We can't actually return the child, since it - // won't ever be found by box. Instead return ourselves, so that box - // will later send us an incremental reflow command. - incrementalChild = this; - - // In order for the child box to know what it needs to reflow, we need - // to call its Dirty method... - nsIFrame* ignore; - nsIBox* ibox; - if (NS_SUCCEEDED(popup->QueryInterface(NS_GET_IID(nsIBox), (void**)&ibox)) && ibox) - ibox->Dirty(aPresContext, aReflowState, ignore); - } - - return rv; -} - NS_IMETHODIMP nsPopupSetFrame::RemoveFrame(nsIPresContext* aPresContext, nsIPresShell& aPresShell, diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.h b/mozilla/layout/xul/base/src/nsPopupSetFrame.h index d8ac563a5e3..fae729fe306 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.h +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.h @@ -72,8 +72,6 @@ public: NS_IMETHOD DidReflow(nsIPresContext* aPresContext, nsDidReflowStatus aStatus); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild); - NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, @@ -107,6 +105,13 @@ public: nsIFrame* GetActiveChild(); void GetActiveChildElement(nsIContent** aResult); + NS_IMETHOD GetFrameName(nsString& aResult) const + { + aResult = "PopupSet"; + return NS_OK; + } + + protected: void MarkAsGenerated(nsIContent* aPopupContent); void UpdateDismissalListener(nsIMenuParent* aMenuParent); diff --git a/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp b/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp index 313956a25c8..551b1961b6a 100644 --- a/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp +++ b/mozilla/layout/xul/base/src/nsProgressMeterFrame.cpp @@ -27,171 +27,14 @@ // See documentation in associated header file // -static float STRIPE_SKEW = 1.0; // pixels -static int STRIPE_WIDTH = 20; // pixels -static int ANIMATION_INCREMENT = 4; // pixels -static int ANIMATION_SPEED = 250; // miliseconds - -#include "nsINameSpaceManager.h" #include "nsProgressMeterFrame.h" -#include "nsIStyleContext.h" #include "nsCSSRendering.h" #include "nsIContent.h" #include "nsIPresContext.h" #include "nsHTMLAtoms.h" #include "nsXULAtoms.h" #include "nsINameSpaceManager.h" -#include "nsITimerCallback.h" -#include "nsITimer.h" -#include "nsIView.h" -#include "nsIViewManager.h" -#include "nsIReflowCommand.h" -#include "nsHTMLParts.h" -#include "nsIPresShell.h" - -class StripeTimer : public nsITimerCallback { -public: - StripeTimer(); - virtual ~StripeTimer(); - - NS_DECL_ISUPPORTS - - void AddFrame(nsIPresContext* aPresContext, nsProgressMeterFrame* aFrame); - - PRBool RemoveFrame(nsProgressMeterFrame* aFrame); - - PRInt32 FrameCount(); - - void Start(); - - void Stop(); - - NS_IMETHOD_(void) Notify(nsITimer *timer); - - PRInt32 GetFrameData(nsProgressMeterFrame* aFrame); - - struct FrameData { - nsIPresContext* mPresContext; // pres context associated with the frame - nsProgressMeterFrame* mFrame; - - - FrameData(nsIPresContext* aPresContext, - nsProgressMeterFrame* aFrame) - : mPresContext(aPresContext), mFrame(aFrame) {} - }; - - nsITimer* mTimer; - nsVoidArray mFrames; -}; - -static StripeTimer* gStripeAnimator; - -StripeTimer::StripeTimer() -{ - NS_INIT_REFCNT(); - mTimer = nsnull; -} - -StripeTimer::~StripeTimer() -{ - Stop(); -} - -void StripeTimer::Start() -{ - nsresult rv = NS_NewTimer(&mTimer); - if (NS_OK == rv) { - mTimer->Init(this, ANIMATION_SPEED, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); - } -} - -void StripeTimer::Stop() -{ - if (nsnull != mTimer) { - mTimer->Cancel(); - NS_RELEASE(mTimer); - } -} - -static NS_DEFINE_IID(kITimerCallbackIID, NS_ITIMERCALLBACK_IID); -NS_IMPL_ISUPPORTS(StripeTimer, kITimerCallbackIID); - -PRInt32 StripeTimer::GetFrameData(nsProgressMeterFrame* aFrame) -{ - PRInt32 i, n = mFrames.Count(); - for (i = 0; i < n; i++) { - FrameData* frameData = (FrameData*) mFrames.ElementAt(i); - - if (frameData->mFrame == aFrame) { - return i; - } - } - - return -1; -} - -void StripeTimer::AddFrame(nsIPresContext* aPresContext, nsProgressMeterFrame* aFrame) { - - // see if the frame is already here. - if (GetFrameData(aFrame) > -1) - return; - - // if not add it. - FrameData* frameData = new FrameData(aPresContext, aFrame); - mFrames.AppendElement(frameData); - if (1 == mFrames.Count()) { - Start(); - } -} - -PRBool StripeTimer::RemoveFrame(nsProgressMeterFrame* aFrame) { - PRBool rv = PR_FALSE; - PRInt32 i = GetFrameData(aFrame); - - if (i > -1) { - FrameData* frameData = (FrameData*)mFrames.ElementAt(i); - rv = mFrames.RemoveElementAt(i); - delete frameData; - } - if (0 == mFrames.Count()) { - Stop(); - } - return rv; -} - -PRInt32 StripeTimer::FrameCount() { - return mFrames.Count(); -} - -NS_IMETHODIMP_(void) StripeTimer::Notify(nsITimer *timer) -{ - // XXX hack to get auto-repeating timers; restart before doing - // expensive work so that time between ticks is more even -#ifndef REPEATING_TIMERS - Stop(); - Start(); -#endif - - PRInt32 i, n = mFrames.Count(); - for (i = 0; i < n; i++) { - FrameData* frameData = (FrameData*) mFrames.ElementAt(i); - frameData->mFrame->animate(); - - // Determine damaged area and tell view manager to redraw it - nsPoint offset; - nsRect bounds; - frameData->mFrame->GetRect(bounds); - nsIView* view; - frameData->mFrame->GetOffsetFromView(frameData->mPresContext, offset, &view); - nsIViewManager* vm; - view->GetViewManager(vm); - bounds.x = offset.x; - bounds.y = offset.y; - vm->UpdateView(view, bounds, 0); - NS_RELEASE(vm); - } -} - +#include "nsCOMPtr.h" // // NS_NewToolbarFrame // @@ -208,7 +51,6 @@ NS_NewProgressMeterFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; - // it->SetFlags(aFlags); *aNewFrame = it; return NS_OK; @@ -221,17 +63,9 @@ NS_NewProgressMeterFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) // nsProgressMeterFrame :: nsProgressMeterFrame ( ) { - // if we haven't created the timer create it. - if (nsnull == gStripeAnimator) { - gStripeAnimator = new StripeTimer(); - } - - NS_ADDREF(gStripeAnimator); - mProgress = float(0.0); mHorizontal = PR_TRUE; mUndetermined = PR_FALSE; - mStripeOffset = STRIPE_WIDTH; } // @@ -241,7 +75,6 @@ nsProgressMeterFrame :: nsProgressMeterFrame ( ) // nsProgressMeterFrame :: ~nsProgressMeterFrame ( ) { - gStripeAnimator->RemoveFrame(this); } NS_IMETHODIMP @@ -273,10 +106,6 @@ nsProgressMeterFrame::Init(nsIPresContext* aPresContext, mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::mode, mode); setMode(mode); - nsCOMPtr barPseudo ( dont_AddRef(NS_NewAtom(":progressmeter-stripe")) ); - aPresContext->ProbePseudoStyleContextFor(aContent, barPseudo, aContext, - PR_FALSE, getter_AddRefs(mBarStyle)); - return rv; } @@ -297,43 +126,6 @@ nsProgressMeterFrame::setProgress(nsAutoString progress) mProgress = float(v)/float(100); } -void -nsProgressMeterFrame::setSize(nsAutoString sizeString, int& size, PRBool& isPercent) -{ - // -1 means unset - size = -1; - - int length = sizeString.Length(); - if (length == 0) - return; - - char w[100]; - sizeString.ToCString(w,100); - - if (w[length-1] == '%') - isPercent = PR_TRUE; - else - isPercent = PR_FALSE; - - // convert to and integer - PRInt32 error; - PRInt32 v = sizeString.ToInteger(&error); - - // adjust to 0 and 100 - if (isPercent) { - if (v < 0) - v = 0; - else if (v > 100) - v = 100; - } - - // printf("size=%d\n", v); - - size = v; -} - - - void nsProgressMeterFrame::setAlignment(nsAutoString progress) { @@ -376,42 +168,35 @@ nsProgressMeterFrame :: Paint ( nsIPresContext* aPresContext, nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) - { - // get our border - const nsStyleSpacing* spacing = - (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border(0,0,0,0); - spacing->CalcBorderFor(this, border); + if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) + { + if (!mUndetermined) { + // get our border + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin border(0,0,0,0); + spacing->CalcBorderFor(this, border); - const nsStyleColor* colorStyle = - (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); + const nsStyleColor* colorStyle = + (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); - nscolor color = colorStyle->mColor; - - // figure our twips convertion ratio - // float p2t; - // aPresContext->GetScaledPixelsToTwips(p2t); - // nscoord onePixel = NSIntPixelsToTwips(1, p2t); + nscolor color = colorStyle->mColor; - // figure out our rectangle - nsRect rect(0,0,mRect.width, mRect.height); + // figure out our rectangle + nsRect rect(0,0,mRect.width, mRect.height); - // if its vertical then transform the coords to the X coordinate system - // and do our calculations there. - if (!mHorizontal) - rect = TransformYtoX(rect); - //CalcSize(aPresContext,rect.width,rect.height); - rect.x = border.left; - rect.y = border.top; - rect.width -= border.left*2; - rect.height -= border.top*2; + //CalcSize(aPresContext,rect.width,rect.height); + rect.x = border.left; + rect.y = border.top; + rect.width -= border.left + border.right; + rect.height -= border.top + border.bottom; + + // paint the current progress in blue + PaintBar(aPresContext, aRenderingContext, rect, mProgress, color); + } + } - // paint the current progress in blue - PaintBar(aPresContext, aRenderingContext, rect, mProgress, color); - } - return NS_OK; } // Paint @@ -422,233 +207,17 @@ nsProgressMeterFrame :: PaintBar ( nsIPresContext* aPresContext, float progress, nscolor color) { - // if the bar is undetermined then use the whole progress area. - // if the bar is determined then figure out the current progress and make - // the bar only that percent of the full progress meter. + nsRect bar(rect); - nsRect bar(rect); - - if (!mUndetermined) - { - nscoord p = (nscoord)(bar.width*progress); - bar.width = p; - } - - // fill the bar first then we will do the shading over it. - aRenderingContext.SetColor(color); - - if (mHorizontal) - aRenderingContext.FillRect(bar); - else { // if we are vert then transfrom to the y cood system. - nsRect nbar = TransformXtoY(bar); - aRenderingContext.FillRect(nbar); - } - - // draw the stripped barber shop if undetermined. - if (mUndetermined) - PaintBarStripped(aPresContext,aRenderingContext,bar, color); - else - PaintBarSolid(aPresContext,aRenderingContext,bar, color, 0); - -} - -nsRect -nsProgressMeterFrame::TransformXtoY(const nsRect& rect) -{ - return nsRect(rect.y, mRect.height - (rect.x + rect.width), rect.height, rect.width); -} - -nsRect -nsProgressMeterFrame::TransformYtoX(const nsRect& rect) -{ - return nsRect(mRect.width - (rect.y + rect.height), rect.x, rect.height, rect.width); -} - -nscolor -nsProgressMeterFrame::BrightenBy(nscolor c, PRUint8 amount) -{ - PRUint8 r = NS_GET_R(c); - PRUint8 g = NS_GET_G(c); - PRUint8 b = NS_GET_B(c); - - return NS_RGB(r+amount, g+amount, b+amount); -} - -PRUint8 -nsProgressMeterFrame::GetBrightness(nscolor c) -{ - - // get the biggest rgb component; - PRUint8 r = NS_GET_R(c); - PRUint8 g = NS_GET_G(c); - PRUint8 b = NS_GET_B(c); - - PRUint8 biggest = r; - - if (r > g && r > b) - biggest = r; - else if (g > r && g > b) - biggest = g; - else if (b > r && b > g) - biggest = b; - - return biggest; -} - -void -nsProgressMeterFrame::PaintBarSolid(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, - const nsRect& rect, nscolor color, float skew) -{ - - // figure out a pixel size - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - nscoord onePixel = NSIntPixelsToTwips(1, p2t); - - // how many pixel lines will fit? - int segments = 0; - if(onePixel) { - segments = (rect.height/2) / onePixel; - } else { - // Zero-height rect? Bail, don't paint. - return; - } - - // get the skew in pixels; - int skewedPixels = int(skew * onePixel); - - // we will draw from the top to center and from the bottom to center at the same time - // so we need 2 rects one for the top and one for the bottom - - // top. - - nsRect tr(rect); - tr.height= onePixel; - - // bottom - nsRect br(rect); - br.height = onePixel; - br.y = rect.y + 2*segments*onePixel; - br.x = rect.x + 2*segments*skewedPixels; - - // get the brightness of the color - PRUint8 brightness = GetBrightness(color); - - // we need to figure out how bright we can get. - PRUint8 units = 0; - if(segments) { - units = (255 - brightness)/segments; - } else { - // Divide-by-zero case, zero-height rect? - units = 0; - } - - // get a color we can set - nscolor c(color); - - for (int i=0; i <= segments; i++) - { - // set the color and fill the top and bottom lines - aRenderingContext.SetColor(c); + if (mHorizontal) + bar.width = (nscoord)(bar.width*progress); + else + bar.height = (nscoord)(bar.height*progress); - if (mHorizontal) { - aRenderingContext.FillRect(tr); - aRenderingContext.FillRect(br); - } else { - aRenderingContext.FillRect(TransformXtoY(tr)); - aRenderingContext.FillRect(TransformXtoY(br)); - } - // brighten the color - c = BrightenBy(c, units); - - // move one line down - tr.x += skewedPixels; - tr.y += onePixel; - - // move one line up - br.y -= onePixel; - br.x -= skewedPixels; - } + aRenderingContext.SetColor(color); + aRenderingContext.FillRect(bar); } - -void -nsProgressMeterFrame::PaintBarStripped(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, - const nsRect& r, nscolor color) -{ - // get stripe color from the style system - nsCOMPtr style (mBarStyle) ; - - nscolor altColor = NS_RGB(128,128,128); - - // if we got a style then get the color from it - if (style != 0) - { - const nsStyleColor* barColor = (const nsStyleColor*)style->GetStyleData(eStyleStruct_Color); - altColor = barColor->mColor; - } - - float skew = STRIPE_SKEW; - float stripeWidth = float(STRIPE_WIDTH); - - nsRect rect(r); - - PRBool clipState; - - // Clip so we don't render outside the inner rect - aRenderingContext.PushState(); - if (mHorizontal) - aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect, clipState); - else - aRenderingContext.SetClipRect(TransformXtoY(rect), nsClipCombine_kIntersect, clipState); - - - float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); - // nscoord onePixel = NSIntPixelsToTwips(1, p2t); - - int stripeWidthInTwips = (int)(stripeWidth * p2t); - - int offset = int(float(r.height) * skew); - - //make things a little bigger and just clip them - rect.width += offset*2; - rect.x -= (offset + int(float(mStripeOffset)*p2t)); - - int stripes = rect.width / (stripeWidthInTwips/2) + 2; - - nsRect sr(rect.x,rect.y,stripeWidthInTwips,rect.height); - - PRBool onoff = PR_FALSE; - nscolor c; - - - for (int i=0; i < stripes; i++) - { - if (onoff) - c = color; - else - c = altColor; - - PaintBarSolid(aPresContext,aRenderingContext,sr, c, skew); - sr.x += (stripeWidthInTwips/2); - - onoff = !onoff; - } - - aRenderingContext.PopState(clipState); -} - -void -nsProgressMeterFrame::animate() -{ - mStripeOffset -= ANIMATION_INCREMENT; - // printf("animate=%d\n", mStripeOffset); - if (mStripeOffset < 0) - mStripeOffset = STRIPE_WIDTH; -} - - // // Reflow // @@ -661,6 +230,7 @@ nsProgressMeterFrame :: Reflow ( nsIPresContext* aPresContext, nsReflowStatus& aStatus) { + // handle dirty and incremental reflow if (eReflowReason_Incremental == aReflowState.reason) { nsIFrame* targetFrame; @@ -669,13 +239,10 @@ nsProgressMeterFrame :: Reflow ( nsIPresContext* aPresContext, if (this == targetFrame) { Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); } + } else if (eReflowReason_Dirty == aReflowState.reason) { + Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); } - if (mUndetermined) - gStripeAnimator->AddFrame(aPresContext, this); - else - gStripeAnimator->RemoveFrame(this); - return nsLeafFrame::Reflow ( aPresContext, aDesiredSize, aReflowState, aStatus ); } // Reflow @@ -701,9 +268,9 @@ nsProgressMeterFrame::GetDesiredSize(nsIPresContext* aPresContext, void nsProgressMeterFrame::CalcSize(nsIPresContext* aPresContext, int& width, int& height) { - // make sure we convert to twips. + // set up a default size for the progress meter. float p2t; - aPresContext->GetScaledPixelsToTwips(&p2t); + aPresContext->GetScaledPixelsToTwips(&p2t); if (mHorizontal) { width = (int)(100 * p2t); @@ -714,6 +281,28 @@ nsProgressMeterFrame::CalcSize(nsIPresContext* aPresContext, int& width, int& he } } +NS_IMETHODIMP +nsProgressMeterFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) +{ + CalcSize(aPresContext, aSize.prefSize.width, aSize.prefSize.height); + aSize.minSize = aSize.prefSize; + return NS_OK; +} + +NS_INTERFACE_MAP_BEGIN(nsProgressMeterFrame) + NS_INTERFACE_MAP_ENTRY(nsIBox) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBox) +NS_INTERFACE_MAP_END_INHERITING(nsLeafFrame) + + + +NS_IMETHODIMP +nsProgressMeterFrame::InvalidateCache(nsIFrame* aChild) +{ + // we don't have any cached children + return NS_OK; +} + NS_IMETHODIMP nsProgressMeterFrame::AttributeChanged(nsIPresContext* aPresContext, nsIContent* aChild, @@ -744,8 +333,9 @@ nsProgressMeterFrame::AttributeChanged(nsIPresContext* aPresContext, setMode(newValue); // needs to reflow so we start the timer. - if (aHint != NS_STYLE_HINT_REFLOW) - Reflow(aPresContext); + /// if (aHint != NS_STYLE_HINT_REFLOW) + // Reflow(aPresContext); + aPresContext->StopAllLoadImagesFor(this); } else if (nsHTMLAtoms::align == aAttribute) { nsAutoString newValue; @@ -764,63 +354,24 @@ nsProgressMeterFrame::AttributeChanged(nsIPresContext* aPresContext, void nsProgressMeterFrame::Reflow(nsIPresContext* aPresContext) { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + // reflow - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - - nsCOMPtr reflowCmd; - nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this, - nsIReflowCommand::StyleChanged); - if (NS_SUCCEEDED(rv)) - shell->AppendReflowCommand(reflowCmd); + mState |= NS_FRAME_IS_DIRTY; + mParent->ReflowDirtyChild(shell, this); } void nsProgressMeterFrame::Redraw(nsIPresContext* aPresContext) { nsRect frameRect; - GetRect(frameRect); - nsRect rect(0, 0, frameRect.width, frameRect.height); + GetRect(frameRect); + nsRect rect(0, 0, frameRect.width, frameRect.height); Invalidate(aPresContext, rect, PR_TRUE); } -NS_IMETHODIMP -nsProgressMeterFrame::GetAdditionalStyleContext(PRInt32 aIndex, - nsIStyleContext** aStyleContext) const -{ - NS_PRECONDITION(nsnull != aStyleContext, "null OUT parameter pointer"); - if (aIndex < 0) { - return NS_ERROR_INVALID_ARG; - } - *aStyleContext = nsnull; - switch (aIndex) { - case NS_PROGRESS_METER_STRIPE_CONTEXT_INDEX: - *aStyleContext = mBarStyle; - NS_IF_ADDREF(*aStyleContext); - break; - default: - return NS_ERROR_INVALID_ARG; - } - return NS_OK; -} - -NS_IMETHODIMP -nsProgressMeterFrame::SetAdditionalStyleContext(PRInt32 aIndex, - nsIStyleContext* aStyleContext) -{ - if (aIndex < 0) { - return NS_ERROR_INVALID_ARG; - } - switch (aIndex) { - case NS_PROGRESS_METER_STRIPE_CONTEXT_INDEX: - mBarStyle = aStyleContext; - break; - } - return NS_OK; -} - - diff --git a/mozilla/layout/xul/base/src/nsProgressMeterFrame.h b/mozilla/layout/xul/base/src/nsProgressMeterFrame.h index b74994cfd2d..8abdfaf666e 100644 --- a/mozilla/layout/xul/base/src/nsProgressMeterFrame.h +++ b/mozilla/layout/xul/base/src/nsProgressMeterFrame.h @@ -45,18 +45,14 @@ #include "nsLeafFrame.h" #include "nsColor.h" -#include "nsCOMPtr.h" -#include "nsIStyleContext.h" -#include "nsIPresContext.h" #include "prtypes.h" +#include "nsIBox.h" class nsIPresContext; class nsIStyleContext; -#define NS_PROGRESS_METER_STRIPE_CONTEXT_INDEX 1 - -class nsProgressMeterFrame : public nsLeafFrame +class nsProgressMeterFrame : public nsLeafFrame, nsIBox { public: friend nsresult NS_NewProgressMeterFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); @@ -67,6 +63,13 @@ public: nsIStyleContext* aContext, nsIFrame* aPrevInFlow); + NS_IMETHOD_(nsrefcnt) AddRef(void) { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release(void) { return NS_OK; } + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); + NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); + + NS_IMETHOD InvalidateCache(nsIFrame* aChild); + // nsIHTMLReflow overrides NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -83,12 +86,6 @@ public: nsIAtom* aAttribute, PRInt32 aHint); - NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, - nsIStyleContext** aStyleContext) const; - NS_IMETHOD SetAdditionalStyleContext(PRInt32 aIndex, - nsIStyleContext* aStyleContext); - - virtual void animate(); virtual void Reflow(nsIPresContext* aPresContext); @@ -111,18 +108,6 @@ protected: nscolor color); - virtual void PaintBarStripped(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, - const nsRect& rect, nscolor color); - - virtual void PaintBarSolid(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, - const nsRect& rect, nscolor color, float skew); - - - virtual nscolor BrightenBy(nscolor color, PRUint8 amount); - virtual PRUint8 GetBrightness(nscolor c); - virtual nsRect TransformXtoY(const nsRect& rect); - virtual nsRect TransformYtoX(const nsRect& rect); - // pass-by-value not allowed for a coordinator because it corresponds 1-to-1 // with an element in the UI. nsProgressMeterFrame ( const nsProgressMeterFrame& aFrame ) ; // DO NOT IMPLEMENT @@ -133,11 +118,8 @@ private: void setProgress(nsAutoString progress); void setAlignment(nsAutoString alignment); void setMode(nsAutoString mode); - void setSize(nsAutoString s, int& size, PRBool& isPercent); - nsCOMPtr mBarStyle; float mProgress; PRBool mHorizontal; PRBool mUndetermined; - int mStripeOffset; }; // class nsProgressMeterFrame diff --git a/mozilla/layout/xul/base/src/nsRepeatService.cpp b/mozilla/layout/xul/base/src/nsRepeatService.cpp index f8a4a657abe..e87c8c68990 100644 --- a/mozilla/layout/xul/base/src/nsRepeatService.cpp +++ b/mozilla/layout/xul/base/src/nsRepeatService.cpp @@ -84,12 +84,18 @@ NS_IMETHODIMP_(void) nsRepeatService::Notify(nsITimer *timer) // if the repeat delay is the initial one reset it. if (mRepeatTimer) { mRepeatTimer->Cancel(); + } + + // do callback + if (mCallback) + mCallback->Notify(timer); + + // start timer again. + if (mRepeatTimer) { NS_NewTimer(getter_AddRefs(mRepeatTimer)); mRepeatTimer->Init(this, REPEAT_DELAY); } - if (mCallback) - mCallback->Notify(timer); } NS_IMPL_ISUPPORTS(nsRepeatService, NS_GET_IID(nsITimerCallback)); diff --git a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp index 965ac077731..9d795319c45 100644 --- a/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsScrollbarButtonFrame.cpp @@ -99,6 +99,7 @@ nsScrollbarButtonFrame::HandlePress(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { + MouseClicked(); nsRepeatService::GetInstance()->Start(this); return NS_OK; } @@ -121,7 +122,7 @@ NS_IMETHODIMP_(void) nsScrollbarButtonFrame::Notify(nsITimer *timer) void nsScrollbarButtonFrame::MouseClicked(nsIPresContext* aPresContext) { - MouseClicked(); + //MouseClicked(); } void diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.cpp b/mozilla/layout/xul/base/src/nsSliderFrame.cpp index 4f735515474..037fd204952 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSliderFrame.cpp @@ -60,8 +60,6 @@ #define DEBUG_SLIDER PR_FALSE -nscoord nsSliderFrame::gChange = 0; - nsresult NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame) @@ -80,14 +78,14 @@ NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame) } // NS_NewSliderFrame nsSliderFrame::nsSliderFrame() -: mCurPos(0), mScrollbarListener(nsnull) +: mCurPos(0), mScrollbarListener(nsnull),mChange(0) { } // stop timer nsSliderFrame::~nsSliderFrame() { - + mRedrawImmediate = PR_FALSE; } nsresult NS_CreateAnonymousNode(nsIContent* aParent, nsIAtom* aTag, PRInt32 aNameSpaceId, nsCOMPtr& aNewNode); @@ -227,13 +225,17 @@ nsSliderFrame::AttributeChanged(nsIPresContext* aPresContext, aAttribute == nsXULAtoms::increment)) { nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); - + + /* nsCOMPtr reflowCmd; rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this, nsIReflowCommand::StyleChanged); if (NS_SUCCEEDED(rv)) shell->AppendReflowCommand(reflowCmd); + */ + mState |= NS_FRAME_IS_DIRTY; + return mParent->ReflowDirtyChild(shell, this); } return rv; @@ -479,6 +481,10 @@ nsSliderFrame::HandleEvent(nsIPresContext* aPresContext, if (isDraggingThumb(aPresContext)) { + // we want to draw immediately if the user doing it directly with the + // mouse that makes redrawing much faster. + mRedrawImmediate = PR_TRUE; + switch (aEvent->message) { case NS_MOUSE_MOVE: { // convert coord to pixels @@ -549,6 +555,11 @@ nsSliderFrame::HandleEvent(nsIPresContext* aPresContext, AddListener(); DragThumb(aPresContext, PR_FALSE); } + + // we want to draw immediately if the user doing it directly with the + // mouse that makes redrawing much faster. Switch it back now. + mRedrawImmediate = PR_FALSE; + //return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); return NS_OK; } @@ -658,7 +669,7 @@ nsSliderFrame::CurrentPositionChanged(nsIPresContext* aPresContext) changeRect.UnionRect(thumbRect, newThumbRect); // redraw just the change - Invalidate(aPresContext, changeRect, PR_TRUE); + Invalidate(aPresContext, changeRect, mRedrawImmediate); if (mScrollbarListener) mScrollbarListener->PositionChanged(aPresContext, mCurPos, curpos); @@ -916,9 +927,10 @@ nsSliderFrame::HandlePress(nsIPresContext* aPresContext, if ((isHorizontal && aEvent->point.x < thumbRect.x) || (!isHorizontal && aEvent->point.y < thumbRect.y)) change = -1; - gChange = change; - nsRepeatService::GetInstance()->Start(this); + mChange = change; + mClickPoint = aEvent->point; PageUpDown(thumbFrame, change); + nsRepeatService::GetInstance()->Start(this); return NS_OK; } @@ -979,9 +991,42 @@ nsSliderFrame::SetScrollbarListener(nsIScrollbarListener* aListener) } NS_IMETHODIMP_(void) nsSliderFrame::Notify(nsITimer *timer) -{ - nsIFrame* thumbFrame = mFrames.FirstChild(); - PageUpDown(thumbFrame, gChange); +{ + PRBool stop = PR_FALSE; + + nsIFrame* thumbFrame = mFrames.FirstChild(); + nsRect thumbRect; + thumbFrame->GetRect(thumbRect); + + nsIContent* scrollbar = GetScrollBar(); + PRBool isHorizontal = IsHorizontal(scrollbar); + + // see if the thumb has moved passed our original click point. + // if it has we want to stop. + if (isHorizontal) { + if (mChange < 0) { + if (thumbRect.x < mClickPoint.x) + stop = PR_TRUE; + } else { + if (thumbRect.x + thumbRect.width > mClickPoint.x) + stop = PR_TRUE; + } + } else { + if (mChange < 0) { + if (thumbRect.y < mClickPoint.y) + stop = PR_TRUE; + } else { + if (thumbRect.y + thumbRect.width > mClickPoint.y) + stop = PR_TRUE; + } + } + + + if (stop) { + nsRepeatService::GetInstance()->Stop(); + } else { + PageUpDown(thumbFrame, mChange); + } } class nsThumbFrame : public nsTitledButtonFrame diff --git a/mozilla/layout/xul/base/src/nsSliderFrame.h b/mozilla/layout/xul/base/src/nsSliderFrame.h index 089cb27f257..4949d7bfdc6 100644 --- a/mozilla/layout/xul/base/src/nsSliderFrame.h +++ b/mozilla/layout/xul/base/src/nsSliderFrame.h @@ -233,7 +233,10 @@ private: // XXX Hack nsIPresContext* mPresContext; // weak reference - static nscoord gChange; + nscoord mChange; + nsPoint mClickPoint; + PRBool mRedrawImmediate; + }; // class nsSliderFrame #endif diff --git a/mozilla/layout/xul/base/src/nsSplitterFrame.cpp b/mozilla/layout/xul/base/src/nsSplitterFrame.cpp index 012421ba9fe..96d3a2e1352 100644 --- a/mozilla/layout/xul/base/src/nsSplitterFrame.cpp +++ b/mozilla/layout/xul/base/src/nsSplitterFrame.cpp @@ -50,6 +50,9 @@ #include "nsIStyleContext.h" #include "nsWidgetsCID.h" +#define REAL_TIME_DRAG PR_FALSE + + const PRInt32 kMaxZ = 0x7fffffff; //XXX: Shouldn't there be a define somewhere for MaxInt for PRInt32 @@ -64,19 +67,19 @@ public: PRInt32 index; }; -class nsSplitterFrameImpl : public nsIDOMMouseListener, public nsIDOMMouseMotionListener { +class nsSplitterFrameInner : public nsIDOMMouseListener, public nsIDOMMouseMotionListener { public: NS_DECL_ISUPPORTS - nsSplitterFrameImpl(nsSplitterFrame* aSplitter) + nsSplitterFrameInner(nsSplitterFrame* aSplitter) { - mSplitter = aSplitter; + mOuter = aSplitter; mRefCnt = 0; mPressed = PR_FALSE; } - virtual ~nsSplitterFrameImpl() {} + virtual ~nsSplitterFrameInner() {} // mouse listener virtual nsresult MouseDown(nsIDOMEvent* aMouseEvent); @@ -128,7 +131,9 @@ public: void Reverse(nsSplitterInfo*& aIndexes, PRInt32 aCount); CollapseDirection GetCollapseDirection(); - nsSplitterFrame* mSplitter; + void MoveSplitterBy(nsIPresContext* aPresContext, nscoord aDiff); + + nsSplitterFrame* mOuter; PRBool mDidDrag; nscoord mDragStartPx; nscoord mCurrentPos; @@ -147,13 +152,13 @@ public: }; -NS_IMPL_ISUPPORTS2(nsSplitterFrameImpl, nsIDOMMouseListener, nsIDOMMouseMotionListener) +NS_IMPL_ISUPPORTS2(nsSplitterFrameInner, nsIDOMMouseListener, nsIDOMMouseMotionListener) -nsSplitterFrameImpl::ResizeType -nsSplitterFrameImpl::GetResizeBefore() +nsSplitterFrameInner::ResizeType +nsSplitterFrameInner::GetResizeBefore() { nsCOMPtr content; - mSplitter->GetContent(getter_AddRefs(content)); + mOuter->GetContent(getter_AddRefs(content)); nsString value; content->GetAttribute(kNameSpaceID_None, nsXULAtoms::resizebefore, value); @@ -163,11 +168,11 @@ nsSplitterFrameImpl::GetResizeBefore() return Closest; } -nsSplitterFrameImpl::ResizeType -nsSplitterFrameImpl::GetResizeAfter() +nsSplitterFrameInner::ResizeType +nsSplitterFrameInner::GetResizeAfter() { nsCOMPtr content; - mSplitter->GetContent(getter_AddRefs(content)); + mOuter->GetContent(getter_AddRefs(content)); nsString value; content->GetAttribute(kNameSpaceID_None, nsXULAtoms::resizeafter, value); @@ -179,11 +184,11 @@ nsSplitterFrameImpl::GetResizeAfter() return Closest; } -nsSplitterFrameImpl::State -nsSplitterFrameImpl::GetState() +nsSplitterFrameInner::State +nsSplitterFrameInner::GetState() { nsCOMPtr content; - mSplitter->GetContent(getter_AddRefs(content)); + mOuter->GetContent(getter_AddRefs(content)); nsString value; content->GetAttribute(kNameSpaceID_None, nsXULAtoms::state, value); @@ -219,17 +224,17 @@ NS_NewSplitterFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ) nsSplitterFrame::nsSplitterFrame() { - mImpl = new nsSplitterFrameImpl(this); - mImpl->AddRef(); - mImpl->mChildInfosAfter = nsnull; - mImpl->mChildInfosBefore = nsnull; - mImpl->mState = nsSplitterFrameImpl::Open; + mInner = new nsSplitterFrameInner(this); + mInner->AddRef(); + mInner->mChildInfosAfter = nsnull; + mInner->mChildInfosBefore = nsnull; + mInner->mState = nsSplitterFrameInner::Open; } nsSplitterFrame::~nsSplitterFrame() { - mImpl->RemoveListener(); - mImpl->Release(); + mInner->RemoveListener(); + mInner->Release(); } // @@ -256,8 +261,8 @@ nsSplitterFrame::CreateAnonymousContent(nsIPresContext* aPresContext, // create a grippy if we have no children and teh collapse attribute is before or after. if (count == 0) { - nsSplitterFrameImpl::CollapseDirection d = mImpl->GetCollapseDirection(); - if (d != nsSplitterFrameImpl::None) + nsSplitterFrameInner::CollapseDirection d = mInner->GetCollapseDirection(); + if (d != nsSplitterFrameInner::None) { // create a spring nsCOMPtr content; @@ -314,7 +319,7 @@ nsSplitterFrame::AttributeChanged(nsIPresContext* aPresContext, if (grippy) grippy->AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint); } else if (aAttribute == nsXULAtoms::state) { - mImpl->UpdateState(); + mInner->UpdateState(); } return rv; @@ -338,6 +343,7 @@ nsSplitterFrame::Init(nsIPresContext* aPresContext, nsHTMLContainerFrame::CreateViewForFrame(aPresContext,this,aContext,PR_TRUE); nsIView* view; GetView(aPresContext, &view); +#if 1 view->SetContentTransparency(PR_TRUE); view->SetZIndex(kMaxZ); /* @@ -349,8 +355,21 @@ nsSplitterFrame::Init(nsIPresContext* aPresContext, &widgetData, nsnull); */ +#else + static NS_DEFINE_CID(kCChildCID, NS_CHILD_CID); + nsCOMPtr viewManager; + view->GetViewManager(*getter_AddRefs(viewManager)); + viewManager->SetViewContentTransparency(view, PR_TRUE); + viewManager->SetViewZIndex(view, kMaxZ); - mImpl->AddListener(aPresContext); + // Need to have a widget to appear on top of other widgets. + view->CreateWidget(kCChildCID); +#endif + + + mInner->mState = nsSplitterFrameInner::Open; + mInner->UpdateState(); + mInner->AddListener(aPresContext); return rv; } @@ -417,7 +436,7 @@ NS_IMETHODIMP nsSplitterFrame::GetFrameForPoint(nsIPresContext* aPresContext, nsIFrame** aFrame) { // if the mouse is captured always return us as the frame. - if (mImpl->IsMouseCaptured(aPresContext)) + if (mInner->IsMouseCaptured(aPresContext)) { *aFrame = this; return NS_OK; @@ -432,12 +451,12 @@ nsSplitterFrame::HandleEvent(nsIPresContext* aPresContext, { switch (aEvent->message) { case NS_MOUSE_MOVE: - mImpl->MouseDrag(aPresContext, aEvent); + mInner->MouseDrag(aPresContext, aEvent); break; case NS_MOUSE_RIGHT_BUTTON_UP: case NS_MOUSE_LEFT_BUTTON_UP: - mImpl->MouseUp(aPresContext, aEvent); + mInner->MouseUp(aPresContext, aEvent); break; } @@ -445,22 +464,33 @@ nsSplitterFrame::HandleEvent(nsIPresContext* aPresContext, } void -nsSplitterFrameImpl::MouseUp(nsIPresContext* aPresContext, nsGUIEvent* aEvent) +nsSplitterFrameInner::MouseUp(nsIPresContext* aPresContext, nsGUIEvent* aEvent) { if (IsMouseCaptured(aPresContext)) { AdjustChildren(aPresContext); AddListener(aPresContext); CaptureMouse(aPresContext, PR_FALSE); - mSplitter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "", PR_TRUE); + State newState = GetState(); + // if the state is dragging then make it Open. + if (newState == Dragging) + mOuter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "", PR_TRUE); + mPressed = PR_FALSE; + + //printf("MouseUp\n"); + } } void -nsSplitterFrameImpl::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent) +nsSplitterFrameInner::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent) { if (IsMouseCaptured(aPresContext)) { - PRBool isHorizontal = !mSplitter->IsHorizontal(); + + // printf("Dragging\n"); + + + PRBool isHorizontal = !mOuter->IsHorizontal(); // convert coord to pixels nscoord pos = isHorizontal ? aEvent->point.x : aEvent->point.y; @@ -476,7 +506,7 @@ nsSplitterFrameImpl::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent) nscoord start = startpx*onePixel; // get it into our coordintate system by subtracting our parents offsets. - nsIFrame* parent = mSplitter; + nsIFrame* parent = mOuter; while(parent != nsnull) { // if we hit a scrollable view make sure we take into account @@ -509,7 +539,7 @@ nsSplitterFrameImpl::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent) PRBool bounded; - if (resizeAfter == nsSplitterFrameImpl::Grow) + if (resizeAfter == nsSplitterFrameInner::Grow) bounded = PR_FALSE; else bounded = PR_TRUE; @@ -521,38 +551,53 @@ nsSplitterFrameImpl::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent) for (i=0; i < mChildInfosAfterCount; i++) mChildInfosAfter[i].changed = mChildInfosAfter[i].current; -// nscoord oldPos = pos; + nscoord oldPos = pos; ResizeChildTo(aPresContext, pos, mChildInfosBefore, mChildInfosAfter, mChildInfosBeforeCount, mChildInfosAfterCount, bounded); - /* - if (oldPos > 0 && oldPos > pos) + State currentState = GetState(); + CollapseDirection dir = GetCollapseDirection(); + + // if we are in a collapsed position + if ((oldPos > 0 && oldPos > pos && dir == After) || (oldPos < 0 && oldPos < pos && dir == Before)) { - printf("Collapse right\n"); - if (GetCollapseDirection() == After) { - mSplitter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "collapsed", PR_TRUE); - AdjustChildren(aPresContext); - AddListener(); - CaptureMouse(PR_FALSE); - mPressed = PR_FALSE; - return; + // and we are not collapsed then collapse + if (currentState == Dragging) { + if (oldPos > 0 && oldPos > pos) + { + //printf("Collapse right\n"); + if (GetCollapseDirection() == After) + { + mOuter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "collapsed", PR_TRUE); + + } + + } else if (oldPos < 0 && oldPos < pos) + { + //printf("Collapse left\n"); + if (GetCollapseDirection() == Before) + { + mOuter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "collapsed", PR_TRUE); + + } + } } + } else { + // if we are not in a collapsed position and we are not dragging make sure + // we are dragging. + if (currentState != Dragging) + mOuter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "dragging", PR_TRUE); + +#if REAL_TIME_DRAG + AdjustChildren(aPresContext); +#else + MoveSplitterBy(aPresContext, pos); +#endif } + + - if (oldPos < 0 && oldPos < pos) - { - printf("Collapse left\n"); - if (GetCollapseDirection() == Before) { - mSplitter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "collapsed", PR_TRUE); - AdjustChildren(aPresContext); - AddListener(); - CaptureMouse(PR_FALSE); - mPressed = PR_FALSE; - return; - } - } - */ // printf("----- resize ----- "); /* @@ -562,26 +607,33 @@ nsSplitterFrameImpl::MouseDrag(nsIPresContext* aPresContext, nsGUIEvent* aEvent) printf("after, index=%d, current=%d, changed=%d\n", mChildInfosAfter[i].index, mChildInfosAfter[i].current, mChildInfosAfter[i].changed); */ + /* nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); nsCOMPtr reflowCmd; - nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), mSplitter->mParent, + nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), mOuter->mParent, nsIReflowCommand::StyleChanged); if (NS_SUCCEEDED(rv)) shell->AppendReflowCommand(reflowCmd); + + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + mOuter->mState |= NS_FRAME_IS_DIRTY; + mOuter->mParent->ReflowDirtyChild(shell, mOuter); +*/ mDidDrag = PR_TRUE; } } void -nsSplitterFrameImpl::AddListener(nsIPresContext* aPresContext) +nsSplitterFrameInner::AddListener(nsIPresContext* aPresContext) { nsIFrame* thumbFrame = nsnull; - mSplitter->FirstChild(aPresContext, nsnull,&thumbFrame); + mOuter->FirstChild(aPresContext, nsnull,&thumbFrame); nsCOMPtr content; - mSplitter->GetContent(getter_AddRefs(content)); + mOuter->GetContent(getter_AddRefs(content)); nsCOMPtr reciever(do_QueryInterface(content)); @@ -590,10 +642,10 @@ nsSplitterFrameImpl::AddListener(nsIPresContext* aPresContext) } void -nsSplitterFrameImpl::RemoveListener() +nsSplitterFrameInner::RemoveListener() { nsCOMPtr content; - mSplitter->GetContent(getter_AddRefs(content)); + mOuter->GetContent(getter_AddRefs(content)); nsCOMPtr reciever(do_QueryInterface(content)); @@ -602,11 +654,11 @@ nsSplitterFrameImpl::RemoveListener() } nsresult -nsSplitterFrameImpl :: CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents) +nsSplitterFrameInner :: CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents) { // get its view nsIView* view = nsnull; - mSplitter->GetView(aPresContext, &view); + mOuter->GetView(aPresContext, &view); nsCOMPtr viewMan; PRBool result; //nsCOMPtr widget; @@ -631,11 +683,11 @@ nsSplitterFrameImpl :: CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMo } PRBool -nsSplitterFrameImpl :: IsMouseCaptured(nsIPresContext* aPresContext) +nsSplitterFrameInner :: IsMouseCaptured(nsIPresContext* aPresContext) { // get its view nsIView* view = nsnull; - mSplitter->GetView(aPresContext, &view); + mOuter->GetView(aPresContext, &view); nsCOMPtr viewMan; if (view) { @@ -653,15 +705,14 @@ nsSplitterFrameImpl :: IsMouseCaptured(nsIPresContext* aPresContext) } nsresult -nsSplitterFrameImpl::MouseUp(nsIDOMEvent* aMouseEvent) +nsSplitterFrameInner::MouseUp(nsIDOMEvent* aMouseEvent) { - // printf("Released\n"); mPressed = PR_FALSE; return NS_OK; } nsresult -nsSplitterFrameImpl::MouseDown(nsIDOMEvent* aMouseEvent) +nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent) { mCurrentPos = 0; mPressed = PR_TRUE; @@ -669,12 +720,12 @@ nsSplitterFrameImpl::MouseDown(nsIDOMEvent* aMouseEvent) mDidDrag = PR_FALSE; nsIFrame* parent = nsnull; - mSplitter->GetParent(&parent); + mOuter->GetParent(&parent); mParentBox = (nsBoxFrame*)parent; // get our index - nscoord childIndex = nsFrameNavigator::IndexOf(mSplitter->mPresContext, mParentBox, mSplitter); - PRInt32 childCount = nsFrameNavigator::CountFrames(mSplitter->mPresContext, mParentBox); + nscoord childIndex = nsFrameNavigator::IndexOf(mOuter->mPresContext, mParentBox, mOuter); + PRInt32 childCount = nsFrameNavigator::CountFrames(mOuter->mPresContext, mParentBox); // if its 0 or the last index then stop right here. if (childIndex == 0 || childIndex == childCount-1) { @@ -699,7 +750,7 @@ nsSplitterFrameImpl::MouseDown(nsIDOMEvent* aMouseEvent) mChildInfosAfterCount = 0; nsIFrame* childFrame = nsnull; - mParentBox->FirstChild(mSplitter->mPresContext, nsnull, &childFrame); + mParentBox->FirstChild(mOuter->mPresContext, nsnull, &childFrame); while (nsnull != childFrame) { @@ -768,17 +819,17 @@ nsSplitterFrameImpl::MouseDown(nsIDOMEvent* aMouseEvent) nsRect vr(0,0,0,0); nsIView *v; - mSplitter->GetView(mSplitter->mPresContext, &v); + mOuter->GetView(mOuter->mPresContext, &v); v->GetBounds(vr); PRInt32 c = 0; if (isHorizontal) { mouseEvent->GetClientX(&c); - mSplitterPos = mSplitter->mRect.x; + mSplitterPos = mOuter->mRect.x; mSplitterViewPos = vr.x; } else { mouseEvent->GetClientY(&c); - mSplitterPos = mSplitter->mRect.y; + mSplitterPos = mOuter->mRect.y; mSplitterViewPos = vr.y; } @@ -790,30 +841,26 @@ nsSplitterFrameImpl::MouseDown(nsIDOMEvent* aMouseEvent) } nsresult -nsSplitterFrameImpl::MouseMove(nsIDOMEvent* aMouseEvent) +nsSplitterFrameInner::MouseMove(nsIDOMEvent* aMouseEvent) { //printf("Mouse move\n"); if (!mPressed) return NS_OK; - if (IsMouseCaptured(mSplitter->mPresContext)) + if (IsMouseCaptured(mOuter->mPresContext)) return NS_OK; - // if (mState == Collapsed) - // return NS_OK; - - - mSplitter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "dragging", PR_TRUE); + mOuter->mContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::state, "dragging", PR_TRUE); RemoveListener(); - CaptureMouse(mSplitter->mPresContext, PR_TRUE); + CaptureMouse(mOuter->mPresContext, PR_TRUE); return NS_OK; } void -nsSplitterFrameImpl::Reverse(nsSplitterInfo*& aChildInfos, PRInt32 aCount) +nsSplitterFrameInner::Reverse(nsSplitterInfo*& aChildInfos, PRInt32 aCount) { nsSplitterInfo* infos = new nsSplitterInfo[aCount]; @@ -824,11 +871,11 @@ nsSplitterFrameImpl::Reverse(nsSplitterInfo*& aChildInfos, PRInt32 aCount) aChildInfos = infos; } -nsSplitterFrameImpl::CollapseDirection -nsSplitterFrameImpl::GetCollapseDirection() +nsSplitterFrameInner::CollapseDirection +nsSplitterFrameInner::GetCollapseDirection() { nsString value; - if (NS_CONTENT_ATTR_HAS_VALUE == mSplitter->mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::collapse, value)) + if (NS_CONTENT_ATTR_HAS_VALUE == mOuter->mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::collapse, value)) { if (value.EqualsIgnoreCase("before")) return Before; @@ -842,7 +889,7 @@ nsSplitterFrameImpl::GetCollapseDirection() } void -nsSplitterFrameImpl::UpdateState() +nsSplitterFrameInner::UpdateState() { @@ -871,7 +918,7 @@ nsSplitterFrameImpl::UpdateState() style = mCollapsedChildStyle; } else if ((mState == Open || mState == Dragging) && newState == Collapsed) { // when clicked see if we are in a splitter. - nsIFrame* splitter = mSplitter; + nsIFrame* splitter = mOuter; // get the splitters content node nsCOMPtr content; @@ -884,7 +931,7 @@ nsSplitterFrameImpl::UpdateState() // find the child just in the box just before the splitter. If we are not currently collapsed then // then get the childs style attribute and store it. Then set the child style attribute to be display none. // if we are already collapsed then set the child's style back to our stored value. - nsIFrame* child = nsFrameNavigator::GetChildBeforeAfter(mSplitter->mPresContext, splitter,(d == Before)); + nsIFrame* child = nsFrameNavigator::GetChildBeforeAfter(mOuter->mPresContext, splitter,(d == Before)); if (child == nsnull) return; @@ -908,24 +955,22 @@ nsSplitterFrameImpl::UpdateState() } void -nsSplitterFrameImpl::AdjustChildren(nsIPresContext* aPresContext) +nsSplitterFrameInner::AdjustChildren(nsIPresContext* aPresContext) { PRBool isHorizontal = mParentBox->IsHorizontal(); AdjustChildren(aPresContext, mChildInfosBefore, mChildInfosBeforeCount, isHorizontal); AdjustChildren(aPresContext, mChildInfosAfter, mChildInfosAfterCount, isHorizontal); - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); - nsCOMPtr reflowCmd; - nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), mParentBox, - nsIReflowCommand::StyleChanged); - if (NS_SUCCEEDED(rv)) - shell->AppendReflowCommand(reflowCmd); + mOuter->mState |= NS_FRAME_IS_DIRTY; + mOuter->mParent->ReflowDirtyChild(shell, mOuter->mParent); + } void -nsSplitterFrameImpl::AdjustChildren(nsIPresContext* aPresContext, nsSplitterInfo* aChildInfos, PRInt32 aCount, PRBool aIsHorizontal) +nsSplitterFrameInner::AdjustChildren(nsIPresContext* aPresContext, nsSplitterInfo* aChildInfos, PRInt32 aCount, PRBool aIsHorizontal) { // printf("------- AdjustChildren------\n"); @@ -970,13 +1015,13 @@ nsSplitterFrameImpl::AdjustChildren(nsIPresContext* aPresContext, nsSplitterInfo sprintf(ch,"%d",pref/onePixel); //printf("index=%d, pref=%s\n", i, ch); content->SetAttribute(kNameSpaceID_None, attribute, ch, PR_FALSE); - mParentBox->SetChildNeedsRecalc(index, PR_TRUE); + mParentBox->InvalidateCache(childFrame); } } void -nsSplitterFrameImpl::AddRemoveSpace(nscoord aDiff, +nsSplitterFrameInner::AddRemoveSpace(nscoord aDiff, nsSplitterInfo* aChildInfos, PRInt32 aCount, PRInt32& aSpaceLeft) @@ -1018,7 +1063,7 @@ nsSplitterFrameImpl::AddRemoveSpace(nscoord aDiff, */ void -nsSplitterFrameImpl::ResizeChildTo(nsIPresContext* aPresContext, +nsSplitterFrameInner::ResizeChildTo(nsIPresContext* aPresContext, nscoord& aDiff, nsSplitterInfo* aChildrenBeforeInfos, nsSplitterInfo* aChildrenAfterInfos, @@ -1041,23 +1086,28 @@ nsSplitterFrameImpl::ResizeChildTo(nsIPresContext* aPresContext, spaceLeft = 0; } } +} - const nsRect& r = mSplitter->mRect; + +void +nsSplitterFrameInner::MoveSplitterBy(nsIPresContext* aPresContext, nscoord aDiff) +{ + const nsRect& r = mOuter->mRect; nsRect vr; nsCOMPtr vm; nsIView *v; - mSplitter->GetView(aPresContext, &v); + mOuter->GetView(aPresContext, &v); v->GetViewManager(*getter_AddRefs(vm)); v->GetBounds(vr); nsRect invalid; if (mParentBox->IsHorizontal()) { - mSplitter->MoveTo(aPresContext, mSplitterPos + aDiff, r.y); + mOuter->MoveTo(aPresContext, mSplitterPos + aDiff, r.y); vm->MoveViewTo(v, mSplitterViewPos + aDiff, vr.y); - invalid.UnionRect(r,mSplitter->mRect); + invalid.UnionRect(r,mOuter->mRect); } else { - mSplitter->MoveTo(aPresContext, r.x, mSplitterPos + aDiff); + mOuter->MoveTo(aPresContext, r.x, mSplitterPos + aDiff); vm->MoveViewTo(v, vr.x, mSplitterViewPos + aDiff); - invalid.UnionRect(r,mSplitter->mRect); + invalid.UnionRect(r,mOuter->mRect); } // redraw immediately only what changed. This is animation so @@ -1065,3 +1115,4 @@ nsSplitterFrameImpl::ResizeChildTo(nsIPresContext* aPresContext, mParentBox->Invalidate(aPresContext, invalid, PR_TRUE); } + diff --git a/mozilla/layout/xul/base/src/nsSplitterFrame.h b/mozilla/layout/xul/base/src/nsSplitterFrame.h index 5e2b91e2128..a5d4fdfafb6 100644 --- a/mozilla/layout/xul/base/src/nsSplitterFrame.h +++ b/mozilla/layout/xul/base/src/nsSplitterFrame.h @@ -32,7 +32,7 @@ #include "nsIAnonymousContentCreator.h" class nsISupportsArray; -class nsSplitterFrameImpl; +class nsSplitterFrameInner; nsresult NS_NewSplitterFrame(nsIPresShell* aPresShell, nsIFrame** aResult) ; @@ -98,11 +98,10 @@ public: // return true if the alignment is horizontal false if vertical virtual PRBool GetInitialAlignment(); - private: - friend class nsSplitterFrameImpl; - nsSplitterFrameImpl* mImpl; + friend class nsSplitterFrameInner; + nsSplitterFrameInner* mInner; // XXX Hack nsIPresContext* mPresContext; // weak reference diff --git a/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp b/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp index 64c614ed419..7d8c342aef0 100644 --- a/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTitledButtonFrame.cpp @@ -176,32 +176,24 @@ nsTitledButtonFrame::AttributeChanged(nsIPresContext* aPresContext, PRInt32 aHint) { mNeedsLayout = PR_TRUE; - UpdateAttributes(aPresContext, aAttribute); + PRBool aResize; + PRBool aRedraw; + PRBool aUpdateAccessUnderline; + UpdateAttributes(aPresContext, aAttribute, aResize, aRedraw, aUpdateAccessUnderline); // added back in because boxes now handle only redraw what is reflowed. // reflow - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - - if (aHint != NS_STYLE_HINT_REFLOW && - (aAttribute == nsHTMLAtoms::align || aAttribute == nsHTMLAtoms::value || - aAttribute == nsHTMLAtoms::src || aAttribute == nsXULAtoms::crop)) { - nsCOMPtr reflowCmd; - nsresult rv = NS_NewHTMLReflowCommand(getter_AddRefs(reflowCmd), this, - nsIReflowCommand::StyleChanged); - if (NS_SUCCEEDED(rv)) - shell->AppendReflowCommand(reflowCmd); - } - - if (aAttribute == nsXULAtoms::accesskey || - aAttribute == nsHTMLAtoms::value || - aAttribute == nsXULAtoms::crop) { + if (aUpdateAccessUnderline) UpdateAccessUnderline(); - nsFrame::Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height), PR_FALSE); - } - // redraw - mRenderer->Redraw(aPresContext); + if (aResize) { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + mParent->ReflowDirtyChild(shell, this); + } else if (aRedraw) { + mRenderer->Redraw(aPresContext); + } #if !ONLOAD_CALLED_TOO_EARLY // onload handlers are called to early, so we have to do this code @@ -291,7 +283,8 @@ nsTitledButtonFrame::Init(nsIPresContext* aPresContext, mImageLoader.Init(this, UpdateImageFrame, nsnull, baseURL, src); NS_IF_RELEASE(baseURL); - UpdateAttributes(aPresContext, nsnull /* all */); + PRBool a,b,c; + UpdateAttributes(aPresContext, nsnull, a, b, c /* all */); // the following block is to append the accesskey to to mTitle if there is an accesskey // but the mTitle doesn't have the character @@ -344,50 +337,87 @@ nsTitledButtonFrame::GetImageSource(nsString& aResult) } void -nsTitledButtonFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute) +nsTitledButtonFrame::UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline) { + aResize = PR_FALSE; + aRedraw = PR_FALSE; + aUpdateAccessUnderline = PR_FALSE; + if (aAttribute == nsnull || aAttribute == nsHTMLAtoms::align) { - nsAutoString value; + PRIntn align; + nsAutoString value; mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::align, value); if (value.EqualsIgnoreCase(ALIGN_LEFT)) - mAlign = NS_SIDE_LEFT; + align = NS_SIDE_LEFT; else if (value.EqualsIgnoreCase(ALIGN_RIGHT)) - mAlign = NS_SIDE_RIGHT; + align = NS_SIDE_RIGHT; else if (value.EqualsIgnoreCase(ALIGN_BOTTOM)) - mAlign = NS_SIDE_BOTTOM; + align = NS_SIDE_BOTTOM; else - mAlign = NS_SIDE_TOP; + align = NS_SIDE_TOP; + + if (align != mAlign) { + aRedraw = PR_TRUE; + mAlign = align; + } } if (aAttribute == nsnull || aAttribute == nsXULAtoms::crop) { nsAutoString value; mContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::crop, value); + CroppingStyle cropType; if (value.EqualsIgnoreCase(CROP_LEFT)) - mCropType = CropLeft; + cropType = CropLeft; else if (value.EqualsIgnoreCase(CROP_CENTER)) - mCropType = CropCenter; + cropType = CropCenter; else if (value.EqualsIgnoreCase(CROP_RIGHT)) - mCropType = CropRight; + cropType = CropRight; else - mCropType = CropNone; + cropType = CropNone; + + if (cropType != mCropType) { + aResize = PR_TRUE; + mCropType = cropType; + aUpdateAccessUnderline = PR_TRUE; + } } if (aAttribute == nsnull || aAttribute == nsHTMLAtoms::value) { nsAutoString value; mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, value); - mTitle = value; + if (!value.Equals(mTitle)) { + /* + ListTag(stdout); + char a[100]; + char b[100]; + mTitle.ToCString(a,100); + value.ToCString(b,100); + + printf(" value changed '%s'->'%s'\n",a,b); + */ + aResize = PR_TRUE; + mTitle = value; + aUpdateAccessUnderline = PR_TRUE; + } } if (aAttribute == nsnull || aAttribute == nsHTMLAtoms::src) { - UpdateImage(aPresContext); + UpdateImage(aPresContext, aResize); } + + if (aAttribute == nsXULAtoms::accesskey) { + aUpdateAccessUnderline = PR_TRUE; + } + } void -nsTitledButtonFrame::UpdateImage(nsIPresContext* aPresContext) +nsTitledButtonFrame::UpdateImage(nsIPresContext* aPresContext, PRBool& aResize) { + aResize = PR_FALSE; + // see if the source changed // get the old image src nsAutoString oldSrc =""; @@ -399,7 +429,6 @@ nsTitledButtonFrame::UpdateImage(nsIPresContext* aPresContext) // see if the images are different if (!oldSrc.Equals(src)) { -// if (loadStatus & NS_IMAGE_LOAD_STATUS_IMAGE_READY) { if (!src.Equals("")) { mSizeFrozen = PR_FALSE; @@ -409,42 +438,9 @@ nsTitledButtonFrame::UpdateImage(nsIPresContext* aPresContext) mHasImage = PR_FALSE; } - mImageLoader.UpdateURLSpec(aPresContext, src); - //PRUint32 loadStatus = mImageLoader.GetLoadStatus(); + mImageLoader.UpdateURLSpec(aPresContext, src); - /* - // if the image is the same size only redraw otherwise reflow - PRBool reflow = PR_TRUE; - - if (mImageLoader.IsImageSizeKnown()) { - nsIImage* image = mImageLoader.GetImage(); - if ( image ) { - // imageLib stores width/height in pixels and we store it in twips. do the conversion - // before comparing. - float p2t = 0.0; - aPresContext->GetScaledPixelsToTwips(&p2t); - int imageWidth = NSIntPixelsToTwips(image->GetWidth(), p2t); - int imageHeight = NSIntPixelsToTwips(image->GetHeight(), p2t); - if ( imageWidth == mImageRect.width && imageHeight == mImageRect.height ) { - reflow = PR_FALSE; - Invalidate(nsRect(0, 0, mRect.width, mRect.height), PR_FALSE); - } - } - } - - if (reflow) { - // Force a reflow when the image size isn't already known - if (nsnull != mContent) { - nsIDocument* document = nsnull; - mContent->GetDocument(document); - if (nsnull != document) { - document->ContentChanged(mContent, nsnull); - NS_RELEASE(document); - } - } - } - */ - + aResize = PR_TRUE; } } @@ -941,7 +937,7 @@ nsTitledButtonFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - // redraw us on a reflow + // redraw us if we are flowed incremental and we are targeted or we are dirty. mNeedsAccessUpdate = PR_TRUE; if (eReflowReason_Incremental == aReflowState.reason) { nsIFrame* targetFrame; @@ -951,10 +947,22 @@ nsTitledButtonFrame::Reflow(nsIPresContext* aPresContext, if (this == targetFrame) { Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); } + } else if (eReflowReason_Dirty == aReflowState.reason) { + Invalidate(aPresContext, nsRect(0,0,mRect.width,mRect.height), PR_FALSE); } + + mNeedsLayout = PR_TRUE; nsresult result = nsLeafFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus); + if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) + NS_ASSERTION(aMetrics.width == aReflowState.mComputedWidth + aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right, + "TitledButtons width is wrong!!!"); + + if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) + NS_ASSERTION(aMetrics.height == aReflowState.mComputedHeight + aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom, + "TitledButtons height is wrong!!!"); + return result; } @@ -975,16 +983,16 @@ nsTitledButtonFrame::GetDesiredSize(nsIPresContext* aPresContext, // if either the width or the height was not computed use our intrinsic size if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) - if (aReflowState.mComputedWidth > info.minSize.width) + //if (aReflowState.mComputedWidth > info.minSize.width) aDesiredSize.width = aReflowState.mComputedWidth; - else - aDesiredSize.width = info.minSize.width; + //else + // aDesiredSize.width = info.minSize.width; if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) - if (aReflowState.mComputedHeight > info.minSize.height) + //if (aReflowState.mComputedHeight > info.minSize.height) aDesiredSize.height = aReflowState.mComputedHeight; - else - aDesiredSize.height = info.minSize.height; + //else +// aDesiredSize.height = info.minSize.height; } @@ -1374,7 +1382,8 @@ NS_IMETHODIMP nsTitledButtonFrame :: DidSetStyleContext( nsIPresContext* aPresContext ) { // if list-style-image change we want to change the image - UpdateImage(aPresContext); + PRBool aResize; + UpdateImage(aPresContext, aResize); return NS_OK; @@ -1416,6 +1425,13 @@ nsTitledButtonFrame::GetImageSize(nsIPresContext* aPresContext) } +NS_IMETHODIMP +nsTitledButtonFrame::InvalidateCache(nsIFrame* aChild) +{ + // we don't cache any information + return NS_OK; +} + /** * Ok return our dimensions */ @@ -1514,14 +1530,6 @@ nsTitledButtonFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) return nsLeafFrame::QueryInterface(aIID, aInstancePtr); } -NS_IMETHODIMP -nsTitledButtonFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) -{ - // leafs should just return themselves as the incremental child - incrementalChild = this; - return NS_OK; -} - /* * We are a frame and we do not maintain a ref count */ @@ -1541,6 +1549,20 @@ nsTitledButtonFrame::Release(void) NS_IMETHODIMP nsTitledButtonFrame::GetFrameName(nsString& aResult) const { - aResult = "TitledButton"; + aResult = "TitledButton[value="; + aResult += mTitle; + aResult += "]"; return NS_OK; } + +NS_IMETHODIMP +nsTitledButtonFrame::ContentChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsISupports* aSubContent) +{ + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + mState |= NS_FRAME_IS_DIRTY; + return mParent->ReflowDirtyChild(shell, this); + +} diff --git a/mozilla/layout/xul/base/src/nsTitledButtonFrame.h b/mozilla/layout/xul/base/src/nsTitledButtonFrame.h index aa4f1fcb88f..810db35d19b 100644 --- a/mozilla/layout/xul/base/src/nsTitledButtonFrame.h +++ b/mozilla/layout/xul/base/src/nsTitledButtonFrame.h @@ -39,7 +39,7 @@ public: // nsIBox frame interface NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild); + NS_IMETHOD InvalidateCache(nsIFrame* aChild); NS_DECL_ISUPPORTS @@ -65,8 +65,8 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; - virtual void UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute); - virtual void UpdateImage(nsIPresContext* aPresContext); + virtual void UpdateAttributes(nsIPresContext* aPresContext, nsIAtom* aAttribute, PRBool& aResize, PRBool& aRedraw, PRBool& aUpdateAccessUnderline); + virtual void UpdateImage(nsIPresContext* aPresContext, PRBool& aResize); // nsIHTMLReflow overrides NS_IMETHOD Reflow(nsIPresContext* aPresContext, @@ -147,6 +147,11 @@ protected: virtual void GetImageSize(nsIPresContext* aPresContext); + NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsISupports* aSubContent); + + private: // tri state methods diff --git a/mozilla/layout/xul/base/src/nsToolbarFrame.h b/mozilla/layout/xul/base/src/nsToolbarFrame.h index 94ee4da05f6..9a91b4e1530 100644 --- a/mozilla/layout/xul/base/src/nsToolbarFrame.h +++ b/mozilla/layout/xul/base/src/nsToolbarFrame.h @@ -99,6 +99,13 @@ public: void SetDropfeedbackLocation(nscoord aX) { mXDropLoc = aX; } #endif + + NS_IMETHOD GetFrameName(nsString& aResult) const + { + aResult = "Toolbar"; + return NS_OK; + } + protected: nsToolbarFrame(); diff --git a/mozilla/layout/xul/base/src/nsToolboxFrame.h b/mozilla/layout/xul/base/src/nsToolboxFrame.h index 3c4d4385042..d003d663688 100644 --- a/mozilla/layout/xul/base/src/nsToolboxFrame.h +++ b/mozilla/layout/xul/base/src/nsToolboxFrame.h @@ -99,6 +99,12 @@ public: virtual nsresult DragGesture(nsIDOMEvent* aDragEvent) { return NS_OK; } /*END implementations of dragevent handler interface*/ + NS_IMETHOD GetFrameName(nsString& aResult) const + { + aResult = "Toolbox"; + return NS_OK; + } + protected: enum { kGrippyWidthInPixels = 10, kCollapsedGrippyHeightInPixels = 10, kCollapsedGrippyWidthInPixels = 50 } ; enum { kNoGrippyHilighted = -1 } ; diff --git a/mozilla/layout/xul/base/src/nsTreeFrame.cpp b/mozilla/layout/xul/base/src/nsTreeFrame.cpp index a4f60cc93b0..9489428ccdb 100644 --- a/mozilla/layout/xul/base/src/nsTreeFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTreeFrame.cpp @@ -372,8 +372,8 @@ nsTreeFrame::Reflow(nsIPresContext* aPresContext, NS_ASSERTION(aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE, "Reflowing tree with unconstrained width!!!!"); - NS_ASSERTION(aReflowState.mComputedHeight != NS_UNCONSTRAINEDSIZE, - "Reflowing tree with unconstrained height!!!!"); + //NS_ASSERTION(aReflowState.mComputedHeight != NS_UNCONSTRAINEDSIZE, + // "Reflowing tree with unconstrained height!!!!"); //printf("Tree Width: %d, Tree Height: %d\n", aReflowState.mComputedWidth, aReflowState.mComputedHeight); diff --git a/mozilla/layout/xul/base/src/nsTreeOuterFrame.cpp b/mozilla/layout/xul/base/src/nsTreeOuterFrame.cpp index 92935f3484c..2615981e975 100644 --- a/mozilla/layout/xul/base/src/nsTreeOuterFrame.cpp +++ b/mozilla/layout/xul/base/src/nsTreeOuterFrame.cpp @@ -108,12 +108,29 @@ nsTreeOuterFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - NS_ASSERTION(aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE, - "Reflowing outer tree frame with unconstrained width!!!!"); - - NS_ASSERTION(aReflowState.mComputedHeight != NS_UNCONSTRAINEDSIZE, - "Reflowing outer tree frame with unconstrained height!!!!"); + /* + // XXX at the moment we don't handle non incremental dirty reflow commands. So just convert them + // to style changes for now. + if (aReflowState.reason == eReflowReason_Dirty) { + NS_WARNING("Converting Dirty to StyleChange!! Table need to implement reflow Dirty!!"); + nsHTMLReflowState goodState(aReflowState); + goodState.reason = eReflowReason_StyleChange; + return Reflow(aPresContext, aDesiredSize, goodState, aStatus); + } + */ + PRBool badWidth = PR_FALSE; + + if (aReflowState.mComputedWidth == NS_UNCONSTRAINEDSIZE) { + NS_WARNING("Inefficient XUL: Reflowing outer tree frame with unconstrained width, try giving it a width in CSS!"); + nsHTMLReflowState goodState(aReflowState); + goodState.mComputedWidth = 1000; + return Reflow(aPresContext, aDesiredSize, goodState, aStatus); + } + + if (aReflowState.mComputedHeight == NS_UNCONSTRAINEDSIZE) { + NS_WARNING("Inefficient XUL: Reflowing outer tree frame with unconstrained height, try giving it a height in CSS!"); + } //printf("TOF Width: %d, TOF Height: %d\n", aReflowState.mComputedWidth, aReflowState.mComputedHeight); nsresult rv = nsTableOuterFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); @@ -138,26 +155,6 @@ nsTreeOuterFrame::Reflow(nsIPresContext* aPresContext, return rv; } -/** - * Ok return our dimensions - */ -NS_IMETHODIMP -nsTreeOuterFrame::GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize) -{ - aSize.minSize.width = 0; - aSize.minSize.height = 0; - aSize.prefSize.width = 100; - aSize.prefSize.height = 100; - - ((nsCalculatedBoxInfo&)aSize).prefWidthIntrinsic = PR_FALSE; - ((nsCalculatedBoxInfo&)aSize).prefHeightIntrinsic = PR_FALSE; - - return NS_OK; -} - -/** - * We can be a nsIBox - */ NS_IMETHODIMP nsTreeOuterFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) { @@ -167,12 +164,7 @@ nsTreeOuterFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) *aInstancePtr = NULL; - if (aIID.Equals(NS_GET_IID(nsIBox))) { - *aInstancePtr = (void*)(nsIBox*) this; - NS_ADDREF_THIS(); - return NS_OK; - } - else if (aIID.Equals(NS_GET_IID(nsISelfScrollingFrame))) { + if (aIID.Equals(NS_GET_IID(nsISelfScrollingFrame))) { *aInstancePtr = (void*)(nsISelfScrollingFrame*) this; return NS_OK; } @@ -180,13 +172,6 @@ nsTreeOuterFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) return nsTableOuterFrame::QueryInterface(aIID, aInstancePtr); } -NS_IMETHODIMP -nsTreeOuterFrame::Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild) -{ - incrementalChild = this; - return NS_OK; -} - /* * We are a frame and we do not maintain a ref count */ diff --git a/mozilla/layout/xul/base/src/nsTreeOuterFrame.h b/mozilla/layout/xul/base/src/nsTreeOuterFrame.h index 54570bc4ba9..fbb186e40ea 100644 --- a/mozilla/layout/xul/base/src/nsTreeOuterFrame.h +++ b/mozilla/layout/xul/base/src/nsTreeOuterFrame.h @@ -25,7 +25,7 @@ #include "nsISelfScrollingFrame.h" #include "nsITreeFrame.h" -class nsTreeOuterFrame : public nsTableOuterFrame, public nsIBox, public nsISelfScrollingFrame +class nsTreeOuterFrame : public nsTableOuterFrame, nsISelfScrollingFrame { public: friend nsresult NS_NewTreeOuterFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); @@ -49,9 +49,6 @@ public: NS_DECL_ISUPPORTS - NS_IMETHOD GetBoxInfo(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsBoxInfo& aSize); - NS_IMETHOD Dirty(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsIFrame*& incrementalChild); - NS_IMETHOD FixBadReflowState(const nsHTMLReflowState& aParentReflowState, nsHTMLReflowState& aChildReflowState); diff --git a/mozilla/layout/xul/content/src/nsXULAtomList.h b/mozilla/layout/xul/content/src/nsXULAtomList.h index d5d01cec2eb..fae78a9f6db 100644 --- a/mozilla/layout/xul/content/src/nsXULAtomList.h +++ b/mozilla/layout/xul/content/src/nsXULAtomList.h @@ -97,6 +97,7 @@ XUL_ATOM(mode, "mode") XUL_ATOM(box, "box") XUL_ATOM(flex, "flex") XUL_ATOM(spring, "spring") +XUL_ATOM(orient, "orient") XUL_ATOM(deck, "deck") XUL_ATOM(tabcontrol, "tabcontrol") diff --git a/mozilla/mailnews/base/resources/skin/messenger.css b/mozilla/mailnews/base/resources/skin/messenger.css index e46065b6cae..67e0011029d 100644 --- a/mozilla/mailnews/base/resources/skin/messenger.css +++ b/mozilla/mailnews/base/resources/skin/messenger.css @@ -316,3 +316,12 @@ menu.push[disabled="true"]:active { text-decoration: none; } +/** + * Make sure the min height is small so we can + * resize the pane vertically -EDV + */ +box#messagepanebox +{ + min-height: 10px; +} + diff --git a/mozilla/xpfe/browser/resources/content/navigator.xul b/mozilla/xpfe/browser/resources/content/navigator.xul index 97504c8714a..7f8a0c7e6e6 100644 --- a/mozilla/xpfe/browser/resources/content/navigator.xul +++ b/mozilla/xpfe/browser/resources/content/navigator.xul @@ -29,7 +29,7 @@ Contributor(s): ______________________________________. --> -szZ_XFvUc( zR6x|+l5CkNr4BKrshFc}HfCCq<9O<1)8stNPKz(|AI>|R^X})~?|tv{enEsEJv<|A zVYaXg9oXpT=ptqg_zQ!<>_(BKKq|%GFD!5&&K*8Y``5_ySumIm%oV%_Z?FZggLr)N zYnmp&`&_+e*>&>T@|~#cL$eQO8xke@v2wg?5L+Mr+U;rWqpr%`o_VEct5^Gjighpa z_~bclp+poNkx>Td&%5bJsM;&3$0T+d!!9AZGpPSQ=S7!WKFTGE>f{X2OIvO5R!!vi z8^On#>f`$^voCfxr7qSD4S2Anq_+}MHz%0YWG5&p$6^DQ<4(yj$_8MB}V#bRv z$VcI#s4m*#ZA&ZWsFHnJlXeeyzJp(3okuO`v(!DRY8`5~@(~c2YV-es%iN;pauvH7 zki`kWFOw7>oYTaPMOJzbj@({5Extk2wA%kMfO$MbOZPp{N&$obvvO5@DncAlm#+iW zIuSrgR7r-Bxh~_aFUdzOjH2R704HqwvhmiBJ*pd({z<>KZm7=xJnx51!)!g@pzs(n zw-zUmSZ#bW!mKT#O@k`G3b3A}Jl<%md9T5Lo>wE%ydpEknvXKtneNN*?{Ddh&WhXH zC-w5#SJBZdfqZ0$z`RN7Yuk^nc2%$SMeHjJH!gu}KLpqVU0*0R#mezmY~s3yFX4mS z2k@43^iN^0{B70~ddceaYp?(#nzDXbHSIY4rlRmlvE?=-29gjA@F5BMT(L7&Zt6Nl z@PB$)He8wF_o#^$U_&GHwy@zd!^!hYrI$#A)g|r3`}^ygi&v5%0U-e2NTtcxv2G0$Katm)$Xaw(=#Axc8 zo(umwg6NQ(!?MV~jjnN6-(OXtS<-0DDeXvberwkWxe8Knx&%9QS$F8zQf{u5dG5lk z3Om!5bLyb9#3HpvopL4LJxggUf=2KTOoA9w_KZ)I-Jvr(iWn^&>GV7B$L5wdjakLc zlBM7jd0h`*c5zT&32MGXwSCIozN=%VMVLq9PPE3FZYb(MLcJ@Kv_T7V?pyh4@RR23eEK-&w7 zdn%PCp2>9>VvJ*C%q#}|`4hULTilB@+5j08iMIzD0b1O0g2kH=uk8d<5V6?vSCu%1 zD0q+{q@mO-(3i*oO znR6g_LE`c4RGQ2wnjAR;EzR^d9!96FI9VgCwoufc70bwtj+|VP`xb9nAmkVz!f6~a zLFL+{J~!?Aq#P(c-onC$Uj3M#xne~Ty}?m=tzby~R_y?Z2;uRaKbhh)nL{HIJZR*t zT$?k&IqW_e?sQ>nl9z^6y^en}06d#Q98*C8`UBxhmqQWc-Bjf~3MSSjq@}x+aKOIy zu0$MhZ_{u023E7b;&L7zGe)RUT7J{z-C@%U)WJ%7Ey0IOH+d#4EGIe8iyV_mgzj77 zQ13;H_~NV$Zepru?Y)-^uqBjf$E%9&^z``Ul=qz@(wHTo87TEVu0n*z+(RLBVP5|O DSd5#( literal 0 HcmV?d00001