зеркало из https://github.com/mozilla/pjs.git
Bug 232838. Properly relayout scrollbars if we need to hide one because there's no room. Prefer to hide the horizontal scrollbar if we have to choose between them. r+sr=dbaron,a=choffman
This commit is contained in:
Родитель
9b10aac055
Коммит
693c921022
|
@ -116,8 +116,8 @@ public:
|
||||||
|
|
||||||
PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
||||||
PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
||||||
PRBool RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
||||||
PRBool RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
void RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
||||||
|
|
||||||
nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext);
|
nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext);
|
||||||
|
|
||||||
|
@ -1117,16 +1117,26 @@ nsGfxScrollFrameInner::AddVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aS
|
||||||
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_TRUE);
|
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
void
|
||||||
nsGfxScrollFrameInner::RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop)
|
nsGfxScrollFrameInner::RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop)
|
||||||
{
|
{
|
||||||
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_FALSE);
|
// removing a scrollbar should always fit
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRBool result =
|
||||||
|
#endif
|
||||||
|
AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_FALSE);
|
||||||
|
NS_ASSERTION(result, "Removing horizontal scrollbar failed to fit??");
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
void
|
||||||
nsGfxScrollFrameInner::RemoveVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight)
|
nsGfxScrollFrameInner::RemoveVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight)
|
||||||
{
|
{
|
||||||
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_FALSE);
|
// removing a scrollbar should always fit
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRBool result =
|
||||||
|
#endif
|
||||||
|
AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_FALSE);
|
||||||
|
NS_ASSERTION(result, "Removing vertical scrollbar failed to fit??");
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -1307,28 +1317,34 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
nsRect clientRect(0,0,0,0);
|
nsRect clientRect(0,0,0,0);
|
||||||
mOuter->GetClientRect(clientRect);
|
mOuter->GetClientRect(clientRect);
|
||||||
|
|
||||||
|
|
||||||
// get the preferred size of the scrollbars
|
|
||||||
nsSize hSize(0,0);
|
|
||||||
nsSize vSize(0,0);
|
|
||||||
nsSize hMinSize(0,0);
|
|
||||||
nsSize vMinSize(0,0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
mHScrollbarBox->GetPrefSize(aState, hSize);
|
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
mHScrollbarBox->GetMinSize(aState, hMinSize);
|
|
||||||
mVScrollbarBox->GetMinSize(aState, vMinSize);
|
|
||||||
|
|
||||||
nsBox::AddMargin(mHScrollbarBox, hSize);
|
|
||||||
nsBox::AddMargin(mVScrollbarBox, vSize);
|
|
||||||
nsBox::AddMargin(mHScrollbarBox, hMinSize);
|
|
||||||
nsBox::AddMargin(mVScrollbarBox, vMinSize);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// the scroll area size starts off as big as our content area
|
// the scroll area size starts off as big as our content area
|
||||||
nsRect scrollAreaRect(clientRect);
|
nsRect scrollAreaRect(clientRect);
|
||||||
|
|
||||||
|
/**************
|
||||||
|
Our basic strategy here is to first try laying out the content with
|
||||||
|
the scrollbars in their current state. We're hoping that that will
|
||||||
|
just "work"; the content will overflow wherever there's a scrollbar
|
||||||
|
already visible. If that does work, then there's no need to lay out
|
||||||
|
the scrollarea. Otherwise we fix up the scrollbars; first we add a
|
||||||
|
vertical one to scroll the content if necessary, or remove it if
|
||||||
|
it's not needed. Then we reflow the content if the scrollbar
|
||||||
|
changed. Then we add a horizontal scrollbar if necessary (or
|
||||||
|
remove if not needed), and if that changed, we reflow the content
|
||||||
|
again. At this point, any scrollbars that are needed to scroll the
|
||||||
|
content have been added.
|
||||||
|
|
||||||
|
In the second phase we check to see if any scrollbars are too small
|
||||||
|
to display, and if so, we remove them. We check the horizontal
|
||||||
|
scrollbar first; removing it might make room for the vertical
|
||||||
|
scrollbar, and if we have room for just one scrollbar we'll save
|
||||||
|
the vertical one.
|
||||||
|
|
||||||
|
Finally we position and size the scrollbars and scrollcorner (the
|
||||||
|
square that is needed in the corner of the window when two
|
||||||
|
scrollbars are visible), and reflow any fixed position views
|
||||||
|
(if we're the viewport and we added or removed a scrollbar).
|
||||||
|
**************/
|
||||||
|
|
||||||
nsGfxScrollFrame::ScrollbarStyles styles = mOuter->GetScrollbarStyles();
|
nsGfxScrollFrame::ScrollbarStyles styles = mOuter->GetScrollbarStyles();
|
||||||
|
|
||||||
// Look at our style do we always have vertical or horizontal scrollbars?
|
// Look at our style do we always have vertical or horizontal scrollbars?
|
||||||
|
@ -1364,18 +1380,16 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
if (mHasVerticalScrollbar) {
|
if (mHasVerticalScrollbar) {
|
||||||
// We left room for the vertical scrollbar, but it's not needed;
|
// We left room for the vertical scrollbar, but it's not needed;
|
||||||
// remove it.
|
// remove it.
|
||||||
if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) {
|
RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight);
|
||||||
needsLayout = PR_TRUE;
|
needsLayout = PR_TRUE;
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!mHasVerticalScrollbar) {
|
if (!mHasVerticalScrollbar) {
|
||||||
// We didn't leave room for the vertical scrollbar, but it turns
|
// We didn't leave room for the vertical scrollbar, but it turns
|
||||||
// out we needed it
|
// out we needed it
|
||||||
if (AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight))
|
if (AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight))
|
||||||
needsLayout = PR_TRUE;
|
needsLayout = PR_TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1433,7 +1447,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
// if the area is smaller or equal to and we have a scrollbar then
|
// if the area is smaller or equal to and we have a scrollbar then
|
||||||
// remove it.
|
// remove it.
|
||||||
if (mHasHorizontalScrollbar) {
|
if (mHasHorizontalScrollbar) {
|
||||||
if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom))
|
RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom);
|
||||||
needsLayout = PR_TRUE;
|
needsLayout = PR_TRUE;
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
}
|
}
|
||||||
|
@ -1469,89 +1483,85 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
if (fm)
|
if (fm)
|
||||||
fm->GetHeight(fontHeight);
|
fm->GetHeight(fontHeight);
|
||||||
|
|
||||||
|
// get the preferred size of the scrollbars
|
||||||
|
nsSize hSize(0,0);
|
||||||
|
nsSize vSize(0,0);
|
||||||
|
nsSize hMinSize(0,0);
|
||||||
|
nsSize vMinSize(0,0);
|
||||||
|
|
||||||
|
if (mHScrollbarBox && mHasHorizontalScrollbar) {
|
||||||
|
mHScrollbarBox->GetPrefSize(aState, hSize);
|
||||||
|
mHScrollbarBox->GetMinSize(aState, hMinSize);
|
||||||
|
nsBox::AddMargin(mHScrollbarBox, hSize);
|
||||||
|
nsBox::AddMargin(mHScrollbarBox, hMinSize);
|
||||||
|
}
|
||||||
|
if (mVScrollbarBox && mHasVerticalScrollbar) {
|
||||||
|
mVScrollbarBox->GetPrefSize(aState, vSize);
|
||||||
|
mVScrollbarBox->GetMinSize(aState, vMinSize);
|
||||||
|
nsBox::AddMargin(mVScrollbarBox, vSize);
|
||||||
|
nsBox::AddMargin(mVScrollbarBox, vMinSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(vMinSize.width == vSize.width, "vertical scrollbar can change width");
|
||||||
|
NS_ASSERTION(hMinSize.height == hSize.height, "horizontal scrollbar can change height");
|
||||||
|
|
||||||
|
// Disable scrollbars that are too small
|
||||||
|
// Disable horizontal scrollbar first. If we have to disable only one
|
||||||
|
// scrollbar, we'd rather keep the vertical scrollbar.
|
||||||
|
if (mHasHorizontalScrollbar &&
|
||||||
|
(hMinSize.width > clientRect.width - vSize.width
|
||||||
|
|| hMinSize.height > clientRect.height)) {
|
||||||
|
RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom);
|
||||||
|
needsLayout = PR_TRUE;
|
||||||
|
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
|
// set the scrollbar to zero height to make it go away
|
||||||
|
hSize.height = 0;
|
||||||
|
hMinSize.height = 0;
|
||||||
|
}
|
||||||
|
// Now disable vertical scrollbar if necessary
|
||||||
|
if (mHasVerticalScrollbar &&
|
||||||
|
(vMinSize.height > clientRect.height - hSize.height
|
||||||
|
|| vMinSize.width > clientRect.width)) {
|
||||||
|
RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight);
|
||||||
|
needsLayout = PR_TRUE;
|
||||||
|
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
|
// set the scrollbar to zero width to make it go away
|
||||||
|
vSize.width = 0;
|
||||||
|
vMinSize.width = 0;
|
||||||
|
}
|
||||||
|
|
||||||
nscoord maxX = scrolledContentSize.width - scrollAreaRect.width;
|
nscoord maxX = scrolledContentSize.width - scrollAreaRect.width;
|
||||||
nscoord maxY = scrolledContentSize.height - scrollAreaRect.height;
|
nscoord maxY = scrolledContentSize.height - scrollAreaRect.height;
|
||||||
|
|
||||||
nsIScrollableView* scrollable = GetScrollableView(presContext);
|
nsIScrollableView* scrollable = GetScrollableView(presContext);
|
||||||
scrollable->SetLineHeight(fontHeight);
|
scrollable->SetLineHeight(fontHeight);
|
||||||
|
|
||||||
if (mHScrollbarBox)
|
if (mVScrollbarBox) {
|
||||||
mHScrollbarBox->GetPrefSize(aState, hSize);
|
|
||||||
|
|
||||||
if (mVScrollbarBox)
|
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
|
|
||||||
// layout vertical scrollbar
|
|
||||||
nsRect vRect(clientRect);
|
|
||||||
|
|
||||||
vRect.width = mHasVerticalScrollbar ? vSize.width : 0;
|
|
||||||
vRect.y = clientRect.y;
|
|
||||||
|
|
||||||
if (mHasHorizontalScrollbar) {
|
|
||||||
vRect.height -= hSize.height;
|
|
||||||
if (!scrollBarBottom)
|
|
||||||
vRect.y += hSize.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
vRect.x = clientRect.x;
|
|
||||||
|
|
||||||
if (scrollBarRight)
|
|
||||||
vRect.x += clientRect.width - vRect.width;
|
|
||||||
|
|
||||||
if (mHasVerticalScrollbar && mVScrollbarBox) {
|
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY);
|
SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY);
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight));
|
SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight));
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight);
|
SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight);
|
||||||
}
|
|
||||||
|
|
||||||
if (mVScrollbarBox) {
|
nsRect vRect(scrollAreaRect);
|
||||||
|
vRect.width = vSize.width;
|
||||||
|
vRect.x = scrollBarRight ? scrollAreaRect.XMost() : clientRect.x;
|
||||||
|
nsMargin margin;
|
||||||
|
mVScrollbarBox->GetMargin(margin);
|
||||||
|
vRect.Deflate(margin);
|
||||||
LayoutBox(aState, mVScrollbarBox, vRect);
|
LayoutBox(aState, mVScrollbarBox, vRect);
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
mVScrollbarBox->GetMinSize(aState, vMinSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mHasVerticalScrollbar && mVScrollbarBox && (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) {
|
|
||||||
if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) {
|
|
||||||
needsLayout = PR_TRUE;
|
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layout horizontal scrollbar
|
|
||||||
nsRect hRect(clientRect);
|
|
||||||
hRect.height = mHasHorizontalScrollbar ? hSize.height : 0;
|
|
||||||
|
|
||||||
hRect.x = clientRect.x;
|
|
||||||
|
|
||||||
if (mHasVerticalScrollbar) {
|
|
||||||
hRect.width -= vSize.width;
|
|
||||||
if (!scrollBarRight)
|
|
||||||
hRect.x += vSize.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
hRect.y = clientRect.y;
|
|
||||||
|
|
||||||
if (scrollBarBottom)
|
|
||||||
hRect.y += clientRect.height - hRect.height;
|
|
||||||
|
|
||||||
if (mHasHorizontalScrollbar && mHScrollbarBox) {
|
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX);
|
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8));
|
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHScrollbarBox) {
|
if (mHScrollbarBox) {
|
||||||
LayoutBox(aState, mHScrollbarBox, hRect);
|
SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX);
|
||||||
mHScrollbarBox->GetMinSize(aState, hMinSize);
|
SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8));
|
||||||
}
|
SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel);
|
||||||
|
|
||||||
if (mHasHorizontalScrollbar && mHScrollbarBox && (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) {
|
nsRect hRect(scrollAreaRect);
|
||||||
if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) {
|
hRect.height = hSize.height;
|
||||||
needsLayout = PR_TRUE;
|
hRect.y = scrollBarBottom ? scrollAreaRect.YMost() : clientRect.y;
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
nsMargin margin;
|
||||||
}
|
mHScrollbarBox->GetMargin(margin);
|
||||||
|
hRect.Deflate(margin);
|
||||||
|
LayoutBox(aState, mHScrollbarBox, hRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only need to set the rect. The inner child stays the same size.
|
// we only need to set the rect. The inner child stays the same size.
|
||||||
|
|
|
@ -116,8 +116,8 @@ public:
|
||||||
|
|
||||||
PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
||||||
PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
||||||
PRBool RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
|
||||||
PRBool RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
void RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
|
||||||
|
|
||||||
nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext);
|
nsIScrollableView* GetScrollableView(nsIPresContext* aPresContext);
|
||||||
|
|
||||||
|
@ -1117,16 +1117,26 @@ nsGfxScrollFrameInner::AddVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aS
|
||||||
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_TRUE);
|
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
void
|
||||||
nsGfxScrollFrameInner::RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop)
|
nsGfxScrollFrameInner::RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnTop)
|
||||||
{
|
{
|
||||||
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_FALSE);
|
// removing a scrollbar should always fit
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRBool result =
|
||||||
|
#endif
|
||||||
|
AddRemoveScrollbar(aState, aScrollAreaSize, aOnTop, PR_TRUE, PR_FALSE);
|
||||||
|
NS_ASSERTION(result, "Removing horizontal scrollbar failed to fit??");
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
void
|
||||||
nsGfxScrollFrameInner::RemoveVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight)
|
nsGfxScrollFrameInner::RemoveVerticalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight)
|
||||||
{
|
{
|
||||||
return AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_FALSE);
|
// removing a scrollbar should always fit
|
||||||
|
#ifdef DEBUG
|
||||||
|
PRBool result =
|
||||||
|
#endif
|
||||||
|
AddRemoveScrollbar(aState, aScrollAreaSize, aOnRight, PR_FALSE, PR_FALSE);
|
||||||
|
NS_ASSERTION(result, "Removing vertical scrollbar failed to fit??");
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -1307,28 +1317,34 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
nsRect clientRect(0,0,0,0);
|
nsRect clientRect(0,0,0,0);
|
||||||
mOuter->GetClientRect(clientRect);
|
mOuter->GetClientRect(clientRect);
|
||||||
|
|
||||||
|
|
||||||
// get the preferred size of the scrollbars
|
|
||||||
nsSize hSize(0,0);
|
|
||||||
nsSize vSize(0,0);
|
|
||||||
nsSize hMinSize(0,0);
|
|
||||||
nsSize vMinSize(0,0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
mHScrollbarBox->GetPrefSize(aState, hSize);
|
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
mHScrollbarBox->GetMinSize(aState, hMinSize);
|
|
||||||
mVScrollbarBox->GetMinSize(aState, vMinSize);
|
|
||||||
|
|
||||||
nsBox::AddMargin(mHScrollbarBox, hSize);
|
|
||||||
nsBox::AddMargin(mVScrollbarBox, vSize);
|
|
||||||
nsBox::AddMargin(mHScrollbarBox, hMinSize);
|
|
||||||
nsBox::AddMargin(mVScrollbarBox, vMinSize);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// the scroll area size starts off as big as our content area
|
// the scroll area size starts off as big as our content area
|
||||||
nsRect scrollAreaRect(clientRect);
|
nsRect scrollAreaRect(clientRect);
|
||||||
|
|
||||||
|
/**************
|
||||||
|
Our basic strategy here is to first try laying out the content with
|
||||||
|
the scrollbars in their current state. We're hoping that that will
|
||||||
|
just "work"; the content will overflow wherever there's a scrollbar
|
||||||
|
already visible. If that does work, then there's no need to lay out
|
||||||
|
the scrollarea. Otherwise we fix up the scrollbars; first we add a
|
||||||
|
vertical one to scroll the content if necessary, or remove it if
|
||||||
|
it's not needed. Then we reflow the content if the scrollbar
|
||||||
|
changed. Then we add a horizontal scrollbar if necessary (or
|
||||||
|
remove if not needed), and if that changed, we reflow the content
|
||||||
|
again. At this point, any scrollbars that are needed to scroll the
|
||||||
|
content have been added.
|
||||||
|
|
||||||
|
In the second phase we check to see if any scrollbars are too small
|
||||||
|
to display, and if so, we remove them. We check the horizontal
|
||||||
|
scrollbar first; removing it might make room for the vertical
|
||||||
|
scrollbar, and if we have room for just one scrollbar we'll save
|
||||||
|
the vertical one.
|
||||||
|
|
||||||
|
Finally we position and size the scrollbars and scrollcorner (the
|
||||||
|
square that is needed in the corner of the window when two
|
||||||
|
scrollbars are visible), and reflow any fixed position views
|
||||||
|
(if we're the viewport and we added or removed a scrollbar).
|
||||||
|
**************/
|
||||||
|
|
||||||
nsGfxScrollFrame::ScrollbarStyles styles = mOuter->GetScrollbarStyles();
|
nsGfxScrollFrame::ScrollbarStyles styles = mOuter->GetScrollbarStyles();
|
||||||
|
|
||||||
// Look at our style do we always have vertical or horizontal scrollbars?
|
// Look at our style do we always have vertical or horizontal scrollbars?
|
||||||
|
@ -1364,18 +1380,16 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
if (mHasVerticalScrollbar) {
|
if (mHasVerticalScrollbar) {
|
||||||
// We left room for the vertical scrollbar, but it's not needed;
|
// We left room for the vertical scrollbar, but it's not needed;
|
||||||
// remove it.
|
// remove it.
|
||||||
if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) {
|
RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight);
|
||||||
needsLayout = PR_TRUE;
|
needsLayout = PR_TRUE;
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!mHasVerticalScrollbar) {
|
if (!mHasVerticalScrollbar) {
|
||||||
// We didn't leave room for the vertical scrollbar, but it turns
|
// We didn't leave room for the vertical scrollbar, but it turns
|
||||||
// out we needed it
|
// out we needed it
|
||||||
if (AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight))
|
if (AddVerticalScrollbar(aState, scrollAreaRect, scrollBarRight))
|
||||||
needsLayout = PR_TRUE;
|
needsLayout = PR_TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1433,7 +1447,7 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
// if the area is smaller or equal to and we have a scrollbar then
|
// if the area is smaller or equal to and we have a scrollbar then
|
||||||
// remove it.
|
// remove it.
|
||||||
if (mHasHorizontalScrollbar) {
|
if (mHasHorizontalScrollbar) {
|
||||||
if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom))
|
RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom);
|
||||||
needsLayout = PR_TRUE;
|
needsLayout = PR_TRUE;
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
}
|
}
|
||||||
|
@ -1469,89 +1483,85 @@ nsGfxScrollFrameInner::Layout(nsBoxLayoutState& aState)
|
||||||
if (fm)
|
if (fm)
|
||||||
fm->GetHeight(fontHeight);
|
fm->GetHeight(fontHeight);
|
||||||
|
|
||||||
|
// get the preferred size of the scrollbars
|
||||||
|
nsSize hSize(0,0);
|
||||||
|
nsSize vSize(0,0);
|
||||||
|
nsSize hMinSize(0,0);
|
||||||
|
nsSize vMinSize(0,0);
|
||||||
|
|
||||||
|
if (mHScrollbarBox && mHasHorizontalScrollbar) {
|
||||||
|
mHScrollbarBox->GetPrefSize(aState, hSize);
|
||||||
|
mHScrollbarBox->GetMinSize(aState, hMinSize);
|
||||||
|
nsBox::AddMargin(mHScrollbarBox, hSize);
|
||||||
|
nsBox::AddMargin(mHScrollbarBox, hMinSize);
|
||||||
|
}
|
||||||
|
if (mVScrollbarBox && mHasVerticalScrollbar) {
|
||||||
|
mVScrollbarBox->GetPrefSize(aState, vSize);
|
||||||
|
mVScrollbarBox->GetMinSize(aState, vMinSize);
|
||||||
|
nsBox::AddMargin(mVScrollbarBox, vSize);
|
||||||
|
nsBox::AddMargin(mVScrollbarBox, vMinSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(vMinSize.width == vSize.width, "vertical scrollbar can change width");
|
||||||
|
NS_ASSERTION(hMinSize.height == hSize.height, "horizontal scrollbar can change height");
|
||||||
|
|
||||||
|
// Disable scrollbars that are too small
|
||||||
|
// Disable horizontal scrollbar first. If we have to disable only one
|
||||||
|
// scrollbar, we'd rather keep the vertical scrollbar.
|
||||||
|
if (mHasHorizontalScrollbar &&
|
||||||
|
(hMinSize.width > clientRect.width - vSize.width
|
||||||
|
|| hMinSize.height > clientRect.height)) {
|
||||||
|
RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom);
|
||||||
|
needsLayout = PR_TRUE;
|
||||||
|
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
|
// set the scrollbar to zero height to make it go away
|
||||||
|
hSize.height = 0;
|
||||||
|
hMinSize.height = 0;
|
||||||
|
}
|
||||||
|
// Now disable vertical scrollbar if necessary
|
||||||
|
if (mHasVerticalScrollbar &&
|
||||||
|
(vMinSize.height > clientRect.height - hSize.height
|
||||||
|
|| vMinSize.width > clientRect.width)) {
|
||||||
|
RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight);
|
||||||
|
needsLayout = PR_TRUE;
|
||||||
|
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
||||||
|
// set the scrollbar to zero width to make it go away
|
||||||
|
vSize.width = 0;
|
||||||
|
vMinSize.width = 0;
|
||||||
|
}
|
||||||
|
|
||||||
nscoord maxX = scrolledContentSize.width - scrollAreaRect.width;
|
nscoord maxX = scrolledContentSize.width - scrollAreaRect.width;
|
||||||
nscoord maxY = scrolledContentSize.height - scrollAreaRect.height;
|
nscoord maxY = scrolledContentSize.height - scrollAreaRect.height;
|
||||||
|
|
||||||
nsIScrollableView* scrollable = GetScrollableView(presContext);
|
nsIScrollableView* scrollable = GetScrollableView(presContext);
|
||||||
scrollable->SetLineHeight(fontHeight);
|
scrollable->SetLineHeight(fontHeight);
|
||||||
|
|
||||||
if (mHScrollbarBox)
|
if (mVScrollbarBox) {
|
||||||
mHScrollbarBox->GetPrefSize(aState, hSize);
|
|
||||||
|
|
||||||
if (mVScrollbarBox)
|
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
|
|
||||||
// layout vertical scrollbar
|
|
||||||
nsRect vRect(clientRect);
|
|
||||||
|
|
||||||
vRect.width = mHasVerticalScrollbar ? vSize.width : 0;
|
|
||||||
vRect.y = clientRect.y;
|
|
||||||
|
|
||||||
if (mHasHorizontalScrollbar) {
|
|
||||||
vRect.height -= hSize.height;
|
|
||||||
if (!scrollBarBottom)
|
|
||||||
vRect.y += hSize.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
vRect.x = clientRect.x;
|
|
||||||
|
|
||||||
if (scrollBarRight)
|
|
||||||
vRect.x += clientRect.width - vRect.width;
|
|
||||||
|
|
||||||
if (mHasVerticalScrollbar && mVScrollbarBox) {
|
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY);
|
SetAttribute(mVScrollbarBox, nsXULAtoms::maxpos, maxY);
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight));
|
SetAttribute(mVScrollbarBox, nsXULAtoms::pageincrement, nscoord(scrollAreaRect.height - fontHeight));
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight);
|
SetAttribute(mVScrollbarBox, nsXULAtoms::increment, fontHeight);
|
||||||
}
|
|
||||||
|
|
||||||
if (mVScrollbarBox) {
|
nsRect vRect(scrollAreaRect);
|
||||||
|
vRect.width = vSize.width;
|
||||||
|
vRect.x = scrollBarRight ? scrollAreaRect.XMost() : clientRect.x;
|
||||||
|
nsMargin margin;
|
||||||
|
mVScrollbarBox->GetMargin(margin);
|
||||||
|
vRect.Deflate(margin);
|
||||||
LayoutBox(aState, mVScrollbarBox, vRect);
|
LayoutBox(aState, mVScrollbarBox, vRect);
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
mVScrollbarBox->GetMinSize(aState, vMinSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mHasVerticalScrollbar && mVScrollbarBox && (vMinSize.width > vRect.width || vMinSize.height > vRect.height)) {
|
|
||||||
if (RemoveVerticalScrollbar(aState, scrollAreaRect, scrollBarRight)) {
|
|
||||||
needsLayout = PR_TRUE;
|
|
||||||
SetAttribute(mVScrollbarBox, nsXULAtoms::curpos, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mVScrollbarBox->GetPrefSize(aState, vSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// layout horizontal scrollbar
|
|
||||||
nsRect hRect(clientRect);
|
|
||||||
hRect.height = mHasHorizontalScrollbar ? hSize.height : 0;
|
|
||||||
|
|
||||||
hRect.x = clientRect.x;
|
|
||||||
|
|
||||||
if (mHasVerticalScrollbar) {
|
|
||||||
hRect.width -= vSize.width;
|
|
||||||
if (!scrollBarRight)
|
|
||||||
hRect.x += vSize.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
hRect.y = clientRect.y;
|
|
||||||
|
|
||||||
if (scrollBarBottom)
|
|
||||||
hRect.y += clientRect.height - hRect.height;
|
|
||||||
|
|
||||||
if (mHasHorizontalScrollbar && mHScrollbarBox) {
|
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX);
|
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8));
|
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHScrollbarBox) {
|
if (mHScrollbarBox) {
|
||||||
LayoutBox(aState, mHScrollbarBox, hRect);
|
SetAttribute(mHScrollbarBox, nsXULAtoms::maxpos, maxX);
|
||||||
mHScrollbarBox->GetMinSize(aState, hMinSize);
|
SetAttribute(mHScrollbarBox, nsXULAtoms::pageincrement, nscoord(float(scrollAreaRect.width)*0.8));
|
||||||
}
|
SetAttribute(mHScrollbarBox, nsXULAtoms::increment, 10*mOnePixel);
|
||||||
|
|
||||||
if (mHasHorizontalScrollbar && mHScrollbarBox && (hMinSize.width > hRect.width || hMinSize.height > hRect.height)) {
|
nsRect hRect(scrollAreaRect);
|
||||||
if (RemoveHorizontalScrollbar(aState, scrollAreaRect, scrollBarBottom)) {
|
hRect.height = hSize.height;
|
||||||
needsLayout = PR_TRUE;
|
hRect.y = scrollBarBottom ? scrollAreaRect.YMost() : clientRect.y;
|
||||||
SetAttribute(mHScrollbarBox, nsXULAtoms::curpos, 0);
|
nsMargin margin;
|
||||||
}
|
mHScrollbarBox->GetMargin(margin);
|
||||||
|
hRect.Deflate(margin);
|
||||||
|
LayoutBox(aState, mHScrollbarBox, hRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only need to set the rect. The inner child stays the same size.
|
// we only need to set the rect. The inner child stays the same size.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче