mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 12:55:46 +00:00
Fix for 57139. a=ben
This commit is contained in:
parent
86fe4426e1
commit
85a1b3c0cd
@ -8262,8 +8262,10 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext,
|
||||
if (aContainer) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContainer->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && (tag.get() == nsXULAtoms::treechildren ||
|
||||
tag.get() == nsXULAtoms::treeitem)) {
|
||||
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
|
||||
PRBool treeItem = tag && tag.get() == nsXULAtoms::treeitem;
|
||||
|
||||
if (treeChildren || treeItem) {
|
||||
// Walk up to the outermost tree row group frame and tell it that
|
||||
// content was added.
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
@ -8287,15 +8289,40 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext,
|
||||
|
||||
// Get the primary frame for the parent of the child that's being added.
|
||||
nsIFrame* innerFrame = GetFrameFor(shell, aPresContext, aContainer);
|
||||
|
||||
treeRowGroup->ClearRowGroupInfo();
|
||||
|
||||
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
|
||||
nsXULTreeGroupFrame* innerGroup = (nsXULTreeGroupFrame*) innerFrame;
|
||||
if (innerGroup) {
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
innerGroup->MarkDirtyChildren(state);
|
||||
}
|
||||
shell->FlushPendingNotifications();
|
||||
else {
|
||||
treeRowGroup->MarkDirtyChildren(state);
|
||||
|
||||
// Resolve our style context to find out if we need to clear out our
|
||||
// undisplayed content.
|
||||
if (treeChildren) {
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
aContainer->GetParent(*getter_AddRefs(parent));
|
||||
if (parent) {
|
||||
nsAutoString open;
|
||||
parent->GetAttribute(kNameSpaceID_None, nsXULAtoms::open, open);
|
||||
if (open.EqualsIgnoreCase("true")) {
|
||||
// Clear our undisplayed content.
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
aPresContext->GetShell(getter_AddRefs(shell));
|
||||
nsCOMPtr<nsIFrameManager> frameManager;
|
||||
shell->GetFrameManager(getter_AddRefs(frameManager));
|
||||
frameManager->ClearUndisplayedContentIn(aContainer, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
treeRowGroup->RegenerateRowGroupInfo(0);
|
||||
|
||||
if (!treeRowGroup->IsBatching())
|
||||
shell->FlushPendingNotifications();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -8567,8 +8594,9 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
if (aContainer) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContainer->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && (tag.get() == nsXULAtoms::treechildren ||
|
||||
tag.get() == nsXULAtoms::treeitem)) {
|
||||
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
|
||||
PRBool treeItem = tag && tag.get() == nsXULAtoms::treeitem;
|
||||
if (treeChildren || treeItem) {
|
||||
// Walk up to the outermost tree row group frame and tell it that
|
||||
// content was added.
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
@ -8600,7 +8628,7 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
nsIFrame* prevSibling = FindPreviousSibling(shell,
|
||||
aContainer,
|
||||
aIndexInContainer);
|
||||
if (prevSibling || innerFrame) {
|
||||
if (innerFrame) {
|
||||
// We're onscreen, but because of the fact that we can be called to
|
||||
// "kill" a displayed frame (e.g., when you close a tree node), we
|
||||
// have to see if this slaying is taking place. If so, then we don't
|
||||
@ -8617,16 +8645,18 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
styleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
|
||||
|
||||
nsFrameConstructorState state(aPresContext, mFixedContainingBlock,
|
||||
nsFrameConstructorState state(aPresContext, mFixedContainingBlock,
|
||||
GetAbsoluteContainingBlock(aPresContext, innerFrame),
|
||||
GetFloaterContainingBlock(aPresContext, innerFrame),
|
||||
aFrameState);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay && treeItem) {
|
||||
state.mFrameManager->SetUndisplayedContent(aChild, styleContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (prevSibling || innerFrame) {
|
||||
nsXULTreeGroupFrame* innerGroup = (nsXULTreeGroupFrame*) innerFrame;
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
|
||||
@ -8638,11 +8668,12 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
else innerGroup->MarkDirtyChildren(state);
|
||||
}
|
||||
|
||||
treeRowGroup->ClearRowGroupInfo();
|
||||
treeRowGroup->RegenerateRowGroupInfo(0);
|
||||
treeRowGroup->MarkDirtyChildren(state);
|
||||
}
|
||||
|
||||
shell->FlushPendingNotifications();
|
||||
if (!treeRowGroup->IsBatching())
|
||||
shell->FlushPendingNotifications();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@ -9236,15 +9267,18 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext,
|
||||
if (aContainer) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContainer->GetTag(*getter_AddRefs(tag));
|
||||
if (tag.get() == nsXULAtoms::treechildren ||
|
||||
tag.get() == nsXULAtoms::treeitem) {
|
||||
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
|
||||
PRBool treeItem = tag && tag.get() == nsXULAtoms::treeitem;
|
||||
|
||||
if (treeChildren || treeItem) {
|
||||
PRInt32 onScreenDelta = 0;
|
||||
if (childFrame) {
|
||||
// Convert to a tree row group frame.
|
||||
nsIFrame* parentFrame;
|
||||
childFrame->GetParent(&parentFrame);
|
||||
nsXULTreeGroupFrame* treeRowGroup = (nsXULTreeGroupFrame*)parentFrame;
|
||||
if (treeRowGroup) {
|
||||
treeRowGroup->OnContentRemoved(aPresContext, childFrame, aIndexInContainer);
|
||||
treeRowGroup->OnContentRemoved(aPresContext, childFrame, aIndexInContainer, onScreenDelta);
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -9270,10 +9304,16 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext,
|
||||
// Convert to a tree row group frame.
|
||||
nsXULTreeOuterGroupFrame* treeRowGroup = (nsXULTreeOuterGroupFrame*)parentFrame;
|
||||
if (treeRowGroup) {
|
||||
// If a tree item is removed, try to find an item we can use
|
||||
// to detect if the removed item was above our current scroll
|
||||
// position.
|
||||
treeRowGroup->RegenerateRowGroupInfo(onScreenDelta);
|
||||
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
treeRowGroup->MarkDirtyChildren(state);
|
||||
treeRowGroup->ClearRowGroupInfo();
|
||||
shell->FlushPendingNotifications();
|
||||
|
||||
if (!treeRowGroup->IsBatching())
|
||||
shell->FlushPendingNotifications();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3127,9 +3127,7 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand)
|
||||
(!gAsyncReflowDuringDocLoad && !mBatchReflows && !mDocumentLoading)) {
|
||||
// If we're in the middle of a drag, process it right away (needed for mac,
|
||||
// might as well do it on all platforms just to keep the code paths the same).
|
||||
if ( IsDragInProgress() )
|
||||
FlushPendingNotifications();
|
||||
else
|
||||
if ( !IsDragInProgress() )
|
||||
PostReflowEvent();
|
||||
}
|
||||
|
||||
|
@ -3127,9 +3127,7 @@ PresShell::AppendReflowCommand(nsIReflowCommand* aReflowCommand)
|
||||
(!gAsyncReflowDuringDocLoad && !mBatchReflows && !mDocumentLoading)) {
|
||||
// If we're in the middle of a drag, process it right away (needed for mac,
|
||||
// might as well do it on all platforms just to keep the code paths the same).
|
||||
if ( IsDragInProgress() )
|
||||
FlushPendingNotifications();
|
||||
else
|
||||
if ( !IsDragInProgress() )
|
||||
PostReflowEvent();
|
||||
}
|
||||
|
||||
|
@ -8262,8 +8262,10 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext,
|
||||
if (aContainer) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContainer->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && (tag.get() == nsXULAtoms::treechildren ||
|
||||
tag.get() == nsXULAtoms::treeitem)) {
|
||||
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
|
||||
PRBool treeItem = tag && tag.get() == nsXULAtoms::treeitem;
|
||||
|
||||
if (treeChildren || treeItem) {
|
||||
// Walk up to the outermost tree row group frame and tell it that
|
||||
// content was added.
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
@ -8287,15 +8289,40 @@ nsCSSFrameConstructor::ContentAppended(nsIPresContext* aPresContext,
|
||||
|
||||
// Get the primary frame for the parent of the child that's being added.
|
||||
nsIFrame* innerFrame = GetFrameFor(shell, aPresContext, aContainer);
|
||||
|
||||
treeRowGroup->ClearRowGroupInfo();
|
||||
|
||||
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
|
||||
nsXULTreeGroupFrame* innerGroup = (nsXULTreeGroupFrame*) innerFrame;
|
||||
if (innerGroup) {
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
innerGroup->MarkDirtyChildren(state);
|
||||
}
|
||||
shell->FlushPendingNotifications();
|
||||
else {
|
||||
treeRowGroup->MarkDirtyChildren(state);
|
||||
|
||||
// Resolve our style context to find out if we need to clear out our
|
||||
// undisplayed content.
|
||||
if (treeChildren) {
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
aContainer->GetParent(*getter_AddRefs(parent));
|
||||
if (parent) {
|
||||
nsAutoString open;
|
||||
parent->GetAttribute(kNameSpaceID_None, nsXULAtoms::open, open);
|
||||
if (open.EqualsIgnoreCase("true")) {
|
||||
// Clear our undisplayed content.
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
aPresContext->GetShell(getter_AddRefs(shell));
|
||||
nsCOMPtr<nsIFrameManager> frameManager;
|
||||
shell->GetFrameManager(getter_AddRefs(frameManager));
|
||||
frameManager->ClearUndisplayedContentIn(aContainer, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
treeRowGroup->RegenerateRowGroupInfo(0);
|
||||
|
||||
if (!treeRowGroup->IsBatching())
|
||||
shell->FlushPendingNotifications();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -8567,8 +8594,9 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
if (aContainer) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContainer->GetTag(*getter_AddRefs(tag));
|
||||
if (tag && (tag.get() == nsXULAtoms::treechildren ||
|
||||
tag.get() == nsXULAtoms::treeitem)) {
|
||||
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
|
||||
PRBool treeItem = tag && tag.get() == nsXULAtoms::treeitem;
|
||||
if (treeChildren || treeItem) {
|
||||
// Walk up to the outermost tree row group frame and tell it that
|
||||
// content was added.
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
@ -8600,7 +8628,7 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
nsIFrame* prevSibling = FindPreviousSibling(shell,
|
||||
aContainer,
|
||||
aIndexInContainer);
|
||||
if (prevSibling || innerFrame) {
|
||||
if (innerFrame) {
|
||||
// We're onscreen, but because of the fact that we can be called to
|
||||
// "kill" a displayed frame (e.g., when you close a tree node), we
|
||||
// have to see if this slaying is taking place. If so, then we don't
|
||||
@ -8617,16 +8645,18 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
const nsStyleDisplay* display = (const nsStyleDisplay*)
|
||||
styleContext->GetStyleData(eStyleStruct_Display);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
|
||||
|
||||
nsFrameConstructorState state(aPresContext, mFixedContainingBlock,
|
||||
nsFrameConstructorState state(aPresContext, mFixedContainingBlock,
|
||||
GetAbsoluteContainingBlock(aPresContext, innerFrame),
|
||||
GetFloaterContainingBlock(aPresContext, innerFrame),
|
||||
aFrameState);
|
||||
|
||||
if (NS_STYLE_DISPLAY_NONE == display->mDisplay && treeItem) {
|
||||
state.mFrameManager->SetUndisplayedContent(aChild, styleContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (prevSibling || innerFrame) {
|
||||
nsXULTreeGroupFrame* innerGroup = (nsXULTreeGroupFrame*) innerFrame;
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
|
||||
@ -8638,11 +8668,12 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext,
|
||||
else innerGroup->MarkDirtyChildren(state);
|
||||
}
|
||||
|
||||
treeRowGroup->ClearRowGroupInfo();
|
||||
treeRowGroup->RegenerateRowGroupInfo(0);
|
||||
treeRowGroup->MarkDirtyChildren(state);
|
||||
}
|
||||
|
||||
shell->FlushPendingNotifications();
|
||||
if (!treeRowGroup->IsBatching())
|
||||
shell->FlushPendingNotifications();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@ -9236,15 +9267,18 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext,
|
||||
if (aContainer) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
aContainer->GetTag(*getter_AddRefs(tag));
|
||||
if (tag.get() == nsXULAtoms::treechildren ||
|
||||
tag.get() == nsXULAtoms::treeitem) {
|
||||
PRBool treeChildren = tag && tag.get() == nsXULAtoms::treechildren;
|
||||
PRBool treeItem = tag && tag.get() == nsXULAtoms::treeitem;
|
||||
|
||||
if (treeChildren || treeItem) {
|
||||
PRInt32 onScreenDelta = 0;
|
||||
if (childFrame) {
|
||||
// Convert to a tree row group frame.
|
||||
nsIFrame* parentFrame;
|
||||
childFrame->GetParent(&parentFrame);
|
||||
nsXULTreeGroupFrame* treeRowGroup = (nsXULTreeGroupFrame*)parentFrame;
|
||||
if (treeRowGroup) {
|
||||
treeRowGroup->OnContentRemoved(aPresContext, childFrame, aIndexInContainer);
|
||||
treeRowGroup->OnContentRemoved(aPresContext, childFrame, aIndexInContainer, onScreenDelta);
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -9270,10 +9304,16 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext,
|
||||
// Convert to a tree row group frame.
|
||||
nsXULTreeOuterGroupFrame* treeRowGroup = (nsXULTreeOuterGroupFrame*)parentFrame;
|
||||
if (treeRowGroup) {
|
||||
// If a tree item is removed, try to find an item we can use
|
||||
// to detect if the removed item was above our current scroll
|
||||
// position.
|
||||
treeRowGroup->RegenerateRowGroupInfo(onScreenDelta);
|
||||
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
treeRowGroup->MarkDirtyChildren(state);
|
||||
treeRowGroup->ClearRowGroupInfo();
|
||||
shell->FlushPendingNotifications();
|
||||
|
||||
if (!treeRowGroup->IsBatching())
|
||||
shell->FlushPendingNotifications();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -38,6 +38,9 @@ interface nsITreeBoxObject : nsISupports
|
||||
long getNumberOfVisibleRows();
|
||||
long getIndexOfFirstVisibleRow();
|
||||
long getRowCount();
|
||||
|
||||
void beginBatch();
|
||||
void endBatch();
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -46,6 +46,8 @@ public:
|
||||
NS_IMETHOD GetNumberOfVisibleRows(PRInt32* aResult) = 0;
|
||||
NS_IMETHOD GetIndexOfFirstVisibleRow(PRInt32* aResult) = 0;
|
||||
NS_IMETHOD GetRowCount(PRInt32* aResult) = 0;
|
||||
NS_IMETHOD BeginBatch()=0;
|
||||
NS_IMETHOD EndBatch()=0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -201,10 +201,6 @@ nsSliderFrame::AttributeChanged(nsIPresContext* aPresContext,
|
||||
scrollbarFrame->GetScrollbarMediator(getter_AddRefs(mediator));
|
||||
if (mediator) {
|
||||
mediator->PositionChanged(GetCurrentPosition(scrollbar), current);
|
||||
char ch[100];
|
||||
sprintf(ch,"%d", current);
|
||||
scrollbar->SetAttribute(kNameSpaceID_None, nsXULAtoms::curpos, NS_ConvertASCIItoUCS2(ch), PR_FALSE);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetItemAtIndex(PRInt32 index, nsIDOMElement **_re
|
||||
/* long getIndexOfItem (in nsIDOMElement item); */
|
||||
NS_IMETHODIMP nsTreeBoxObject::GetIndexOfItem(nsIDOMElement* aElement, PRInt32 *aResult)
|
||||
{
|
||||
*aResult = -1;
|
||||
*aResult = 0;
|
||||
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (!frame)
|
||||
@ -177,6 +177,26 @@ NS_IMETHODIMP nsTreeBoxObject::GetRowCount(PRInt32 *aResult)
|
||||
return treeFrame->GetRowCount(aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeBoxObject::BeginBatch()
|
||||
{
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (!frame)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
|
||||
return treeFrame->BeginBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeBoxObject::EndBatch()
|
||||
{
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (!frame)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsITreeFrame> treeFrame(do_QueryInterface(frame));
|
||||
return treeFrame->EndBatch();
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
|
@ -260,7 +260,7 @@ nsTreeLayout::LayoutInternal(nsIBox* aBox, nsBoxLayoutState& aState)
|
||||
box->GetNextBox(&box);
|
||||
}
|
||||
|
||||
if (group && (group == outer) && availableHeight > 0) {
|
||||
if (group && (group == outer)) {
|
||||
// We have enough available height left to add some more rows
|
||||
// Since we can't do this during layout, we post a callback
|
||||
// that will be processed after the reflow completes.
|
||||
@ -354,6 +354,8 @@ nsTreeLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
|
||||
|
||||
if (isOuterGroup) {
|
||||
nsXULTreeOuterGroupFrame* outer = (nsXULTreeOuterGroupFrame*) frame;
|
||||
if (outer->IsBatching())
|
||||
return NS_OK;
|
||||
|
||||
// Always ensure an accurate scrollview position
|
||||
// This is an edge case that was caused by the row height
|
||||
|
@ -245,7 +245,6 @@ nsXULTreeFrame::GetIndexOfItem(nsIPresContext* aPresContext, nsIDOMElement* aEle
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
*aResult = 0;
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
|
||||
nsCOMPtr<nsIContent> root;
|
||||
treeOuterGroup->GetContent(getter_AddRefs(root));
|
||||
@ -290,6 +289,32 @@ nsXULTreeFrame::GetRowCount(PRInt32 *aResult)
|
||||
return XULTreeOuterGroup->GetRowCount(aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::BeginBatch()
|
||||
{
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* treeOuterGroup = nsnull;
|
||||
GetTreeBody(&treeOuterGroup);
|
||||
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
return treeOuterGroup->BeginBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeFrame::EndBatch()
|
||||
{
|
||||
// Get our treechildren child frame.
|
||||
nsXULTreeOuterGroupFrame* treeOuterGroup = nsnull;
|
||||
GetTreeBody(&treeOuterGroup);
|
||||
|
||||
if (!treeOuterGroup)
|
||||
return NS_OK; // No tree body. Just bail.
|
||||
|
||||
return treeOuterGroup->EndBatch();
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTreeFrame::GetTreeBody(nsXULTreeOuterGroupFrame** aResult)
|
||||
{
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
NS_IMETHOD GetNumberOfVisibleRows(PRInt32 *aResult);
|
||||
NS_IMETHOD GetIndexOfFirstVisibleRow(PRInt32 *aResult);
|
||||
NS_IMETHOD GetRowCount(PRInt32* aResult);
|
||||
NS_IMETHOD BeginBatch();
|
||||
NS_IMETHOD EndBatch();
|
||||
|
||||
protected:
|
||||
nsXULTreeFrame(nsIPresShell* aPresShell, PRBool aIsRoot = nsnull, nsIBoxLayout* aLayoutManager = nsnull, PRBool aDefaultHorizontal = PR_TRUE);
|
||||
|
@ -418,17 +418,26 @@ nsXULTreeGroupFrame::OnContentInserted(nsIPresContext* aPresContext, nsIFrame* a
|
||||
// content was inserted
|
||||
if (mTopFrame == nsnull) return;
|
||||
|
||||
// if we're inserting content at the top of visible content,
|
||||
// then ignore it because it would go off-screen
|
||||
// except of course in the case of the first row, where we're
|
||||
// actually adding visible content
|
||||
// if we're inserting the item before the first visible content,
|
||||
// then ignore it because it will end up off-screen
|
||||
// (except of course in the case of the first row, where we're
|
||||
// actually adding visible content)
|
||||
if(aNextSibling == mTopFrame) {
|
||||
if (aIndex == 0)
|
||||
// it's the first row, blow away mTopFrame so it can be
|
||||
// crecreated later
|
||||
if (aIndex > 0) // We aren't at the front, so we have to be offscreen.
|
||||
return; // Just bail.
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
aNextSibling->GetContent(getter_AddRefs(content));
|
||||
PRInt32 siblingIndex;
|
||||
mContent->IndexOf(content, siblingIndex);
|
||||
|
||||
if (siblingIndex == 1 && mOuterFrame->GetYPosition() == 0)
|
||||
// We just inserted an item in front of the first of our children
|
||||
// and we're at the top, such that we have to show the row.
|
||||
// This item is our new visible top row.
|
||||
mTopFrame = nsnull;
|
||||
else
|
||||
// it's not visible, nothing to do
|
||||
// The newly inserted row is offscreen. We can just bail.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -450,7 +459,7 @@ nsXULTreeGroupFrame::OnContentInserted(nsIPresContext* aPresContext, nsIFrame* a
|
||||
|
||||
void nsXULTreeGroupFrame::OnContentRemoved(nsIPresContext* aPresContext,
|
||||
nsIFrame* aChildFrame,
|
||||
PRInt32 aIndex)
|
||||
PRInt32 aIndex, PRInt32& aOnScreenRowCount)
|
||||
{
|
||||
// if we're removing the top row, the new top row is the next row
|
||||
if (mTopFrame && mTopFrame == aChildFrame)
|
||||
@ -459,34 +468,14 @@ void nsXULTreeGroupFrame::OnContentRemoved(nsIPresContext* aPresContext,
|
||||
// Go ahead and delete the frame.
|
||||
nsBoxLayoutState state(aPresContext);
|
||||
if (aChildFrame) {
|
||||
nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(aChildFrame));
|
||||
if (slice)
|
||||
slice->GetOnScreenRowCount(&aOnScreenRowCount);
|
||||
|
||||
mFrameConstructor->RemoveMappingsForFrameSubtree(aPresContext, aChildFrame, nsnull);
|
||||
|
||||
Remove(state, aChildFrame);
|
||||
mFrames.DestroyFrame(aPresContext, aChildFrame);
|
||||
MarkDirtyChildren(state);
|
||||
|
||||
// Get our old row count.
|
||||
PRInt32 rowCount = mOuterFrame->GetRowCount();
|
||||
|
||||
// See if the last row is visible. If it is, we need to pull back
|
||||
// by the amount of rows that we lose.
|
||||
PRInt32 index;
|
||||
mOuterFrame->GetIndexOfFirstVisibleRow(&index);
|
||||
PRInt32 vis;
|
||||
mOuterFrame->GetNumberOfVisibleRows(&vis);
|
||||
|
||||
if (index > 0 && index + vis >= rowCount) {
|
||||
// Danger, Will Robinson, danger! We need to scroll backwards.
|
||||
mOuterFrame->ClearRowGroupInfo();
|
||||
PRInt32 newCount = mOuterFrame->GetRowCount();
|
||||
PRInt32 delta = rowCount - newCount;
|
||||
mOuterFrame->ScrollToIndex(index-delta);
|
||||
if (index-delta <= 0) {
|
||||
// Repaint the world.
|
||||
mOuterFrame->Redraw(state, nsnull, PR_FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MarkDirtyChildren(state);
|
||||
|
@ -86,7 +86,7 @@ public:
|
||||
|
||||
// Responses to changes
|
||||
void OnContentInserted(nsIPresContext* aPresContext, nsIFrame* aNextSibling, PRInt32 aIndex);
|
||||
void OnContentRemoved(nsIPresContext* aPresContext, nsIFrame* aChildFrame, PRInt32 aIndex);
|
||||
void OnContentRemoved(nsIPresContext* aPresContext, nsIFrame* aChildFrame, PRInt32 aIndex, PRInt32& aOnScreenRowCount);
|
||||
|
||||
// nsIXULTreeSlice
|
||||
NS_IMETHOD IsOutermostFrame(PRBool* aResult) { *aResult = PR_FALSE; return NS_OK; };
|
||||
|
@ -230,7 +230,7 @@ NS_NewXULTreeOuterGroupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRB
|
||||
// Constructor
|
||||
nsXULTreeOuterGroupFrame::nsXULTreeOuterGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal)
|
||||
:nsXULTreeGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal),
|
||||
mRowGroupInfo(nsnull), mRowHeight(0), mCurrentIndex(0),
|
||||
mBatchCount(0), mRowGroupInfo(nsnull), mRowHeight(0), mCurrentIndex(0), mOldIndex(0),
|
||||
mTreeIsSorted(PR_FALSE), mDragOverListener(nsnull), mCanDropBetweenRows(PR_TRUE),
|
||||
mRowHeightWasSet(PR_FALSE), mReflowCallbackPosted(PR_FALSE), mYPosition(0), mScrolling(PR_FALSE),
|
||||
mScrollSmoother(nsnull), mTimePerRow(TIME_PER_ROW_INITAL), mAdjustScroll(PR_FALSE)
|
||||
@ -545,6 +545,9 @@ nsXULTreeOuterGroupFrame::ScrollbarButtonPressed(PRInt32 aOldIndex, PRInt32 aNew
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeOuterGroupFrame::PositionChanged(PRInt32 aOldIndex, PRInt32& aNewIndex)
|
||||
{
|
||||
if (mScrolling)
|
||||
return NS_OK;
|
||||
|
||||
PRInt32 oldTwipIndex, newTwipIndex;
|
||||
oldTwipIndex = mCurrentIndex*mRowHeight;
|
||||
newTwipIndex = (aNewIndex*mOnePixel);
|
||||
@ -627,31 +630,26 @@ nsXULTreeOuterGroupFrame::InternalPositionChangedCallback()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeOuterGroupFrame::InternalPositionChanged(PRBool aUp, PRInt32 aDelta)
|
||||
nsXULTreeOuterGroupFrame::InternalPositionChanged(PRBool aUp, PRInt32 aDelta, PRBool aForceDestruct)
|
||||
{
|
||||
if (aDelta == 0)
|
||||
return NS_OK;
|
||||
|
||||
// begin timing how long it takes to scroll a row
|
||||
PRTime start = PR_Now();
|
||||
// begin timing how long it takes to scroll a row
|
||||
PRTime start = PR_Now();
|
||||
|
||||
//printf("Actually doing scroll mCurrentIndex=%d, delta=%d!\n", mCurrentIndex, aDelta);
|
||||
//printf("Actually doing scroll mCurrentIndex=%d, delta=%d!\n", mCurrentIndex, aDelta);
|
||||
|
||||
//if (mContentChain) {
|
||||
// XXX Eventually we need to make the code smart enough to look at a content chain
|
||||
// when building ANOTHER content chain.
|
||||
// Ensure all reflows happen first and make sure we're dirty.
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
mPresContext->GetShell(getter_AddRefs(shell));
|
||||
shell->FlushPendingNotifications();
|
||||
// }
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
mPresContext->GetShell(getter_AddRefs(shell));
|
||||
shell->FlushPendingNotifications();
|
||||
|
||||
PRInt32 visibleRows = 0;
|
||||
if (mRowHeight)
|
||||
visibleRows = GetAvailableHeight()/mRowHeight;
|
||||
|
||||
// Get our presentation context.
|
||||
if (aDelta < visibleRows) {
|
||||
if (aDelta < visibleRows && !aForceDestruct) {
|
||||
PRInt32 loseRows = aDelta;
|
||||
|
||||
// scrolling down
|
||||
@ -710,15 +708,16 @@ nsXULTreeOuterGroupFrame::InternalPositionChanged(PRBool aUp, PRInt32 aDelta)
|
||||
|
||||
mYPosition = mCurrentIndex*mRowHeight;
|
||||
nsBoxLayoutState state(mPresContext);
|
||||
nsCOMPtr<nsIBoxLayout> layout;
|
||||
GetLayoutManager(getter_AddRefs(layout));
|
||||
nsTreeLayout* treeLayout = (nsTreeLayout*)layout.get();
|
||||
treeLayout->LazyRowCreator(state, this);
|
||||
mScrolling = PR_TRUE;
|
||||
MarkDirtyChildren(state);
|
||||
shell->FlushPendingNotifications();
|
||||
mScrolling = PR_FALSE;
|
||||
|
||||
VerticalScroll(mYPosition);
|
||||
|
||||
if (aForceDestruct)
|
||||
Redraw(state, nsnull, PR_FALSE);
|
||||
|
||||
PRTime end = PR_Now();
|
||||
|
||||
PRTime difTime;
|
||||
@ -1092,6 +1091,10 @@ nsXULTreeOuterGroupFrame::FindNextRowContent(PRInt32& aDelta, nsIContent* aUpwar
|
||||
void
|
||||
nsXULTreeOuterGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
|
||||
{
|
||||
NS_ASSERTION(aRowIndex >= 0, "Ensure row is visible called with a negative number!");
|
||||
if (aRowIndex < 0)
|
||||
return;
|
||||
|
||||
PRInt32 rows = 0;
|
||||
if (mRowHeight)
|
||||
rows = GetAvailableHeight()/mRowHeight;
|
||||
@ -1106,8 +1109,8 @@ nsXULTreeOuterGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
|
||||
|
||||
PRBool up = aRowIndex < mCurrentIndex;
|
||||
if (up) {
|
||||
mCurrentIndex = aRowIndex;
|
||||
delta = mCurrentIndex - aRowIndex;
|
||||
mCurrentIndex = aRowIndex;
|
||||
}
|
||||
else {
|
||||
// Bring it just into view.
|
||||
@ -1119,7 +1122,7 @@ nsXULTreeOuterGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex)
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTreeOuterGroupFrame::ScrollToIndex(PRInt32 aRowIndex)
|
||||
nsXULTreeOuterGroupFrame::ScrollToIndex(PRInt32 aRowIndex, PRBool aForceDestruct)
|
||||
{
|
||||
if (( aRowIndex < 0 ) || (mRowHeight == 0))
|
||||
return;
|
||||
@ -1130,11 +1133,14 @@ nsXULTreeOuterGroupFrame::ScrollToIndex(PRInt32 aRowIndex)
|
||||
|
||||
// Check to be sure we're not scrolling off the bottom of the tree
|
||||
PRInt32 lastPageTopRow = GetRowCount() - (GetAvailableHeight() / mRowHeight);
|
||||
if (lastPageTopRow < 0)
|
||||
lastPageTopRow = 0;
|
||||
|
||||
if (aRowIndex > lastPageTopRow)
|
||||
return;
|
||||
|
||||
mCurrentIndex = newIndex;
|
||||
InternalPositionChanged(up, delta);
|
||||
InternalPositionChanged(up, delta, aForceDestruct);
|
||||
|
||||
// This change has to happen immediately.
|
||||
// Flush any pending reflow commands.
|
||||
@ -1206,6 +1212,24 @@ nsXULTreeOuterGroupFrame::IndexOfItem(nsIContent* aRoot, nsIContent* aContent,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeOuterGroupFrame::EndBatch()
|
||||
{
|
||||
NS_ASSERTION(mBatchCount, "EndBatch called on a tree that isn't batching!\n");
|
||||
if (mBatchCount == 0)
|
||||
return NS_OK;
|
||||
|
||||
mBatchCount--;
|
||||
if (mBatchCount == 0) {
|
||||
if (mCurrentIndex == mOldIndex) {
|
||||
nsBoxLayoutState state(mPresContext);
|
||||
MarkDirtyChildren(state);
|
||||
}
|
||||
else ScrollToIndex(mCurrentIndex, PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeOuterGroupFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlushFlag)
|
||||
{
|
||||
@ -1251,6 +1275,82 @@ nsXULTreeOuterGroupFrame::ReflowFinished(nsIPresShell* aPresShell, PRBool* aFlus
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTreeOuterGroupFrame::RegenerateRowGroupInfo(PRBool aOnScreenCount)
|
||||
{
|
||||
NeedsRecalc();
|
||||
|
||||
PRInt32 oldRowCount = GetRowCount();
|
||||
if (mRowGroupInfo)
|
||||
mRowGroupInfo->Clear();
|
||||
PRInt32 newRowCount = GetRowCount();
|
||||
|
||||
if (mRowHeight <= 0)
|
||||
return;
|
||||
|
||||
// For removal only, we need to know how many rows are onscreen. These subtract
|
||||
// from the amount that we need to adjust. For example, if the tree widget is
|
||||
// scrolled to index 40, and if a folder that is offscreen at index 0
|
||||
// is deleted, and it contains 9 kids, then a total of 10 rows are vanishing.
|
||||
// newRowCount - oldRowCount will be -10 following the removal. However, if 4 of those
|
||||
// 10 rows were onscreen, then the tree widget's index only needs to be adjusted by
|
||||
// -6 (-10 + 4).
|
||||
PRInt32 delta = newRowCount-oldRowCount+aOnScreenCount;
|
||||
PRInt32 newIndex = mCurrentIndex + delta;
|
||||
PRBool adjust = PR_FALSE;
|
||||
|
||||
// Check to be sure we're not scrolling off the bottom of the tree
|
||||
PRInt32 lastPageTopRow = newRowCount - (GetAvailableHeight() / mRowHeight);
|
||||
if (lastPageTopRow < 0) {
|
||||
if (aOnScreenCount > 0)
|
||||
adjust = PR_TRUE;
|
||||
lastPageTopRow = 0;
|
||||
}
|
||||
|
||||
if (newIndex > lastPageTopRow) {
|
||||
newIndex = lastPageTopRow;
|
||||
if (aOnScreenCount > 0)
|
||||
adjust = PR_TRUE;
|
||||
}
|
||||
|
||||
if (newIndex < 0)
|
||||
newIndex = 0;
|
||||
|
||||
if (!adjust) {
|
||||
if (mCurrentIndex == 0 || delta == 0)
|
||||
return; // Just a simple update or we aren't scrolled, so bail.
|
||||
|
||||
nsCOMPtr<nsIContent> row;
|
||||
GetFirstRowContent(getter_AddRefs(row));
|
||||
NS_ASSERTION(row, "No row in regen check!");
|
||||
if (!row)
|
||||
return;
|
||||
|
||||
// An element was passed in that was either removed or added.
|
||||
// We need to adjust our scroll position if this element's index
|
||||
// is < our current scrolled index.
|
||||
PRInt32 index = 0;
|
||||
nsCOMPtr<nsIContent> item;
|
||||
row->GetParent(*getter_AddRefs(item));
|
||||
IndexOfItem(mContent, item, PR_FALSE, PR_TRUE, &index);
|
||||
if (index == -1 || index == mCurrentIndex)
|
||||
return;
|
||||
}
|
||||
|
||||
// We mark the outer row group dirty and force a comprehensive
|
||||
// rebuild of all tree widget frames. This ensures that we
|
||||
// stay precisely in sync whenever we lose content from above.
|
||||
if (IsBatching())
|
||||
mCurrentIndex = newIndex;
|
||||
else ScrollToIndex(newIndex, !adjust);
|
||||
|
||||
if (adjust) {
|
||||
// Force a full redraw.
|
||||
nsBoxLayoutState state(mPresContext);
|
||||
Redraw(state, nsnull, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Paint
|
||||
//
|
||||
@ -1261,6 +1361,7 @@ nsXULTreeOuterGroupFrame :: Paint ( nsIPresContext* aPresContext, nsIRenderingCo
|
||||
const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
|
||||
res = nsBoxFrame::Paint ( aPresContext, aRenderingContext, aDirtyRect, aWhichLayer );
|
||||
|
||||
if ( (aWhichLayer == eFramePaintLayer_Content) &&
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
return mRowHeight;
|
||||
}
|
||||
|
||||
void ClearRowGroupInfo() { if (mRowGroupInfo) mRowGroupInfo->Clear(); NeedsRecalc(); };
|
||||
void RegenerateRowGroupInfo(PRInt32 aOnscreenCount);
|
||||
|
||||
void SetRowHeight(PRInt32 aRowHeight);
|
||||
PRBool IsFixedRowSize();
|
||||
@ -147,6 +147,9 @@ public:
|
||||
|
||||
NS_IMETHOD GetRowCount(PRInt32* aResult) { *aResult = GetRowCount(); return NS_OK; }
|
||||
|
||||
NS_IMETHOD BeginBatch() { mBatchCount++; mOldIndex = mCurrentIndex; return NS_OK; }
|
||||
NS_IMETHOD EndBatch();
|
||||
|
||||
NS_IMETHOD PositionChanged(PRInt32 aOldIndex, PRInt32& aNewIndex);
|
||||
NS_IMETHOD ScrollbarButtonPressed(PRInt32 aOldIndex, PRInt32 aNewIndex);
|
||||
NS_IMETHOD VisibilityChanged(PRBool aVisible);
|
||||
@ -172,14 +175,14 @@ public:
|
||||
// that the row is at the top of the screen (if the row was offscreen to start with).
|
||||
void EnsureRowIsVisible(PRInt32 aRowIndex);
|
||||
|
||||
void ScrollToIndex(PRInt32 aRowIndex);
|
||||
void ScrollToIndex(PRInt32 aRowIndex, PRBool aForceDestruct=PR_FALSE);
|
||||
|
||||
NS_IMETHOD IndexOfItem(nsIContent* aRoot, nsIContent* aContent,
|
||||
PRBool aDescendIntoRows, // Invariant
|
||||
PRBool aParentIsOpen,
|
||||
PRInt32 *aResult);
|
||||
|
||||
NS_IMETHOD InternalPositionChanged(PRBool aUp, PRInt32 aDelta);
|
||||
NS_IMETHOD InternalPositionChanged(PRBool aUp, PRInt32 aDelta, PRBool aForceDestruct=PR_FALSE);
|
||||
NS_IMETHOD InternalPositionChangedCallback();
|
||||
|
||||
NS_IMETHOD Destroy(nsIPresContext* aPresContext);
|
||||
@ -189,6 +192,7 @@ public:
|
||||
|
||||
void PostReflowCallback();
|
||||
|
||||
PRBool IsBatching() const { return mBatchCount > 0; };
|
||||
|
||||
protected:
|
||||
|
||||
@ -203,10 +207,12 @@ protected:
|
||||
nsresult StopScrollTracking();
|
||||
#endif
|
||||
|
||||
PRUint32 mBatchCount;
|
||||
nsXULTreeRowGroupInfo* mRowGroupInfo;
|
||||
PRInt32 mRowHeight;
|
||||
nscoord mOnePixel;
|
||||
PRInt32 mCurrentIndex; // Row-based
|
||||
PRInt32 mOldIndex;
|
||||
PRPackedBool mTreeIsSorted;
|
||||
PRPackedBool mCanDropBetweenRows; // is the user allowed to drop between rows
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user