improved LibraryTreeModel allows node filtering, see #645

This commit is contained in:
hneemann 2021-02-11 08:09:36 +01:00
parent bb3ea8aebe
commit e1f5d4da4c
2 changed files with 68 additions and 14 deletions

View File

@ -15,14 +15,16 @@ import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath; import javax.swing.tree.TreePath;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
/** /**
* TreeModel based on a {@link ElementLibrary} * TreeModel based on a {@link ElementLibrary}
*/ */
public class LibraryTreeModel implements TreeModel, LibraryListener { public class LibraryTreeModel implements TreeModel, LibraryListener {
private final LibraryNode root; private final LibraryNode root;
private final Filter filter;
private final ArrayList<TreeModelListener> listeners = new ArrayList<>(); private final ArrayList<TreeModelListener> listeners = new ArrayList<>();
private HashMap<LibraryNode, Container> map; private final HashMap<LibraryNode, Container> map;
/** /**
* Creates a new library tree model * Creates a new library tree model
@ -30,7 +32,18 @@ public class LibraryTreeModel implements TreeModel, LibraryListener {
* @param library the library * @param library the library
*/ */
public LibraryTreeModel(ElementLibrary library) { public LibraryTreeModel(ElementLibrary library) {
this(library, null);
}
/**
* Creates a new library tree model
*
* @param library the library
* @param filter used to filter library entries
*/
public LibraryTreeModel(ElementLibrary library, Filter filter) {
root = library.getRoot(); root = library.getRoot();
this.filter = filter;
map = new HashMap<>(); map = new HashMap<>();
library.addListener(this); library.addListener(this);
} }
@ -84,26 +97,51 @@ public class LibraryTreeModel implements TreeModel, LibraryListener {
} }
/** /**
* Same as getRoot() but returns the typed root element * @return the parent of the first leave
*
* @return the root LibraryNode
*/ */
public LibraryNode getTypedRoot() { public LibraryNode getFirstLeafParent() {
return root; Container c = getContainer(root);
if (c.size() == 0)
return root;
while (true) {
for (LibraryNode n : c)
if (n.isLeaf())
return c.node;
c = getContainer(c.getChild(0));
}
} }
private Container getContainer(LibraryNode libraryNode) { private Container getContainer(LibraryNode libraryNode) {
return map.computeIfAbsent(libraryNode, Container::new); Container c = map.get(libraryNode);
if (c == null) {
c = new Container(libraryNode, filter);
map.put(libraryNode, c);
}
return c;
} }
private static final class Container { private final class Container implements Iterable<LibraryNode> {
private final ArrayList<LibraryNode> list; private final ArrayList<LibraryNode> list;
private final LibraryNode node;
private Container(LibraryNode libraryNode) { private Container(LibraryNode libraryNode, Filter filter) {
list = new ArrayList<>(libraryNode.size()); list = new ArrayList<>(libraryNode.size());
for (LibraryNode ln : libraryNode) node = libraryNode;
if (!ln.isHidden()) for (LibraryNode ln : libraryNode) {
list.add(ln); if (!ln.isHidden()) {
if (filter == null)
list.add(ln);
else {
if (ln.isLeaf()) {
if (filter.accept(ln))
list.add(ln);
} else {
if (getContainer(ln).size() > 0)
list.add(ln);
}
}
}
}
} }
private LibraryNode getChild(int i) { private LibraryNode getChild(int i) {
@ -117,7 +155,23 @@ public class LibraryTreeModel implements TreeModel, LibraryListener {
private int indexOf(LibraryNode o1) { private int indexOf(LibraryNode o1) {
return list.indexOf(o1); return list.indexOf(o1);
} }
@Override
public Iterator<LibraryNode> iterator() {
return list.iterator();
}
} }
/**
* filter interface
*/
public interface Filter {
/**
* Returns true if the node should be shown in the tree
*
* @param node the node
* @return true if visible
*/
boolean accept(LibraryNode node);
}
} }

View File

@ -65,7 +65,7 @@ public class SelectTree extends JTree {
setToolTipText(""); setToolTipText("");
// open first child // open first child
expandPath(new TreePath(model.getTypedRoot().getChild(0).getPath())); expandPath(new TreePath(model.getFirstLeafParent().getPath()));
} }
@Override @Override