All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.jaxx.runtime.swing.JAXXList Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * JAXX :: Runtime
 * %%
 * Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nuiton.jaxx.runtime.swing;

import javax.swing.AbstractListModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;
import javax.swing.ListModel;
import java.awt.Component;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class JAXXList extends JList {

    private static final long serialVersionUID = 1L;

    public class JAXXListModel extends AbstractListModel {

        private final List items;

        private static final long serialVersionUID = -1598924187490122036L;

        public JAXXListModel(List items) {
            this.items = items;

            PropertyChangeListener listener = e -> {
                if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) {
                    Item item = (Item) e.getSource();
                    int itemIndex = JAXXListModel.this.items.indexOf(item);
                    int[] oldSelection = getSelectedIndices();
                    int[] newSelection;
                    int index = -1;
                    for (int i = 0; i < oldSelection.length; i++) {
                        if (oldSelection[i] == itemIndex) {
                            index = i;
                            break;
                        }
                    }
                    if (item.isSelected()) {
                        if (index != -1) // it was already selected
                        {
                            return;
                        }
                        newSelection = new int[oldSelection.length + 1];
                        System.arraycopy(oldSelection, 0, newSelection, 0, oldSelection.length);
                        newSelection[newSelection.length - 1] = itemIndex;
                    } else {
                        if (index == -1) // it already wasn't selected
                        {
                            return;
                        }
                        newSelection = new int[oldSelection.length - 1];
                        System.arraycopy(oldSelection, 0, newSelection, 0, index);
                        System.arraycopy(oldSelection, index + 1, newSelection, index, oldSelection.length - 1 - index);
                    }
                    setSelectedIndices(newSelection);
                } else {
                    for (int i = 0; i < getSize(); i++) {
                        if (getElementAt(i) == ((Item) e.getSource()).getValue()) {
                            fireContentsChanged(JAXXListModel.this, i, i);
                            if (isSelectedIndex(i)) {
                                fireSelectionValueChanged(i, i, false);
                            }
                            return;
                        }
                    }
                }
            };
            for (Item item : items) {
                item.addPropertyChangeListener(listener);
            }
        }

        public List getItems() {
            return items;
        }

        @Override
        public Item getElementAt(int i) {
            return items.get(i);
        }

        @Override
        public int getSize() {
            return items.size();
        }
    }

    public JAXXList() {
        setCellRenderer(new DefaultListCellRenderer() {

            private static final long serialVersionUID = 1L;

            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                ListModel model = list.getModel();
                if (model instanceof JAXXListModel) {
                    Item item = ((JAXXListModel) model).items.get(index);
                    String label = item.getLabel();
                    if (label != null) {
                        value = label;
                    }
                }
                return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            }
        });

        addListSelectionListener(e -> {
            ListModel model = getModel();
            if (model instanceof JAXXListModel) {
                List items = ((JAXXListModel) model).items;
                for (int i = items.size() - 1; i >= 0; i--) {
                    boolean selected = isSelectedIndex(i);
                    Item item = items.get(i);
                    if (selected != item.isSelected()) {
                        item.setSelected(selected);
                    }
                }
            }
        });
    }

    // this way we can keep it marked protected and still allow code in this file to call it

    @Override
    protected void fireSelectionValueChanged(int firstIndex, int lastIndex, boolean isAdjusting) {
        super.fireSelectionValueChanged(firstIndex, lastIndex, isAdjusting);
    }

    public void setItems(List items) {
        setModel(new JAXXListModel(items));
        List selectedIndexList = new ArrayList<>();
        for (int i = 0; i < items.size(); i++) {
            if (items.get(i).isSelected()) {
                selectedIndexList.add(i);
            }
        }
        int[] selectedIndices = new int[selectedIndexList.size()];
        for (int i = 0; i < selectedIndexList.size(); i++) {
            selectedIndices[i] = selectedIndexList.get(i);
        }
        setSelectedIndices(selectedIndices);
    }

    public List getItems() {
        if (getModel() instanceof JAXXListModel) {
            return ((JAXXListModel) getModel()).getItems();
        }
        return null;
    }

    public void setSelectedValue(Object value) {
        super.setSelectedValue(value, true);
    }

    /**
     * Set the selected Objects
     *
     * @param values Objects must be selected in the list
     */
    public void setSelectedValues(Object[] values) {
        if (values != null) {
            List selectedIndices = new ArrayList<>();
            ListModel model = getModel();
            for (int i = 0; i < model.getSize(); i++) {
                Object o = model.getElementAt(i);
                for (Object value : values) {
                    if (o.equals(value)) {
                        selectedIndices.add(i);
                        break;
                    }
                }
            }
            int[] ints = new int[selectedIndices.size()];
            for (int i = 0; i < ints.length; i++) {
                ints[i] = selectedIndices.get(i);
            }
            setSelectedIndices(ints);
        } else {
            // No selection if values is null
            setSelectedIndex(-1);
        }
    }

    public void setSelectedItem(Item item) {
        super.setSelectedValue(item.getValue(), true);
    }

    public void setSelectedItems(List itemsToSelect) {
        if (itemsToSelect != null) {
            List items = getItems();
            int[] indices = new int[itemsToSelect.size()];
            int i = 0;
            for (Item item : itemsToSelect) {
                indices[i] = items.indexOf(item);
                i++;
            }
            super.setSelectedIndices(indices);
        }
    }

    public Item getSelectedItem() {
        Object selected = super.getSelectedValue();
        return findItem(selected);
    }

    public List getSelectedItems() {
        List selected = super.getSelectedValuesList();
        java.util.List itemsSelected = new ArrayList<>();
        for (Object s : selected) {
            itemsSelected.add(findItem(s));
        }
        return itemsSelected;
    }

    public Item findItem(Object value) {
        List items = getItems();
        if (items != null) {
            for (Item i : items) {
                if (i.getValue().equals(value)) {
                    return i;
                }
            }
        }
        return null;
    }

    public void addItem(Item item) {
        List items = getItems();
        if (items != null) {
            items.add(item);
            setItems(items);
        }
    }

    public void addAllItems(Collection itemsToAdd) {
        List items = getItems();
        if (items != null) {
            items.addAll(itemsToAdd);
            setItems(items);
        }
    }

    public void removeItem(Item item) {
        List items = getItems();
        if (items != null) {
            items.remove(item);
            setItems(items);
        }
    }

    public void removeAllItems(Collection itemsToRemove) {
        List items = getItems();
        if (items != null) {
            items.removeAll(itemsToRemove);
            setItems(items);
        }
    }

    /**
     * Fill a list model with some datas, and select after all the given object
     *
     * @param data    data ot inject in combo
     * @param selects the objects to select in list after reflling his model
     */
    public void fillList(Collection data, Collection selects) {
        if (selects == null) {
            selects = java.util.Collections.EMPTY_LIST;
        }
        List items = new ArrayList<>();
        for (Object o : data) {
            boolean selected = false;
            for (Object select : selects) {
                if (selected = o.equals(select)) {
                    break;
                }
            }
            items.add(new Item(o.toString(), o.toString(), o, selected));
        }
        setItems(items);
    }

    /**
     * Fill a list model with some datas, and select after all the given object
     *
     * @param data   data ot inject in combo
     * @param select object to select in list after reflling his model
     */
    public void fillList(Collection data, Object select) {
        List items = new ArrayList<>();
        for (Object o : data) {
            boolean selected = o.equals(select);
            items.add(new Item(o.toString(), o.toString(), o, selected));
        }
        setItems(items);
    }

    /**
     * Fill a list model with some datas, and select after all the given object
     *
     * @param data       data ot inject in combo
     * @param select     object to select in list after reflling his model
     * @param methodName method to invoke to display data's name
     */
    public void fillList(Collection data, Object select, String methodName) {
        // prepare method to use
        Method m = null;

        List items = new ArrayList<>();
        for (Object o : data) {
            boolean selected = o.equals(select);
            if (m == null) {
                try {
                    m = o.getClass().getMethod(methodName);
                    m.setAccessible(true);
                } catch (NoSuchMethodException e) {
                    throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass());
                }
            }
            try {
                items.add(new Item(o.toString(), (String) m.invoke(o), o, selected));
            } catch (SecurityException | InvocationTargetException | IllegalArgumentException | IllegalAccessException e) {
                // shoudl never happen ?
                throw new RuntimeException(e);
            }
        }
        setItems(items);
    }

    /**
     * Fill a list model with some datas, and select after all the given object
     *
     * @param data       data ot inject in combo
     * @param selects    the objects to select in list after reflling his model
     * @param methodName method to invoke to display data's name
     */
    public void fillList(Collection data, Collection selects, String methodName) {
        // prepare method to use
        Method m = null;

        List items = new ArrayList<>();
        for (Object o : data) {
            boolean selected = selects.contains(o);
            if (m == null) {
                try {
                    m = o.getClass().getMethod(methodName);
                    m.setAccessible(true);
                } catch (NoSuchMethodException e) {
                    throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass());
                }
            }
            try {
                items.add(new Item(o.toString(), (String) m.invoke(o), o, selected));
            } catch (SecurityException | InvocationTargetException | IllegalArgumentException | IllegalAccessException e) {
                // shoudl never happen ?
                throw new RuntimeException(e);
            }
        }
        setItems(items);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy