X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fui%2FListModel.java;h=7cc23b8c34b78262b33b5dc065e525d6e2a1ce90;hb=712ddafb749aada41daab85c36ac12f657b2307e;hp=cf16d5f0a111e660171102b3efad3bdefe1d6d48;hpb=3177622aa63d2e126ce9426b440a3443a2ea8bab;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/ui/ListModel.java b/src/be/nikiroo/utils/ui/ListModel.java deleted file mode 100644 index cf16d5f..0000000 --- a/src/be/nikiroo/utils/ui/ListModel.java +++ /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). - *

- * It also offers filter options, supports hovered changes and some more utility - * functions. - * - * @author niki - * - * @param - * the type of elements and items (the same type) - */ -public class ListModel extends DefaultListModel6 { - 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 - * the type of elements and items (the same type) - */ - public interface Predicate { - /** - * 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 - * the type of elements and items (the same type) - */ - public interface TooltipCreator { - /** - * Generate a tooltip {@link Window} for this element. - *

- * 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 items = new ArrayList(); - private boolean keepSelection = true; - - private TooltipCreator 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 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 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 list, TooltipCreator 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 list, JPopupMenu popup, - TooltipCreator tooltipCreator) { - this((JList) list, popup, tooltipCreator); - } - - /** - * 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 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}. - *

- * 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}. - *

- * 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 tooltipCreator) { - this(list, null, tooltipCreator); - } - - /** - * 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 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 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() { - @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. - *

- * 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. - * - * @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 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 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. - *

- * 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 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 getSelectedElements() { - List selected = new ArrayList(); - for (int index : list.getSelectedIndices()) { - selected.add(get(index)); - } - - return selected; - } - - /** - * Return the selected element if one and only one 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 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 - * 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 ListCellRenderer6 generateRenderer( - final ListModel model) { - return new ListCellRenderer6() { - @Override - public Component getListCellRendererComponent(JList6 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; - } - }; - } -}