From 5600a406b256b37ca8ef7b3f28efcac9fa63013a Mon Sep 17 00:00:00 2001 From: fedejeanne Date: Thu, 16 Jan 2025 15:56:18 +0100 Subject: [PATCH] Provide method to avoid expanding widgets in AbstractTreeViewer --- .../jface/viewers/AbstractTreeViewer.java | 19 ++++++++ .../jface/tests/viewers/TreeViewerTest.java | 46 +++++++++++++++++++ 2 files changed, 65 insertions(+) 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 e50d51b3fdf..52dd8248cf0 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 @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.function.Predicate; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IStatus; @@ -139,6 +140,8 @@ public abstract class AbstractTreeViewer extends ColumnViewer { */ private boolean isTreePathContentProvider = false; + private Predicate shouldItemExpand; + /** * Safe runnable used to update an item. */ @@ -166,6 +169,7 @@ public void run() { */ protected AbstractTreeViewer() { // do nothing + this.shouldItemExpand = createShouldItemExpand(); } /** @@ -1162,6 +1166,7 @@ public void expandToLevel(Object elementOrTreePath, int level, boolean disableRe control.setRedraw(false); } Widget w = internalExpand(elementOrTreePath, true); + shouldItemExpand = createShouldItemExpand(); if (w != null) { internalExpandToLevel(w, level); } @@ -1172,6 +1177,17 @@ public void expandToLevel(Object elementOrTreePath, int level, boolean disableRe } } + /** + * @return the predicate. It should return {@code true} if the received + * {@code Item} should be expanded when expanding the whole tree and + * {@code false} otherwise. + * + * @since 3.36 + */ + protected Predicate createShouldItemExpand() { + return w -> true; + } + /** * Fires a tree collapsed event. Only listeners registered at the time this * method is called are notified. @@ -1856,6 +1872,9 @@ private void internalCustomizedExpandToLevel(Widget widget, int level, createChildren(widget, false); // XXX for performance widget should be expanded after expanding children: if (widget instanceof Item it) { + if (!shouldItemExpand.test(it)) { + return; + } setExpanded(it, true); } if (level == ALL_LEVELS || level > 1) { 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..78170a32757 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 @@ -13,6 +13,7 @@ *******************************************************************************/ package org.eclipse.jface.tests.viewers; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -21,6 +22,7 @@ import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.function.Predicate; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.StructuredViewer; @@ -28,6 +30,7 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Item; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swt.widgets.Widget; @@ -114,4 +117,47 @@ protected void internalExpandToLevel(Widget widget, int level) { } } + @Test + public void testExpandOnlyArbitraryChild() { + + TestElement modelRoot = TestElement.createModel(3, 5); + + // select an arbitrary child to be expanded + TestElement childToBeExpanded = modelRoot.getChildAt(modelRoot.getChildCount() - 1); + + TreeViewer viewer = new TreeViewer(fShell) { + @Override + protected Predicate createShouldItemExpand() { + // Expand only "childToBeExpanded" + return it -> { + if (!(it.getData() instanceof TestElement)) { + throw new RuntimeException("Data: " + it.getData()); + } + + return it.getData() instanceof TestElement d && d.equals(childToBeExpanded); + }; + } + }; + + viewer.setContentProvider(new TestModelContentProvider()); + viewer.setInput(modelRoot); + + // Even when expanding all elements, the provided predicate will take precedence + viewer.expandToLevel(AbstractTreeViewer.ALL_LEVELS); + + Queue elements = new ConcurrentLinkedQueue<>(Arrays.asList(modelRoot.getChildren())); + while (!elements.isEmpty()) { + TestElement currentElement = elements.poll(); + + boolean shouldExpand = currentElement.equals(childToBeExpanded); + + assertEquals("The expanded state of the element " + currentElement + " is wrong", shouldExpand, + viewer.getExpandedState(currentElement)); + elements.addAll(Arrays.asList(currentElement.getChildren())); + } + + // Double check that the desired element is there and that it was expanded + assertTrue("The element " + childToBeExpanded + " should have been expanded", + viewer.getExpandedState(childToBeExpanded)); + } }