Merge branch 'subtree'
[fanfix.git] / src / be / nikiroo / utils / ui / ListModel.java
index 06e7914c1a80a5dbcc6287d8d636f96c8de000e2..e349deef344a0bdbe33078da7c5cd7fdc19edbce 100644 (file)
@@ -80,51 +80,68 @@ public class ListModel<T> extends DefaultListModel6<T> {
 
        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);
 
@@ -185,6 +202,31 @@ public class ListModel<T> extends DefaultListModel6<T> {
                });
        }
 
+       /**
+        * (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.
         * 
@@ -287,8 +329,13 @@ public class ListModel<T> extends DefaultListModel6<T> {
         *            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)) {
@@ -296,6 +343,9 @@ public class ListModel<T> extends DefaultListModel6<T> {
                        }
                }
 
+               if (keepSelection)
+                       snapshot.apply();
+
                list.repaint();
        }
 
@@ -354,7 +404,7 @@ public class ListModel<T> extends DefaultListModel6<T> {
                }
        }
 
-       @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);