From: Niki Roo Date: Tue, 28 Apr 2020 07:41:38 +0000 (+0200) Subject: Merge branch 'subtree' X-Git-Url: http://git.nikiroo.be/?p=fanfix.git;a=commitdiff_plain;h=b3b9a09308f124fc63b8fdad52c91c1027b2ac99;hp=fa9ed2183664589496a443157f195a03862f0c66 Merge branch 'subtree' --- diff --git a/src/be/nikiroo/utils/ui/DataNode.java b/src/be/nikiroo/utils/ui/DataNode.java index 2d3ac26..b4dbe7b 100644 --- a/src/be/nikiroo/utils/ui/DataNode.java +++ b/src/be/nikiroo/utils/ui/DataNode.java @@ -78,8 +78,14 @@ public class DataNode { return userData; } - protected int count() { - int s = 0; + /** + * The total number of nodes present in this {@link DataNode} (including + * itself and descendants). + * + * @return the number + */ + public int count() { + int s = 1; for (DataNode child : children) { s += child.count(); } diff --git a/src/be/nikiroo/utils/ui/DataTree.java b/src/be/nikiroo/utils/ui/DataTree.java index e941a71..6b3657d 100644 --- a/src/be/nikiroo/utils/ui/DataTree.java +++ b/src/be/nikiroo/utils/ui/DataTree.java @@ -10,7 +10,7 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.MutableTreeNode; public abstract class DataTree { - private DataNode data; + protected DataNode data; public DataNode loadData() throws IOException { return this.data = extractData(); @@ -65,24 +65,4 @@ public abstract class DataTree { return new DataNode(children, source.getUserData()); } - - // TODO: not in this class: - - public void loadInto(DefaultMutableTreeNode root, String filter) { - DataNode filtered = getRoot(filter); - for (DataNode child : filtered.getChildren()) { - root.add(nodeToNode(child)); - } - } - - private MutableTreeNode nodeToNode(DataNode node) { - // TODO: node.toString - DefaultMutableTreeNode otherNode = new DefaultMutableTreeNode( - node.toString()); - for (DataNode child : node.getChildren()) { - otherNode.add(nodeToNode(child)); - } - - return otherNode; - } } diff --git a/src/be/nikiroo/utils/ui/ListModel.java b/src/be/nikiroo/utils/ui/ListModel.java index 06e7914..e349dee 100644 --- a/src/be/nikiroo/utils/ui/ListModel.java +++ b/src/be/nikiroo/utils/ui/ListModel.java @@ -80,51 +80,68 @@ public class ListModel extends DefaultListModel6 { private int hoveredIndex; private List items = new ArrayList(); - private JList6 list; + private boolean keepSelection = true; + + @SuppressWarnings("rawtypes") // JList not compatible Java 1.6 + private JList list; /** * Create a new {@link ListModel}. * * @param list - * the {@link JList} we will handle the data of (cannot be NULL) + * the {@link JList6} we will handle the data of (cannot be NULL) */ - @SuppressWarnings({ "unchecked", "rawtypes" }) // not compatible Java 1.6 - public ListModel(JList list) { - this((JList6) list); + @SuppressWarnings("rawtypes") // JList not compatible Java 1.6 + public ListModel(JList6 list) { + this((JList) list); } /** * Create a new {@link ListModel}. * * @param list - * the {@link JList} we will handle the data of (cannot be NULL) + * the {@link JList6} we will handle the data of (cannot be NULL) * @param popup * the popup to use and keep track of (can be NULL) */ - @SuppressWarnings({ "unchecked", "rawtypes" }) // not compatible Java 1.6 - public ListModel(final JList list, final JPopupMenu popup) { - this((JList6) list, popup); + @SuppressWarnings("rawtypes") // JList not compatible Java 1.6 + public ListModel(final JList6 list, final JPopupMenu popup) { + this((JList) list, popup); } /** * Create a new {@link ListModel}. + *

+ * Note that you must take care of passing a {@link JList} that only handles + * elements of the type of this {@link ListModel} -- you can also use + * {@link ListModel#ListModel(JList6)} instead. * * @param list - * the {@link JList6} we will handle the data of (cannot be NULL) + * the {@link JList} we will handle the data of (cannot be NULL, + * must only contain elements of the type of this + * {@link ListModel}) */ - public ListModel(JList6 list) { + @SuppressWarnings("rawtypes") // JList not compatible Java 1.6 + public ListModel(JList list) { this(list, null); } /** * Create a new {@link ListModel}. + *

+ * Note that you must take care of passing a {@link JList} that only handles + * elements of the type of this {@link ListModel} -- you can also use + * {@link ListModel#ListModel(JList6, JPopupMenu)} instead. * * @param list - * the {@link JList6} we will handle the data of (cannot be NULL) + * the {@link JList} we will handle the data of (cannot be NULL, + * must only contain elements of the type of this + * {@link ListModel}) * @param popup * the popup to use and keep track of (can be NULL) */ - public ListModel(final JList6 list, final JPopupMenu popup) { + @SuppressWarnings({ "unchecked", "rawtypes" }) // JList not in Java 1.6 + public ListModel(final JList list, final JPopupMenu popup) { this.list = list; list.setModel(this); @@ -185,6 +202,31 @@ public class ListModel extends DefaultListModel6 { }); } + /** + * (Try and) keep the elements that were selected when filtering. + *

+ * This will use toString on the elements to identify them, and can be a bit + * resource intensive. + * + * @return TRUE if we do + */ + public boolean isKeepSelection() { + return keepSelection; + } + + /** + * (Try and) keep the elements that were selected when filtering. + *

+ * This will use toString on the elements to identify them, and can be a bit + * resource intensive. + * + * @param keepSelection + * TRUE to try and keep them selected + */ + public void setKeepSelection(boolean keepSelection) { + this.keepSelection = keepSelection; + } + /** * Check if this element is currently under the mouse. * @@ -287,8 +329,13 @@ public class ListModel extends DefaultListModel6 { * the filter will be copied as an element (can be NULL, in that * case all items will be copied as elements) */ - @SuppressWarnings("unchecked") // ListModel and JList are not java 1.6 + @SuppressWarnings("unchecked") // JList not compatible Java 1.6 public void filter(Predicate filter) { + ListSnapshot snapshot = null; + + if (keepSelection) + snapshot = new ListSnapshot(list); + clear(); for (T item : items) { if (filter == null || filter.test(item)) { @@ -296,6 +343,9 @@ public class ListModel extends DefaultListModel6 { } } + if (keepSelection) + snapshot.apply(); + list.repaint(); } @@ -354,7 +404,7 @@ public class ListModel extends DefaultListModel6 { } } - @SuppressWarnings("unchecked") // ListModel and JList are not java 1.6 + @SuppressWarnings("unchecked") // JList not compatible Java 1.6 @Override public T get(int index) { return (T) super.get(index); diff --git a/src/be/nikiroo/utils/ui/ListSnapshot.java b/src/be/nikiroo/utils/ui/ListSnapshot.java new file mode 100644 index 0000000..d2e89c8 --- /dev/null +++ b/src/be/nikiroo/utils/ui/ListSnapshot.java @@ -0,0 +1,62 @@ +package be.nikiroo.utils.ui; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JList; + +public class ListSnapshot { + private JList list; + private List elements = new ArrayList(); + + public ListSnapshot(JList list) { + this.list = list; + + for (int index : list.getSelectedIndices()) { + elements.add(list.getModel().getElementAt(index)); + } + } + + public void apply() { + applyTo(list); + } + + public void applyTo(JList list) { + List indices = new ArrayList(); + for (int i = 0; i < list.getModel().getSize(); i++) { + Object newObject = list.getModel().getElementAt(i); + for (Object oldObject : elements) { + if (isSameElement(oldObject, newObject)) { + indices.add(i); + break; + } + } + } + + int a[] = new int[indices.size()]; + for (int i = 0; i < indices.size(); i++) { + a[i] = indices.get(i); + } + list.setSelectedIndices(a); + } + + // You can override this + protected boolean isSameElement(Object oldElement, Object newElement) { + if (oldElement == null || newElement == null) + return oldElement == null && newElement == null; + + return oldElement.toString().equals(newElement.toString()); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("List Snapshot of: ").append(list).append("\n"); + builder.append("Selected elements:\n"); + for (Object element : elements) { + builder.append("\t").append(element).append("\n"); + } + + return builder.toString(); + } +}