package uk.ac.starlink.topcat.plot;

import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import uk.ac.starlink.table.StarTable;
import uk.ac.starlink.topcat.TopcatModel;
import uk.ac.starlink.ttools.plot.ErrorMode;

/**
 * Defines an object which provides column selectors for a plot.
 * An instance of this interface is owned by each {@link PointSelector}.
 *
 * @author   Mark Taylor
 * @since    1 Jun 2007
 */
public interface AxesSelector {

    /**
     * Returns the panel which contains column selectors and any other
     * UI components that the concrete subclass wants to place.
     *
     * @return   column selector panel
     */
    JComponent getColumnSelectorPanel();

    /**
     * Returns the array of combo boxes which are used to select column or
     * other values.
     *
     * @return  array of column selector combo boxes
     */
    JComboBox[] getColumnSelectors();

    /** 
     * Set up column selectors correctly for the given model.
     * This will involve setting the column selector models appropriately.
     * If the submitted table is null, then the selector models should be
     * unselected. 
     * 
     * @param  tcModel   table for which selectors must be configured
     */
    void setTable( TopcatModel tcModel );

    /** 
     * Hint to set up the values of the column selectors to a
     * sensible value.  An implementation which does nothing is legal.
     */
    void initialiseSelectors();

    /**
     * Adds a listener which is notified when any of the selections made
     * by this component changes.
     *
     * @param  listener  listener to add
     */
    void addActionListener( ActionListener listener );

    /**
     * Removes a listener added by {@link #addActionListener}.
     *
     * @param  listener  listener to remove
     */
    void removeActionListener( ActionListener listener );

    /** 
     * Returns the number of columns in the table that {@link #getData} will
     * return.
     *
     * @return  dimensionality
     */     
    int getNdim();

    /** 
     * Indicates whether this selector has enough state filled in to be
     * able to specify some point data.
     *
     * @return   true iff properly filled in
     */     
    boolean isReady();

    /**
     * Returns a StarTable which corresponds to the data in the columns
     * selected by the current selections on this object.
     *
     * <p>Note: for performance reasons, it is <em>imperative</em> that
     * two tables returned from this method must match according to the
     * {@link java.lang.Object#equals} method if they are known to
     * contain the same cell data (i.e. if the state of this selector
     * has not changed in the mean time).  Don't forget to do
     * <code>hashCode</code> too.
     *
     * @return   table containing the data from the current selection
     */
    StarTable getData();

    /**
     * Returns a StarTable which corresponds to the error data defined
     * by the current selections.  The details of how the table columns
     * are laid out are down to the concrete subclass.
     *
     * <p>See the notes in {@link #getData} about table equality - 
     * the same constraints apply.
     *
     * @return  error data table
     */
    StarTable getErrorData();

    /**
     * Returns a StarTable whose single column contains a label for each
     * point.
     *
     * <p>See the notes in {@link #getData} about table equality - 
     * the same constraints apply.
     *
     * @return   label table
     */
    StarTable getLabelData();

    /**
     * Constructs an array of AxisEditor objects suitable for modifying the
     * axes which are defined by this selector.  The number of
     * them is often, but not necessarily, the same as the dimensionality
     * of this selector.
     *
     * @return  array of new AxisEditors
     */
    AxisEditor[] createAxisEditors();

    /**
     * Returns a PointStore suitable for storing coordinate and error
     * information generated by the current state of this selector.
     * The store will have to store <code>npoint</code> points, and
     * its {@link PointStore#storePoint} method will be called with
     * the result of acquiring rows from the tables got from this
     * selector's {@link #getData} and {@link #getErrorData} methods.
     *
     * @param   npoint  number of points to store
     * @return   new point store
     */
    PointStore createPointStore( int npoint );

    /**
     * Returns the error modes currently in force for this selector.
     *
     * @return   error mode array
     */
    ErrorMode[] getErrorModes();
}
