throw IO when image is used on close
[nikiroo-utils.git] / src / be / nikiroo / utils / ui / ListModel.java
diff --git a/src/be/nikiroo/utils/ui/ListModel.java b/src/be/nikiroo/utils/ui/ListModel.java
deleted file mode 100644 (file)
index cf16d5f..0000000
+++ /dev/null
@@ -1,610 +0,0 @@
-package be.nikiroo.utils.ui;
-
-import java.awt.Component;
-import java.awt.Point;
-import java.awt.Window;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.swing.JList;
-import javax.swing.JPopupMenu;
-import javax.swing.ListCellRenderer;
-import javax.swing.SwingWorker;
-
-import be.nikiroo.utils.compat.DefaultListModel6;
-import be.nikiroo.utils.compat.JList6;
-import be.nikiroo.utils.compat.ListCellRenderer6;
-
-/**
- * A {@link javax.swing.ListModel} that can maintain 2 lists; one with the
- * actual data (the elements), and a second one with the items that are
- * currently displayed (the items).
- * <p>
- * It also offers filter options, supports hovered changes and some more utility
- * functions.
- * 
- * @author niki
- *
- * @param <T>
- *            the type of elements and items (the same type)
- */
-public class ListModel<T> extends DefaultListModel6<T> {
-       private static final long serialVersionUID = 1L;
-
-       /**
-        * A filter interface, to check for a condition (note that a Predicate class
-        * already exists in Java 1.8+, and is compatible with this one if you
-        * change the signatures -- but I support java 1.6+).
-        * 
-        * @author niki
-        *
-        * @param <T>
-        *            the type of elements and items (the same type)
-        */
-       public interface Predicate<T> {
-               /**
-                * Check if an item or an element pass a filter.
-                * 
-                * @param item
-                *            the item to test
-                * 
-                * @return TRUE if the test passed, FALSE if not
-                */
-               public boolean test(T item);
-       }
-
-       /**
-        * A simple interface your elements must implement if you want to use
-        * {@link ListModel#generateRenderer(ListModel)}.
-        * 
-        * @author niki
-        */
-       public interface Hoverable {
-               /**
-                * The element is currently selected.
-                * 
-                * @param selected
-                *            TRUE for selected, FALSE for unselected
-                */
-               public void setSelected(boolean selected);
-
-               /**
-                * The element is currently under the mouse cursor.
-                * 
-                * @param hovered
-                *            TRUE if it is, FALSE if not
-                */
-               public void setHovered(boolean hovered);
-       }
-
-       /**
-        * An interface required to support tooltips on this {@link ListModel}.
-        * 
-        * @author niki
-        *
-        * @param <T>
-        *            the type of elements and items (the same type)
-        */
-       public interface TooltipCreator<T> {
-               /**
-                * Generate a tooltip {@link Window} for this element.
-                * <p>
-                * Note that the tooltip can be of two modes: undecorated or standalone.
-                * An undecorated tooltip will be taken care of by this
-                * {@link ListModel}, but a standalone one is supposed to be its own
-                * Dialog or Frame (it won't be automatically closed).
-                * 
-                * @param t
-                *            the element to generate a tooltip for
-                * @param undecorated
-                *            TRUE for undecorated tooltip, FALSE for standalone
-                *            tooltips
-                * 
-                * @return the generated tooltip or NULL for none
-                */
-               public Window generateTooltip(T t, boolean undecorated);
-       }
-
-       private int hoveredIndex;
-       private List<T> items = new ArrayList<T>();
-       private boolean keepSelection = true;
-
-       private TooltipCreator<T> tooltipCreator;
-       private Window tooltip;
-
-       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
-       private JList list;
-
-       /**
-        * Create a new {@link ListModel}.
-        * 
-        * @param list
-        *            the {@link JList6} we will handle the data of (cannot be NULL)
-        */
-       @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 JList6} we will handle the data of (cannot be NULL)
-        * @param popup
-        *            the popup to use and keep track of (can be NULL)
-        */
-       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
-       public ListModel(JList6<T> list, JPopupMenu popup) {
-               this((JList) list, popup);
-       }
-
-       /**
-        * Create a new {@link ListModel}.
-        * 
-        * @param list
-        *            the {@link JList6} we will handle the data of (cannot be NULL)
-        * @param tooltipCreator
-        *            use this if you want the list to display tooltips on hover
-        *            (can be NULL)
-        */
-       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
-       public ListModel(JList6<T> list, TooltipCreator<T> tooltipCreator) {
-               this((JList) list, null, tooltipCreator);
-       }
-
-       /**
-        * Create a new {@link ListModel}.
-        * 
-        * @param list
-        *            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)
-        * @param tooltipCreator
-        *            use this if you want the list to display tooltips on hover
-        *            (can be NULL)
-        */
-       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
-       public ListModel(JList6<T> list, JPopupMenu popup,
-                       TooltipCreator<T> tooltipCreator) {
-               this((JList) list, popup, tooltipCreator);
-       }
-
-       /**
-        * 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 JList} we will handle the data of (cannot be NULL,
-        *            must only contain elements of the type of this
-        *            {@link ListModel})
-        */
-       @SuppressWarnings("rawtypes") // JList<?> not compatible Java 1.6
-       public ListModel(JList list) {
-               this(list, null, 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 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)
-        */
-       @SuppressWarnings("rawtypes") // JList<?> not in Java 1.6
-       public ListModel(JList list, JPopupMenu popup) {
-               this(list, popup, 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 JList} we will handle the data of (cannot be NULL,
-        *            must only contain elements of the type of this
-        *            {@link ListModel})
-        * @param tooltipCreator
-        *            use this if you want the list to display tooltips on hover
-        *            (can be NULL)
-        */
-       @SuppressWarnings("rawtypes") // JList<?> not in Java 1.6
-       public ListModel(JList list, TooltipCreator<T> tooltipCreator) {
-               this(list, null, tooltipCreator);
-       }
-
-       /**
-        * 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 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)
-        * @param tooltipCreator
-        *            use this if you want the list to display tooltips on hover
-        *            (can be NULL)
-        */
-       @SuppressWarnings({ "unchecked", "rawtypes" }) // JList<?> not in Java 1.6
-       public ListModel(final JList list, final JPopupMenu popup,
-                       TooltipCreator<T> tooltipCreator) {
-               this.list = list;
-               this.tooltipCreator = tooltipCreator;
-
-               list.setModel(this);
-
-               final DelayWorker tooltipWatcher = new DelayWorker(500);
-               if (tooltipCreator != null) {
-                       tooltipWatcher.start();
-               }
-
-               list.addMouseMotionListener(new MouseAdapter() {
-                       @Override
-                       public void mouseMoved(final MouseEvent me) {
-                               if (popup != null && popup.isShowing())
-                                       return;
-
-                               Point p = new Point(me.getX(), me.getY());
-                               final int index = list.locationToIndex(p);
-                               if (index != hoveredIndex) {
-                                       int oldIndex = hoveredIndex;
-                                       hoveredIndex = index;
-                                       fireElementChanged(oldIndex);
-                                       fireElementChanged(index);
-
-                                       if (ListModel.this.tooltipCreator != null) {
-                                               tooltipWatcher.delay("tooltip",
-                                                               new SwingWorker<Void, Void>() {
-                                                                       @Override
-                                                                       protected Void doInBackground()
-                                                                                       throws Exception {
-                                                                               return null;
-                                                                       }
-
-                                                                       @Override
-                                                                       protected void done() {
-                                                                               Window oldTooltip = tooltip;
-                                                                               tooltip = null;
-                                                                               if (oldTooltip != null) {
-                                                                                       oldTooltip.setVisible(false);
-                                                                               }
-
-                                                                               if (index < 0
-                                                                                               || index != hoveredIndex) {
-                                                                                       return;
-                                                                               }
-
-                                                                               tooltip = newTooltip(index, me);
-                                                                       }
-                                                               });
-                                       }
-                               }
-                       }
-               });
-
-               list.addMouseListener(new MouseAdapter() {
-                       @Override
-                       public void mousePressed(MouseEvent e) {
-                               check(e);
-                       }
-
-                       @Override
-                       public void mouseReleased(MouseEvent e) {
-                               check(e);
-                       }
-
-                       @Override
-                       public void mouseExited(MouseEvent e) {
-                               if (popup != null && popup.isShowing())
-                                       return;
-
-                               if (hoveredIndex > -1) {
-                                       int oldIndex = hoveredIndex;
-                                       hoveredIndex = -1;
-                                       fireElementChanged(oldIndex);
-                               }
-                       }
-
-                       private void check(MouseEvent e) {
-                               if (popup == null) {
-                                       return;
-                               }
-
-                               if (e.isPopupTrigger()) {
-                                       if (list.getSelectedIndices().length <= 1) {
-                                               list.setSelectedIndex(
-                                                               list.locationToIndex(e.getPoint()));
-                                       }
-
-                                       popup.show(list, e.getX(), e.getY());
-                               }
-                       }
-
-               });
-       }
-
-       /**
-        * (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.
-        * 
-        * @param element
-        *            the element to check
-        * 
-        * @return TRUE if it is
-        */
-       public boolean isHovered(T element) {
-               return indexOf(element) == hoveredIndex;
-       }
-
-       /**
-        * Check if this element is currently under the mouse.
-        * 
-        * @param index
-        *            the index of the element to check
-        * 
-        * @return TRUE if it is
-        */
-       public boolean isHovered(int index) {
-               return index == hoveredIndex;
-       }
-
-       /**
-        * Add an item to the model.
-        * 
-        * @param item
-        *            the new item to add
-        */
-       public void addItem(T item) {
-               items.add(item);
-       }
-
-       /**
-        * Add items to the model.
-        * 
-        * @param items
-        *            the new items to add
-        */
-       public void addAllItems(Collection<T> items) {
-               this.items.addAll(items);
-       }
-
-       /**
-        * Removes the first occurrence of the specified element from this list, if
-        * it is present (optional operation).
-        * 
-        * @param item
-        *            the item to remove if possible (can be NULL)
-        * 
-        * @return TRUE if one element was removed, FALSE if not found
-        */
-       public boolean removeItem(T item) {
-               return items.remove(item);
-       }
-
-       /**
-        * Remove the items that pass the given filter (or all items if the filter
-        * is NULL).
-        * 
-        * @param filter
-        *            the filter (if the filter returns TRUE, the item will be
-        *            removed)
-        * 
-        * @return TRUE if at least one item was removed
-        */
-       public boolean removeItemIf(Predicate<T> filter) {
-               boolean changed = false;
-               if (filter == null) {
-                       changed = !items.isEmpty();
-                       clearItems();
-               } else {
-                       for (int i = 0; i < items.size(); i++) {
-                               if (filter.test(items.get(i))) {
-                                       items.remove(i--);
-                                       changed = true;
-                               }
-                       }
-               }
-
-               return changed;
-       }
-
-       /**
-        * Removes all the items from this model.
-        */
-       public void clearItems() {
-               items.clear();
-       }
-
-       /**
-        * Filter the current elements.
-        * <p>
-        * This method will clear all the elements then look into all the items:
-        * those that pass the given filter will be copied as elements.
-        * 
-        * @param filter
-        *            the filter to select which elements to keep; an item that pass
-        *            the filter will be copied as an element (can be NULL, in that
-        *            case all items will be copied as elements)
-        */
-       @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)) {
-                               addElement(item);
-                       }
-               }
-
-               if (keepSelection)
-                       snapshot.apply();
-
-               list.repaint();
-       }
-
-       /**
-        * Return the currently selected elements.
-        * 
-        * @return the selected elements
-        */
-       public List<T> getSelectedElements() {
-               List<T> selected = new ArrayList<T>();
-               for (int index : list.getSelectedIndices()) {
-                       selected.add(get(index));
-               }
-
-               return selected;
-       }
-
-       /**
-        * Return the selected element if <b>one</b> and <b>only one</b> element is
-        * selected. I.E., if zero, two or more elements are selected, NULL will be
-        * returned.
-        * 
-        * @return the element if it is the only selected element, NULL otherwise
-        */
-       public T getUniqueSelectedElement() {
-               List<T> selected = getSelectedElements();
-               if (selected.size() == 1) {
-                       return selected.get(0);
-               }
-
-               return null;
-       }
-
-       /**
-        * Notify that this element has been changed.
-        * 
-        * @param index
-        *            the index of the element
-        */
-       public void fireElementChanged(int index) {
-               if (index >= 0) {
-                       fireContentsChanged(this, index, index);
-               }
-       }
-
-       /**
-        * Notify that this element has been changed.
-        * 
-        * @param element
-        *            the element
-        */
-       public void fireElementChanged(T element) {
-               int index = indexOf(element);
-               if (index >= 0) {
-                       fireContentsChanged(this, index, index);
-               }
-       }
-
-       @SuppressWarnings("unchecked") // JList<?> not compatible Java 1.6
-       @Override
-       public T get(int index) {
-               return (T) super.get(index);
-       }
-
-       private Window newTooltip(final int index, final MouseEvent me) {
-               final T value = ListModel.this.get(index);
-
-               final Window newTooltip = tooltipCreator.generateTooltip(value, true);
-
-               if (newTooltip != null) {
-                       newTooltip.addMouseListener(new MouseAdapter() {
-                               @Override
-                               public void mouseClicked(MouseEvent e) {
-
-                                       Window promotedTooltip = tooltipCreator
-                                                       .generateTooltip(value, false);
-                                       promotedTooltip.setLocation(newTooltip.getLocation());
-                                       newTooltip.setVisible(false);
-                                       promotedTooltip.setVisible(true);
-                               }
-                       });
-                       newTooltip.setLocation(me.getXOnScreen(), me.getYOnScreen());
-
-                       newTooltip.setVisible(true);
-               }
-
-               return newTooltip;
-       }
-
-       /**
-        * Generate a {@link ListCellRenderer} that supports {@link Hoverable}
-        * elements.
-        * 
-        * @param <T>
-        *            the type of elements and items (the same type), which should
-        *            implement {@link Hoverable} (it will not cause issues if not,
-        *            but then, it will be a default renderer)
-        * @param model
-        *            the model to use
-        * 
-        * @return a suitable, {@link Hoverable} compatible renderer
-        */
-       static public <T extends Component> ListCellRenderer6<T> generateRenderer(
-                       final ListModel<T> model) {
-               return new ListCellRenderer6<T>() {
-                       @Override
-                       public Component getListCellRendererComponent(JList6<T> list,
-                                       T item, int index, boolean isSelected,
-                                       boolean cellHasFocus) {
-                               if (item instanceof Hoverable) {
-                                       Hoverable hoverable = (Hoverable) item;
-                                       hoverable.setSelected(isSelected);
-                                       hoverable.setHovered(model.isHovered(index));
-                               }
-
-                               return item;
-                       }
-               };
-       }
-}