implement EnsureRowIsVisible for bug #17763

r=scottip
This commit is contained in:
alecf%netscape.com 1999-11-05 02:02:09 +00:00
Родитель e297d950f4
Коммит 7560815b97
2 изменённых файлов: 152 добавлений и 48 удалений

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
@ -114,9 +114,7 @@ void nsTreeRowGroupFrame::DestroyRows(nsTableFrame* aTableFrame, nsIPresContext&
// reduced. A reflow will then pick up and create the new frames.
nsIFrame* childFrame = GetFirstFrame();
while (childFrame && rowsToLose > 0) {
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay)
if (IsTableRowGroupFrame(childFrame))
{
PRInt32 rowGroupCount;
((nsTreeRowGroupFrame*)childFrame)->GetRowCount(rowGroupCount);
@ -129,7 +127,7 @@ void nsTreeRowGroupFrame::DestroyRows(nsTableFrame* aTableFrame, nsIPresContext&
else
((nsTreeRowGroupFrame*)childFrame)->DestroyRows(aTableFrame, aPresContext, rowsToLose);
}
else if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
else if (IsTableRowFrame(childFrame))
{
// Lost a row.
rowsToLose--;
@ -153,9 +151,7 @@ void nsTreeRowGroupFrame::ReverseDestroyRows(nsTableFrame* aTableFrame, nsIPresC
// reduced. A reflow will then pick up and create the new frames.
nsIFrame* childFrame = GetLastFrame();
while (childFrame && rowsToLose > 0) {
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay)
if (IsTableRowGroupFrame(childFrame))
{
PRInt32 rowGroupCount;
((nsTreeRowGroupFrame*)childFrame)->GetRowCount(rowGroupCount);
@ -168,7 +164,7 @@ void nsTreeRowGroupFrame::ReverseDestroyRows(nsTableFrame* aTableFrame, nsIPresC
else
((nsTreeRowGroupFrame*)childFrame)->ReverseDestroyRows(aTableFrame, aPresContext, rowsToLose);
}
else if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
else if (IsTableRowFrame(childFrame))
{
// Lost a row.
rowsToLose--;
@ -204,7 +200,8 @@ nsTreeRowGroupFrame::ConstructContentChain(nsIContent* aRowContent)
}
void
nsTreeRowGroupFrame::ConstructOldContentChain(nsIPresContext& aPresContext, nsIContent* aOldRowContent)
nsTreeRowGroupFrame::ConstructOldContentChain(nsIPresContext& aPresContext,
nsIContent* aOldRowContent)
{
nsCOMPtr<nsIContent> childOfCommonAncestor;
@ -256,11 +253,14 @@ nsTreeRowGroupFrame::FindChildOfCommonContentChainAncestor(nsIContent *startCont
}
// if oldRowContent is an ancestor of rowContent, return true,
// and return the previous ancestor if requested
PRBool
nsTreeRowGroupFrame::IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowContent, nsIContent** firstDescendant)
{
nsCOMPtr<nsIContent> prevContent;
nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aOldRowContent);
while (currContent) {
if(aRowContent == currContent.get())
@ -272,6 +272,7 @@ nsTreeRowGroupFrame::IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowCont
}
return PR_TRUE;
}
prevContent = currContent;
prevContent->GetParent(*getter_AddRefs(currContent));
}
@ -279,6 +280,30 @@ nsTreeRowGroupFrame::IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowCont
return PR_FALSE;
}
PRBool
nsTreeRowGroupFrame::IsTableRowGroupFrame(nsIFrame *frame)
{
if (!frame) return PR_FALSE;
const nsStyleDisplay *display;
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&)display);
return (display->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW_GROUP);
}
PRBool
nsTreeRowGroupFrame::IsTableRowFrame(nsIFrame *frame)
{
if (!frame) return PR_FALSE;
const nsStyleDisplay *display;
frame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&)display);
return (display->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW);
}
void
nsTreeRowGroupFrame::CreateOldContentChain(nsIPresContext& aPresContext, nsIContent* aOldRowContent, nsIContent* topOfChain)
{
@ -288,22 +313,18 @@ nsTreeRowGroupFrame::CreateOldContentChain(nsIPresContext& aPresContext, nsICont
nsCOMPtr<nsIPresShell> shell;
aPresContext.GetShell(getter_AddRefs(shell));
//For each item between the oldtoprow and the new first child of common ancestor between
//new top row and old top row we need to see if the content chain has to be reset.
//For each item between the (oldtoprow) and
// (the new first child of common ancestry between new top row and old top row)
// we need to see if the content chain has to be reset.
while(currContent.get() != topOfChain)
{
nsIFrame* result = nsnull;
shell->GetPrimaryFrameFor(currContent, &result);
nsIFrame* primaryFrame = nsnull;
shell->GetPrimaryFrameFor(currContent, &primaryFrame);
if(result)
if(primaryFrame)
{
const nsStyleDisplay *display;
result->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if (display->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW_GROUP)
if (IsTableRowGroupFrame(primaryFrame))
{
nsTreeRowGroupFrame *curRowGroup = (nsTreeRowGroupFrame*)result;
//Get the current content's parent's first child
nsCOMPtr<nsIContent> parent;
currContent->GetParent(*getter_AddRefs(parent));
@ -311,22 +332,24 @@ nsTreeRowGroupFrame::CreateOldContentChain(nsIPresContext& aPresContext, nsICont
nsCOMPtr<nsIContent> firstChild;
parent->ChildAt(0, *getter_AddRefs(firstChild));
nsTreeRowGroupFrame *curRowGroup = (nsTreeRowGroupFrame*)primaryFrame;
nsIFrame *parentFrame;
curRowGroup->GetParent(&parentFrame);
result->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if (display->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW_GROUP)
if (IsTableRowGroupFrame(parentFrame))
{
//Get the current content's parent's first frame.
nsTreeRowGroupFrame *parentRowGroupFrame = (nsTreeRowGroupFrame*)parentFrame;
nsTreeRowGroupFrame *parentRowGroupFrame =
(nsTreeRowGroupFrame*)parentFrame;
nsIFrame *currentTopFrame = parentRowGroupFrame->GetFirstFrame();
nsCOMPtr<nsIContent> topContent;
currentTopFrame->GetContent(getter_AddRefs(topContent));
//If the current content's parent's first child is different than the
//current frame's parent's first child then we know they are out of synch
//and we need to set the content chain correctly.
// If the current content's parent's first child is different
// than the current frame's parent's first child then we know
// they are out of synch and we need to set the content
// chain correctly.
if(topContent.get() != firstChild.get())
{
@ -351,15 +374,13 @@ nsTreeRowGroupFrame::GetFirstRowContent(nsIContent** aResult)
*aResult = nsnull;
nsIFrame* kid = GetFirstFrame();
while (kid) {
const nsStyleDisplay *childDisplay;
kid->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay)
if (IsTableRowGroupFrame(kid))
{
((nsTreeRowGroupFrame*)kid)->GetFirstRowContent(aResult);
if (*aResult)
return;
}
else if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
else if (IsTableRowFrame(kid))
{
kid->GetContent(aResult); // The ADDREF happens here.
return;
@ -369,7 +390,8 @@ nsTreeRowGroupFrame::GetFirstRowContent(nsIContent** aResult)
}
void
nsTreeRowGroupFrame::FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent,
nsTreeRowGroupFrame::FindRowContentAtIndex(PRInt32& aIndex,
nsIContent* aParent,
nsIContent** aResult)
{
// Init to nsnull.
@ -387,6 +409,8 @@ nsTreeRowGroupFrame::FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent,
aParent->ChildAt(i, *getter_AddRefs(childContent));
nsCOMPtr<nsIAtom> tag;
childContent->GetTag(*getter_AddRefs(tag));
// treerow - Count this row, if we're at 0, then we've found the row.
if (tag.get() == nsXULAtoms::treerow) {
aIndex--;
if (aIndex < 0) {
@ -549,6 +573,7 @@ nsTreeRowGroupFrame::ComputeVisibleRowCount(PRInt32& aCount, nsIContent* aParent
nsCOMPtr<nsIContent> parent;
childContent->GetParent(*getter_AddRefs(parent));
parent->GetAttribute(kNameSpaceID_None, openAtom, isOpen);
if (isOpen == "true")
ComputeVisibleRowCount(aCount, childContent);
}
}
@ -557,6 +582,9 @@ nsTreeRowGroupFrame::ComputeVisibleRowCount(PRInt32& aCount, nsIContent* aParent
NS_IMETHODIMP
nsTreeRowGroupFrame::PositionChanged(nsIPresContext& aPresContext, PRInt32 aOldIndex, PRInt32 aNewIndex)
{
#ifdef DEBUG_alecf
printf("PositionChanged from %d to %d\n", aOldIndex, aNewIndex);
#endif
if (aNewIndex < 0)
return NS_OK;
@ -581,15 +609,21 @@ nsTreeRowGroupFrame::PositionChanged(nsIPresContext& aPresContext, PRInt32 aOldI
// Figure out how many rows we need to lose (if we moved down) or gain (if we moved up).
PRInt32 delta = aNewIndex > aOldIndex ? aNewIndex - aOldIndex : aOldIndex - aNewIndex;
//printf("The delta is: %d\n", delta);
#ifdef DEBUG_alecf
printf("Scrolling, the delta is: %d\n", delta);
#endif
// Get our presentation context.
if (delta < rowCount) {
PRInt32 loseRows = delta;
// scrolling down
if (aNewIndex > aOldIndex) {
// Figure out how many rows we have to lose off the top.
DestroyRows(tableFrame, aPresContext, loseRows);
}
// scrolling up
else {
// Get our first row content.
nsCOMPtr<nsIContent> rowContent;
@ -647,6 +681,9 @@ nsTreeRowGroupFrame::PagedUpDown()
char ch[100];
sprintf(ch,"%d", rowGroupCount);
#ifdef DEBUG_alecf
printf("PagedUpDown, setting increment to %d\n", rowGroupCount);
#endif
scrollbarContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::pageincrement, nsString(ch), PR_FALSE);
}
@ -679,18 +716,14 @@ PRBool nsTreeRowGroupFrame::RowGroupDesiresExcessSpace()
{
nsIFrame* parentFrame;
GetParent(&parentFrame);
const nsStyleDisplay *display;
parentFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if (display->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW_GROUP)
if (IsTableRowGroupFrame(parentFrame))
return PR_FALSE; // Nested groups don't grow.
else return PR_TRUE; // The outermost group can grow.
}
PRBool nsTreeRowGroupFrame::RowGroupReceivesExcessSpace()
{
const nsStyleDisplay *display;
GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == display->mDisplay)
if (IsTableRowGroupFrame(this))
return PR_TRUE;
else return PR_FALSE; // Headers and footers don't get excess space.
}
@ -1060,9 +1093,7 @@ nsTreeRowGroupFrame::GetFirstFrameForReflow(nsIPresContext& aPresContext)
//printf("Created a frame\n");
mBottomFrame = mTopFrame;
const nsStyleDisplay *rowDisplay;
mTopFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay);
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
if (IsTableRowFrame(mTopFrame)) {
nsCOMPtr<nsIContent> rowContent;
mTopFrame->GetContent(getter_AddRefs(rowContent));
/*nsCOMPtr<nsIContent> cellContent;
@ -1099,7 +1130,7 @@ nsTreeRowGroupFrame::GetFirstFrameForReflow(nsIPresContext& aPresContext)
}
}
}
else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP==rowDisplay->mDisplay && mContentChain) {
else if (IsTableRowGroupFrame(mTopFrame) && mContentChain) {
// We have just instantiated a row group, and we have a content chain. This
// means we need to potentially pass a sub-content chain to the instantiated
// frame, so that it can also sync up with its children.
@ -1168,9 +1199,7 @@ nsTreeRowGroupFrame::GetNextFrameForReflow(nsIPresContext& aPresContext, nsIFram
// XXX Can be optimized if we detect that we're appending a row to the end of the tree.
// Also the act of appending or inserting a row group is harmless.
const nsStyleDisplay *rowDisplay;
(*aResult)->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay);
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
if (IsTableRowFrame(*aResult)) {
nsCOMPtr<nsIContent> topRowContent;
PRInt32 delta = 1;
@ -1398,9 +1427,13 @@ nsTreeRowGroupFrame::IndexOfRow(nsIPresContext& aPresContext,
else {
// We didn't find a frame. This mean we have no choice but to crawl
// the row group.
#ifdef DEBUG_alecf
printf("Searching for non-visible content node\n");
#endif
}
}
PRBool
nsTreeRowGroupFrame::IsValidRow(PRInt32 aRowIndex)
{
@ -1412,13 +1445,72 @@ nsTreeRowGroupFrame::IsValidRow(PRInt32 aRowIndex)
void
nsTreeRowGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
{
//XXX need to write
// if no scrollbar, then it must be visible
if (!mScrollbar) return;
PRInt32 rows;
GetRowCount(rows);
PRInt32 bottomIndex = mCurrentIndex +rows - 1;
// if row is visible, ignore
if (mCurrentIndex <= aRowIndex && aRowIndex <= bottomIndex)
return;
#ifdef DEBUG_alecf
printf("top = %d, bottom = %d, going to %d\n",
mCurrentIndex, bottomIndex, aRowIndex);
#endif
nsCOMPtr<nsIContent> scrollbarContent;
mScrollbar->GetContent(getter_AddRefs(scrollbarContent));
PRInt32 scrollTo = mCurrentIndex;
if (aRowIndex < mCurrentIndex) {
// row is above us, scroll up from mCurrentIndex
// scroll such that mCurrentIndex = aRowIndex
#ifdef DEBUG_alecf
printf("row is above, scroll to %d\n", aRowIndex);
#endif
scrollTo=aRowIndex;
} else {
// aRowIndex > bottomIndex here
// row is below us, so scroll down from bottomIndex
// scroll such that mCurrentIndex = (aRowIndex - aRowCount)
NS_ASSERTION(aRowIndex - rows >=0, "scrolling to negative row?!");
scrollTo=aRowIndex - rows;
#ifdef DEBUG_alecf
printf("row is below, scroll to %d\n", scrollTo);
#endif
}
nsString value;
#ifdef DEBUG_alecf
// dump state
scrollbarContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::maxpos, value);
printf("maxpos = %s\n", value.ToNewCString());
scrollbarContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::curpos, value);
printf("curpos = %s\n", value.ToNewCString());
value="";
#endif
// scrollTo++; // off by one?
value.Append(scrollTo);
//rv = scrollbarContent->GetAttribute(kNamespaceID_None, nsXULAtoms::curpos,
// value, PR_TRUE);
scrollbarContent->SetAttribute(kNameSpaceID_None, nsXULAtoms::curpos,
value, PR_TRUE);
}
void
nsTreeRowGroupFrame::GetCellFrameAtIndex(PRInt32 aRowIndex, PRInt32 aColIndex,
nsTreeCellFrame** aResult)
{
#ifdef DEBUG_alecf
printf("Looking for cell (%d, %d)..", aRowIndex, aColIndex);
#endif
// The screen index = (aRowIndex - mCurrentIndex)
PRInt32 screenIndex = aRowIndex - mCurrentIndex;
@ -1428,6 +1520,10 @@ nsTreeRowGroupFrame::GetCellFrameAtIndex(PRInt32 aRowIndex, PRInt32 aColIndex,
nsTableCellFrame* cellFrame;
#ifdef DEBUG_alecf
printf("(screen index (%d,%d))\n", screenIndex, aColIndex);
#endif
nsCellMap * cellMap = tableFrame->GetCellMap();
CellData* cellData = cellMap->GetCellAt(screenIndex, aColIndex);
if (cellData) {
@ -1436,6 +1532,10 @@ nsTreeRowGroupFrame::GetCellFrameAtIndex(PRInt32 aRowIndex, PRInt32 aColIndex,
*aResult = (nsTreeCellFrame*)cellFrame; // XXX I am evil.
}
}
#ifdef DEBUG_alecf
printf("got cell frame %p\n", *aResult);
#endif
}
void nsTreeRowGroupFrame::PostAppendRow(nsIFrame* aRowFrame, nsIPresContext& aPresContext)

Просмотреть файл

@ -121,7 +121,7 @@ protected:
void FindPreviousRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,
nsIContent* aDownwardHint, nsIContent** aResult);
void FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent,
static void FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent,
nsIContent** aResult);
void MarkTreeAsDirty(nsIPresContext& aPresContext, nsTreeFrame* aTreeFrame);
@ -159,6 +159,10 @@ public:
PRInt32 GetVisibleRowCount() { return mRowCount; };
static PRBool IsTableRowGroupFrame(nsIFrame*);
static PRBool IsTableRowFrame(nsIFrame*);
protected: // Data Members
nsIFrame* mTopFrame; // The current topmost frame in the view.
nsIFrame* mBottomFrame; // The current bottom frame in the view.