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

net.sf.cuf.state.ui.SwingListSelectionState Maven / Gradle / Ivy

The newest version!
package net.sf.cuf.state.ui;

import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.JComboBox;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

/**
 * The SwingListSelectionState class models a State with the ListSelectionModel
 * of a Swing JTable or JList as the state source. The value of
 * the state is determined by comparing the ListSelectionModel's
 * selection with a user-defined selection index.
 * If the user-defined index is contained in the ListSelectionModel's
 * selection, the state is true.
 * The state also supports "reverse index" match so you can can not only check e.g.
 * if the first row is selected but also if the last row is selected.
 */
public class SwingListSelectionState extends AbstractSwingState implements ListSelectionListener, ActionListener, TableModelListener, ListDataListener
{
    /** The marker for no selection. */
    public static final int NO_SELECTION = -1;

    /** the selection we monitor, only null when mComboBoxModel is not null */
    private ListSelectionModel mListSelectionModel;
    /** the combo box we monitor, only null when mListSelectionModel is not null */
    private JComboBox          mComboBox;
    /** null or the table model if we were constructed by a JTable */
    private TableModel         mTableModel;
    /** null or the list model if we were constructed by a JList */
    private ListModel          mListModel;
    /** user provided index we check against, the default is NO_SELECTION */
    private int                mListIndex;
    /** flag if we should do look on the reverse index, the default is false */
    private boolean            mReverseIndex;

    /**
     * Creates a new state, using the selection model of the handed list
     * as its state source.
     * If the selection contains NO_SELECTION, then the
     * state is true.
     * @param pList list we take the selection model from, must not be null
     */
    public SwingListSelectionState(final JList pList)
    {
        this(pList, NO_SELECTION);
    }

    /**
     * Creates a new state, using the selection model of the handed list
     * as its state source.
     * If the selection contains pIndex, then the state is true.
     * @param pList list we take the selection model from, must not be null
     * @param pIndex user-provided index we check the selection against
     */
    public SwingListSelectionState(final JList pList, final int pIndex)
    {
        this(pList, pIndex, false);
    }

    /**
     * Creates a new state, using the selection model of the handed list
     * as its state source.
     * If the selection contains pIndex, then the state is true.
     * @param pList list we take the selection model from, must not be null
     * @param pIndex user-provided index we check the selection against
     * @param pReverseIndex flag if we should take the index as a reverse index
     */
    public SwingListSelectionState(final JList pList, final int pIndex, final boolean pReverseIndex)
    {
        super();
        if (pList == null)
        {
            throw new IllegalArgumentException("JList must not be null");
        }
        init(pList.getSelectionModel(), pList.getModel(), pIndex, pReverseIndex);
    }

    /**
     * Creates a new state, using the selection model of the handed table
     * as its state source.
     * If the selection contains NO_SELECTION, then the
     * state is true.
     * @param pTable table we take the selection model from, must not be null
     */
    public SwingListSelectionState(final JTable pTable)
    {
        this(pTable, NO_SELECTION);
    }

    /**
     * Creates a new state, using the selection model of the handed table
     * as its state source.
     * If the selection contains pIndex, then the state is true.
     * @param pTable table we take the selection model from.
     * @param pIndex user-provided index we check the selection against
     */
    public SwingListSelectionState(final JTable pTable, final int pIndex)
    {
        this(pTable, pIndex, false);
    }

    /**
     * Creates a new state, using the selection model of the handed table
     * as its state source.
     * If the selection contains pIndex, then the state is true.
     * @param pTable table we take the selection model from.
     * @param pIndex user-provided index we check the selection against
     * @param pReverseIndex flag if we should take the index as a reverse index
     */
    public SwingListSelectionState(final JTable pTable, final int pIndex, final boolean pReverseIndex)
    {
        super();
        if (pTable == null)
        {
            throw new IllegalArgumentException("JTable must not be null");
        }
        init(pTable.getSelectionModel(), pTable.getModel(), pIndex, pReverseIndex);
    }

    /**
     * Creates a new state, using the handed selection model as its state source.
     * If the selection contains pIndex, then the state is true.
     * @param pSelectionModel the selection we monitor
     * @param pIndex user-provided index we check the selection against
     */
    public SwingListSelectionState(final ListSelectionModel pSelectionModel, final int pIndex)
    {
        super();
        init(pSelectionModel, pIndex);

    }

    /**
     * Creates a new state, using the selection model of the handed combobox
     * as its state source.
     * If the selection is NO_SELECTION, then the state is true.
     * @param pComboBox combobox we take the model from, must not be null
     */
    public SwingListSelectionState(final JComboBox pComboBox)
    {
        this(pComboBox, NO_SELECTION);
    }

    /**
     * Creates a new state, using the selection model of the handed table
     * as its state source.
     * If the selection is pIndex, then the state is true.
     * @param pComboBox combobox we take the model from, must not be null
     * @param pIndex user-provided index we check the selection against
     */
    public SwingListSelectionState(final JComboBox pComboBox, final int pIndex)
    {
        this(pComboBox, pIndex, false);
    }

    /**
     * Creates a new state, using the selection model of the handed table
     * as its state source.
     * If the selection is pIndex, then the state is true.
     * @param pComboBox combobox we take the model from, must not be null
     * @param pIndex user-provided index we check the selection against
     * @param pReverseIndex flag if we should take the index as a reverse index
     */
    public SwingListSelectionState(final JComboBox pComboBox, final int pIndex, final boolean pReverseIndex)
    {
        super();
        if (pComboBox == null)
        {
            throw new IllegalArgumentException("JComboBox must not be null");
        }
        init(pComboBox, pIndex, pReverseIndex);
    }

    /**
     * Common init stuff of the constructors.
     * @param pSelectionModel the selection we monitor, must not be null
     * @param pTableModel the table model we monitor, must not be null
     * @param pIndex index we check the selection against
     * @param pReverseIndex flag if we should take the index as a reverse index
     */
    private void init(final ListSelectionModel pSelectionModel, final TableModel pTableModel, final int pIndex, final boolean pReverseIndex)
    {
        if (pTableModel == null)
        {
            throw new IllegalArgumentException("table model must not be null");
        }
        mReverseIndex= pReverseIndex;
        mTableModel= pTableModel;
        init(pSelectionModel, pIndex);
        mTableModel.addTableModelListener(this);
    }

    /**
     * Common init stuff of the constructors.
     * @param pSelectionModel the selection we monitor, must not be null
     * @param pListModel the list model we monitor, must not be null
     * @param pIndex index we check the selection against
     * @param pReverseIndex flag if we should take the index as a reverse index
     */
    private void init(final ListSelectionModel pSelectionModel, final ListModel pListModel, final int pIndex, final boolean pReverseIndex)
    {
        if (pListModel == null)
        {
            throw new IllegalArgumentException("list model must not be null");
        }
        mReverseIndex= pReverseIndex;
        mListModel= pListModel;
        init(pSelectionModel, pIndex);
        mListModel.addListDataListener(this);
    }


    /**
     * Common init stuff of the constructors.
     * @param pSelectionModel the selection we monitor, must not be null
     * @param pIndex index we check the selection against
     */
    private void init(final ListSelectionModel pSelectionModel, final int pIndex)
    {
        if (pSelectionModel == null)
        {
            throw new IllegalArgumentException("list selection must not be null");
        }
        checkIndex(pIndex);
        mListIndex         = pIndex;
        mListSelectionModel= pSelectionModel;
        mComboBox          = null;

        // initially set the state according to selection model
        mIsEnabled= getInternalState();

        mListSelectionModel.addListSelectionListener(this);
    }

    /**
     * Common init stuff of the constructors.
     * @param pComboBox the combobox we monitor, must not be null
     * @param pIndex index we check the selection against
     * @param pReverseIndex flag if we should take the index as a reverse index
     */
    private void init(final JComboBox pComboBox, final int pIndex, final boolean pReverseIndex)
    {
        checkIndex(pIndex);
        mReverseIndex      = pReverseIndex;
        mListIndex         = pIndex;
        mListSelectionModel= null;
        mComboBox          = pComboBox;

        // initially set the state according to selection model
        mIsEnabled= getInternalState();

        mComboBox.addActionListener(this);
        mComboBox.getModel().addListDataListener(this);
    }


    /**
     * Small helper to check the index.
     * @param pIndex index to check
     * @throws IllegalArgumentException if index is less than NO_SELECTION
     */
    private void checkIndex(final int pIndex) throws IllegalArgumentException
    {
        if (pIndex < NO_SELECTION)
        {
            throw new IllegalArgumentException("index must be >= " + NO_SELECTION);
        }
    }

    /**
     * Sets the index we try to find in the list selection.
     * @param pIndex user-provided index we check the selection against
     */
    public void setCompareContent(final int pIndex)
    {
        checkIndex(pIndex);
        mListIndex = pIndex;
        checkStateChange();
    }

    /**
     * Called whenever the value of the selection changes.
     * @param pEvent the event that characterizes the change.
     */
    @Override
    public void valueChanged(final ListSelectionEvent pEvent)
    {
        // ignore intermediate events
        if (pEvent.getValueIsAdjusting())
        {
            return;
        }

        checkStateChange();
    }


    /**
     * Called whenever our table model changes.
     * @param pEvent the event that characterizes the change.
     */
    @Override
    public void tableChanged(final TableModelEvent pEvent)
    {
        checkStateChange();
    }

    /**
     * Called whenever our combo box or list data data changes.
     * @param pEvent the event that characterizes the change.
     */
    @Override
    public void intervalAdded(final ListDataEvent pEvent)
    {
        checkStateChange();
    }

    /**
     * Called whenever our combo box or list data data changes.
     * @param pEvent the event that characterizes the change.
     */
    @Override
    public void intervalRemoved(final ListDataEvent pEvent)
    {
        checkStateChange();
    }

    /**
     * Called whenever our combo box or list data data changes.
     * @param pEvent the event that characterizes the change.
     */
    @Override
    public void contentsChanged(final ListDataEvent pEvent)
    {
        checkStateChange();
    }

    /**
     * Handler for combobox callbacks.
     * @param pEvent not used
     */
    @Override
    public void actionPerformed(final ActionEvent pEvent)
    {
        checkStateChange();
    }

    /**
     * Check if mListIndex is selected, if mListIndex is NO_SELECTION, check if there is no selection.
     * @return the state, true if the user provided index is contained in the list/combobox selection
     */
    @Override
    protected boolean getInternalState()
    {
        if (mListSelectionModel!=null)
        {
            // we monitor a JTable or JList
            if ((mListIndex == NO_SELECTION) && mListSelectionModel.isSelectionEmpty())
            {
                return true;
            }
            else
            {
                int index= calcIndex();
                return (index >= 0) && mListSelectionModel.isSelectedIndex(index);
            }
        }
        else
        {
            // we monitor a JComboBox
            if (mListIndex == NO_SELECTION)
            {
                return (NO_SELECTION==mComboBox.getSelectedIndex());
            }
            else
            {
                int index= calcIndex();
                return (index >= 0) && (mComboBox.getSelectedIndex()==index);
            }
        }
    }

    /**
     * Helper to calculate the index we want to check.
     * @return the index, may be <0 if we have a reverse index.
     */
    private int calcIndex()
    {
        if (mReverseIndex)
        {
            int size;
            if (mComboBox!=null)
            {
                size= mComboBox.getModel().getSize();
            }
            else if (mTableModel!=null)
            {
                size= mTableModel.getRowCount();
            }
            else if (mListModel!=null)
            {
                size= mListModel.getSize();
            }
            else
            {
                throw new IllegalStateException("could not calc size for reverse index");
            }

            return size-1-mListIndex;
        }
        else
        {
            return mListIndex;
        }
    }

    /**
     * Set the source of the state as the reason for a change.
     */
    @Override
    protected void setReason()
    {
        mReason= mListSelectionModel;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy