001/*
002 * $Id: SortController.java 3498 2009-09-10 09:35:40Z kleopatra $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 * 
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 * Lesser General Public License for more details.
016 * 
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020 */
021
022package org.jdesktop.swingx.sort;
023
024import java.util.Comparator;
025
026import javax.swing.RowFilter;
027import javax.swing.SortOrder;
028
029/**
030 * Defines the interactive sort control for sortable collection components (like 
031 * JXList, JXTable). All sort gesture requests from their sort api 
032 * are routed through the SortController.
033 * <p>
034 * 
035 * This is very-much work-in-progress: while moving from ol' SwingX sorting to 
036 * core jdk6 sorting we need a hook for sorting api on the view. So in terms of
037 * jdk6 classes, this is something like:<p>
038 * 
039 * <code><pre>
040 * SortController == DefaultRowSorter - RowSorter + XX
041 * </pre></code>
042 * All methods which change sort state must respect per-controller and per-column 
043 * sortable property, as follows
044 * <ol>
045 * <li> if per-controller sortable is false, do nothing
046 * <li> if per-controller sortable is true, if per-column sortable is false, do nothing
047 * <li> if both are true toggle the SortOrder of the given column
048 * </ol>
049 *
050 * 
051 *  @author <a href="mailto:jesse@swank.ca">Jesse Wilson</a>
052 *  @author Jeanette Winzenburg
053 * 
054 */
055public interface SortController<M> {
056
057//----------------- configuration
058    
059    /**
060     * Sets whether or not this controller is sortable.<p>
061     * 
062     * The default is true.<p>
063     * 
064     * PENDING JW: define behaviour if sortable is disabled while has sortOrders.
065     * In this case JXTable resets all sorts.
066     * 
067     * @param sortable whether or not this controller is sortable
068     * @see #isSortable()        
069     */
070    void setSortable(boolean sortable);
071    
072    /**
073     * Returns true if this controller is sortable; otherwise, false.
074     *
075     * @return true if this controller is sortable
076     *         
077     * @see #isSortable()
078     */
079    boolean isSortable();
080    
081    /**
082     * Sets whether or not the specified column is sortable.<p>
083     * 
084     * The default is true.<p>
085     * 
086     * PENDING JW: define behaviour if sortable is disabled while has sortOrders.
087     * In this case JXTable removes the sort of the column.<p>
088     * 
089     * PENDING JW: decide whether or not this method should trigger a resort
090     * DefaultRowSorter explicitly doesn't, JXTable does.
091     * 
092     * @param column the column to enable or disable sorting on, in terms
093     *        of the underlying model
094     * @param sortable whether or not the specified column is sortable
095     * @throws IndexOutOfBoundsException if <code>column</code> is outside
096     *         the range of the model
097     * @see #isSortable(int)        
098     * @see #toggleSortOrder(int)
099     * @see #setSortOrder(int, SortOrder)
100     */
101    void setSortable(int column, boolean sortable);
102    
103    /**
104     * Returns true if the specified column is sortable. <p>
105     * This returns true if both the controller's sortable property and
106     * the column's sortable property is true. Returns false if any of
107     * them is false.
108     *
109     * @param column the column to check sorting for, in terms of the
110     *        underlying model
111     * @return true if the column is sortable
112     * @throws IndexOutOfBoundsException if column is outside
113     *         the range of the underlying model
114     *         
115     * @see #isSortable(int)
116     */
117    boolean isSortable(int column);
118
119    /**
120     * Sets the <code>Comparator</code> to use when sorting the specified
121     * column.  This does not trigger a sort.  If you want to sort after
122     * setting the comparator you need to explicitly invoke <code>sort</code>.
123     *
124     * @param column the index of the column the <code>Comparator</code> is
125     *        to be used for, in terms of the underlying model
126     * @param comparator the <code>Comparator</code> to use
127     * @throws IndexOutOfBoundsException if <code>column</code> is outside
128     *         the range of the underlying model
129     */
130    public void setComparator(int column, Comparator<?> comparator);
131
132    /**
133     * Returns the <code>Comparator</code> for the specified 
134     * column.  This will return <code>null</code> if a <code>Comparator</code>
135     * has not been specified for the column.
136     *
137     * @param column the column to fetch the <code>Comparator</code> for, in
138     *        terms of the underlying model
139     * @return the <code>Comparator</code> for the specified column
140     * @throws IndexOutOfBoundsException if column is outside
141     *         the range of the underlying model
142     */
143    public Comparator<?> getComparator(int column);
144    
145    /**
146     * Sets the cycle of sort ordes to toggle through. Zero or more SortOrders which
147     * must not be null.
148     * 
149     * @param cycle the SortOrders to cycle through, may be empty
150     * @throws NullPointerException if the array or any of its elements is null
151     */
152    void setSortOrderCycle(SortOrder... cycle);
153    
154    /**
155     * Returns the cycle of sort orders to cycle through.
156     * 
157     * @return
158     */
159    SortOrder[] getSortOrderCycle();
160    
161    /**
162     * If true, specifies that a sort should happen when the underlying
163     * model is updated (<code>rowsUpdated</code> is invoked).  For
164     * example, if this is true and the user edits an entry the
165     * location of that item in the view may change.  The default is
166     * true.
167     *
168     * @param sortsOnUpdates whether or not to sort on update events
169     */
170    void setSortsOnUpdates(boolean sortsOnUpdates);
171
172    /**
173     * Returns true if  a sort should happen when the underlying
174     * model is updated; otherwise, returns false.
175     *
176     * @return whether or not to sort when the model is updated
177     */
178    boolean getSortsOnUpdates();
179    
180    /**
181     * Sets the StringValueProvider to look up the StringValues. If the value
182     * is not-null, it guarantees to use it exclusively for string conversion. <p>
183     * 
184     * PENDING JW: this is more or less parallel to TableStringConverter. Need to think
185     * about merging somehow.
186     * 
187     * @param provider the look up for StringValues, may be null.
188     */
189    void setStringValueProvider(StringValueProvider provider);
190
191    /**
192     * Returns the StringValueProvider used to look up StringValues.
193     * 
194     * @return StringValueProvider used to look up StringValues, guaranteed to
195     *  be not null.
196     */
197    StringValueProvider getStringValueProvider();
198    
199//------------------------ sort
200    
201    /**
202     * Reverses the sort order of the specified column. The exact behaviour is
203     * up to implementations.<p>
204     * 
205     * Implementations must respect the per-controller and per-column-sortable 
206     * property.
207     * 
208     * @param column the model index of the column to toggle
209     * @see #isSortable(int) 
210     * @see #isSortable()
211     */
212    void toggleSortOrder(int column);
213
214    /**
215     * Sets the sort order of the specified column. <p>
216     * 
217     * Implementations must respect the per-controller and per-column-sortable 
218     * property.
219     *
220     * @param column the model index of the column to set
221     * @param sortOrder the SortOrder to set for the column
222     * 
223     * @see #isSortable(int) 
224     * @see #isSortable()
225     */
226    void setSortOrder(int column, SortOrder sortOrder);
227 
228    /**
229     * Returns the sort order of the specified column.
230     * 
231     * 
232     * @return one of {@link SortOrder#ASCENDING},
233     *     {@link SortOrder#DESCENDING} or {@link SortOrder#UNSORTED}.
234     */
235    SortOrder getSortOrder(int column);
236
237    
238    /**
239     * Resets all interactive sorting. <p>
240     * 
241     * Implementations must respect the per-controller and per-column-sortable 
242     * property.
243     * 
244     */
245    void resetSortOrders();
246    
247//-------------------- filter
248    
249    /**
250     * Sets the filter that determines which rows, if any, should be
251     * hidden from the view.  The filter is applied before sorting.  A value
252     * of <code>null</code> indicates all values from the model should be
253     * included.
254     * <p>
255     * <code>RowFilter</code>'s <code>include</code> method is passed an
256     * <code>Entry</code> that wraps the underlying model.  The number
257     * of columns in the <code>Entry</code> corresponds to the
258     * number of columns in the underlying model.  The identifier
259     * comes from the underlying model as well.
260     * <p>
261     * This method triggers a sort.
262     *
263     * PENDING JW: the "underlying model" is the ModelWrapper ... want to 
264     * expose here as well? Otherwise, the second paramter doesn't make much sense.
265     * 
266     * @param filter the filter used to determine what entries should be
267     *        included
268     */
269     void setRowFilter(RowFilter<? super M, ? super Integer> filter);
270
271    /**
272     * Returns the filter that determines which rows, if any, should
273     * be hidden from view.
274     *
275     * @return the filter
276     */
277     RowFilter<? super M,? super Integer> getRowFilter();
278
279
280
281}