Skip to content

Commit b907b50

Browse files
committed
Skip dummy item creation when removing invalid element from tree #3525
Due to the fix for Bug 210747, a dummy tree-item is added to the viewer if the same element is removed twice. The intend of the original fix is to remove the "expand" icon from a tree item, when its still collapsed children are removed from the viewer (but not the model). The problem with this approach is that it doesn't take the situation into consideration, where the children of the item have already been removed. Given a tree item with at least one child in the data model but where all child-widgets have been removed in the viewer. When removing the children again, this internally calls `updatePlus(Item,Object)`. But because the number of child-widgets doesn't match the number of children, this method now creates a dummy item, to correct this inconsistency. This problem doesn't occur when calling `internalRemove(Object,Object[])`, because here the call to `updatePlus(Item,Object)` is guarded by a check to make sure the tree item has at least one child-widget. To reproduce: 1) Make sure the ".* resources" filter is enabled 2) Create a new project "Project A" and "Project B" 3) Create a new text file "test" in "Project A" 4) Move "test" to "Project B" Closes #3525
1 parent 02fc196 commit b907b50

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2019 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -2095,12 +2095,7 @@ protected void internalRemove(Object[] elementsOrPaths) {
20952095
Object parent = getParentElement(element);
20962096
if (parent != null && !equals(parent, getRoot())
20972097
&& !(parent instanceof TreePath tp && tp.getSegmentCount() == 0)) {
2098-
Widget[] parentItems = internalFindItems(parent);
2099-
for (Widget parentItem : parentItems) {
2100-
if (parentItem instanceof Item it) {
2101-
updatePlus(it, parent);
2102-
}
2103-
}
2098+
internalRemove(parent, new Object[] { element });
21042099
}
21052100
}
21062101
}

tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/TreeViewerTest.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2006 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,7 +14,10 @@
1414
package org.eclipse.jface.tests.viewers;
1515

1616
import static org.junit.Assert.assertFalse;
17+
import static org.junit.Assert.assertNull;
1718
import static org.junit.Assert.assertTrue;
19+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20+
import static org.junit.jupiter.api.Assertions.assertNotNull;
1821

1922
import java.util.ArrayList;
2023
import java.util.Arrays;
@@ -114,4 +117,43 @@ protected void internalExpandToLevel(Widget widget, int level) {
114117
}
115118
}
116119

120+
/**
121+
* Removing the same element twice should not produce a dummy tree-item.
122+
*/
123+
@Test
124+
public void testIssue3525() {
125+
TestElement modelRoot = TestElement.createModel(2, 1);
126+
TestElement modelParent = modelRoot.getChildAt(0);
127+
TestElement modelChild = modelParent.getChildAt(0);
128+
fTreeViewer.setInput(modelRoot);
129+
fTreeViewer.expandAll();
130+
131+
TreeItem widgetParent = (TreeItem) fTreeViewer.testFindItem(modelParent);
132+
TreeItem widgetChild = (TreeItem) fTreeViewer.testFindItem(modelChild);
133+
assertNotNull(widgetParent);
134+
assertNotNull(widgetChild);
135+
assertArrayEquals(widgetParent.getItems(), new TreeItem[] { widgetChild });
136+
137+
// This workaround is needed because of TreeViewerWithLimitCompatibilityTest
138+
// When calling setDisplayIncrementally(...) with a positive number, you are
139+
// no longer able to remove elements from the viewer without first removing
140+
// them from the model
141+
modelParent.fChildren.remove(modelChild);
142+
fTreeViewer.remove(modelChild);
143+
modelParent.fChildren.add(modelChild);
144+
145+
widgetParent = (TreeItem) fTreeViewer.testFindItem(modelParent);
146+
widgetChild = (TreeItem) fTreeViewer.testFindItem(modelChild);
147+
assertNotNull(widgetParent);
148+
assertNull(widgetChild);
149+
assertArrayEquals(widgetParent.getItems(), new TreeItem[0]);
150+
151+
fTreeViewer.remove(modelChild);
152+
153+
widgetParent = (TreeItem) fTreeViewer.testFindItem(modelParent);
154+
widgetChild = (TreeItem) fTreeViewer.testFindItem(modelChild);
155+
assertNotNull(widgetParent);
156+
assertNull(widgetChild);
157+
assertArrayEquals(widgetParent.getItems(), new TreeItem[0]);
158+
}
117159
}

0 commit comments

Comments
 (0)