001    /*
002     * $Id: ComponentAdapter.java,v 1.6 2006/05/14 08:12:13 dmouse Exp $
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    
022    package org.jdesktop.swingx.decorator;
023    
024    import javax.swing.JComponent;
025    
026    /**
027     * Abstract base class for all component data adapter classes.
028     * A <code>ComponentAdapter</code> allows a {@link Filter}, {@link Sorter},
029     * or {@link Highlighter} to interact with a {@link #target} component through a
030     * common API.
031     * 
032     * It has two aspects:
033     * <ul>
034     * <li> interact with the data of the component. The methods for this are those 
035     * taking row/column indices as parameters. The coordinates
036     * are in model coordinate system. Typical clients of are Filters.
037     * <li> interact with the view state for a given data element. The row/cloumn fields and the
038     * parameterless methods service this aspect. The coordinates are in view coordinate system.
039     * Typical clients are the highlighting part of Highlighters.
040     * </ul>
041     * 
042     * The adapter is responsible for mapping column coordinates. 
043     * 
044     * All input column 
045     * indices are in model coordinates with exactly two exceptions:
046     * <ul>
047     * <li> {@link #column} in column view coordinates
048     * <li> the mapping method viewToModel(columnIndex) in view coordinates
049     * </ul>
050     * 
051     * All input row indices are in model coordinates with exactly two exceptions:
052     * <ul>
053     * <li> {@link #row} in row view coordinates
054     * <li> the access method for the filtered value takes the row in view coordinates.
055     * </ul>
056     *  
057     * 
058     * @author Ramesh Gupta
059     */
060    public abstract class ComponentAdapter {
061        /** current row in view coordinates. */
062        public int row = 0;
063        /** current column in view coordinates. */
064        public int column = 0;
065        protected final JComponent  target;
066    
067        /**
068         * Constructs a ComponentAdapter, setting the specified component as the
069         * target component.
070         *
071         * @param component target component for this adapter
072         */
073        public ComponentAdapter(JComponent component) {
074            target = component;
075        }
076    
077        public JComponent getComponent() {
078            return target;
079        }
080    
081    //---------------------------- accessing the target's model
082        
083        /**
084         * returns the column's label (= headerValue).
085         * 
086         * Used f.i. in SearchPanel to fill the field with the 
087         * column name.
088         * 
089         * Note: it's up to the implementation to decide for which
090         * columns it returns a name - most will do so for the
091         * subset with isTestable = true.
092         * 
093         * @param columnIndex in model coordinates
094         * @return column name or null if not found/not testable.
095         */
096        public abstract String getColumnName(int columnIndex);
097    
098        /**
099         * returns the logical name (== identifier) of the column at 
100         * columnIndex in model coordinates.
101         * 
102         * Used f.i. JNTable to store and apply column properties by identifier.
103         * 
104         * Note: it's up to the implementation to decide for which
105         * columns it returns a name - most will do so for the
106         * subset with isTestable = true.
107         * 
108         * @param columnIndex in model coordinates
109         * @return the String value of the column identifier at columnIndex
110         *   or null if no identifier set
111         */
112        public abstract String getColumnIdentifier(int columnIndex);
113    
114        /**
115         * Returns the number of columns in the target's data model.
116         *
117         * @return the number of columns in the target's data model.
118         */
119        public int getColumnCount() {
120            return 1;   // default for combo-boxes, lists, and trees
121        }
122    
123        /**
124         * Returns the number of rows in the target's data model.
125         *
126         * @return the number of rows in the target's data model.
127         */
128        public int getRowCount() {
129            return 0;
130        }
131    
132        /**
133         * Returns the value of the target component's cell identified by the
134         * specified row and column in model coordinates.
135         *
136         * @param row in model coordinates
137         * @param column in model coordinates
138         * @return the value of the target component's cell identified by the
139         * specified row and column
140         */
141        public abstract Object getValueAt(int row, int column);
142        public abstract void setValueAt(Object aValue, int row, int column);
143    
144        public abstract boolean isCellEditable(int row, int column);
145    
146        /**
147         * returns true if the column should be included in testing.
148         * Here: returns true if visible (that is modelToView gives a valid
149         * view column coordinate).
150         * 
151         * @param column in model coordinates
152         * @return true if the column should be included in testing
153         */
154        public  boolean isTestable(int column) {
155            return modelToView(column) >= 0;
156        }
157        
158    //----------------------- accessing the target's view state
159        
160        /**
161         * Returns the value of the cell identified by this adapter by invoking
162         * {@link #getValueAt(int, int)}, passing in the {@link #row} and
163         * {@link #column} values of this adapter. For target components that don't
164         * support multiple columns, the value of <code>column</code> is always zero.
165         *
166         * PENDING: needs clarification/cleanup - getValueAt(row, column) expects 
167         * model coordinates!.
168         * 
169         * @return the value of the cell identified by this adapter
170         */
171        public Object getValue() {
172            return getValueAt(row, column);
173        }
174    
175        /**
176         * returns the filtered value of the cell identified by the row
177         * in view coordinate and the column in model coordinates.
178         * 
179         * Note: the asymetry of the coordinates is intentional - clients like
180         * Highlighters are interested in view values but might need to access
181         * non-visible columns for testing.
182         * 
183         * @param row
184         * @param column
185         * @return the filtered value of the cell identified by the row
186         * in view coordinate and the column in model coordiantes
187         */
188        public abstract Object getFilteredValueAt(int row, int column);
189    
190        /**
191         * Returns true if the cell identified by this adapter currently has focus;
192         * Otherwise, it returns false.
193         *
194         * @return true if the cell identified by this adapter currently has focus;
195         *  Otherwise, return false
196         */
197        public abstract boolean hasFocus();
198    
199        /**
200         * Returns true if the cell identified by this adapter is currently selected;
201         * Otherwise, it returns false.
202         *
203         * @return true if the cell identified by this adapter is currently selected;
204         *  Otherwise, return false
205         */
206        public abstract boolean isSelected();
207    
208        /**
209         * Returns true if the cell identified by this adapter is currently expanded;
210         * Otherwise, it returns false. For components that do not support
211         * hierarchical data, this method always returns true because the cells in
212         * such components can never be collapsed.
213         *
214         * @return true if the cell identified by this adapter is currently expanded;
215         *  Otherwise, return false
216         */
217        public boolean isExpanded() {
218            return true; // sensible default for JList and JTable
219        }
220    
221        /**
222         * Returns true if the cell identified by this adapter is a leaf node;
223         * Otherwise, it returns false. For components that do not support
224         * hierarchical data, this method always returns true because the cells in
225         * such components can never have children.
226         *
227         * @return true if the cell identified by this adapter is a leaf node;
228         *  Otherwise, return false
229         */
230        public boolean isLeaf() {
231            return true; // sensible default for JList and JTable
232        }
233    
234        /**
235         * Returns true if the cell identified by this adapter displays the hierarchical node;
236         * Otherwise, it returns false. For components that do not support
237         * hierarchical data, this method always returns false because the cells in
238         * such components can never have children.
239         *
240         * @return true if the cell identified by this adapter displays the hierarchical node;
241         *  Otherwise, return false
242         */
243        public boolean isHierarchical() {
244            return false; // sensible default for JList and JTable
245        }
246    
247        /**
248         * For target components that support multiple columns in their model,
249         * along with column reordering in the view, this method transforms the
250         * specified columnIndex from model coordinates to view coordinates. For all
251         * other types of target components, this method returns the columnIndex
252         * unchanged.
253         *
254         * @param columnIndex index of a column in model coordinates
255         * @return index of the specified column in view coordinates
256         */
257        public int modelToView(int columnIndex) {
258            return columnIndex; // sensible default for JList and JTree
259        }
260    
261       /**
262         * For target components that support multiple columns in their model,
263         * along with column reordering in the view, this method transforms the
264         * specified columnIndex from view coordinates to model coordinates. For all
265         * other types of target components, this method returns the columnIndex
266         * unchanged.
267         *
268         * @param columnIndex index of a column in view coordinates
269         * @return index of the specified column in model coordinates
270         */
271        public int viewToModel(int columnIndex) {
272            return columnIndex; // sensible default for JList and JTree
273        }
274    
275        public void refresh() {
276            target.revalidate();
277            target.repaint();
278        }
279    }