View Javadoc

1   /***
2    * TransposableTableModel.java
3    *
4    * This file is part of the creme library.
5    * The creme library intends to ease the development effort of large
6    * applications by providing easy to use support classes.
7    *
8    * Copyright (C) 2003 Denis Bregeon
9    *
10   * This library is free software; you can redistribute it and/or
11   * modify it under the terms of the GNU Lesser General Public
12   * License as published by the Free Software Foundation; either
13   * version 2.1 of the License, or (at your option) any later version.
14   *
15   * This library is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   * Lesser General Public License for more details.
19   *
20   * You should have received a copy of the GNU Lesser General Public
21   * License along with this library; if not, write to the Free Software
22   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23   *
24   * contact information: dbregeon@sourceforge.net
25   */
26  package org.jcreme.swing.table;
27  
28  import java.util.Arrays;
29  
30  import javax.swing.table.AbstractTableModel;
31  import javax.swing.table.TableModel;
32  
33  /***
34   * This TableModel implementation enables to transpose another TableModel. It is
35   * to be used in conjunction with a JTransposableTable to ensure the cells are
36   * correctly rendered and edited.
37   * 
38   * @author $Author: dbregeon $
39   * @version $Revision: 1.1 $
40   */
41  public class TransposableTableModel extends AbstractTableModel {
42  
43      /***
44       * When this policy is used, the column names disappear in the
45       * transposition.
46       */
47      public static final int IGNORE_COLUMN_NAMES = 0;
48  
49      /***
50       * When this policy is used, the column names form the first column in the
51       * transposition.
52       */
53      public static final int USE_COLUMN_NAMES = 1;
54  
55      /***
56       * When this policy is used, the first row provides the column names in the
57       * transposition.
58       */
59      public static final int FIRST_ROW_COLUMN_NAMES = 0;
60  
61      /***
62       * When this policy is used, letters are used for column names in the
63       * transposition.
64       */
65      public static final int LETTERS_COLUMN_NAMES = 1;
66  
67      /***
68       * When this policy is used, numbers are used for column names in the
69       * transposition.
70       */
71      public static final int NUMBERS_COLUMN_NAMES = 2;
72  
73      /***
74       * An array of letters used to generate letter column names.
75       */
76      protected static final char[] LETTERS = new char[] { 'A', 'B', 'C', 'D',
77              'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
78              'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
79  
80      /***
81       * Signals the current status of the Model.
82       */
83      private boolean transpose = false;
84  
85      /***
86       * This variable controls whether column names are part of the transposition
87       * or not.
88       */
89      private int columnNamesPolicy = USE_COLUMN_NAMES;
90  
91      /***
92       * This variable controls what the columns names are in the transposition.
93       */
94      private int transposedColumnNamesPolicy = FIRST_ROW_COLUMN_NAMES;
95  
96      /***
97       * The TableModel transposed by this TransposableTableModel.
98       */
99      private TableModel underlyingModel = null;
100 
101     /***
102      * Enables to transpose or untranspose the underlyingModel.
103      * 
104      * @param b
105      *            true to transpose the underlyingModel. false otherwise.
106      */
107     public void setTranspose(boolean b) {
108         if (this.transpose != b) {
109             this.transpose = b;
110             fireTableStructureChanged();
111         }
112     }
113 
114     /***
115      * Gives access to the current status of the TransposableTableModel.
116      * 
117      * @return true if the underlyingModel is transposed. false otherwise.
118      */
119     public boolean getTranspose() {
120         return this.transpose;
121     }
122 
123     /***
124      * Enables to change the policy regarding the transposition of the column
125      * names.
126      * 
127      * @param policy
128      *            the new policy.
129      */
130     public void setColumnNamesPolicy(int policy) {
131         if ((policy == IGNORE_COLUMN_NAMES) || (policy == USE_COLUMN_NAMES)) {
132             this.columnNamesPolicy = policy;
133         }
134     }
135 
136     /***
137      * Gives access to the current column names' policy.
138      * 
139      * @return the current column names' policy.
140      */
141     public int getColumnNamesPolicy() {
142         return this.columnNamesPolicy;
143     }
144 
145     /***
146      * 
147      * @param policy
148      */
149     public void setTransposedColumnNamesPolicy(int policy) {
150         if ((policy == FIRST_ROW_COLUMN_NAMES)
151                 || (policy == LETTERS_COLUMN_NAMES)
152                 || (policy == NUMBERS_COLUMN_NAMES)) {
153             this.transposedColumnNamesPolicy = policy;
154         }
155     }
156 
157     /***
158      * 
159      * @return the policy to transpose column names.
160      */
161     public int getTransposedColumnNamesPolicy() {
162         return this.transposedColumnNamesPolicy;
163     }
164 
165     /***
166      * Enables to change the underlyingModel that is transposed by this
167      * TransposableTableModel.
168      * 
169      * @param model
170      *            the TableModel to transpose.
171      */
172     public void setUnderlyingModel(TableModel model) {
173         this.underlyingModel = model;
174         fireTableStructureChanged();
175     }
176 
177     /***
178      * Gives access to the TableModel that is transposed by this
179      * TransposableTableModel.
180      * 
181      * @return the transposed TableModel.
182      */
183     public TableModel getUnderlyingModel() {
184         return this.underlyingModel;
185     }
186 
187     /***
188      * @see javax.swing.table.TableModel#getRowCount()
189      */
190     public int getRowCount() {
191         int result = 0;
192         if (this.underlyingModel != null) {
193             if (this.transpose) {
194                 if (this.transposedColumnNamesPolicy == FIRST_ROW_COLUMN_NAMES) {
195                     result = this.underlyingModel.getColumnCount() - 1;
196                 } else {
197                     result = this.underlyingModel.getColumnCount();
198                 }
199             } else {
200                 result = this.underlyingModel.getRowCount();
201             }
202         }
203         return result;
204     }
205 
206     /***
207      * @see javax.swing.table.TableModel#getColumnCount()
208      */
209     public int getColumnCount() {
210         int result = 0;
211         if (this.underlyingModel != null) {
212             if (this.transpose) {
213                 result = this.underlyingModel.getRowCount() - 1
214                         + this.columnNamesPolicy;
215             } else {
216                 result = this.underlyingModel.getColumnCount();
217             }
218         }
219         return result;
220     }
221 
222     /***
223      * @see javax.swing.table.TableModel#getValueAt(int, int)
224      */
225     public Object getValueAt(int rowIndex, int columnIndex) {
226         Object result = null;
227         if (this.underlyingModel != null) {
228             if (this.transpose) {
229                 int offset = ((this.transposedColumnNamesPolicy == FIRST_ROW_COLUMN_NAMES) ? 1
230                         : 0);
231                 if (columnIndex < this.columnNamesPolicy) {
232                     result = this.underlyingModel.getColumnName(rowIndex
233                             + offset);
234                 } else {
235                     result = this.underlyingModel.getValueAt(columnIndex
236                             + this.columnNamesPolicy, rowIndex + offset);
237                 }
238             } else {
239                 result = this.underlyingModel.getValueAt(rowIndex, columnIndex);
240             }
241         }
242         return result;
243     }
244 
245     /***
246      * @see javax.swing.table.TableModel#getColumnClass(int)
247      */
248     public Class getColumnClass(int columnIndex) {
249         Class result = null;
250         if (this.transpose) {
251             result = TransposedValue.class;
252         } else {
253             if (this.underlyingModel != null) {
254                 result = this.underlyingModel.getColumnClass(columnIndex);
255             }
256         }
257         return result;
258     }
259 
260     /***
261      * @see javax.swing.table.TableModel#getColumnName(int)
262      */
263     public String getColumnName(int column) {
264         String result = null;
265         if (this.underlyingModel != null) {
266             if (this.transpose) {
267                 if (this.transposedColumnNamesPolicy == FIRST_ROW_COLUMN_NAMES) {
268                     if (column < this.columnNamesPolicy) {
269                         result = this.underlyingModel.getColumnName(column);
270                     } else {
271                         Object value = this.underlyingModel.getValueAt(column
272                                 - this.columnNamesPolicy, 0);
273                         if (value != null) {
274                             result = value.toString();
275                         }
276                     }
277                 } else if (this.transposedColumnNamesPolicy == LETTERS_COLUMN_NAMES) {
278                     result = getColumnLetters(column);
279                 } else if (this.transposedColumnNamesPolicy == NUMBERS_COLUMN_NAMES) {
280                     result = Integer.toString(column + 1);
281                 }
282             } else {
283                 result = this.underlyingModel.getColumnName(column);
284             }
285         }
286         return result;
287     }
288 
289     /***
290      * @see javax.swing.table.TableModel#isCellEditable(int, int)
291      */
292     public boolean isCellEditable(int rowIndex, int columnIndex) {
293         boolean result = false;
294         if (this.underlyingModel != null) {
295             if (this.transpose) {
296                 int offset = ((this.transposedColumnNamesPolicy == FIRST_ROW_COLUMN_NAMES) ? 1
297                         : 0);
298                 if (columnIndex >= this.columnNamesPolicy) {
299                     result = this.underlyingModel.isCellEditable(columnIndex
300                             + this.columnNamesPolicy, rowIndex + offset);
301                 }
302             } else {
303                 result = this.underlyingModel.isCellEditable(rowIndex,
304                         columnIndex);
305             }
306         }
307         return result;
308     }
309 
310     /***
311      * @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int)
312      */
313     public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
314         if (this.underlyingModel != null) {
315             int offset = ((this.transposedColumnNamesPolicy == FIRST_ROW_COLUMN_NAMES) ? 1
316                     : 0);
317             if (this.transpose) {
318                 if (columnIndex >= this.columnNamesPolicy) {
319                     this.underlyingModel.setValueAt(aValue, columnIndex
320                             + this.columnNamesPolicy, rowIndex + offset);
321                 }
322             } else {
323                 this.underlyingModel.setValueAt(aValue, rowIndex, columnIndex);
324             }
325         }
326     }
327 
328     protected String getColumnLetters(int column) {
329         char[] letters = new char[column / LETTERS.length + 1];
330         Arrays.fill(letters, LETTERS[column % LETTERS.length]);
331         return new String(letters);
332     }
333 
334     /***
335      * A Place holder class to enable to define special renderers in the
336      * transposed tables.
337      * 
338      * @author $Author: dbregeon $
339      * @version $Revision: 1.1 $
340      */
341     public static interface TransposedValue {
342         // Place Holder.
343     }
344 }