Skip to content

Commit

Permalink
TreeViewer: AutoExpandTrivialPaths
Browse files Browse the repository at this point in the history
This commit addresses the need to automatically expand paths which
consist of chained singular nodes, eg:

com.wittmaxi.plugin
 └─src
    └─org.foo.com
       └─Bar.java

It introduces two new methods to the API of TreeViewer

-setAutoExpandTrivialPathsLevel
-getAutoExpandTrivialPathsLevel
  • Loading branch information
Maximilian Wittmer authored and Maximilian Wittmer committed Aug 30, 2023
1 parent 81e7679 commit 4f7651d
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 7 deletions.
11 changes: 11 additions & 0 deletions bundles/org.eclipse.jface/.settings/.api_filters
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.jface" version="2">
<resource path="src/org/eclipse/jface/viewers/AbstractTreeViewer.java" type="org.eclipse.jface.viewers.AbstractTreeViewer">
<filter id="336658481">
<message_arguments>
<message_argument value="org.eclipse.jface.viewers.AbstractTreeViewer"/>
<message_argument value="NO_EXPAND"/>
</message_arguments>
</filter>
</resource>
</component>
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,18 @@ public abstract class AbstractTreeViewer extends ColumnViewer {
*
* @see #expandToLevel(int)
* @see #collapseToLevel(Object, int)
* @see #setAutoExpandTrivialPathsLevel(int)
*/
public static final int ALL_LEVELS = -1;

/**
* Constant indicating that no level of the tree should be expanded or collapsed
*
* @see #setAutoExpandTrivialPathsLevel(int)
* @since 3.31
*/
public static final int NO_EXPAND = 0;

/**
* List of registered tree listeners (element type:
* <code>TreeListener</code>).
Expand All @@ -101,8 +110,14 @@ public abstract class AbstractTreeViewer extends ColumnViewer {
private int expandToLevel = 0;

/**
* Indicates if filters should be checked to determine expandability of
* a tree node.
* How many levels to autoexpand in a trivial path. 0 will disable the feature,
* while a negative value (<code>ALL_LEVELS</code>) will expand to infinity
*/
private int expandTrivialPathsLevel = 0;

/**
* Indicates if filters should be checked to determine expandability of a tree
* node.
*/
private boolean isExpandableCheckFilters = false;

Expand Down Expand Up @@ -140,6 +155,40 @@ protected AbstractTreeViewer() {
// do nothing
}

/**
* Expands a widget and creates it's children.
*
* @param w Widget to expand
* @return The children of the Widget
* @since 3.31
*/
protected Item[] expandAndCreateChildren(Widget w) {
setExpanded((Item) w, true);
createChildren(w);
return getChildren(w);
}

/**
* Will expand the current node and create it's children. If the node only has
* one single child and maxDepth isn't zero, it will recursively expand the
* children until a child has more than a single expandable child or maxDepth is
* reached
*
* @param w the widget to expand
* @param maxDepth how deep to recursively expand a trivial path
* @since 3.31
*/
protected void expandTrivialPath(Widget w, int maxDepth) {
if (maxDepth == 0) {
return;
}

Item[] children = expandAndCreateChildren(w);
if (children.length == 1) {
expandTrivialPath(children[0], maxDepth - 1);
}
}

/**
* Adds the given child elements to this viewer as children of the given parent
* element. If this viewer does not have a sorter, the elements are added at the
Expand Down Expand Up @@ -1229,6 +1278,16 @@ public int getAutoExpandLevel() {
return expandToLevel;
}

/**
* @return 0 for disabled, <code> ALL_LEVELS </code> for infinite expansion or
* any integer value for the currently set level of expansion
* @since 3.31
*/
public int getAutoExpandTrivialPathsLevel() {
return expandTrivialPathsLevel;
}


/**
* Returns the SWT child items for the given SWT widget.
*
Expand Down Expand Up @@ -2466,6 +2525,28 @@ public void setAutoExpandLevel(int level) {
expandToLevel = level;
}

/**
* Sets the level of auto expand on Trivial Paths. 0 means that trivial paths
* are not automatically expanded. Trivial paths are paths that chain multiple
* nodes each only containing one single child.
* <p>
* Auto Expansion of trivial paths is off by default. Turning this behaviour off
* should be done cautiously on trees with lazy-loaded child-nodes.
* <p>
* <p>
* Using <code> ALL_LEVELS </code> as arguments will set to infinite
* auto-expansion of trivial paths
* </p>
*
* @param level 0 for disabled, <code> ALL_LEVELS </code> for infinite expansion
* or any integer value to set a level to which trivial paths are
* automatically expanded to
* @since 3.31
*/
public void setAutoExpandTrivialPathsLevel(int level) {
expandTrivialPathsLevel = level;
}

/**
* Sets the content provider used by this <code>AbstractTreeViewer</code>.
* <p>
Expand Down Expand Up @@ -2597,11 +2678,9 @@ public void setExpandedState(Object elementOrTreePath, boolean expanded) {
if (checkBusy())
return;
Widget item = internalExpand(elementOrTreePath, false);
if (item instanceof Item) {
if (expanded) {
createChildren(item);
}
setExpanded((Item) item, expanded);

if (expandAndCreateChildren(item).length == 1) {
expandTrivialPath(getChildren(item)[0], getAutoExpandTrivialPathsLevel());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public class TreeViewer extends AbstractTreeViewer {

private boolean contentProviderIsTreeBased;


/**
* The row object reused
*/
Expand Down Expand Up @@ -246,6 +247,20 @@ protected void hookControl(Control control) {
super.hookControl(control);
Tree treeControl = (Tree) control;

treeControl.addTreeListener(new TreeListener() {
@Override
public void treeExpanded(TreeEvent e) {
if (expandAndCreateChildren(e.item).length == 1) {
expandTrivialPath(getChildren(e.item)[0], getAutoExpandTrivialPathsLevel());
}
}

@Override
public void treeCollapsed(TreeEvent e) {
// No need for this method
}
});

if ((treeControl.getStyle() & SWT.VIRTUAL) != 0) {
treeControl.addDisposeListener(e -> {
treeIsDisposed = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
Expand Down Expand Up @@ -165,6 +166,7 @@ public void createPartControl(Composite aParent) {
if (this.userFilters.stream().anyMatch(UserFilter::isEnabled)) {
getCommonViewer().refresh();
}
getCommonViewer().setAutoExpandTrivialPathsLevel(AbstractTreeViewer.ALL_LEVELS);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,46 @@ public void testExpandToLevel() {
assertNotNull("first3 is visible", fViewer.testFindItem(first3));
}

public void testAutoExpandTrivialPath() {
TestElement trivialPathRoot = fRootElement.getFirstChild().basicAddChild();
trivialPathRoot.basicAddChild().basicAddChild().basicAddChild();
fTreeViewer.setAutoExpandTrivialPathsLevel(1);
fTreeViewer.setExpandedState(trivialPathRoot, true);

assertTrue("The expanded widget child is expanded", fTreeViewer.getExpandedState(trivialPathRoot));
assertTrue("The first child of the trivial path was auto-expanded",
fTreeViewer.getExpandedState(trivialPathRoot.getFirstChild()));
assertTrue("Trivial path is only expanded up to specified depth ",
fTreeViewer.getExpandedState(trivialPathRoot.getFirstChild().getFirstChild()) == false);
fTreeViewer.setAutoExpandTrivialPathsLevel(AbstractTreeViewer.NO_EXPAND);
}

public void testAutoExpandTrivialPathManualDisable() {
TestElement trivialPathRoot = fRootElement.getFirstChild().basicAddChild();
trivialPathRoot.basicAddChild().basicAddChild().basicAddChild();
fTreeViewer.setAutoExpandTrivialPathsLevel(AbstractTreeViewer.NO_EXPAND);
fTreeViewer.setExpandedState(trivialPathRoot, true);

assertTrue("The expanded widget child is expanded", fTreeViewer.getExpandedState(trivialPathRoot));
assertTrue("The first child of the trivial path was not auto-expanded",
fTreeViewer.getExpandedState(trivialPathRoot.getFirstChild()) == false);
}

public void testAutoExpandTrivialPathInfiniteExpand() {
TestElement trivialPathRoot = fRootElement.getFirstChild().basicAddChild();
trivialPathRoot.basicAddChild().basicAddChild().basicAddChild().basicAddChild();
fTreeViewer.setAutoExpandTrivialPathsLevel(AbstractTreeViewer.ALL_LEVELS);
fTreeViewer.setExpandedState(trivialPathRoot, true);

assertTrue("The expanded widget child is expanded", fTreeViewer.getExpandedState(trivialPathRoot));
assertTrue("The first child of the trivial path was auto-expanded",
fTreeViewer.getExpandedState(trivialPathRoot.getFirstChild()));
assertTrue("The second child of the trivial path was auto-expanded",
fTreeViewer.getExpandedState(trivialPathRoot.getFirstChild().getFirstChild()));
assertTrue("The third child of the trivial path was auto-expanded",
fTreeViewer.getExpandedState(trivialPathRoot.getFirstChild().getFirstChild().getFirstChild()));
}

public void testFilterExpanded() {
TestElement first = fRootElement.getFirstChild();
TestElement first2 = first.getFirstChild();
Expand Down

0 comments on commit 4f7651d

Please sign in to comment.