diff --git a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF index b2c427bf1af..81de89277b6 100644 --- a/bundles/org.eclipse.jface/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.jface/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jface;singleton:=true -Bundle-Version: 3.38.100.qualifier +Bundle-Version: 3.38.200.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.jface, diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java index 3b02bf424fa..954d851b421 100644 --- a/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractTreeViewer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -2095,12 +2095,7 @@ protected void internalRemove(Object[] elementsOrPaths) { Object parent = getParentElement(element); if (parent != null && !equals(parent, getRoot()) && !(parent instanceof TreePath tp && tp.getSegmentCount() == 0)) { - Widget[] parentItems = internalFindItems(parent); - for (Widget parentItem : parentItems) { - if (parentItem instanceof Item it) { - updatePlus(it, parent); - } - } + internalRemove(parent, new Object[] { element }); } } } diff --git a/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF index b8dc172d3e3..8cadbfa2c6c 100644 --- a/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.jface.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.jface.tests -Bundle-Version: 1.4.1100.qualifier +Bundle-Version: 1.4.1200.qualifier Automatic-Module-Name: org.eclipse.jface.tests Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.junit;bundle-version="4.12.0", diff --git a/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/TreeViewerTest.java b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/TreeViewerTest.java index 4d325a0202e..80db8ce27d7 100644 --- a/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/TreeViewerTest.java +++ b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/TreeViewerTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,7 +14,10 @@ package org.eclipse.jface.tests.viewers; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.ArrayList; import java.util.Arrays; @@ -114,4 +117,43 @@ protected void internalExpandToLevel(Widget widget, int level) { } } + /** + * Removing the same element twice should not produce a dummy tree-item. + */ + @Test + public void testIssue3525() { + TestElement modelRoot = TestElement.createModel(2, 1); + TestElement modelParent = modelRoot.getChildAt(0); + TestElement modelChild = modelParent.getChildAt(0); + fTreeViewer.setInput(modelRoot); + fTreeViewer.expandAll(); + + TreeItem widgetParent = (TreeItem) fTreeViewer.testFindItem(modelParent); + TreeItem widgetChild = (TreeItem) fTreeViewer.testFindItem(modelChild); + assertNotNull(widgetParent); + assertNotNull(widgetChild); + assertArrayEquals(widgetParent.getItems(), new TreeItem[] { widgetChild }); + + // This workaround is needed because of TreeViewerWithLimitCompatibilityTest + // When calling setDisplayIncrementally(...) with a positive number, you are + // no longer able to remove elements from the viewer without first removing + // them from the model + modelParent.fChildren.remove(modelChild); + fTreeViewer.remove(modelChild); + modelParent.fChildren.add(modelChild); + + widgetParent = (TreeItem) fTreeViewer.testFindItem(modelParent); + widgetChild = (TreeItem) fTreeViewer.testFindItem(modelChild); + assertNotNull(widgetParent); + assertNull(widgetChild); + assertArrayEquals(widgetParent.getItems(), new TreeItem[0]); + + fTreeViewer.remove(modelChild); + + widgetParent = (TreeItem) fTreeViewer.testFindItem(modelParent); + widgetChild = (TreeItem) fTreeViewer.testFindItem(modelChild); + assertNotNull(widgetParent); + assertNull(widgetChild); + assertArrayEquals(widgetParent.getItems(), new TreeItem[0]); + } }