Bug 310668. Don't retain frame pointers in nsTreeBodyFrame. sr=bz

git-svn-id: svn://10.0.0.236/trunk@195410 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
roc+%cs.cmu.edu
2006-04-26 01:47:58 +00:00
parent de521137f8
commit 5a96bd2d29
2 changed files with 231 additions and 223 deletions

View File

@@ -146,10 +146,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsLeafBoxFrame)
// Constructor
nsTreeBodyFrame::nsTreeBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
:nsLeafBoxFrame(aPresShell, aContext),
mScrollbar(nsnull),
mHorzScrollbar(nsnull),
mColScrollContent(nsnull),
mColScrollView(nsnull),
mHorzPosition(0),
mHorzWidth(0),
mRowHeight(0),
@@ -188,47 +184,6 @@ nsTreeBodyFrame::Release(void)
return NS_OK;
}
void nsTreeBodyFrame::InitScrollbarFrames(nsPresContext* aPresContext, nsIFrame* aCurrFrame,
nsIScrollbarMediator* aSM)
{
if (mScrollbar && mHorzScrollbar && mColScrollContent)
return;
if (!mColScrollContent) {
nsIScrollableFrame* scrollFrame;
if (NS_SUCCEEDED(CallQueryInterface(aCurrFrame, &scrollFrame)))
if (scrollFrame->GetScrollableView())
mColScrollContent = aCurrFrame->GetContent();
}
// Check ourselves
nsIScrollbarFrame *sf = nsnull;
CallQueryInterface(aCurrFrame, &sf);
if (sf) {
PRBool isHorizontal = PR_FALSE;
if (NS_FAILED(aCurrFrame->GetOrientation(isHorizontal)))
return;
if (!mScrollbar && !isHorizontal) {
sf->SetScrollbarMediator(aSM);
mScrollbar = aCurrFrame;
return;
}
if (!mHorzScrollbar && isHorizontal) {
sf->SetScrollbarMediator(aSM);
mHorzScrollbar = aCurrFrame;
return;
}
}
nsIFrame* child = aCurrFrame->GetFirstChild(nsnull);
while (child && !(mScrollbar && mHorzScrollbar && mColScrollContent)) {
InitScrollbarFrames(aPresContext, child, aSM);
child = child->GetNextSibling();
}
}
static void
GetBorderPadding(nsStyleContext* aContext, nsMargin& aMargin)
{
@@ -476,12 +431,13 @@ NS_IMETHODIMP
nsTreeBodyFrame::SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
PRBool aRemoveOverflowArea)
{
if ((aRect != mRect || mHorzWidth != CalcHorzWidth()) && !mReflowCallbackPosted) {
nscoord horzWidth = CalcHorzWidth(GetScrollParts());
if ((aRect != mRect || mHorzWidth != horzWidth) && !mReflowCallbackPosted) {
mReflowCallbackPosted = PR_TRUE;
GetPresContext()->PresShell()->PostReflowCallback(this);
}
mHorzWidth = CalcHorzWidth();
mHorzWidth = horzWidth;
return nsLeafBoxFrame::SetBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
}
@@ -492,18 +448,15 @@ nsTreeBodyFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag)
{
if (mView) {
CalcInnerBox();
mHorzWidth = CalcHorzWidth();
ScrollParts parts = GetScrollParts();
mHorzWidth = CalcHorzWidth(parts);
if (!mHasFixedRowCount) {
#ifdef DEBUG_roc
printf("*** SETTING mPageLength in ReflowFinished, mInnerBox=%d,%d,%d,%d\n",
mInnerBox.x, mInnerBox.y, mInnerBox.width, mInnerBox.height);
#endif
mPageLength = mInnerBox.height / mRowHeight;
}
PRInt32 lastPageTopRow = PR_MAX(0, mRowCount - mPageLength);
if (mTopRowIndex > lastPageTopRow)
ScrollToRow(lastPageTopRow);
ScrollToRowInternal(parts, lastPageTopRow);
// make sure that the current selected item is still
// visible after the tree changes size.
@@ -513,11 +466,11 @@ nsTreeBodyFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag)
PRInt32 currentIndex;
sel->GetCurrentIndex(&currentIndex);
if (currentIndex != -1)
EnsureRowIsVisible(currentIndex);
EnsureRowIsVisibleInternal(parts, currentIndex);
}
InvalidateScrollbars();
CheckOverflow();
InvalidateScrollbars(parts);
CheckOverflow(parts);
}
mReflowCallbackPosted = PR_FALSE;
@@ -583,13 +536,14 @@ NS_IMETHODIMP nsTreeBodyFrame::SetView(nsITreeView * aView)
if (box)
box->SetPropertyAsSupports(view.get(), mView);
ScrollParts parts = GetScrollParts();
// The scrollbar will need to be updated.
InvalidateScrollbars();
InvalidateScrollbars(parts);
// Reset scrollbar position.
UpdateScrollbars();
UpdateScrollbars(parts);
CheckOverflow();
CheckOverflow(parts);
}
return NS_OK;
@@ -647,7 +601,7 @@ NS_IMETHODIMP
nsTreeBodyFrame::GetRowWidth(PRInt32 *aRowWidth)
{
float t2p = GetPresContext()->TwipsToPixels();
*aRowWidth = ((float)CalcHorzWidth() * t2p);
*aRowWidth = ((float)CalcHorzWidth(GetScrollParts()) * t2p);
return NS_OK;
}
@@ -777,55 +731,91 @@ nsTreeBodyFrame::InvalidateRange(PRInt32 aStart, PRInt32 aEnd)
return NS_OK;
}
PRBool
nsTreeBodyFrame::EnsureScrollable(PRBool ensureboth)
static void
FindScrollParts(nsIFrame* aCurrFrame, nsTreeBodyFrame::ScrollParts* aResult)
{
if (!aResult->mColumnsScrollableView) {
nsIScrollableFrame* f;
CallQueryInterface(aCurrFrame, &f);
if (f) {
aResult->mColumnsScrollableView = f->GetScrollableView();
}
}
nsIScrollbarFrame *sf = nsnull;
CallQueryInterface(aCurrFrame, &sf);
if (sf) {
PRBool isHorizontal = PR_FALSE;
if (NS_SUCCEEDED(aCurrFrame->GetOrientation(isHorizontal))) {
if (!isHorizontal) {
if (!aResult->mVScrollbar) {
aResult->mVScrollbar = sf;
}
} else {
if (!aResult->mHScrollbar) {
aResult->mHScrollbar = sf;
}
}
}
// don't bother searching inside a scrollbar
return;
}
nsIFrame* child = aCurrFrame->GetFirstChild(nsnull);
while (child &&
(!aResult->mVScrollbar || !aResult->mHScrollbar ||
!aResult->mColumnsScrollableView)) {
FindScrollParts(child, aResult);
child = child->GetNextSibling();
}
}
nsTreeBodyFrame::ScrollParts nsTreeBodyFrame::GetScrollParts()
{
nsPresContext* presContext = GetPresContext();
if (!mScrollbar || (ensureboth && (!mHorzScrollbar || !mColScrollView))) {
// Try to find it.
nsIContent* parContent = GetBaseElement();
nsIFrame* treeFrame = presContext->PresShell()
->GetPrimaryFrameFor(parContent);
if (treeFrame)
InitScrollbarFrames(presContext, treeFrame, this);
ScrollParts result = { nsnull, nsnull, nsnull, nsnull, nsnull };
nsIFrame* treeFrame = presContext->PresShell()->GetPrimaryFrameFor(GetBaseElement());
if (treeFrame) {
// The way we do this, searching through the entire frame subtree, is pretty
// dumb! We should know where these frames are.
FindScrollParts(treeFrame, &result);
if (result.mHScrollbar) {
result.mHScrollbar->SetScrollbarMediator(this);
nsIFrame* f;
CallQueryInterface(result.mHScrollbar, &f);
result.mHScrollbarContent = f->GetContent();
}
if (result.mVScrollbar) {
result.mVScrollbar->SetScrollbarMediator(this);
nsIFrame* f;
CallQueryInterface(result.mVScrollbar, &f);
result.mVScrollbarContent = f->GetContent();
}
}
NS_ASSERTION(mScrollbar, "no scroll bar");
// The view pointer we have is volatile and strange, update it
mColScrollView = NULL;
nsIFrame* colFrame = presContext->PresShell()->GetPrimaryFrameFor(mColScrollContent);
if (colFrame) {
nsIScrollableFrame* scrollFrame;
if (NS_SUCCEEDED(CallQueryInterface(colFrame, &scrollFrame)))
mColScrollView = scrollFrame->GetScrollableView();
}
return (mScrollbar && (!ensureboth || (mHorzScrollbar && mColScrollView))) ? PR_TRUE : PR_FALSE;
return result;
}
void
nsTreeBodyFrame::UpdateScrollbars()
nsTreeBodyFrame::UpdateScrollbars(const ScrollParts& aParts)
{
if (!EnsureScrollable(PR_FALSE))
return;
float t2p = GetPresContext()->TwipsToPixels();
nscoord rowHeightAsPixels = NSToCoordRound((float)mRowHeight*t2p);
nsAutoString curPos;
curPos.AppendInt(mTopRowIndex*rowHeightAsPixels);
mScrollbar->GetContent()->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curPos, PR_TRUE);
if (aParts.mVScrollbar) {
nsAutoString curPos;
curPos.AppendInt(mTopRowIndex*rowHeightAsPixels);
aParts.mVScrollbarContent->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curPos, PR_TRUE);
}
if (mHorzScrollbar) {
curPos.Truncate();
if (aParts.mHScrollbar) {
nsAutoString curPos;
curPos.AppendInt(mHorzPosition);
mHorzScrollbar->GetContent()->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curPos, PR_TRUE);
aParts.mHScrollbarContent->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curPos, PR_TRUE);
}
}
void
nsTreeBodyFrame::CheckOverflow()
nsTreeBodyFrame::CheckOverflow(const ScrollParts& aParts)
{
PRBool verticalOverflowChanged = PR_FALSE;
@@ -849,12 +839,10 @@ nsTreeBodyFrame::CheckOverflow()
nsEventDispatcher::Dispatch(mContent, presContext, &event, nsnull, &status);
}
PRBool horizontalOverflowChanged = PR_FALSE;
if (!EnsureScrollable(PR_TRUE))
if (!aParts.mColumnsScrollableView)
return;
nsRect bounds = mColScrollView->View()->GetBounds();
nsRect bounds = aParts.mColumnsScrollableView->View()->GetBounds();
if (bounds.width == 0)
return;
@@ -864,6 +852,7 @@ nsTreeBodyFrame::CheckOverflow()
float p2t = presContext->PixelsToTwips();
bounds.width += (p2t / 2);
PRBool horizontalOverflowChanged = PR_FALSE;
if (!mHorizontalOverflow && bounds.width < mHorzWidth) {
mHorizontalOverflow = PR_TRUE;
horizontalOverflowChanged = PR_TRUE;
@@ -885,49 +874,49 @@ nsTreeBodyFrame::CheckOverflow()
}
void
nsTreeBodyFrame::InvalidateScrollbars()
nsTreeBodyFrame::InvalidateScrollbars(const ScrollParts& aParts)
{
if (mUpdateBatchNest || !mView || !EnsureScrollable(PR_FALSE))
if (mUpdateBatchNest || !mView)
return;
nsPresContext* presContext = GetPresContext();
// Do Vertical Scrollbar
nsIContent* scrollbar = mScrollbar->GetContent();
if (aParts.mVScrollbar) {
// Do Vertical Scrollbar
nsIContent* scrollbar = aParts.mVScrollbarContent;
nsAutoString maxposStr;
float t2p = presContext->TwipsToPixels();
nscoord rowHeightAsPixels = NSToCoordRound((float)mRowHeight*t2p);
PRInt32 size = rowHeightAsPixels * (mRowCount > mPageLength ? mRowCount - mPageLength : 0);
maxposStr.AppendInt(size);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
// Also set our page increment and decrement.
nscoord pageincrement = mPageLength*rowHeightAsPixels;
nsAutoString pageStr;
pageStr.AppendInt(pageincrement);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
}
nsAutoString maxposStr;
if (aParts.mHScrollbar && aParts.mColumnsScrollableView) {
// And now Horizontal scrollbar
nsRect bounds = aParts.mColumnsScrollableView->View()->GetBounds();
nsIContent* scrollbar = aParts.mHScrollbarContent;
nsAutoString maxposStr;
float t2p = presContext->TwipsToPixels();
nscoord rowHeightAsPixels = NSToCoordRound((float)mRowHeight*t2p);
PRInt32 size = rowHeightAsPixels * (mRowCount > mPageLength ? mRowCount - mPageLength : 0);
maxposStr.AppendInt(size);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
// Also set our page increment and decrement.
nscoord pageincrement = mPageLength*rowHeightAsPixels;
nsAutoString pageStr;
pageStr.AppendInt(pageincrement);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
if (!mHorzScrollbar || !mColScrollView)
return;
// And now Horizontal scrollbar
nsRect bounds = mColScrollView->View()->GetBounds();
scrollbar = mHorzScrollbar->GetContent();
maxposStr.Truncate();
maxposStr.AppendInt(mHorzWidth > bounds.width ? mHorzWidth - bounds.width : 0);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
pageStr.Truncate();
pageStr.AppendInt(bounds.width);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
pageStr.Truncate();
pageStr.AppendInt(NSIntPixelsToTwips(16, presContext->PixelsToTwips()));
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::increment, pageStr, PR_TRUE);
maxposStr.AppendInt(mHorzWidth > bounds.width ? mHorzWidth - bounds.width : 0);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::maxpos, maxposStr, PR_TRUE);
nsAutoString pageStr;
pageStr.AppendInt(bounds.width);
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::pageincrement, pageStr, PR_TRUE);
pageStr.Truncate();
pageStr.AppendInt(NSIntPixelsToTwips(16, presContext->PixelsToTwips()));
scrollbar->SetAttr(kNameSpaceID_None, nsXULAtoms::increment, pageStr, PR_TRUE);
}
}
// Takes client x/y in pixels, converts them to twips, and massages them to be
@@ -1544,11 +1533,13 @@ NS_IMETHODIMP nsTreeBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
PRInt32 last = GetLastVisibleRow();
if (aIndex >= mTopRowIndex && aIndex <= last)
InvalidateRange(aIndex, last);
ScrollParts parts = GetScrollParts();
if (mTopRowIndex == 0) {
// Just update the scrollbar and return.
InvalidateScrollbars();
CheckOverflow();
InvalidateScrollbars(parts);
CheckOverflow(parts);
MarkDirtyIfSelect();
return NS_OK;
}
@@ -1558,7 +1549,7 @@ NS_IMETHODIMP nsTreeBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
if (mTopRowIndex > aIndex) {
// Rows came in above us. Augment the top row index.
mTopRowIndex += aCount;
UpdateScrollbars();
UpdateScrollbars(parts);
}
}
else if (aCount < 0) {
@@ -1566,20 +1557,20 @@ NS_IMETHODIMP nsTreeBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
// No need to invalidate. The remove happened
// completely above us (offscreen).
mTopRowIndex -= count;
UpdateScrollbars();
UpdateScrollbars(parts);
}
else if (mTopRowIndex >= aIndex) {
// This is a full-blown invalidate.
if (mTopRowIndex + mPageLength > mRowCount - 1) {
mTopRowIndex = PR_MAX(0, mRowCount - 1 - mPageLength);
UpdateScrollbars();
UpdateScrollbars(parts);
}
Invalidate();
}
}
InvalidateScrollbars();
CheckOverflow();
InvalidateScrollbars(parts);
CheckOverflow(parts);
MarkDirtyIfSelect();
return NS_OK;
@@ -1602,12 +1593,14 @@ NS_IMETHODIMP nsTreeBodyFrame::EndUpdateBatch()
PRInt32 countBeforeUpdate = mRowCount;
mView->GetRowCount(&mRowCount);
if (countBeforeUpdate != mRowCount) {
ScrollParts parts = GetScrollParts();
if (mTopRowIndex + mPageLength > mRowCount - 1) {
mTopRowIndex = PR_MAX(0, mRowCount - 1 - mPageLength);
UpdateScrollbars();
UpdateScrollbars(parts);
}
InvalidateScrollbars();
CheckOverflow();
InvalidateScrollbars(parts);
CheckOverflow(parts);
}
}
}
@@ -1969,7 +1962,7 @@ void nsTreeBodyFrame::CalcInnerBox()
}
nscoord
nsTreeBodyFrame::CalcHorzWidth()
nsTreeBodyFrame::CalcHorzWidth(const ScrollParts& aParts)
{
nscoord width = 0;
nscoord height;
@@ -1978,8 +1971,8 @@ nsTreeBodyFrame::CalcHorzWidth()
// properly covers all contingencies of what could be
// scrollable (columns, body, etc...)
if (EnsureScrollable(PR_TRUE)) {
if (NS_FAILED (mColScrollView->GetContainerSize(&width, &height)))
if (aParts.mColumnsScrollableView) {
if (NS_FAILED (aParts.mColumnsScrollableView->GetContainerSize(&width, &height)))
width = 0;
}
@@ -2244,7 +2237,7 @@ nsTreeBodyFrame::PaintTreeBody(nsIRenderingContext& aRenderingContext,
if (!mHasFixedRowCount)
mPageLength = mInnerBox.height/mRowHeight;
if (oldPageCount != mPageLength || mHorzWidth != CalcHorzWidth()) {
if (oldPageCount != mPageLength || mHorzWidth != CalcHorzWidth(GetScrollParts())) {
// Schedule a ResizeReflow that will update our info properly.
nsBoxLayoutState state(GetPresContext());
MarkDirty(state);
@@ -3333,6 +3326,11 @@ nsTreeBodyFrame::PaintBackgroundLayer(nsStyleContext* aStyleContext,
// Scrolling
NS_IMETHODIMP nsTreeBodyFrame::EnsureRowIsVisible(PRInt32 aRow)
{
return EnsureRowIsVisibleInternal(GetScrollParts(), aRow);
}
nsresult nsTreeBodyFrame::EnsureRowIsVisibleInternal(const ScrollParts& aParts, PRInt32 aRow)
{
if (!mView)
return NS_OK;
@@ -3341,11 +3339,11 @@ NS_IMETHODIMP nsTreeBodyFrame::EnsureRowIsVisible(PRInt32 aRow)
return NS_OK;
if (aRow < mTopRowIndex)
ScrollToRow(aRow);
ScrollToRowInternal(aParts, aRow);
else {
// Bring it just on-screen.
PRInt32 distance = aRow - (mTopRowIndex+mPageLength)+1;
ScrollToRow(mTopRowIndex+distance);
ScrollToRowInternal(aParts, mTopRowIndex+distance);
}
return NS_OK;
@@ -3356,71 +3354,79 @@ NS_IMETHODIMP nsTreeBodyFrame::EnsureCellIsVisible(PRInt32 aRow, nsITreeColumn*
if (!aCol)
return NS_ERROR_INVALID_POINTER;
nsresult rv;
ScrollParts parts = GetScrollParts();
if (EnsureScrollable(PR_TRUE)) {
nscoord result = -1;
nscoord result = -1;
nsTreeColumn* col = NS_STATIC_CAST(nsTreeColumn*, aCol);
nsTreeColumn* col = NS_STATIC_CAST(nsTreeColumn*, aCol);
nscoord columnPos = col->GetX();
nscoord columnWidth = col->GetWidth();
nscoord columnPos = col->GetX();
nscoord columnWidth = col->GetWidth();
// If the start of the column is before the
// start of the horizontal view, then scroll
if (columnPos < mHorzPosition)
result = columnPos;
// If the start of the column is before the
// start of the horizontal view, then scroll
if (columnPos < mHorzPosition)
result = columnPos;
// If the end of the column is past the end of
// the horizontal view, then scroll
else if ((columnPos + columnWidth) > (mHorzPosition + mInnerBox.width))
result = ((columnPos + columnWidth) - (mHorzPosition + mInnerBox.width)) + mHorzPosition;
// If the end of the column is past the end of
// the horizontal view, then scroll
else if ((columnPos + columnWidth) > (mHorzPosition + mInnerBox.width))
result = ((columnPos + columnWidth) - (mHorzPosition + mInnerBox.width)) + mHorzPosition;
if (result != -1) {
rv = ScrollHorzInternal(result);
if(NS_FAILED(rv)) return rv;
}
if (result != -1) {
nsresult rv = ScrollHorzInternal(parts, result);
if(NS_FAILED(rv)) return rv;
}
return EnsureRowIsVisible(aRow);
return EnsureRowIsVisibleInternal(parts, aRow);
}
NS_IMETHODIMP nsTreeBodyFrame::ScrollToCell(PRInt32 aRow, nsITreeColumn* aCol)
{
nsresult rv = ScrollToRow(aRow);
ScrollParts parts = GetScrollParts();
nsresult rv = ScrollToRowInternal(parts, aRow);
if(NS_FAILED(rv)) return rv;
return ScrollToColumn(aCol);
return ScrollToColumnInternal(parts, aCol);
}
NS_IMETHODIMP nsTreeBodyFrame::ScrollToColumn(nsITreeColumn* aCol)
{
if(!aCol)
return ScrollToColumnInternal(GetScrollParts(), aCol);
}
nsresult nsTreeBodyFrame::ScrollToColumnInternal(const ScrollParts& aParts,
nsITreeColumn* aCol)
{
if(!aCol)
return NS_ERROR_INVALID_POINTER;
nsTreeColumn* col = NS_STATIC_CAST(nsTreeColumn*, aCol);
return ScrollHorzInternal(col->GetX());
return ScrollHorzInternal(aParts, col->GetX());
}
NS_IMETHODIMP nsTreeBodyFrame::ScrollToHorizontalPosition(PRInt32 aHorizontalPosition)
{
float p2t = GetPresContext()->PixelsToTwips();
ScrollHorzInternal((float)aHorizontalPosition * p2t);
ScrollHorzInternal(GetScrollParts(), (float)aHorizontalPosition * p2t);
return NS_OK;
}
NS_IMETHODIMP nsTreeBodyFrame::ScrollToRow(PRInt32 aRow)
{
ScrollInternal(aRow);
UpdateScrollbars();
return ScrollToRowInternal(GetScrollParts(), aRow);
}
nsresult nsTreeBodyFrame::ScrollToRowInternal(const ScrollParts& aParts, PRInt32 aRow)
{
ScrollInternal(aParts, aRow);
UpdateScrollbars(aParts);
#if defined(XP_MAC) || defined(XP_MACOSX)
// mac can't process the event loop during a drag, so if we're dragging,
// grab the scroll widget and make it paint synchronously. This is
// sorta slow (having to paint the entire tree), but it works.
if (mSlots && mSlots->mDragSession) {
nsIWidget* scrollWidget = mScrollbar->GetWindow();
if (mSlots && mSlots->mDragSession && aParts.mVScrollbar) {
nsIWidget* scrollWidget = aParts.mVScrollbar->GetWindow();
if (scrollWidget)
scrollWidget->Invalidate(PR_TRUE);
}
@@ -3466,7 +3472,7 @@ NS_IMETHODIMP nsTreeBodyFrame::ScrollByPages(PRInt32 aNumPages)
}
nsresult
nsTreeBodyFrame::ScrollInternal(PRInt32 aRow)
nsTreeBodyFrame::ScrollInternal(const ScrollParts& aParts, PRInt32 aRow)
{
if (!mView)
return NS_OK;
@@ -3513,9 +3519,9 @@ nsTreeBodyFrame::ScrollInternal(PRInt32 aRow)
}
nsresult
nsTreeBodyFrame::ScrollHorzInternal(PRInt32 aPosition)
nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, PRInt32 aPosition)
{
if (!mView || !EnsureScrollable(PR_TRUE))
if (!mView || !aParts.mColumnsScrollableView || !aParts.mHScrollbar)
return NS_OK;
if (aPosition == mHorzPosition)
@@ -3524,7 +3530,7 @@ nsTreeBodyFrame::ScrollHorzInternal(PRInt32 aPosition)
if (aPosition < 0 || aPosition > mHorzWidth)
return NS_OK;
nsRect bounds = mColScrollView->View()->GetBounds();
nsRect bounds = aParts.mColumnsScrollableView->View()->GetBounds();
if (aPosition > (mHorzWidth - bounds.width))
aPosition = mHorzWidth - bounds.width;
@@ -3549,11 +3555,11 @@ nsTreeBodyFrame::ScrollHorzInternal(PRInt32 aPosition)
// Reflect the change in the scrollbar
nsAutoString curPos;
curPos.AppendInt(aPosition);
mHorzScrollbar->GetContent()->SetAttr(kNameSpaceID_None,
nsXULAtoms::curpos, curPos, PR_TRUE);
aParts.mHScrollbarContent->SetAttr(kNameSpaceID_None,
nsXULAtoms::curpos, curPos, PR_TRUE);
// Update the column scroll view
mColScrollView->ScrollTo(mHorzPosition, 0, 0);
aParts.mColumnsScrollableView->ScrollTo(mHorzPosition, 0, 0);
// And fire off an event about it all
nsScrollbarEvent event(PR_TRUE, NS_SCROLL_EVENT, nsnull);
@@ -3571,20 +3577,22 @@ NS_IMETHODIMP
nsTreeBodyFrame::ScrollbarButtonPressed(nsISupports* aScrollbar, PRInt32 aOldIndex, PRInt32 aNewIndex)
{
// Determine which scrollbar we're talking about
nsIFrame* sf = nsnull;
nsIScrollbarFrame* sf = nsnull;
CallQueryInterface(aScrollbar, &sf);
NS_ASSERTION(sf, "scrollbar has no frame");
if (sf == mScrollbar) {
ScrollParts parts = GetScrollParts();
if (sf == parts.mVScrollbar) {
if (aNewIndex > aOldIndex)
ScrollToRow(mTopRowIndex+1);
ScrollToRowInternal(parts, mTopRowIndex+1);
else if (aNewIndex < aOldIndex)
ScrollToRow(mTopRowIndex-1);
ScrollToRowInternal(parts, mTopRowIndex-1);
} else {
ScrollHorzInternal(aNewIndex);
ScrollHorzInternal(parts, aNewIndex);
}
UpdateScrollbars();
UpdateScrollbars(parts);
return NS_OK;
}
@@ -3592,36 +3600,35 @@ nsTreeBodyFrame::ScrollbarButtonPressed(nsISupports* aScrollbar, PRInt32 aOldInd
NS_IMETHODIMP
nsTreeBodyFrame::PositionChanged(nsISupports* aScrollbar, PRInt32 aOldIndex, PRInt32& aNewIndex)
{
if (!EnsureScrollable(PR_FALSE))
return NS_ERROR_UNEXPECTED;
ScrollParts parts = GetScrollParts();
if (aOldIndex == aNewIndex)
return NS_OK;
// Determine which scrollbar we're talking about
nsIFrame* sf = nsnull;
nsIScrollbarFrame* sf = nsnull;
CallQueryInterface(aScrollbar, &sf);
NS_ASSERTION(sf, "scrollbar has no frame");
// Vertical Scrollbar
if (mScrollbar == sf) {
if (parts.mVScrollbar == sf) {
float t2p = GetPresContext()->TwipsToPixels();
nscoord rh = NSToCoordRound((float)mRowHeight*t2p);
nscoord newrow = aNewIndex/rh;
ScrollInternal(newrow);
ScrollInternal(parts, newrow);
// Go exactly where we're supposed to
// Update the scrollbar.
nsAutoString curPos;
curPos.AppendInt(aNewIndex);
mScrollbar->GetContent()->SetAttr(kNameSpaceID_None,
parts.mVScrollbarContent->SetAttr(kNameSpaceID_None,
nsXULAtoms::curpos, curPos, PR_TRUE);
// Horizontal Scrollbar
} else if (mHorzScrollbar && mHorzScrollbar == sf) {
ScrollHorzInternal(aNewIndex);
} else if (parts.mHScrollbar == sf) {
ScrollHorzInternal(parts, aNewIndex);
}
return NS_OK;
@@ -3689,7 +3696,6 @@ nsTreeBodyFrame::ClearStyleAndImageCaches()
mStyleCache.Clear();
mImageCache.EnumerateRead(CancelImageRequest, nsnull);
mImageCache.Clear();
mScrollbar = nsnull;
return NS_OK;
}

View File

@@ -212,6 +212,14 @@ public:
friend nsIFrame* NS_NewTreeBodyFrame(nsIPresShell* aPresShell);
struct ScrollParts {
nsIScrollbarFrame* mVScrollbar;
nsIContent* mVScrollbarContent;
nsIScrollbarFrame* mHScrollbar;
nsIContent* mHScrollbarContent;
nsIScrollableView* mColumnsScrollableView;
};
protected:
PRInt32 GetLastVisibleRow() {
return mTopRowIndex + mPageLength;
@@ -248,35 +256,38 @@ protected:
void CalcInnerBox();
// Calculate the total width of our scrollable portion
nscoord CalcHorzWidth();
nscoord CalcHorzWidth(const ScrollParts& aParts);
// Looks up a style context in the style cache. On a cache miss we resolve
// the pseudo-styles passed in and place them into the cache.
nsStyleContext* GetPseudoStyleContext(nsIAtom* aPseudoElement);
// Makes |mScrollbar| and (when both set) |mHorzScrollbar| non-null if at all possible.
PRBool EnsureScrollable(PRBool both);
// Finds the actual scrollbars and views in the table children
void InitScrollbarFrames(nsPresContext* aPresContext, nsIFrame* aCurrFrame,
nsIScrollbarMediator* aSM);
// Retrieves the scrollbars and scrollview relevant to this treebody. We
// traverse the frame tree under our base element, in frame order, looking
// for the first relevant vertical scrollbar, horizontal scrollbar, and
// scrollable frame (with associated content and scrollable view). These
// are all volatile and should not be retained.
ScrollParts GetScrollParts();
// Update the curpos of the scrollbar.
void UpdateScrollbars();
void UpdateScrollbars(const ScrollParts& aParts);
// Update the maxpos of the scrollbar.
void InvalidateScrollbars();
void InvalidateScrollbars(const ScrollParts& aParts);
// Check overflow and generate events.
void CheckOverflow();
void CheckOverflow(const ScrollParts& aParts);
// Use to auto-fill some of the common properties without the view having to do it.
// Examples include container, open, selected, and focus.
void PrefillPropertyArray(PRInt32 aRowIndex, nsTreeColumn* aCol);
// Our internal scroll method, used by all the public scroll methods.
nsresult ScrollInternal(PRInt32 aRow);
nsresult ScrollHorzInternal(PRInt32 aPosition);
nsresult ScrollInternal(const ScrollParts& aParts, PRInt32 aRow);
nsresult ScrollToRowInternal(const ScrollParts& aParts, PRInt32 aRow);
nsresult ScrollToColumnInternal(const ScrollParts& aParts, nsITreeColumn* aCol);
nsresult ScrollHorzInternal(const ScrollParts& aParts, PRInt32 aPosition);
nsresult EnsureRowIsVisibleInternal(const ScrollParts& aParts, PRInt32 aRow);
// Convert client pixels into twips in our coordinate space.
void AdjustClientCoordsToBoxCoordSpace(PRInt32 aX, PRInt32 aY,
@@ -366,15 +377,6 @@ protected: // Data Members
// It maps directly to an imgIRequest.
nsDataHashtable<nsStringHashKey, nsTreeImageCacheEntry> mImageCache;
// Our scrollbars.
nsIFrame* mScrollbar;
nsIFrame* mHorzScrollbar;
// The scrollable frame and view the columns are contained in. The view is very volatile and
// gets looked up by EnsureScrollable every time it's called.
nsCOMPtr<nsIContent> mColScrollContent;
nsIScrollableView* mColScrollView;
// The index of the first visible row and the # of rows visible onscreen.
// The tree only examines onscreen rows, starting from
// this index and going up to index+pageLength.