Sets the scrolling view's scroll preference and checks whether the scrolled

frame is a BODY frame
This commit is contained in:
troy%netscape.com 1998-10-28 17:29:51 +00:00
parent f7e16c8e8e
commit e447235e34

View File

@ -80,17 +80,20 @@ NS_IMETHODIMP
nsScrollFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList) nsScrollFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
{ {
NS_PRECONDITION(nsnull != aChildList, "no child frame"); 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 // Unless it's already a body frame, scrolled frames that are a container
// need to be wrapped in a body frame. // need to be wrapped in a body frame.
// XXX Check for it already being a body frame... // XXX It would be nice to have a cleaner way to do this...
nsIFrame* wrapperFrame; nsIAbsoluteItems* absoluteItems;
if (CreateWrapperFrame(aPresContext, aChildList, wrapperFrame)) { if (NS_FAILED(aChildList->QueryInterface(kIAbsoluteItemsIID, (void**)&absoluteItems))) {
mFirstChild = wrapperFrame; nsIFrame* wrapperFrame;
} else { if (CreateWrapperFrame(aPresContext, aChildList, wrapperFrame)) {
mFirstChild = aChildList; aChildList = wrapperFrame;
}
} }
mFirstChild = aChildList;
return NS_OK; return NS_OK;
} }
@ -156,6 +159,8 @@ nsScrollFrame::CreateScrollingView()
mStyleContext->GetStyleData(eStyleStruct_Color); mStyleContext->GetStyleData(eStyleStruct_Color);
const nsStyleSpacing* spacing = (const nsStyleSpacing*) const nsStyleSpacing* spacing = (const nsStyleSpacing*)
mStyleContext->GetStyleData(eStyleStruct_Spacing); mStyleContext->GetStyleData(eStyleStruct_Spacing);
const nsStyleDisplay* display = (const nsStyleDisplay*)
mStyleContext->GetStyleData(eStyleStruct_Display);
// Get the z-index // Get the z-index
PRInt32 zIndex = 0; PRInt32 zIndex = 0;
@ -181,6 +186,12 @@ nsScrollFrame::CreateScrollingView()
nsIScrollableView* scrollingView; nsIScrollableView* scrollingView;
view->QueryInterface(kScrollViewIID, (void**)&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 // Set the scrolling view's insets to whatever our border is
nsMargin border; nsMargin border;
spacing->CalcBorderFor(this, border); spacing->CalcBorderFor(this, border);
@ -235,7 +246,7 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext,
nsIFrame* targetFrame; nsIFrame* targetFrame;
nsIFrame* nextFrame; nsIFrame* nextFrame;
// Special handling for the initial reflow and incremental reflow // Special handling for initial reflow and incremental reflow
switch (aReflowState.reason) { switch (aReflowState.reason) {
case eReflowReason_Initial: case eReflowReason_Initial:
// Create the scrolling view and the scrolled view // Create the scrolling view and the scrolled view
@ -262,63 +273,102 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext,
nsMargin border; nsMargin border;
spacing->CalcBorderFor(this, border); spacing->CalcBorderFor(this, border);
// Compute the scroll view frame's max size taking into account our // See whether the scrollbars are always visible or auto
// borders const nsStyleDisplay* display = (const nsStyleDisplay*)
nsSize kidMaxSize; 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()) { 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... // subtract for borders...
kidMaxSize.width = aReflowState.minWidth; scrollAreaSize.width = aReflowState.minWidth;
} }
else { else {
kidMaxSize.width = aReflowState.maxSize.width; // Use the max width in the reflow state
if (NS_UNCONSTRAINEDSIZE != kidMaxSize.width) { scrollAreaSize.width = aReflowState.maxSize.width;
kidMaxSize.width -= border.left + border.right; 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()) { 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... // subtract for borders...
kidMaxSize.height = aReflowState.minHeight; scrollAreaSize.height = aReflowState.minHeight;
} }
else { else {
kidMaxSize.height = aReflowState.maxSize.height; // Use the max height in the reflow state
if (NS_UNCONSTRAINEDSIZE != kidMaxSize.height) { scrollAreaSize.height = aReflowState.maxSize.height;
kidMaxSize.height -= border.top + border.bottom; 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 // Reflow the child and get its desired size. Let it be as high as it
// wants // wants
nsSize kidReflowSize(kidMaxSize.width, NS_UNCONSTRAINEDSIZE); nsSize kidReflowSize(scrollAreaSize.width, NS_UNCONSTRAINEDSIZE);
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState,
// Subtract for the scrollbar width kidReflowSize);
if (NS_UNCONSTRAINEDSIZE != kidReflowSize.width) { nsHTMLReflowMetrics kidDesiredSize(nsnull);
nsIDeviceContext* dc = aPresContext.GetDeviceContext();
float sbWidth, sbHeight;
dc->GetScrollBarDimensions(sbWidth, sbHeight);
kidReflowSize.width -= NSToCoordRound(sbWidth);
NS_RELEASE(dc);
}
nsHTMLReflowState kidReflowState(aPresContext, mFirstChild, aReflowState, ReflowChild(mFirstChild, aPresContext, kidDesiredSize, kidReflowState, aStatus);
kidReflowSize);
// XXX Don't use aDesiredSize...
ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState, aStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); 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. // Place and size the child.
// XXX Make sure it's at least as big as we are... nsRect rect(border.left, border.top, kidDesiredSize.width, kidDesiredSize.height);
nsRect rect(border.left, border.top, aDesiredSize.width, aDesiredSize.height);
mFirstChild->SetRect(rect); mFirstChild->SetRect(rect);
// If this is a resize reflow then repaint the scrolled frame // If this is a resize reflow then repaint the scrolled frame
if (eReflowReason_Resize == aReflowState.reason) { if (eReflowReason_Resize == aReflowState.reason) {
nsIView* scrolledView; nsIView* scrolledView;
nsIViewManager* viewManager; nsIViewManager* viewManager;
nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height); nsRect damageRect(0, 0, kidDesiredSize.width, kidDesiredSize.height);
mFirstChild->GetView(scrolledView); mFirstChild->GetView(scrolledView);
scrolledView->GetViewManager(viewManager); scrolledView->GetViewManager(viewManager);
@ -326,17 +376,26 @@ nsScrollFrame::Reflow(nsIPresContext& aPresContext,
NS_RELEASE(viewManager); NS_RELEASE(viewManager);
} }
// Compute our desired size // Compute our desired size. If our size was fixed then use the fixed size;
aDesiredSize.width = kidMaxSize.width + border.left + border.right; // otherwise, shrink wrap around the scrolled frame
if (NS_UNCONSTRAINEDSIZE == kidMaxSize.height) { if (aReflowState.HaveConstrainedWidth()) {
// Use the scroll view's desired height plus any borders aDesiredSize.width = scrollAreaSize.width;
aDesiredSize.height += border.top + border.bottom;
} else { } else {
// XXX This isn't correct. If our height is fixed, then use the fixed height; aDesiredSize.width = kidDesiredSize.width;
// 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 += 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.ascent = aDesiredSize.height;
aDesiredSize.descent = 0; aDesiredSize.descent = 0;