Merge branch 'subtree'
authorNiki Roo <niki@nikiroo.be>
Tue, 28 Apr 2020 07:41:38 +0000 (09:41 +0200)
committerNiki Roo <niki@nikiroo.be>
Tue, 28 Apr 2020 07:41:38 +0000 (09:41 +0200)
1  2 
src/be/nikiroo/utils/ui/DataNode.java
src/be/nikiroo/utils/ui/DataTree.java
src/be/nikiroo/utils/ui/ListModel.java
src/be/nikiroo/utils/ui/ListSnapshot.java

index 2d3ac267842325333484b68886998471981d8135,b4dbe7bb04130bf69e4e67ca12ea330b812544ef..b4dbe7bb04130bf69e4e67ca12ea330b812544ef
@@@ -78,8 -78,14 +78,14 @@@ public class DataNode<T> 
                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<T> child : children) {
                        s += child.count();
                }
index e941a71d2ac00a238c0c6fd6a67932b7f08ca080,6b3657da7f0f2dbc3a73506ea26aa70b8581b4fc..6b3657da7f0f2dbc3a73506ea26aa70b8581b4fc
@@@ -10,7 -10,7 +10,7 @@@ import javax.swing.tree.DefaultMutableT
  import javax.swing.tree.MutableTreeNode;
  
  public abstract class DataTree<E> {
-       private DataNode<E> data;
+       protected DataNode<E> data;
  
        public DataNode<E> loadData() throws IOException {
                return this.data = extractData();
  
                return new DataNode<E>(children, source.getUserData());
        }
-       // TODO: not in this class:
-       public void loadInto(DefaultMutableTreeNode root, String filter) {
-               DataNode<E> filtered = getRoot(filter);
-               for (DataNode<E> child : filtered.getChildren()) {
-                       root.add(nodeToNode(child));
-               }
-       }
-       private MutableTreeNode nodeToNode(DataNode<E> node) {
-               // TODO: node.toString
-               DefaultMutableTreeNode otherNode = new DefaultMutableTreeNode(
-                               node.toString());
-               for (DataNode<E> child : node.getChildren()) {
-                       otherNode.add(nodeToNode(child));
-               }
-               return otherNode;
-       }
  }
index 06e7914c1a80a5dbcc6287d8d636f96c8de000e2,e349deef344a0bdbe33078da7c5cd7fdc19edbce..e349deef344a0bdbe33078da7c5cd7fdc19edbce
@@@ -80,51 -80,68 +80,68 @@@ public class ListModel<T> extends Defau
  
        private int hoveredIndex;
        private List<T> items = new ArrayList<T>();
-       private JList6<T> 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<T>) list);
+       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
+       public ListModel(JList6<T> 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<T>) list, popup);
+       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
+       public ListModel(final JList6<T> list, final JPopupMenu popup) {
+               this((JList) list, popup);
        }
  
        /**
         * Create a new {@link ListModel}.
+        * <p>
+        * 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<T> list) {
+       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
+       public ListModel(JList list) {
                this(list, null);
        }
  
        /**
         * Create a new {@link ListModel}.
+        * <p>
+        * 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<T> 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);
  
                });
        }
  
+       /**
+        * (Try and) keep the elements that were selected when filtering.
+        * <p>
+        * 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.
+        * <p>
+        * 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.
         * 
         *            the filter will be copied as an element (can be NULL, in that
         *            case all items will be copied as elements)
         */
-       @SuppressWarnings("unchecked") // ListModel<T> and JList<T> are not java 1.6
+       @SuppressWarnings("unchecked") // JList<?> not compatible Java 1.6
        public void filter(Predicate<T> filter) {
+               ListSnapshot snapshot = null;
+               if (keepSelection)
+                       snapshot = new ListSnapshot(list);
                clear();
                for (T item : items) {
                        if (filter == null || filter.test(item)) {
                        }
                }
  
+               if (keepSelection)
+                       snapshot.apply();
                list.repaint();
        }
  
                }
        }
  
-       @SuppressWarnings("unchecked") // ListModel<T> and JList<T> are not java 1.6
+       @SuppressWarnings("unchecked") // JList<?> not compatible Java 1.6
        @Override
        public T get(int index) {
                return (T) super.get(index);
index 0000000000000000000000000000000000000000,d2e89c86884491996cf75a40056079d5bb03038e..d2e89c86884491996cf75a40056079d5bb03038e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,62 +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<Object> elements = new ArrayList<Object>();
+       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<Integer> indices = new ArrayList<Integer>();
+               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();
+       }
+ }