From e447235e34c360e811c56611fc6fd6224c5f638b Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Wed, 28 Oct 1998 17:29:51 +0000 Subject: [PATCH] Sets the scrolling view's scroll preference and checks whether the scrolled frame is a BODY frame --- layout/html/base/src/nsScrollFrame.cpp | 155 +++++++++++++++++-------- 1 file changed, 107 insertions(+), 48 deletions(-) diff --git a/layout/html/base/src/nsScrollFrame.cpp b/layout/html/base/src/nsScrollFrame.cpp index 8ef31b7830b9..526707c84ec3 100644 --- a/layout/html/base/src/nsScrollFrame.cpp +++ b/layout/html/base/src/nsScrollFrame.cpp @@ -80,17 +80,20 @@ NS_IMETHODIMP nsScrollFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList) { NS_PRECONDITION(nsnull != aChildList, "no child frame"); + NS_PRECONDITION(LengthOf(aChildList) == 1, "wrong number child frames"); // Unless it's already a body frame, scrolled frames that are a container // need to be wrapped in a body frame. - // XXX Check for it already being a body frame... - nsIFrame* wrapperFrame; - if (CreateWrapperFrame(aPresContext, aChildList, wrapperFrame)) { - mFirstChild = wrapperFrame; - } else { - mFirstChild = aChildList; + // XXX It would be nice to have a cleaner way to do this... + nsIAbsoluteItems* absoluteItems; + if (NS_FAILED(aChildList->QueryInterface(kIAbsoluteItemsIID, (void**)&absoluteItems))) { + nsIFrame* wrapperFrame; + if (CreateWrapperFrame(aPresContext, aChildList, wrapperFrame)) { + aChildList = wrapperFrame; + } } + mFirstChild = aChildList; return NS_OK; } @@ -156,6 +159,8 @@ nsScrollFrame::CreateScrollingView() mStyleContext->GetStyleData(eStyleStruct_Color); const nsStyleSpacing* spacing = (const nsStyleSpacing*) mStyleContext->GetStyleData(eStyleStruct_Spacing); + const nsStyleDisplay* display = (const nsStyleDisplay*) + mStyleContext->GetStyleData(eStyleStruct_Display); // Get the z-index PRInt32 zIndex = 0; @@ -181,6 +186,12 @@ nsScrollFrame::CreateScrollingView() nsIScrollableView* scrollingView; view->QueryInterface(kScrollViewIID, (void**)&scrollingView); + // Set the scroll prefrence + nsScrollPreference scrollPref = (NS_STYLE_OVERFLOW_SCROLL == display->mOverflow) + ? nsScrollPreference_kAlwaysScroll : + nsScrollPreference_kAuto; + scrollingView->SetScrollPreference(scrollPref); + // Set the scrolling view's insets to whatever our border is nsMargin border; spacing->CalcBorderFor(this, border); @@ -235,7 +246,7 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext, nsIFrame* targetFrame; nsIFrame* nextFrame; - // Special handling for the initial reflow and incremental reflow + // Special handling for initial reflow and incremental reflow switch (aReflowState.reason) { case eReflowReason_Initial: // Create the scrolling view and the scrolled view @@ -262,63 +273,102 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext, nsMargin border; spacing->CalcBorderFor(this, border); - // Compute the scroll view frame's max size taking into account our - // borders - nsSize kidMaxSize; + // See whether the scrollbars are always visible or auto + const nsStyleDisplay* display = (const nsStyleDisplay*) + mStyleContext->GetStyleData(eStyleStruct_Display); + + // Get the scrollbar dimensions + float sbWidth, sbHeight; + nsIDeviceContext* dc = aPresContext.GetDeviceContext(); + + dc->GetScrollBarDimensions(sbWidth, sbHeight); + NS_RELEASE(dc); + + //@ Make me a subroutine... + + // Compute the scroll area size. This is the area inside of our border edge + // and inside of any vertical and horizontal scrollbars + nsSize scrollAreaSize; if (aReflowState.HaveConstrainedWidth()) { - // This value reflects space for the content area only, so don't + // The reflow state width reflects space for the content area only, so don't // subtract for borders... - kidMaxSize.width = aReflowState.minWidth; + scrollAreaSize.width = aReflowState.minWidth; } else { - kidMaxSize.width = aReflowState.maxSize.width; - if (NS_UNCONSTRAINEDSIZE != kidMaxSize.width) { - kidMaxSize.width -= border.left + border.right; + // Use the max width in the reflow state + scrollAreaSize.width = aReflowState.maxSize.width; + if (NS_UNCONSTRAINEDSIZE != scrollAreaSize.width) { + // The width is constrained so subtract for borders + scrollAreaSize.width -= border.left + border.right; + + // Subtract for the width of the vertical scrollbar. We always do this + // regardless of whether scrollbars are auto or always visible + scrollAreaSize.width -= NSToCoordRound(sbWidth); } } + if (aReflowState.HaveConstrainedHeight()) { - // This value reflects space for the content area only, so don't + // The reflow state height reflects space for the content area only, so don't // subtract for borders... - kidMaxSize.height = aReflowState.minHeight; + scrollAreaSize.height = aReflowState.minHeight; } else { - kidMaxSize.height = aReflowState.maxSize.height; - if (NS_UNCONSTRAINEDSIZE != kidMaxSize.height) { - kidMaxSize.height -= border.top + border.bottom; + // Use the max height in the reflow state + scrollAreaSize.height = aReflowState.maxSize.height; + if (NS_UNCONSTRAINEDSIZE != scrollAreaSize.height) { + // The height is constrained so subtract for borders + scrollAreaSize.height -= border.top + border.bottom; + + // If scrollbars are always visible then subtract for the + // height of the horizontal scrollbar + if (NS_STYLE_OVERFLOW_SCROLL == display->mOverflow) { + scrollAreaSize.height -= NSToCoordRound(sbHeight); + } } } + //@ Make me a subroutine... // Reflow the child and get its desired size. Let it be as high as it // wants - nsSize kidReflowSize(kidMaxSize.width, NS_UNCONSTRAINEDSIZE); - - // Subtract for the scrollbar width - if (NS_UNCONSTRAINEDSIZE != kidReflowSize.width) { - nsIDeviceContext* dc = aPresContext.GetDeviceContext(); - float sbWidth, sbHeight; - - dc->GetScrollBarDimensions(sbWidth, sbHeight); - kidReflowSize.width -= NSToCoordRound(sbWidth); - NS_RELEASE(dc); - } + nsSize kidReflowSize(scrollAreaSize.width, NS_UNCONSTRAINEDSIZE); + nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, + kidReflowSize); + nsHTMLReflowMetrics kidDesiredSize(nsnull); - nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, - kidReflowSize); - - // XXX Don't use aDesiredSize... - ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState, aStatus); + ReflowChild(mFirstChild, aPresContext, kidDesiredSize, kidReflowState, aStatus); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + // Make sure the scrolled frame fills the entire scroll area along a + // fixed dimension + if (aReflowState.HaveConstrainedHeight()) { + if (kidDesiredSize.height < scrollAreaSize.height) { + kidDesiredSize.height = scrollAreaSize.height; + } + + if (kidDesiredSize.height <= scrollAreaSize.height) { + // If the scrollbars are auto and the scrolled frame is vully visible + // vertically then the vertical scrollbar will be hidden so increase the + // width of the scrhidden then increase the scrolled frame's width + if (NS_STYLE_OVERFLOW_AUTO == display->mOverflow) { + kidDesiredSize.width += NSToCoordRound(sbWidth); + } + } + } + if (aReflowState.HaveConstrainedWidth()) { + if (kidDesiredSize.width < scrollAreaSize.width) { + kidDesiredSize.width = scrollAreaSize.width; + } + } + // Place and size the child. - // XXX Make sure it's at least as big as we are... - nsRect rect(border.left, border.top, aDesiredSize.width, aDesiredSize.height); + nsRect rect(border.left, border.top, kidDesiredSize.width, kidDesiredSize.height); mFirstChild->SetRect(rect); // If this is a resize reflow then repaint the scrolled frame if (eReflowReason_Resize == aReflowState.reason) { nsIView* scrolledView; nsIViewManager* viewManager; - nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height); + nsRect damageRect(0, 0, kidDesiredSize.width, kidDesiredSize.height); mFirstChild->GetView(scrolledView); scrolledView->GetViewManager(viewManager); @@ -326,17 +376,26 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext, NS_RELEASE(viewManager); } - // Compute our desired size - aDesiredSize.width = kidMaxSize.width + border.left + border.right; - if (NS_UNCONSTRAINEDSIZE == kidMaxSize.height) { - // Use the scroll view's desired height plus any borders - aDesiredSize.height += border.top + border.bottom; + // Compute our desired size. If our size was fixed then use the fixed size; + // otherwise, shrink wrap around the scrolled frame + if (aReflowState.HaveConstrainedWidth()) { + aDesiredSize.width = scrollAreaSize.width; } else { - // XXX This isn't correct. If our height is fixed, then use the fixed height; - // otherwise use the MIN of the constrained height and the scroll view's height - // plus borders... - aDesiredSize.height = kidMaxSize.height + border.top + border.bottom; + aDesiredSize.width = kidDesiredSize.width; } + aDesiredSize.width += border.left + border.right + NSToCoordRound(sbWidth); + + if (aReflowState.HaveConstrainedHeight()) { + aDesiredSize.height = scrollAreaSize.height; + } else { + aDesiredSize.height = kidDesiredSize.height; + } + aDesiredSize.height += border.top + border.bottom; + // XXX This should really be "if we have a visible horizontal scrollbar"... + if (NS_STYLE_OVERFLOW_SCROLL == display->mOverflow) { + aDesiredSize.height += NSToCoordRound(sbHeight); + } + aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0;