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): ______________________________________. --> -