author | ant |
Fri, 31 Jan 2014 18:49:58 +0400 | |
changeset 23280 | df31f522531f |
parent 22574 | 7f8ce0c8c20a |
child 23295 | 6c61adf6111e |
permissions | -rw-r--r-- |
2 | 1 |
/* |
22574
7f8ce0c8c20a
8032627: Add @SuppressWarnings("serial") to appropriate javax.swing classes
darcy
parents:
21982
diff
changeset
|
2 |
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package javax.swing; |
|
27 |
||
28 |
import java.util.*; |
|
29 |
||
30 |
import java.applet.Applet; |
|
31 |
import java.awt.*; |
|
32 |
import java.awt.event.*; |
|
33 |
import java.awt.print.*; |
|
34 |
||
35 |
import java.beans.*; |
|
36 |
||
37 |
import java.io.Serializable; |
|
38 |
import java.io.ObjectOutputStream; |
|
39 |
import java.io.ObjectInputStream; |
|
40 |
import java.io.IOException; |
|
41 |
||
42 |
import javax.accessibility.*; |
|
43 |
||
44 |
import javax.swing.event.*; |
|
45 |
import javax.swing.plaf.*; |
|
46 |
import javax.swing.table.*; |
|
47 |
import javax.swing.border.*; |
|
48 |
||
49 |
import java.text.NumberFormat; |
|
50 |
import java.text.DateFormat; |
|
51 |
import java.text.MessageFormat; |
|
52 |
||
53 |
import javax.print.attribute.*; |
|
54 |
import javax.print.PrintService; |
|
20800 | 55 |
import sun.reflect.misc.ReflectUtil; |
2 | 56 |
|
57 |
import sun.swing.SwingUtilities2; |
|
58 |
import sun.swing.SwingUtilities2.Section; |
|
59 |
import static sun.swing.SwingUtilities2.Section.*; |
|
60 |
import sun.swing.PrintingStatus; |
|
4272
f4742294ef29
6795356: Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc
alexp
parents:
3737
diff
changeset
|
61 |
import sun.swing.SwingLazyValue; |
2 | 62 |
|
63 |
/** |
|
64 |
* The <code>JTable</code> is used to display and edit regular two-dimensional tables |
|
65 |
* of cells. |
|
20455
f6f9a0c2796b
8020688: Broken links in documentation at http://docs.oracle.com/javase/6/docs/api/index.
mcherkas
parents:
20157
diff
changeset
|
66 |
* See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/table.html">How to Use Tables</a> |
2 | 67 |
* in <em>The Java Tutorial</em> |
68 |
* for task-oriented documentation and examples of using <code>JTable</code>. |
|
69 |
* |
|
70 |
* <p> |
|
71 |
* The <code>JTable</code> has many |
|
72 |
* facilities that make it possible to customize its rendering and editing |
|
73 |
* but provides defaults for these features so that simple tables can be |
|
74 |
* set up easily. For example, to set up a table with 10 rows and 10 |
|
75 |
* columns of numbers: |
|
21982 | 76 |
* |
2 | 77 |
* <pre> |
78 |
* TableModel dataModel = new AbstractTableModel() { |
|
79 |
* public int getColumnCount() { return 10; } |
|
80 |
* public int getRowCount() { return 10;} |
|
81 |
* public Object getValueAt(int row, int col) { return new Integer(row*col); } |
|
82 |
* }; |
|
83 |
* JTable table = new JTable(dataModel); |
|
84 |
* JScrollPane scrollpane = new JScrollPane(table); |
|
85 |
* </pre> |
|
86 |
* <p> |
|
87 |
* {@code JTable}s are typically placed inside of a {@code JScrollPane}. By |
|
88 |
* default, a {@code JTable} will adjust its width such that |
|
89 |
* a horizontal scrollbar is unnecessary. To allow for a horizontal scrollbar, |
|
90 |
* invoke {@link #setAutoResizeMode} with {@code AUTO_RESIZE_OFF}. |
|
91 |
* Note that if you wish to use a <code>JTable</code> in a standalone |
|
92 |
* view (outside of a <code>JScrollPane</code>) and want the header |
|
93 |
* displayed, you can get it using {@link #getTableHeader} and |
|
94 |
* display it separately. |
|
95 |
* <p> |
|
96 |
* To enable sorting and filtering of rows, use a |
|
97 |
* {@code RowSorter}. |
|
98 |
* You can set up a row sorter in either of two ways: |
|
99 |
* <ul> |
|
100 |
* <li>Directly set the {@code RowSorter}. For example: |
|
101 |
* {@code table.setRowSorter(new TableRowSorter(model))}. |
|
102 |
* <li>Set the {@code autoCreateRowSorter} |
|
103 |
* property to {@code true}, so that the {@code JTable} |
|
104 |
* creates a {@code RowSorter} for |
|
105 |
* you. For example: {@code setAutoCreateRowSorter(true)}. |
|
106 |
* </ul> |
|
107 |
* <p> |
|
108 |
* When designing applications that use the <code>JTable</code> it is worth paying |
|
109 |
* close attention to the data structures that will represent the table's data. |
|
110 |
* The <code>DefaultTableModel</code> is a model implementation that |
|
111 |
* uses a <code>Vector</code> of <code>Vector</code>s of <code>Object</code>s to |
|
112 |
* store the cell values. As well as copying the data from an |
|
113 |
* application into the <code>DefaultTableModel</code>, |
|
114 |
* it is also possible to wrap the data in the methods of the |
|
115 |
* <code>TableModel</code> interface so that the data can be passed to the |
|
116 |
* <code>JTable</code> directly, as in the example above. This often results |
|
117 |
* in more efficient applications because the model is free to choose the |
|
118 |
* internal representation that best suits the data. |
|
119 |
* A good rule of thumb for deciding whether to use the <code>AbstractTableModel</code> |
|
120 |
* or the <code>DefaultTableModel</code> is to use the <code>AbstractTableModel</code> |
|
121 |
* as the base class for creating subclasses and the <code>DefaultTableModel</code> |
|
122 |
* when subclassing is not required. |
|
123 |
* <p> |
|
124 |
* The "TableExample" directory in the demo area of the source distribution |
|
125 |
* gives a number of complete examples of <code>JTable</code> usage, |
|
126 |
* covering how the <code>JTable</code> can be used to provide an |
|
127 |
* editable view of data taken from a database and how to modify |
|
128 |
* the columns in the display to use specialized renderers and editors. |
|
129 |
* <p> |
|
130 |
* The <code>JTable</code> uses integers exclusively to refer to both the rows and the columns |
|
131 |
* of the model that it displays. The <code>JTable</code> simply takes a tabular range of cells |
|
132 |
* and uses <code>getValueAt(int, int)</code> to retrieve the |
|
133 |
* values from the model during painting. It is important to remember that |
|
134 |
* the column and row indexes returned by various <code>JTable</code> methods |
|
135 |
* are in terms of the <code>JTable</code> (the view) and are not |
|
136 |
* necessarily the same indexes used by the model. |
|
137 |
* <p> |
|
138 |
* By default, columns may be rearranged in the <code>JTable</code> so that the |
|
139 |
* view's columns appear in a different order to the columns in the model. |
|
140 |
* This does not affect the implementation of the model at all: when the |
|
141 |
* columns are reordered, the <code>JTable</code> maintains the new order of the columns |
|
142 |
* internally and converts its column indices before querying the model. |
|
143 |
* <p> |
|
144 |
* So, when writing a <code>TableModel</code>, it is not necessary to listen for column |
|
145 |
* reordering events as the model will be queried in its own coordinate |
|
146 |
* system regardless of what is happening in the view. |
|
147 |
* In the examples area there is a demonstration of a sorting algorithm making |
|
148 |
* use of exactly this technique to interpose yet another coordinate system |
|
149 |
* where the order of the rows is changed, rather than the order of the columns. |
|
150 |
* <p> |
|
151 |
* Similarly when using the sorting and filtering functionality |
|
152 |
* provided by <code>RowSorter</code> the underlying |
|
153 |
* <code>TableModel</code> does not need to know how to do sorting, |
|
154 |
* rather <code>RowSorter</code> will handle it. Coordinate |
|
155 |
* conversions will be necessary when using the row based methods of |
|
156 |
* <code>JTable</code> with the underlying <code>TableModel</code>. |
|
157 |
* All of <code>JTable</code>s row based methods are in terms of the |
|
158 |
* <code>RowSorter</code>, which is not necessarily the same as that |
|
159 |
* of the underlying <code>TableModel</code>. For example, the |
|
160 |
* selection is always in terms of <code>JTable</code> so that when |
|
161 |
* using <code>RowSorter</code> you will need to convert using |
|
162 |
* <code>convertRowIndexToView</code> or |
|
163 |
* <code>convertRowIndexToModel</code>. The following shows how to |
|
164 |
* convert coordinates from <code>JTable</code> to that of the |
|
165 |
* underlying model: |
|
166 |
* <pre> |
|
167 |
* int[] selection = table.getSelectedRows(); |
|
168 |
* for (int i = 0; i < selection.length; i++) { |
|
169 |
* selection[i] = table.convertRowIndexToModel(selection[i]); |
|
170 |
* } |
|
171 |
* // selection is now in terms of the underlying TableModel |
|
172 |
* </pre> |
|
173 |
* <p> |
|
174 |
* By default if sorting is enabled <code>JTable</code> will persist the |
|
175 |
* selection and variable row heights in terms of the model on |
|
176 |
* sorting. For example if row 0, in terms of the underlying model, |
|
177 |
* is currently selected, after the sort row 0, in terms of the |
|
178 |
* underlying model will be selected. Visually the selection may |
|
179 |
* change, but in terms of the underlying model it will remain the |
|
180 |
* same. The one exception to that is if the model index is no longer |
|
181 |
* visible or was removed. For example, if row 0 in terms of model |
|
182 |
* was filtered out the selection will be empty after the sort. |
|
183 |
* <p> |
|
184 |
* J2SE 5 adds methods to <code>JTable</code> to provide convenient access to some |
|
185 |
* common printing needs. Simple new {@link #print()} methods allow for quick |
|
186 |
* and easy addition of printing support to your application. In addition, a new |
|
187 |
* {@link #getPrintable} method is available for more advanced printing needs. |
|
188 |
* <p> |
|
189 |
* As for all <code>JComponent</code> classes, you can use |
|
190 |
* {@link InputMap} and {@link ActionMap} to associate an |
|
191 |
* {@link Action} object with a {@link KeyStroke} and execute the |
|
192 |
* action under specified conditions. |
|
193 |
* <p> |
|
194 |
* <strong>Warning:</strong> Swing is not thread safe. For more |
|
195 |
* information see <a |
|
196 |
* href="package-summary.html#threading">Swing's Threading |
|
197 |
* Policy</a>. |
|
198 |
* <p> |
|
199 |
* <strong>Warning:</strong> |
|
200 |
* Serialized objects of this class will not be compatible with |
|
201 |
* future Swing releases. The current serialization support is |
|
202 |
* appropriate for short term storage or RMI between applications running |
|
203 |
* the same version of Swing. As of 1.4, support for long term storage |
|
20458 | 204 |
* of all JavaBeans™ |
2 | 205 |
* has been added to the <code>java.beans</code> package. |
206 |
* Please see {@link java.beans.XMLEncoder}. |
|
207 |
* |
|
208 |
* |
|
209 |
* @beaninfo |
|
210 |
* attribute: isContainer false |
|
211 |
* description: A component which displays data in a two dimensional grid. |
|
212 |
* |
|
213 |
* @author Philip Milne |
|
214 |
* @author Shannon Hickey (printing support) |
|
215 |
* @see javax.swing.table.DefaultTableModel |
|
216 |
* @see javax.swing.table.TableRowSorter |
|
217 |
*/ |
|
218 |
/* The first versions of the JTable, contained in Swing-0.1 through |
|
219 |
* Swing-0.4, were written by Alan Chung. |
|
220 |
*/ |
|
22574
7f8ce0c8c20a
8032627: Add @SuppressWarnings("serial") to appropriate javax.swing classes
darcy
parents:
21982
diff
changeset
|
221 |
@SuppressWarnings("serial") // Same-version serialization only |
2 | 222 |
public class JTable extends JComponent implements TableModelListener, Scrollable, |
223 |
TableColumnModelListener, ListSelectionListener, CellEditorListener, |
|
224 |
Accessible, RowSorterListener |
|
225 |
{ |
|
226 |
// |
|
227 |
// Static Constants |
|
228 |
// |
|
229 |
||
230 |
/** |
|
231 |
* @see #getUIClassID |
|
232 |
* @see #readObject |
|
233 |
*/ |
|
234 |
private static final String uiClassID = "TableUI"; |
|
235 |
||
236 |
/** Do not adjust column widths automatically; use a horizontal scrollbar instead. */ |
|
237 |
public static final int AUTO_RESIZE_OFF = 0; |
|
238 |
||
239 |
/** When a column is adjusted in the UI, adjust the next column the opposite way. */ |
|
240 |
public static final int AUTO_RESIZE_NEXT_COLUMN = 1; |
|
241 |
||
242 |
/** During UI adjustment, change subsequent columns to preserve the total width; |
|
243 |
* this is the default behavior. */ |
|
244 |
public static final int AUTO_RESIZE_SUBSEQUENT_COLUMNS = 2; |
|
245 |
||
246 |
/** During all resize operations, apply adjustments to the last column only. */ |
|
247 |
public static final int AUTO_RESIZE_LAST_COLUMN = 3; |
|
248 |
||
249 |
/** During all resize operations, proportionately resize all columns. */ |
|
250 |
public static final int AUTO_RESIZE_ALL_COLUMNS = 4; |
|
251 |
||
252 |
||
253 |
/** |
|
254 |
* Printing modes, used in printing <code>JTable</code>s. |
|
255 |
* |
|
256 |
* @see #print(JTable.PrintMode, MessageFormat, MessageFormat, |
|
257 |
* boolean, PrintRequestAttributeSet, boolean) |
|
258 |
* @see #getPrintable |
|
259 |
* @since 1.5 |
|
260 |
*/ |
|
261 |
public enum PrintMode { |
|
262 |
||
263 |
/** |
|
264 |
* Printing mode that prints the table at its current size, |
|
265 |
* spreading both columns and rows across multiple pages if necessary. |
|
266 |
*/ |
|
267 |
NORMAL, |
|
268 |
||
269 |
/** |
|
270 |
* Printing mode that scales the output smaller, if necessary, |
|
271 |
* to fit the table's entire width (and thereby all columns) on each page; |
|
272 |
* Rows are spread across multiple pages as necessary. |
|
273 |
*/ |
|
274 |
FIT_WIDTH |
|
275 |
} |
|
276 |
||
277 |
||
278 |
// |
|
279 |
// Instance Variables |
|
280 |
// |
|
281 |
||
282 |
/** The <code>TableModel</code> of the table. */ |
|
283 |
protected TableModel dataModel; |
|
284 |
||
285 |
/** The <code>TableColumnModel</code> of the table. */ |
|
286 |
protected TableColumnModel columnModel; |
|
287 |
||
288 |
/** The <code>ListSelectionModel</code> of the table, used to keep track of row selections. */ |
|
289 |
protected ListSelectionModel selectionModel; |
|
290 |
||
291 |
/** The <code>TableHeader</code> working with the table. */ |
|
292 |
protected JTableHeader tableHeader; |
|
293 |
||
294 |
/** The height in pixels of each row in the table. */ |
|
295 |
protected int rowHeight; |
|
296 |
||
297 |
/** The height in pixels of the margin between the cells in each row. */ |
|
298 |
protected int rowMargin; |
|
299 |
||
300 |
/** The color of the grid. */ |
|
301 |
protected Color gridColor; |
|
302 |
||
303 |
/** The table draws horizontal lines between cells if <code>showHorizontalLines</code> is true. */ |
|
304 |
protected boolean showHorizontalLines; |
|
305 |
||
306 |
/** The table draws vertical lines between cells if <code>showVerticalLines</code> is true. */ |
|
307 |
protected boolean showVerticalLines; |
|
308 |
||
309 |
/** |
|
310 |
* Determines if the table automatically resizes the |
|
311 |
* width of the table's columns to take up the entire width of the |
|
312 |
* table, and how it does the resizing. |
|
313 |
*/ |
|
314 |
protected int autoResizeMode; |
|
315 |
||
316 |
/** |
|
317 |
* The table will query the <code>TableModel</code> to build the default |
|
318 |
* set of columns if this is true. |
|
319 |
*/ |
|
320 |
protected boolean autoCreateColumnsFromModel; |
|
321 |
||
322 |
/** Used by the <code>Scrollable</code> interface to determine the initial visible area. */ |
|
323 |
protected Dimension preferredViewportSize; |
|
324 |
||
325 |
/** True if row selection is allowed in this table. */ |
|
326 |
protected boolean rowSelectionAllowed; |
|
327 |
||
328 |
/** |
|
329 |
* Obsolete as of Java 2 platform v1.3. Please use the |
|
330 |
* <code>rowSelectionAllowed</code> property and the |
|
331 |
* <code>columnSelectionAllowed</code> property of the |
|
332 |
* <code>columnModel</code> instead. Or use the |
|
333 |
* method <code>getCellSelectionEnabled</code>. |
|
334 |
*/ |
|
335 |
/* |
|
336 |
* If true, both a row selection and a column selection |
|
337 |
* can be non-empty at the same time, the selected cells are the |
|
338 |
* the cells whose row and column are both selected. |
|
339 |
*/ |
|
340 |
protected boolean cellSelectionEnabled; |
|
341 |
||
342 |
/** If editing, the <code>Component</code> that is handling the editing. */ |
|
343 |
transient protected Component editorComp; |
|
344 |
||
345 |
/** |
|
346 |
* The active cell editor object, that overwrites the screen real estate |
|
347 |
* occupied by the current cell and allows the user to change its contents. |
|
348 |
* {@code null} if the table isn't currently editing. |
|
349 |
*/ |
|
350 |
transient protected TableCellEditor cellEditor; |
|
351 |
||
352 |
/** Identifies the column of the cell being edited. */ |
|
353 |
transient protected int editingColumn; |
|
354 |
||
355 |
/** Identifies the row of the cell being edited. */ |
|
356 |
transient protected int editingRow; |
|
357 |
||
358 |
/** |
|
359 |
* A table of objects that display the contents of a cell, |
|
360 |
* indexed by class as declared in <code>getColumnClass</code> |
|
361 |
* in the <code>TableModel</code> interface. |
|
362 |
*/ |
|
363 |
transient protected Hashtable defaultRenderersByColumnClass; |
|
364 |
||
365 |
/** |
|
366 |
* A table of objects that display and edit the contents of a cell, |
|
367 |
* indexed by class as declared in <code>getColumnClass</code> |
|
368 |
* in the <code>TableModel</code> interface. |
|
369 |
*/ |
|
370 |
transient protected Hashtable defaultEditorsByColumnClass; |
|
371 |
||
372 |
/** The foreground color of selected cells. */ |
|
373 |
protected Color selectionForeground; |
|
374 |
||
375 |
/** The background color of selected cells. */ |
|
376 |
protected Color selectionBackground; |
|
377 |
||
378 |
// |
|
379 |
// Private state |
|
380 |
// |
|
381 |
||
382 |
// WARNING: If you directly access this field you should also change the |
|
383 |
// SortManager.modelRowSizes field as well. |
|
384 |
private SizeSequence rowModel; |
|
385 |
private boolean dragEnabled; |
|
386 |
private boolean surrendersFocusOnKeystroke; |
|
387 |
private PropertyChangeListener editorRemover = null; |
|
388 |
/** |
|
389 |
* The last value of getValueIsAdjusting from the column selection models |
|
390 |
* columnSelectionChanged notification. Used to test if a repaint is |
|
391 |
* needed. |
|
392 |
*/ |
|
393 |
private boolean columnSelectionAdjusting; |
|
394 |
/** |
|
395 |
* The last value of getValueIsAdjusting from the row selection models |
|
396 |
* valueChanged notification. Used to test if a repaint is needed. |
|
397 |
*/ |
|
398 |
private boolean rowSelectionAdjusting; |
|
399 |
||
400 |
/** |
|
401 |
* To communicate errors between threads during printing. |
|
402 |
*/ |
|
403 |
private Throwable printError; |
|
404 |
||
405 |
/** |
|
406 |
* True when setRowHeight(int) has been invoked. |
|
407 |
*/ |
|
408 |
private boolean isRowHeightSet; |
|
409 |
||
410 |
/** |
|
411 |
* If true, on a sort the selection is reset. |
|
412 |
*/ |
|
413 |
private boolean updateSelectionOnSort; |
|
414 |
||
415 |
/** |
|
416 |
* Information used in sorting. |
|
417 |
*/ |
|
418 |
private transient SortManager sortManager; |
|
419 |
||
420 |
/** |
|
421 |
* If true, when sorterChanged is invoked it's value is ignored. |
|
422 |
*/ |
|
423 |
private boolean ignoreSortChange; |
|
424 |
||
425 |
/** |
|
426 |
* Whether or not sorterChanged has been invoked. |
|
427 |
*/ |
|
428 |
private boolean sorterChanged; |
|
429 |
||
430 |
/** |
|
431 |
* If true, any time the model changes a new RowSorter is set. |
|
432 |
*/ |
|
433 |
private boolean autoCreateRowSorter; |
|
434 |
||
435 |
/** |
|
436 |
* Whether or not the table always fills the viewport height. |
|
437 |
* @see #setFillsViewportHeight |
|
438 |
* @see #getScrollableTracksViewportHeight |
|
439 |
*/ |
|
440 |
private boolean fillsViewportHeight; |
|
441 |
||
442 |
/** |
|
443 |
* The drop mode for this component. |
|
444 |
*/ |
|
445 |
private DropMode dropMode = DropMode.USE_SELECTION; |
|
446 |
||
447 |
/** |
|
448 |
* The drop location. |
|
449 |
*/ |
|
450 |
private transient DropLocation dropLocation; |
|
451 |
||
452 |
/** |
|
453 |
* A subclass of <code>TransferHandler.DropLocation</code> representing |
|
454 |
* a drop location for a <code>JTable</code>. |
|
455 |
* |
|
456 |
* @see #getDropLocation |
|
457 |
* @since 1.6 |
|
458 |
*/ |
|
459 |
public static final class DropLocation extends TransferHandler.DropLocation { |
|
460 |
private final int row; |
|
461 |
private final int col; |
|
462 |
private final boolean isInsertRow; |
|
463 |
private final boolean isInsertCol; |
|
464 |
||
465 |
private DropLocation(Point p, int row, int col, |
|
466 |
boolean isInsertRow, boolean isInsertCol) { |
|
467 |
||
468 |
super(p); |
|
469 |
this.row = row; |
|
470 |
this.col = col; |
|
471 |
this.isInsertRow = isInsertRow; |
|
472 |
this.isInsertCol = isInsertCol; |
|
473 |
} |
|
474 |
||
475 |
/** |
|
476 |
* Returns the row index where a dropped item should be placed in the |
|
477 |
* table. Interpretation of the value depends on the return of |
|
478 |
* <code>isInsertRow()</code>. If that method returns |
|
479 |
* <code>true</code> this value indicates the index where a new |
|
480 |
* row should be inserted. Otherwise, it represents the value |
|
481 |
* of an existing row on which the data was dropped. This index is |
|
482 |
* in terms of the view. |
|
483 |
* <p> |
|
484 |
* <code>-1</code> indicates that the drop occurred over empty space, |
|
485 |
* and no row could be calculated. |
|
486 |
* |
|
487 |
* @return the drop row |
|
488 |
*/ |
|
489 |
public int getRow() { |
|
490 |
return row; |
|
491 |
} |
|
492 |
||
493 |
/** |
|
494 |
* Returns the column index where a dropped item should be placed in the |
|
495 |
* table. Interpretation of the value depends on the return of |
|
496 |
* <code>isInsertColumn()</code>. If that method returns |
|
497 |
* <code>true</code> this value indicates the index where a new |
|
498 |
* column should be inserted. Otherwise, it represents the value |
|
499 |
* of an existing column on which the data was dropped. This index is |
|
500 |
* in terms of the view. |
|
501 |
* <p> |
|
502 |
* <code>-1</code> indicates that the drop occurred over empty space, |
|
503 |
* and no column could be calculated. |
|
504 |
* |
|
505 |
* @return the drop row |
|
506 |
*/ |
|
507 |
public int getColumn() { |
|
508 |
return col; |
|
509 |
} |
|
510 |
||
511 |
/** |
|
512 |
* Returns whether or not this location represents an insert |
|
513 |
* of a row. |
|
514 |
* |
|
515 |
* @return whether or not this is an insert row |
|
516 |
*/ |
|
517 |
public boolean isInsertRow() { |
|
518 |
return isInsertRow; |
|
519 |
} |
|
520 |
||
521 |
/** |
|
522 |
* Returns whether or not this location represents an insert |
|
523 |
* of a column. |
|
524 |
* |
|
525 |
* @return whether or not this is an insert column |
|
526 |
*/ |
|
527 |
public boolean isInsertColumn() { |
|
528 |
return isInsertCol; |
|
529 |
} |
|
530 |
||
531 |
/** |
|
532 |
* Returns a string representation of this drop location. |
|
533 |
* This method is intended to be used for debugging purposes, |
|
534 |
* and the content and format of the returned string may vary |
|
535 |
* between implementations. |
|
536 |
* |
|
537 |
* @return a string representation of this drop location |
|
538 |
*/ |
|
539 |
public String toString() { |
|
540 |
return getClass().getName() |
|
541 |
+ "[dropPoint=" + getDropPoint() + "," |
|
542 |
+ "row=" + row + "," |
|
543 |
+ "column=" + col + "," |
|
544 |
+ "insertRow=" + isInsertRow + "," |
|
545 |
+ "insertColumn=" + isInsertCol + "]"; |
|
546 |
} |
|
547 |
} |
|
548 |
||
549 |
// |
|
550 |
// Constructors |
|
551 |
// |
|
552 |
||
553 |
/** |
|
554 |
* Constructs a default <code>JTable</code> that is initialized with a default |
|
555 |
* data model, a default column model, and a default selection |
|
556 |
* model. |
|
557 |
* |
|
558 |
* @see #createDefaultDataModel |
|
559 |
* @see #createDefaultColumnModel |
|
560 |
* @see #createDefaultSelectionModel |
|
561 |
*/ |
|
562 |
public JTable() { |
|
563 |
this(null, null, null); |
|
564 |
} |
|
565 |
||
566 |
/** |
|
567 |
* Constructs a <code>JTable</code> that is initialized with |
|
568 |
* <code>dm</code> as the data model, a default column model, |
|
569 |
* and a default selection model. |
|
570 |
* |
|
571 |
* @param dm the data model for the table |
|
572 |
* @see #createDefaultColumnModel |
|
573 |
* @see #createDefaultSelectionModel |
|
574 |
*/ |
|
575 |
public JTable(TableModel dm) { |
|
576 |
this(dm, null, null); |
|
577 |
} |
|
578 |
||
579 |
/** |
|
580 |
* Constructs a <code>JTable</code> that is initialized with |
|
581 |
* <code>dm</code> as the data model, <code>cm</code> |
|
582 |
* as the column model, and a default selection model. |
|
583 |
* |
|
584 |
* @param dm the data model for the table |
|
585 |
* @param cm the column model for the table |
|
586 |
* @see #createDefaultSelectionModel |
|
587 |
*/ |
|
588 |
public JTable(TableModel dm, TableColumnModel cm) { |
|
589 |
this(dm, cm, null); |
|
590 |
} |
|
591 |
||
592 |
/** |
|
593 |
* Constructs a <code>JTable</code> that is initialized with |
|
594 |
* <code>dm</code> as the data model, <code>cm</code> as the |
|
595 |
* column model, and <code>sm</code> as the selection model. |
|
596 |
* If any of the parameters are <code>null</code> this method |
|
597 |
* will initialize the table with the corresponding default model. |
|
598 |
* The <code>autoCreateColumnsFromModel</code> flag is set to false |
|
599 |
* if <code>cm</code> is non-null, otherwise it is set to true |
|
600 |
* and the column model is populated with suitable |
|
601 |
* <code>TableColumns</code> for the columns in <code>dm</code>. |
|
602 |
* |
|
603 |
* @param dm the data model for the table |
|
604 |
* @param cm the column model for the table |
|
605 |
* @param sm the row selection model for the table |
|
606 |
* @see #createDefaultDataModel |
|
607 |
* @see #createDefaultColumnModel |
|
608 |
* @see #createDefaultSelectionModel |
|
609 |
*/ |
|
610 |
public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) { |
|
611 |
super(); |
|
612 |
setLayout(null); |
|
613 |
||
614 |
setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, |
|
615 |
JComponent.getManagingFocusForwardTraversalKeys()); |
|
616 |
setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, |
|
617 |
JComponent.getManagingFocusBackwardTraversalKeys()); |
|
618 |
if (cm == null) { |
|
619 |
cm = createDefaultColumnModel(); |
|
620 |
autoCreateColumnsFromModel = true; |
|
621 |
} |
|
622 |
setColumnModel(cm); |
|
623 |
||
624 |
if (sm == null) { |
|
625 |
sm = createDefaultSelectionModel(); |
|
626 |
} |
|
627 |
setSelectionModel(sm); |
|
628 |
||
629 |
// Set the model last, that way if the autoCreatColumnsFromModel has |
|
630 |
// been set above, we will automatically populate an empty columnModel |
|
631 |
// with suitable columns for the new model. |
|
632 |
if (dm == null) { |
|
633 |
dm = createDefaultDataModel(); |
|
634 |
} |
|
635 |
setModel(dm); |
|
636 |
||
637 |
initializeLocalVars(); |
|
638 |
updateUI(); |
|
639 |
} |
|
640 |
||
641 |
/** |
|
642 |
* Constructs a <code>JTable</code> with <code>numRows</code> |
|
643 |
* and <code>numColumns</code> of empty cells using |
|
644 |
* <code>DefaultTableModel</code>. The columns will have |
|
645 |
* names of the form "A", "B", "C", etc. |
|
646 |
* |
|
647 |
* @param numRows the number of rows the table holds |
|
648 |
* @param numColumns the number of columns the table holds |
|
649 |
* @see javax.swing.table.DefaultTableModel |
|
650 |
*/ |
|
651 |
public JTable(int numRows, int numColumns) { |
|
652 |
this(new DefaultTableModel(numRows, numColumns)); |
|
653 |
} |
|
654 |
||
655 |
/** |
|
656 |
* Constructs a <code>JTable</code> to display the values in the |
|
657 |
* <code>Vector</code> of <code>Vectors</code>, <code>rowData</code>, |
|
658 |
* with column names, <code>columnNames</code>. The |
|
659 |
* <code>Vectors</code> contained in <code>rowData</code> |
|
660 |
* should contain the values for that row. In other words, |
|
661 |
* the value of the cell at row 1, column 5 can be obtained |
|
662 |
* with the following code: |
|
21982 | 663 |
* |
2 | 664 |
* <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre> |
665 |
* <p> |
|
666 |
* @param rowData the data for the new table |
|
667 |
* @param columnNames names of each column |
|
668 |
*/ |
|
669 |
public JTable(Vector rowData, Vector columnNames) { |
|
670 |
this(new DefaultTableModel(rowData, columnNames)); |
|
671 |
} |
|
672 |
||
673 |
/** |
|
674 |
* Constructs a <code>JTable</code> to display the values in the two dimensional array, |
|
675 |
* <code>rowData</code>, with column names, <code>columnNames</code>. |
|
676 |
* <code>rowData</code> is an array of rows, so the value of the cell at row 1, |
|
677 |
* column 5 can be obtained with the following code: |
|
21982 | 678 |
* |
2 | 679 |
* <pre> rowData[1][5]; </pre> |
680 |
* <p> |
|
681 |
* All rows must be of the same length as <code>columnNames</code>. |
|
682 |
* <p> |
|
683 |
* @param rowData the data for the new table |
|
684 |
* @param columnNames names of each column |
|
685 |
*/ |
|
686 |
public JTable(final Object[][] rowData, final Object[] columnNames) { |
|
687 |
this(new AbstractTableModel() { |
|
688 |
public String getColumnName(int column) { return columnNames[column].toString(); } |
|
689 |
public int getRowCount() { return rowData.length; } |
|
690 |
public int getColumnCount() { return columnNames.length; } |
|
691 |
public Object getValueAt(int row, int col) { return rowData[row][col]; } |
|
692 |
public boolean isCellEditable(int row, int column) { return true; } |
|
693 |
public void setValueAt(Object value, int row, int col) { |
|
694 |
rowData[row][col] = value; |
|
695 |
fireTableCellUpdated(row, col); |
|
696 |
} |
|
697 |
}); |
|
698 |
} |
|
699 |
||
700 |
/** |
|
701 |
* Calls the <code>configureEnclosingScrollPane</code> method. |
|
702 |
* |
|
703 |
* @see #configureEnclosingScrollPane |
|
704 |
*/ |
|
705 |
public void addNotify() { |
|
706 |
super.addNotify(); |
|
707 |
configureEnclosingScrollPane(); |
|
708 |
} |
|
709 |
||
710 |
/** |
|
711 |
* If this <code>JTable</code> is the <code>viewportView</code> of an enclosing <code>JScrollPane</code> |
|
712 |
* (the usual situation), configure this <code>ScrollPane</code> by, amongst other things, |
|
713 |
* installing the table's <code>tableHeader</code> as the <code>columnHeaderView</code> of the scroll pane. |
|
714 |
* When a <code>JTable</code> is added to a <code>JScrollPane</code> in the usual way, |
|
715 |
* using <code>new JScrollPane(myTable)</code>, <code>addNotify</code> is |
|
716 |
* called in the <code>JTable</code> (when the table is added to the viewport). |
|
717 |
* <code>JTable</code>'s <code>addNotify</code> method in turn calls this method, |
|
718 |
* which is protected so that this default installation procedure can |
|
719 |
* be overridden by a subclass. |
|
720 |
* |
|
721 |
* @see #addNotify |
|
722 |
*/ |
|
723 |
protected void configureEnclosingScrollPane() { |
|
5449 | 724 |
Container parent = SwingUtilities.getUnwrappedParent(this); |
725 |
if (parent instanceof JViewport) { |
|
726 |
JViewport port = (JViewport) parent; |
|
3737
83fb4621a129
6824395: Several Swing core components prevent using them in wrapper classes
alexp
parents:
2658
diff
changeset
|
727 |
Container gp = port.getParent(); |
2 | 728 |
if (gp instanceof JScrollPane) { |
729 |
JScrollPane scrollPane = (JScrollPane)gp; |
|
730 |
// Make certain we are the viewPort's view and not, for |
|
731 |
// example, the rowHeaderView of the scrollPane - |
|
732 |
// an implementor of fixed columns might do this. |
|
733 |
JViewport viewport = scrollPane.getViewport(); |
|
4278
b7a976422d27
6878399: public SwingUtilities.getParentViewport() is required
alexp
parents:
4272
diff
changeset
|
734 |
if (viewport == null || |
b7a976422d27
6878399: public SwingUtilities.getParentViewport() is required
alexp
parents:
4272
diff
changeset
|
735 |
SwingUtilities.getUnwrappedView(viewport) != this) { |
2 | 736 |
return; |
737 |
} |
|
738 |
scrollPane.setColumnHeaderView(getTableHeader()); |
|
2658 | 739 |
// configure the scrollpane for any LAF dependent settings |
740 |
configureEnclosingScrollPaneUI(); |
|
741 |
} |
|
742 |
} |
|
743 |
} |
|
744 |
||
745 |
/** |
|
746 |
* This is a sub-part of configureEnclosingScrollPane() that configures |
|
747 |
* anything on the scrollpane that may change when the look and feel |
|
748 |
* changes. It needed to be split out from configureEnclosingScrollPane() so |
|
749 |
* that it can be called from updateUI() when the LAF changes without |
|
750 |
* causing the regression found in bug 6687962. This was because updateUI() |
|
751 |
* is called from the constructor which then caused |
|
752 |
* configureEnclosingScrollPane() to be called by the constructor which |
|
753 |
* changes its contract for any subclass that overrides it. So by splitting |
|
754 |
* it out in this way configureEnclosingScrollPaneUI() can be called both |
|
755 |
* from configureEnclosingScrollPane() and updateUI() in a safe manor. |
|
756 |
*/ |
|
757 |
private void configureEnclosingScrollPaneUI() { |
|
5449 | 758 |
Container parent = SwingUtilities.getUnwrappedParent(this); |
759 |
if (parent instanceof JViewport) { |
|
760 |
JViewport port = (JViewport) parent; |
|
3737
83fb4621a129
6824395: Several Swing core components prevent using them in wrapper classes
alexp
parents:
2658
diff
changeset
|
761 |
Container gp = port.getParent(); |
2658 | 762 |
if (gp instanceof JScrollPane) { |
763 |
JScrollPane scrollPane = (JScrollPane)gp; |
|
764 |
// Make certain we are the viewPort's view and not, for |
|
765 |
// example, the rowHeaderView of the scrollPane - |
|
766 |
// an implementor of fixed columns might do this. |
|
767 |
JViewport viewport = scrollPane.getViewport(); |
|
4278
b7a976422d27
6878399: public SwingUtilities.getParentViewport() is required
alexp
parents:
4272
diff
changeset
|
768 |
if (viewport == null || |
b7a976422d27
6878399: public SwingUtilities.getParentViewport() is required
alexp
parents:
4272
diff
changeset
|
769 |
SwingUtilities.getUnwrappedView(viewport) != this) { |
2658 | 770 |
return; |
771 |
} |
|
2 | 772 |
// scrollPane.getViewport().setBackingStoreEnabled(true); |
773 |
Border border = scrollPane.getBorder(); |
|
774 |
if (border == null || border instanceof UIResource) { |
|
775 |
Border scrollPaneBorder = |
|
776 |
UIManager.getBorder("Table.scrollPaneBorder"); |
|
777 |
if (scrollPaneBorder != null) { |
|
778 |
scrollPane.setBorder(scrollPaneBorder); |
|
779 |
} |
|
780 |
} |
|
2658 | 781 |
// add JScrollBar corner component if available from LAF and not already set by the user |
782 |
Component corner = |
|
783 |
scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); |
|
784 |
if (corner == null || corner instanceof UIResource){ |
|
785 |
corner = null; |
|
16088 | 786 |
try { |
787 |
corner = (Component) UIManager.get( |
|
788 |
"Table.scrollPaneCornerComponent"); |
|
789 |
} catch (Exception e) { |
|
790 |
// just ignore and don't set corner |
|
2658 | 791 |
} |
792 |
scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, |
|
793 |
corner); |
|
794 |
} |
|
2 | 795 |
} |
796 |
} |
|
797 |
} |
|
798 |
||
799 |
/** |
|
800 |
* Calls the <code>unconfigureEnclosingScrollPane</code> method. |
|
801 |
* |
|
802 |
* @see #unconfigureEnclosingScrollPane |
|
803 |
*/ |
|
804 |
public void removeNotify() { |
|
805 |
KeyboardFocusManager.getCurrentKeyboardFocusManager(). |
|
806 |
removePropertyChangeListener("permanentFocusOwner", editorRemover); |
|
807 |
editorRemover = null; |
|
808 |
unconfigureEnclosingScrollPane(); |
|
809 |
super.removeNotify(); |
|
810 |
} |
|
811 |
||
812 |
/** |
|
813 |
* Reverses the effect of <code>configureEnclosingScrollPane</code> |
|
814 |
* by replacing the <code>columnHeaderView</code> of the enclosing |
|
815 |
* scroll pane with <code>null</code>. <code>JTable</code>'s |
|
816 |
* <code>removeNotify</code> method calls |
|
817 |
* this method, which is protected so that this default uninstallation |
|
818 |
* procedure can be overridden by a subclass. |
|
819 |
* |
|
820 |
* @see #removeNotify |
|
821 |
* @see #configureEnclosingScrollPane |
|
822 |
* @since 1.3 |
|
823 |
*/ |
|
824 |
protected void unconfigureEnclosingScrollPane() { |
|
5449 | 825 |
Container parent = SwingUtilities.getUnwrappedParent(this); |
826 |
if (parent instanceof JViewport) { |
|
827 |
JViewport port = (JViewport) parent; |
|
3737
83fb4621a129
6824395: Several Swing core components prevent using them in wrapper classes
alexp
parents:
2658
diff
changeset
|
828 |
Container gp = port.getParent(); |
2 | 829 |
if (gp instanceof JScrollPane) { |
830 |
JScrollPane scrollPane = (JScrollPane)gp; |
|
831 |
// Make certain we are the viewPort's view and not, for |
|
832 |
// example, the rowHeaderView of the scrollPane - |
|
833 |
// an implementor of fixed columns might do this. |
|
834 |
JViewport viewport = scrollPane.getViewport(); |
|
4278
b7a976422d27
6878399: public SwingUtilities.getParentViewport() is required
alexp
parents:
4272
diff
changeset
|
835 |
if (viewport == null || |
b7a976422d27
6878399: public SwingUtilities.getParentViewport() is required
alexp
parents:
4272
diff
changeset
|
836 |
SwingUtilities.getUnwrappedView(viewport) != this) { |
2 | 837 |
return; |
838 |
} |
|
839 |
scrollPane.setColumnHeaderView(null); |
|
2658 | 840 |
// remove ScrollPane corner if one was added by the LAF |
841 |
Component corner = |
|
842 |
scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); |
|
843 |
if (corner instanceof UIResource){ |
|
844 |
scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, |
|
845 |
null); |
|
846 |
} |
|
2 | 847 |
} |
848 |
} |
|
849 |
} |
|
850 |
||
851 |
void setUIProperty(String propertyName, Object value) { |
|
852 |
if (propertyName == "rowHeight") { |
|
853 |
if (!isRowHeightSet) { |
|
854 |
setRowHeight(((Number)value).intValue()); |
|
855 |
isRowHeightSet = false; |
|
856 |
} |
|
857 |
return; |
|
858 |
} |
|
859 |
super.setUIProperty(propertyName, value); |
|
860 |
} |
|
861 |
||
862 |
// |
|
863 |
// Static Methods |
|
864 |
// |
|
865 |
||
866 |
/** |
|
867 |
* Equivalent to <code>new JScrollPane(aTable)</code>. |
|
868 |
* |
|
869 |
* @deprecated As of Swing version 1.0.2, |
|
870 |
* replaced by <code>new JScrollPane(aTable)</code>. |
|
871 |
*/ |
|
872 |
@Deprecated |
|
873 |
static public JScrollPane createScrollPaneForTable(JTable aTable) { |
|
874 |
return new JScrollPane(aTable); |
|
875 |
} |
|
876 |
||
877 |
// |
|
878 |
// Table Attributes |
|
879 |
// |
|
880 |
||
881 |
/** |
|
882 |
* Sets the <code>tableHeader</code> working with this <code>JTable</code> to <code>newHeader</code>. |
|
883 |
* It is legal to have a <code>null</code> <code>tableHeader</code>. |
|
884 |
* |
|
885 |
* @param tableHeader new tableHeader |
|
886 |
* @see #getTableHeader |
|
887 |
* @beaninfo |
|
888 |
* bound: true |
|
889 |
* description: The JTableHeader instance which renders the column headers. |
|
890 |
*/ |
|
891 |
public void setTableHeader(JTableHeader tableHeader) { |
|
892 |
if (this.tableHeader != tableHeader) { |
|
893 |
JTableHeader old = this.tableHeader; |
|
894 |
// Release the old header |
|
895 |
if (old != null) { |
|
896 |
old.setTable(null); |
|
897 |
} |
|
898 |
this.tableHeader = tableHeader; |
|
899 |
if (tableHeader != null) { |
|
900 |
tableHeader.setTable(this); |
|
901 |
} |
|
902 |
firePropertyChange("tableHeader", old, tableHeader); |
|
903 |
} |
|
904 |
} |
|
905 |
||
906 |
/** |
|
907 |
* Returns the <code>tableHeader</code> used by this <code>JTable</code>. |
|
908 |
* |
|
909 |
* @return the <code>tableHeader</code> used by this table |
|
910 |
* @see #setTableHeader |
|
911 |
*/ |
|
912 |
public JTableHeader getTableHeader() { |
|
913 |
return tableHeader; |
|
914 |
} |
|
915 |
||
916 |
/** |
|
917 |
* Sets the height, in pixels, of all cells to <code>rowHeight</code>, |
|
918 |
* revalidates, and repaints. |
|
919 |
* The height of the cells will be equal to the row height minus |
|
920 |
* the row margin. |
|
921 |
* |
|
922 |
* @param rowHeight new row height |
|
923 |
* @exception IllegalArgumentException if <code>rowHeight</code> is |
|
924 |
* less than 1 |
|
925 |
* @see #getRowHeight |
|
926 |
* @beaninfo |
|
927 |
* bound: true |
|
928 |
* description: The height of the specified row. |
|
929 |
*/ |
|
930 |
public void setRowHeight(int rowHeight) { |
|
931 |
if (rowHeight <= 0) { |
|
932 |
throw new IllegalArgumentException("New row height less than 1"); |
|
933 |
} |
|
934 |
int old = this.rowHeight; |
|
935 |
this.rowHeight = rowHeight; |
|
936 |
rowModel = null; |
|
937 |
if (sortManager != null) { |
|
938 |
sortManager.modelRowSizes = null; |
|
939 |
} |
|
940 |
isRowHeightSet = true; |
|
941 |
resizeAndRepaint(); |
|
942 |
firePropertyChange("rowHeight", old, rowHeight); |
|
943 |
} |
|
944 |
||
945 |
/** |
|
946 |
* Returns the height of a table row, in pixels. |
|
947 |
* |
|
948 |
* @return the height in pixels of a table row |
|
949 |
* @see #setRowHeight |
|
950 |
*/ |
|
951 |
public int getRowHeight() { |
|
952 |
return rowHeight; |
|
953 |
} |
|
954 |
||
955 |
private SizeSequence getRowModel() { |
|
956 |
if (rowModel == null) { |
|
957 |
rowModel = new SizeSequence(getRowCount(), getRowHeight()); |
|
958 |
} |
|
959 |
return rowModel; |
|
960 |
} |
|
961 |
||
962 |
/** |
|
963 |
* Sets the height for <code>row</code> to <code>rowHeight</code>, |
|
964 |
* revalidates, and repaints. The height of the cells in this row |
|
965 |
* will be equal to the row height minus the row margin. |
|
966 |
* |
|
967 |
* @param row the row whose height is being |
|
968 |
changed |
|
969 |
* @param rowHeight new row height, in pixels |
|
970 |
* @exception IllegalArgumentException if <code>rowHeight</code> is |
|
971 |
* less than 1 |
|
972 |
* @beaninfo |
|
973 |
* bound: true |
|
974 |
* description: The height in pixels of the cells in <code>row</code> |
|
975 |
* @since 1.3 |
|
976 |
*/ |
|
977 |
public void setRowHeight(int row, int rowHeight) { |
|
978 |
if (rowHeight <= 0) { |
|
979 |
throw new IllegalArgumentException("New row height less than 1"); |
|
980 |
} |
|
981 |
getRowModel().setSize(row, rowHeight); |
|
982 |
if (sortManager != null) { |
|
983 |
sortManager.setViewRowHeight(row, rowHeight); |
|
984 |
} |
|
985 |
resizeAndRepaint(); |
|
986 |
} |
|
987 |
||
988 |
/** |
|
989 |
* Returns the height, in pixels, of the cells in <code>row</code>. |
|
990 |
* @param row the row whose height is to be returned |
|
991 |
* @return the height, in pixels, of the cells in the row |
|
992 |
* @since 1.3 |
|
993 |
*/ |
|
994 |
public int getRowHeight(int row) { |
|
995 |
return (rowModel == null) ? getRowHeight() : rowModel.getSize(row); |
|
996 |
} |
|
997 |
||
998 |
/** |
|
999 |
* Sets the amount of empty space between cells in adjacent rows. |
|
1000 |
* |
|
1001 |
* @param rowMargin the number of pixels between cells in a row |
|
1002 |
* @see #getRowMargin |
|
1003 |
* @beaninfo |
|
1004 |
* bound: true |
|
1005 |
* description: The amount of space between cells. |
|
1006 |
*/ |
|
1007 |
public void setRowMargin(int rowMargin) { |
|
1008 |
int old = this.rowMargin; |
|
1009 |
this.rowMargin = rowMargin; |
|
1010 |
resizeAndRepaint(); |
|
1011 |
firePropertyChange("rowMargin", old, rowMargin); |
|
1012 |
} |
|
1013 |
||
1014 |
/** |
|
1015 |
* Gets the amount of empty space, in pixels, between cells. Equivalent to: |
|
1016 |
* <code>getIntercellSpacing().height</code>. |
|
1017 |
* @return the number of pixels between cells in a row |
|
1018 |
* |
|
1019 |
* @see #setRowMargin |
|
1020 |
*/ |
|
1021 |
public int getRowMargin() { |
|
1022 |
return rowMargin; |
|
1023 |
} |
|
1024 |
||
1025 |
/** |
|
1026 |
* Sets the <code>rowMargin</code> and the <code>columnMargin</code> -- |
|
1027 |
* the height and width of the space between cells -- to |
|
1028 |
* <code>intercellSpacing</code>. |
|
1029 |
* |
|
1030 |
* @param intercellSpacing a <code>Dimension</code> |
|
1031 |
* specifying the new width |
|
1032 |
* and height between cells |
|
1033 |
* @see #getIntercellSpacing |
|
1034 |
* @beaninfo |
|
1035 |
* description: The spacing between the cells, |
|
1036 |
* drawn in the background color of the JTable. |
|
1037 |
*/ |
|
1038 |
public void setIntercellSpacing(Dimension intercellSpacing) { |
|
1039 |
// Set the rowMargin here and columnMargin in the TableColumnModel |
|
1040 |
setRowMargin(intercellSpacing.height); |
|
1041 |
getColumnModel().setColumnMargin(intercellSpacing.width); |
|
1042 |
||
1043 |
resizeAndRepaint(); |
|
1044 |
} |
|
1045 |
||
1046 |
/** |
|
1047 |
* Returns the horizontal and vertical space between cells. |
|
5956
e30f106a4b8b
6937415: Some components return undocumented default values under Nimbus LaF
alexp
parents:
5597
diff
changeset
|
1048 |
* The default spacing is look and feel dependent. |
2 | 1049 |
* |
1050 |
* @return the horizontal and vertical spacing between cells |
|
1051 |
* @see #setIntercellSpacing |
|
1052 |
*/ |
|
1053 |
public Dimension getIntercellSpacing() { |
|
1054 |
return new Dimension(getColumnModel().getColumnMargin(), rowMargin); |
|
1055 |
} |
|
1056 |
||
1057 |
/** |
|
1058 |
* Sets the color used to draw grid lines to <code>gridColor</code> and redisplays. |
|
1059 |
* The default color is look and feel dependent. |
|
1060 |
* |
|
1061 |
* @param gridColor the new color of the grid lines |
|
1062 |
* @exception IllegalArgumentException if <code>gridColor</code> is <code>null</code> |
|
1063 |
* @see #getGridColor |
|
1064 |
* @beaninfo |
|
1065 |
* bound: true |
|
1066 |
* description: The grid color. |
|
1067 |
*/ |
|
1068 |
public void setGridColor(Color gridColor) { |
|
1069 |
if (gridColor == null) { |
|
1070 |
throw new IllegalArgumentException("New color is null"); |
|
1071 |
} |
|
1072 |
Color old = this.gridColor; |
|
1073 |
this.gridColor = gridColor; |
|
1074 |
firePropertyChange("gridColor", old, gridColor); |
|
1075 |
// Redraw |
|
1076 |
repaint(); |
|
1077 |
} |
|
1078 |
||
1079 |
/** |
|
1080 |
* Returns the color used to draw grid lines. |
|
1081 |
* The default color is look and feel dependent. |
|
1082 |
* |
|
1083 |
* @return the color used to draw grid lines |
|
1084 |
* @see #setGridColor |
|
1085 |
*/ |
|
1086 |
public Color getGridColor() { |
|
1087 |
return gridColor; |
|
1088 |
} |
|
1089 |
||
1090 |
/** |
|
1091 |
* Sets whether the table draws grid lines around cells. |
|
1092 |
* If <code>showGrid</code> is true it does; if it is false it doesn't. |
|
1093 |
* There is no <code>getShowGrid</code> method as this state is held |
|
1094 |
* in two variables -- <code>showHorizontalLines</code> and <code>showVerticalLines</code> -- |
|
1095 |
* each of which can be queried independently. |
|
1096 |
* |
|
1097 |
* @param showGrid true if table view should draw grid lines |
|
1098 |
* |
|
1099 |
* @see #setShowVerticalLines |
|
1100 |
* @see #setShowHorizontalLines |
|
1101 |
* @beaninfo |
|
1102 |
* description: The color used to draw the grid lines. |
|
1103 |
*/ |
|
1104 |
public void setShowGrid(boolean showGrid) { |
|
1105 |
setShowHorizontalLines(showGrid); |
|
1106 |
setShowVerticalLines(showGrid); |
|
1107 |
||
1108 |
// Redraw |
|
1109 |
repaint(); |
|
1110 |
} |
|
1111 |
||
1112 |
/** |
|
1113 |
* Sets whether the table draws horizontal lines between cells. |
|
1114 |
* If <code>showHorizontalLines</code> is true it does; if it is false it doesn't. |
|
1115 |
* |
|
1116 |
* @param showHorizontalLines true if table view should draw horizontal lines |
|
1117 |
* @see #getShowHorizontalLines |
|
1118 |
* @see #setShowGrid |
|
1119 |
* @see #setShowVerticalLines |
|
1120 |
* @beaninfo |
|
1121 |
* bound: true |
|
1122 |
* description: Whether horizontal lines should be drawn in between the cells. |
|
1123 |
*/ |
|
1124 |
public void setShowHorizontalLines(boolean showHorizontalLines) { |
|
1125 |
boolean old = this.showHorizontalLines; |
|
1126 |
this.showHorizontalLines = showHorizontalLines; |
|
1127 |
firePropertyChange("showHorizontalLines", old, showHorizontalLines); |
|
1128 |
||
1129 |
// Redraw |
|
1130 |
repaint(); |
|
1131 |
} |
|
1132 |
||
1133 |
/** |
|
1134 |
* Sets whether the table draws vertical lines between cells. |
|
1135 |
* If <code>showVerticalLines</code> is true it does; if it is false it doesn't. |
|
1136 |
* |
|
1137 |
* @param showVerticalLines true if table view should draw vertical lines |
|
1138 |
* @see #getShowVerticalLines |
|
1139 |
* @see #setShowGrid |
|
1140 |
* @see #setShowHorizontalLines |
|
1141 |
* @beaninfo |
|
1142 |
* bound: true |
|
1143 |
* description: Whether vertical lines should be drawn in between the cells. |
|
1144 |
*/ |
|
1145 |
public void setShowVerticalLines(boolean showVerticalLines) { |
|
1146 |
boolean old = this.showVerticalLines; |
|
1147 |
this.showVerticalLines = showVerticalLines; |
|
1148 |
firePropertyChange("showVerticalLines", old, showVerticalLines); |
|
1149 |
// Redraw |
|
1150 |
repaint(); |
|
1151 |
} |
|
1152 |
||
1153 |
/** |
|
1154 |
* Returns true if the table draws horizontal lines between cells, false if it |
|
5956
e30f106a4b8b
6937415: Some components return undocumented default values under Nimbus LaF
alexp
parents:
5597
diff
changeset
|
1155 |
* doesn't. The default value is look and feel dependent. |
2 | 1156 |
* |
1157 |
* @return true if the table draws horizontal lines between cells, false if it |
|
1158 |
* doesn't |
|
1159 |
* @see #setShowHorizontalLines |
|
1160 |
*/ |
|
1161 |
public boolean getShowHorizontalLines() { |
|
1162 |
return showHorizontalLines; |
|
1163 |
} |
|
1164 |
||
1165 |
/** |
|
1166 |
* Returns true if the table draws vertical lines between cells, false if it |
|
5956
e30f106a4b8b
6937415: Some components return undocumented default values under Nimbus LaF
alexp
parents:
5597
diff
changeset
|
1167 |
* doesn't. The default value is look and feel dependent. |
2 | 1168 |
* |
1169 |
* @return true if the table draws vertical lines between cells, false if it |
|
1170 |
* doesn't |
|
1171 |
* @see #setShowVerticalLines |
|
1172 |
*/ |
|
1173 |
public boolean getShowVerticalLines() { |
|
1174 |
return showVerticalLines; |
|
1175 |
} |
|
1176 |
||
1177 |
/** |
|
1178 |
* Sets the table's auto resize mode when the table is resized. For further |
|
1179 |
* information on how the different resize modes work, see |
|
1180 |
* {@link #doLayout}. |
|
1181 |
* |
|
1182 |
* @param mode One of 5 legal values: |
|
1183 |
* AUTO_RESIZE_OFF, |
|
1184 |
* AUTO_RESIZE_NEXT_COLUMN, |
|
1185 |
* AUTO_RESIZE_SUBSEQUENT_COLUMNS, |
|
1186 |
* AUTO_RESIZE_LAST_COLUMN, |
|
1187 |
* AUTO_RESIZE_ALL_COLUMNS |
|
1188 |
* |
|
1189 |
* @see #getAutoResizeMode |
|
1190 |
* @see #doLayout |
|
1191 |
* @beaninfo |
|
1192 |
* bound: true |
|
1193 |
* description: Whether the columns should adjust themselves automatically. |
|
1194 |
* enum: AUTO_RESIZE_OFF JTable.AUTO_RESIZE_OFF |
|
1195 |
* AUTO_RESIZE_NEXT_COLUMN JTable.AUTO_RESIZE_NEXT_COLUMN |
|
1196 |
* AUTO_RESIZE_SUBSEQUENT_COLUMNS JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS |
|
1197 |
* AUTO_RESIZE_LAST_COLUMN JTable.AUTO_RESIZE_LAST_COLUMN |
|
1198 |
* AUTO_RESIZE_ALL_COLUMNS JTable.AUTO_RESIZE_ALL_COLUMNS |
|
1199 |
*/ |
|
1200 |
public void setAutoResizeMode(int mode) { |
|
1201 |
if ((mode == AUTO_RESIZE_OFF) || |
|
1202 |
(mode == AUTO_RESIZE_NEXT_COLUMN) || |
|
1203 |
(mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) || |
|
1204 |
(mode == AUTO_RESIZE_LAST_COLUMN) || |
|
1205 |
(mode == AUTO_RESIZE_ALL_COLUMNS)) { |
|
1206 |
int old = autoResizeMode; |
|
1207 |
autoResizeMode = mode; |
|
1208 |
resizeAndRepaint(); |
|
1209 |
if (tableHeader != null) { |
|
1210 |
tableHeader.resizeAndRepaint(); |
|
1211 |
} |
|
1212 |
firePropertyChange("autoResizeMode", old, autoResizeMode); |
|
1213 |
} |
|
1214 |
} |
|
1215 |
||
1216 |
/** |
|
1217 |
* Returns the auto resize mode of the table. The default mode |
|
1218 |
* is AUTO_RESIZE_SUBSEQUENT_COLUMNS. |
|
1219 |
* |
|
1220 |
* @return the autoResizeMode of the table |
|
1221 |
* |
|
1222 |
* @see #setAutoResizeMode |
|
1223 |
* @see #doLayout |
|
1224 |
*/ |
|
1225 |
public int getAutoResizeMode() { |
|
1226 |
return autoResizeMode; |
|
1227 |
} |
|
1228 |
||
1229 |
/** |
|
1230 |
* Sets this table's <code>autoCreateColumnsFromModel</code> flag. |
|
1231 |
* This method calls <code>createDefaultColumnsFromModel</code> if |
|
1232 |
* <code>autoCreateColumnsFromModel</code> changes from false to true. |
|
1233 |
* |
|
1234 |
* @param autoCreateColumnsFromModel true if <code>JTable</code> should automatically create columns |
|
1235 |
* @see #getAutoCreateColumnsFromModel |
|
1236 |
* @see #createDefaultColumnsFromModel |
|
1237 |
* @beaninfo |
|
1238 |
* bound: true |
|
1239 |
* description: Automatically populates the columnModel when a new TableModel is submitted. |
|
1240 |
*/ |
|
1241 |
public void setAutoCreateColumnsFromModel(boolean autoCreateColumnsFromModel) { |
|
1242 |
if (this.autoCreateColumnsFromModel != autoCreateColumnsFromModel) { |
|
1243 |
boolean old = this.autoCreateColumnsFromModel; |
|
1244 |
this.autoCreateColumnsFromModel = autoCreateColumnsFromModel; |
|
1245 |
if (autoCreateColumnsFromModel) { |
|
1246 |
createDefaultColumnsFromModel(); |
|
1247 |
} |
|
1248 |
firePropertyChange("autoCreateColumnsFromModel", old, autoCreateColumnsFromModel); |
|
1249 |
} |
|
1250 |
} |
|
1251 |
||
1252 |
/** |
|
1253 |
* Determines whether the table will create default columns from the model. |
|
1254 |
* If true, <code>setModel</code> will clear any existing columns and |
|
1255 |
* create new columns from the new model. Also, if the event in |
|
1256 |
* the <code>tableChanged</code> notification specifies that the |
|
1257 |
* entire table changed, then the columns will be rebuilt. |
|
1258 |
* The default is true. |
|
1259 |
* |
|
1260 |
* @return the autoCreateColumnsFromModel of the table |
|
1261 |
* @see #setAutoCreateColumnsFromModel |
|
1262 |
* @see #createDefaultColumnsFromModel |
|
1263 |
*/ |
|
1264 |
public boolean getAutoCreateColumnsFromModel() { |
|
1265 |
return autoCreateColumnsFromModel; |
|
1266 |
} |
|
1267 |
||
1268 |
/** |
|
1269 |
* Creates default columns for the table from |
|
1270 |
* the data model using the <code>getColumnCount</code> method |
|
1271 |
* defined in the <code>TableModel</code> interface. |
|
1272 |
* <p> |
|
1273 |
* Clears any existing columns before creating the |
|
1274 |
* new columns based on information from the model. |
|
1275 |
* |
|
1276 |
* @see #getAutoCreateColumnsFromModel |
|
1277 |
*/ |
|
1278 |
public void createDefaultColumnsFromModel() { |
|
1279 |
TableModel m = getModel(); |
|
1280 |
if (m != null) { |
|
1281 |
// Remove any current columns |
|
1282 |
TableColumnModel cm = getColumnModel(); |
|
1283 |
while (cm.getColumnCount() > 0) { |
|
1284 |
cm.removeColumn(cm.getColumn(0)); |
|
1285 |
} |
|
1286 |
||
1287 |
// Create new columns from the data model info |
|
1288 |
for (int i = 0; i < m.getColumnCount(); i++) { |
|
1289 |
TableColumn newColumn = new TableColumn(i); |
|
1290 |
addColumn(newColumn); |
|
1291 |
} |
|
1292 |
} |
|
1293 |
} |
|
1294 |
||
1295 |
/** |
|
1296 |
* Sets a default cell renderer to be used if no renderer has been set in |
|
1297 |
* a <code>TableColumn</code>. If renderer is <code>null</code>, |
|
1298 |
* removes the default renderer for this column class. |
|
1299 |
* |
|
1300 |
* @param columnClass set the default cell renderer for this columnClass |
|
1301 |
* @param renderer default cell renderer to be used for this |
|
1302 |
* columnClass |
|
1303 |
* @see #getDefaultRenderer |
|
1304 |
* @see #setDefaultEditor |
|
1305 |
*/ |
|
1306 |
public void setDefaultRenderer(Class<?> columnClass, TableCellRenderer renderer) { |
|
1307 |
if (renderer != null) { |
|
1308 |
defaultRenderersByColumnClass.put(columnClass, renderer); |
|
1309 |
} |
|
1310 |
else { |
|
1311 |
defaultRenderersByColumnClass.remove(columnClass); |
|
1312 |
} |
|
1313 |
} |
|
1314 |
||
1315 |
/** |
|
1316 |
* Returns the cell renderer to be used when no renderer has been set in |
|
1317 |
* a <code>TableColumn</code>. During the rendering of cells the renderer is fetched from |
|
1318 |
* a <code>Hashtable</code> of entries according to the class of the cells in the column. If |
|
1319 |
* there is no entry for this <code>columnClass</code> the method returns |
|
1320 |
* the entry for the most specific superclass. The <code>JTable</code> installs entries |
|
1321 |
* for <code>Object</code>, <code>Number</code>, and <code>Boolean</code>, all of which can be modified |
|
1322 |
* or replaced. |
|
1323 |
* |
|
1324 |
* @param columnClass return the default cell renderer |
|
1325 |
* for this columnClass |
|
1326 |
* @return the renderer for this columnClass |
|
1327 |
* @see #setDefaultRenderer |
|
1328 |
* @see #getColumnClass |
|
1329 |
*/ |
|
1330 |
public TableCellRenderer getDefaultRenderer(Class<?> columnClass) { |
|
1331 |
if (columnClass == null) { |
|
1332 |
return null; |
|
1333 |
} |
|
1334 |
else { |
|
1335 |
Object renderer = defaultRenderersByColumnClass.get(columnClass); |
|
1336 |
if (renderer != null) { |
|
1337 |
return (TableCellRenderer)renderer; |
|
1338 |
} |
|
1339 |
else { |
|
4379
ce28939f55fc
6888156: With GTK Look and Feel Icons cannot be rendered in Jtable Cells
peterz
parents:
4278
diff
changeset
|
1340 |
Class c = columnClass.getSuperclass(); |
ce28939f55fc
6888156: With GTK Look and Feel Icons cannot be rendered in Jtable Cells
peterz
parents:
4278
diff
changeset
|
1341 |
if (c == null && columnClass != Object.class) { |
ce28939f55fc
6888156: With GTK Look and Feel Icons cannot be rendered in Jtable Cells
peterz
parents:
4278
diff
changeset
|
1342 |
c = Object.class; |
ce28939f55fc
6888156: With GTK Look and Feel Icons cannot be rendered in Jtable Cells
peterz
parents:
4278
diff
changeset
|
1343 |
} |
ce28939f55fc
6888156: With GTK Look and Feel Icons cannot be rendered in Jtable Cells
peterz
parents:
4278
diff
changeset
|
1344 |
return getDefaultRenderer(c); |
2 | 1345 |
} |
1346 |
} |
|
1347 |
} |
|
1348 |
||
1349 |
/** |
|
1350 |
* Sets a default cell editor to be used if no editor has been set in |
|
1351 |
* a <code>TableColumn</code>. If no editing is required in a table, or a |
|
1352 |
* particular column in a table, uses the <code>isCellEditable</code> |
|
1353 |
* method in the <code>TableModel</code> interface to ensure that this |
|
1354 |
* <code>JTable</code> will not start an editor in these columns. |
|
1355 |
* If editor is <code>null</code>, removes the default editor for this |
|
1356 |
* column class. |
|
1357 |
* |
|
1358 |
* @param columnClass set the default cell editor for this columnClass |
|
1359 |
* @param editor default cell editor to be used for this columnClass |
|
1360 |
* @see TableModel#isCellEditable |
|
1361 |
* @see #getDefaultEditor |
|
1362 |
* @see #setDefaultRenderer |
|
1363 |
*/ |
|
1364 |
public void setDefaultEditor(Class<?> columnClass, TableCellEditor editor) { |
|
1365 |
if (editor != null) { |
|
1366 |
defaultEditorsByColumnClass.put(columnClass, editor); |
|
1367 |
} |
|
1368 |
else { |
|
1369 |
defaultEditorsByColumnClass.remove(columnClass); |
|
1370 |
} |
|
1371 |
} |
|
1372 |
||
1373 |
/** |
|
1374 |
* Returns the editor to be used when no editor has been set in |
|
1375 |
* a <code>TableColumn</code>. During the editing of cells the editor is fetched from |
|
1376 |
* a <code>Hashtable</code> of entries according to the class of the cells in the column. If |
|
1377 |
* there is no entry for this <code>columnClass</code> the method returns |
|
1378 |
* the entry for the most specific superclass. The <code>JTable</code> installs entries |
|
1379 |
* for <code>Object</code>, <code>Number</code>, and <code>Boolean</code>, all of which can be modified |
|
1380 |
* or replaced. |
|
1381 |
* |
|
1382 |
* @param columnClass return the default cell editor for this columnClass |
|
1383 |
* @return the default cell editor to be used for this columnClass |
|
1384 |
* @see #setDefaultEditor |
|
1385 |
* @see #getColumnClass |
|
1386 |
*/ |
|
1387 |
public TableCellEditor getDefaultEditor(Class<?> columnClass) { |
|
1388 |
if (columnClass == null) { |
|
1389 |
return null; |
|
1390 |
} |
|
1391 |
else { |
|
1392 |
Object editor = defaultEditorsByColumnClass.get(columnClass); |
|
1393 |
if (editor != null) { |
|
1394 |
return (TableCellEditor)editor; |
|
1395 |
} |
|
1396 |
else { |
|
1397 |
return getDefaultEditor(columnClass.getSuperclass()); |
|
1398 |
} |
|
1399 |
} |
|
1400 |
} |
|
1401 |
||
1402 |
/** |
|
1403 |
* Turns on or off automatic drag handling. In order to enable automatic |
|
1404 |
* drag handling, this property should be set to {@code true}, and the |
|
1405 |
* table's {@code TransferHandler} needs to be {@code non-null}. |
|
1406 |
* The default value of the {@code dragEnabled} property is {@code false}. |
|
1407 |
* <p> |
|
1408 |
* The job of honoring this property, and recognizing a user drag gesture, |
|
1409 |
* lies with the look and feel implementation, and in particular, the table's |
|
1410 |
* {@code TableUI}. When automatic drag handling is enabled, most look and |
|
1411 |
* feels (including those that subclass {@code BasicLookAndFeel}) begin a |
|
1412 |
* drag and drop operation whenever the user presses the mouse button over |
|
1413 |
* an item (in single selection mode) or a selection (in other selection |
|
1414 |
* modes) and then moves the mouse a few pixels. Setting this property to |
|
1415 |
* {@code true} can therefore have a subtle effect on how selections behave. |
|
1416 |
* <p> |
|
1417 |
* If a look and feel is used that ignores this property, you can still |
|
1418 |
* begin a drag and drop operation by calling {@code exportAsDrag} on the |
|
1419 |
* table's {@code TransferHandler}. |
|
1420 |
* |
|
1421 |
* @param b whether or not to enable automatic drag handling |
|
1422 |
* @exception HeadlessException if |
|
1423 |
* <code>b</code> is <code>true</code> and |
|
1424 |
* <code>GraphicsEnvironment.isHeadless()</code> |
|
1425 |
* returns <code>true</code> |
|
1426 |
* @see java.awt.GraphicsEnvironment#isHeadless |
|
1427 |
* @see #getDragEnabled |
|
1428 |
* @see #setTransferHandler |
|
1429 |
* @see TransferHandler |
|
1430 |
* @since 1.4 |
|
1431 |
* |
|
1432 |
* @beaninfo |
|
1433 |
* description: determines whether automatic drag handling is enabled |
|
1434 |
* bound: false |
|
1435 |
*/ |
|
1436 |
public void setDragEnabled(boolean b) { |
|
1437 |
if (b && GraphicsEnvironment.isHeadless()) { |
|
1438 |
throw new HeadlessException(); |
|
1439 |
} |
|
1440 |
dragEnabled = b; |
|
1441 |
} |
|
1442 |
||
1443 |
/** |
|
1444 |
* Returns whether or not automatic drag handling is enabled. |
|
1445 |
* |
|
1446 |
* @return the value of the {@code dragEnabled} property |
|
1447 |
* @see #setDragEnabled |
|
1448 |
* @since 1.4 |
|
1449 |
*/ |
|
1450 |
public boolean getDragEnabled() { |
|
1451 |
return dragEnabled; |
|
1452 |
} |
|
1453 |
||
1454 |
/** |
|
1455 |
* Sets the drop mode for this component. For backward compatibility, |
|
1456 |
* the default for this property is <code>DropMode.USE_SELECTION</code>. |
|
1457 |
* Usage of one of the other modes is recommended, however, for an |
|
1458 |
* improved user experience. <code>DropMode.ON</code>, for instance, |
|
1459 |
* offers similar behavior of showing items as selected, but does so without |
|
1460 |
* affecting the actual selection in the table. |
|
1461 |
* <p> |
|
1462 |
* <code>JTable</code> supports the following drop modes: |
|
1463 |
* <ul> |
|
1464 |
* <li><code>DropMode.USE_SELECTION</code></li> |
|
1465 |
* <li><code>DropMode.ON</code></li> |
|
1466 |
* <li><code>DropMode.INSERT</code></li> |
|
1467 |
* <li><code>DropMode.INSERT_ROWS</code></li> |
|
1468 |
* <li><code>DropMode.INSERT_COLS</code></li> |
|
1469 |
* <li><code>DropMode.ON_OR_INSERT</code></li> |
|
1470 |
* <li><code>DropMode.ON_OR_INSERT_ROWS</code></li> |
|
1471 |
* <li><code>DropMode.ON_OR_INSERT_COLS</code></li> |
|
1472 |
* </ul> |
|
1473 |
* <p> |
|
1474 |
* The drop mode is only meaningful if this component has a |
|
1475 |
* <code>TransferHandler</code> that accepts drops. |
|
1476 |
* |
|
1477 |
* @param dropMode the drop mode to use |
|
1478 |
* @throws IllegalArgumentException if the drop mode is unsupported |
|
1479 |
* or <code>null</code> |
|
1480 |
* @see #getDropMode |
|
1481 |
* @see #getDropLocation |
|
1482 |
* @see #setTransferHandler |
|
1483 |
* @see TransferHandler |
|
1484 |
* @since 1.6 |
|
1485 |
*/ |
|
1486 |
public final void setDropMode(DropMode dropMode) { |
|
1487 |
if (dropMode != null) { |
|
1488 |
switch (dropMode) { |
|
1489 |
case USE_SELECTION: |
|
1490 |
case ON: |
|
1491 |
case INSERT: |
|
1492 |
case INSERT_ROWS: |
|
1493 |
case INSERT_COLS: |
|
1494 |
case ON_OR_INSERT: |
|
1495 |
case ON_OR_INSERT_ROWS: |
|
1496 |
case ON_OR_INSERT_COLS: |
|
1497 |
this.dropMode = dropMode; |
|
1498 |
return; |
|
1499 |
} |
|
1500 |
} |
|
1501 |
||
1502 |
throw new IllegalArgumentException(dropMode + ": Unsupported drop mode for table"); |
|
1503 |
} |
|
1504 |
||
1505 |
/** |
|
1506 |
* Returns the drop mode for this component. |
|
1507 |
* |
|
1508 |
* @return the drop mode for this component |
|
1509 |
* @see #setDropMode |
|
1510 |
* @since 1.6 |
|
1511 |
*/ |
|
1512 |
public final DropMode getDropMode() { |
|
1513 |
return dropMode; |
|
1514 |
} |
|
1515 |
||
1516 |
/** |
|
1517 |
* Calculates a drop location in this component, representing where a |
|
1518 |
* drop at the given point should insert data. |
|
1519 |
* |
|
1520 |
* @param p the point to calculate a drop location for |
|
1521 |
* @return the drop location, or <code>null</code> |
|
1522 |
*/ |
|
1523 |
DropLocation dropLocationForPoint(Point p) { |
|
1524 |
DropLocation location = null; |
|
1525 |
||
1526 |
int row = rowAtPoint(p); |
|
1527 |
int col = columnAtPoint(p); |
|
1528 |
boolean outside = Boolean.TRUE == getClientProperty("Table.isFileList") |
|
1529 |
&& SwingUtilities2.pointOutsidePrefSize(this, row, col, p); |
|
1530 |
||
1531 |
Rectangle rect = getCellRect(row, col, true); |
|
1532 |
Section xSection, ySection; |
|
1533 |
boolean between = false; |
|
1534 |
boolean ltr = getComponentOrientation().isLeftToRight(); |
|
1535 |
||
1536 |
switch(dropMode) { |
|
1537 |
case USE_SELECTION: |
|
1538 |
case ON: |
|
1539 |
if (row == -1 || col == -1 || outside) { |
|
1540 |
location = new DropLocation(p, -1, -1, false, false); |
|
1541 |
} else { |
|
1542 |
location = new DropLocation(p, row, col, false, false); |
|
1543 |
} |
|
1544 |
break; |
|
1545 |
case INSERT: |
|
1546 |
if (row == -1 && col == -1) { |
|
1547 |
location = new DropLocation(p, 0, 0, true, true); |
|
1548 |
break; |
|
1549 |
} |
|
1550 |
||
1551 |
xSection = SwingUtilities2.liesInHorizontal(rect, p, ltr, true); |
|
1552 |
||
1553 |
if (row == -1) { |
|
1554 |
if (xSection == LEADING) { |
|
1555 |
location = new DropLocation(p, getRowCount(), col, true, true); |
|
1556 |
} else if (xSection == TRAILING) { |
|
1557 |
location = new DropLocation(p, getRowCount(), col + 1, true, true); |
|
1558 |
} else { |
|
1559 |
location = new DropLocation(p, getRowCount(), col, true, false); |
|
1560 |
} |
|
1561 |
} else if (xSection == LEADING || xSection == TRAILING) { |
|
1562 |
ySection = SwingUtilities2.liesInVertical(rect, p, true); |
|
1563 |
if (ySection == LEADING) { |
|
1564 |
between = true; |
|
1565 |
} else if (ySection == TRAILING) { |
|
1566 |
row++; |
|
1567 |
between = true; |
|
1568 |
} |
|
1569 |
||
1570 |
location = new DropLocation(p, row, |
|
1571 |
xSection == TRAILING ? col + 1 : col, |
|
1572 |
between, true); |
|
1573 |
} else { |
|
1574 |
if (SwingUtilities2.liesInVertical(rect, p, false) == TRAILING) { |
|
1575 |
row++; |
|
1576 |
} |
|
1577 |
||
1578 |
location = new DropLocation(p, row, col, true, false); |
|
1579 |
} |
|
1580 |
||
1581 |
break; |
|
1582 |
case INSERT_ROWS: |
|
1583 |
if (row == -1 && col == -1) { |
|
1584 |
location = new DropLocation(p, -1, -1, false, false); |
|
1585 |
break; |
|
1586 |
} |
|
1587 |
||
1588 |
if (row == -1) { |
|
1589 |
location = new DropLocation(p, getRowCount(), col, true, false); |
|
1590 |
break; |
|
1591 |
} |
|
1592 |
||
1593 |
if (SwingUtilities2.liesInVertical(rect, p, false) == TRAILING) { |
|
1594 |
row++; |
|
1595 |
} |
|
1596 |
||
1597 |
location = new DropLocation(p, row, col, true, false); |
|
1598 |
break; |
|
1599 |
case ON_OR_INSERT_ROWS: |
|
1600 |
if (row == -1 && col == -1) { |
|
1601 |
location = new DropLocation(p, -1, -1, false, false); |
|
1602 |
break; |
|
1603 |
} |
|
1604 |
||
1605 |
if (row == -1) { |
|
1606 |
location = new DropLocation(p, getRowCount(), col, true, false); |
|
1607 |
break; |
|
1608 |
} |
|
1609 |
||
1610 |
ySection = SwingUtilities2.liesInVertical(rect, p, true); |
|
1611 |
if (ySection == LEADING) { |
|
1612 |
between = true; |
|
1613 |
} else if (ySection == TRAILING) { |
|
1614 |
row++; |
|
1615 |
between = true; |
|
1616 |
} |
|
1617 |
||
1618 |
location = new DropLocation(p, row, col, between, false); |
|
1619 |
break; |
|
1620 |
case INSERT_COLS: |
|
1621 |
if (row == -1) { |
|
1622 |
location = new DropLocation(p, -1, -1, false, false); |
|
1623 |
break; |
|
1624 |
} |
|
1625 |
||
1626 |
if (col == -1) { |
|
1627 |
location = new DropLocation(p, getColumnCount(), col, false, true); |
|
1628 |
break; |
|
1629 |
} |
|
1630 |
||
1631 |
if (SwingUtilities2.liesInHorizontal(rect, p, ltr, false) == TRAILING) { |
|
1632 |
col++; |
|
1633 |
} |
|
1634 |
||
1635 |
location = new DropLocation(p, row, col, false, true); |
|
1636 |
break; |
|
1637 |
case ON_OR_INSERT_COLS: |
|
1638 |
if (row == -1) { |
|
1639 |
location = new DropLocation(p, -1, -1, false, false); |
|
1640 |
break; |
|
1641 |
} |
|
1642 |
||
1643 |
if (col == -1) { |
|
1644 |
location = new DropLocation(p, row, getColumnCount(), false, true); |
|
1645 |
break; |
|
1646 |
} |
|
1647 |
||
1648 |
xSection = SwingUtilities2.liesInHorizontal(rect, p, ltr, true); |
|
1649 |
if (xSection == LEADING) { |
|
1650 |
between = true; |
|
1651 |
} else if (xSection == TRAILING) { |
|
1652 |
col++; |
|
1653 |
between = true; |
|
1654 |
} |
|
1655 |
||
1656 |
location = new DropLocation(p, row, col, false, between); |
|
1657 |
break; |
|
1658 |
case ON_OR_INSERT: |
|
1659 |
if (row == -1 && col == -1) { |
|
1660 |
location = new DropLocation(p, 0, 0, true, true); |
|
1661 |
break; |
|
1662 |
} |
|
1663 |
||
1664 |
xSection = SwingUtilities2.liesInHorizontal(rect, p, ltr, true); |
|
1665 |
||
1666 |
if (row == -1) { |
|
1667 |
if (xSection == LEADING) { |
|
1668 |
location = new DropLocation(p, getRowCount(), col, true, true); |
|
1669 |
} else if (xSection == TRAILING) { |
|
1670 |
location = new DropLocation(p, getRowCount(), col + 1, true, true); |
|
1671 |
} else { |
|
1672 |
location = new DropLocation(p, getRowCount(), col, true, false); |
|
1673 |
} |
|
1674 |
||
1675 |
break; |
|
1676 |
} |
|
1677 |
||
1678 |
ySection = SwingUtilities2.liesInVertical(rect, p, true); |
|
1679 |
if (ySection == LEADING) { |
|
1680 |
between = true; |
|
1681 |
} else if (ySection == TRAILING) { |
|
1682 |
row++; |
|
1683 |
between = true; |
|
1684 |
} |
|
1685 |
||
1686 |
location = new DropLocation(p, row, |
|
1687 |
xSection == TRAILING ? col + 1 : col, |
|
1688 |
between, |
|
1689 |
xSection != MIDDLE); |
|
1690 |
||
1691 |
break; |
|
1692 |
default: |
|
1693 |
assert false : "Unexpected drop mode"; |
|
1694 |
} |
|
1695 |
||
1696 |
return location; |
|
1697 |
} |
|
1698 |
||
1699 |
/** |
|
1700 |
* Called to set or clear the drop location during a DnD operation. |
|
1701 |
* In some cases, the component may need to use it's internal selection |
|
1702 |
* temporarily to indicate the drop location. To help facilitate this, |
|
1703 |
* this method returns and accepts as a parameter a state object. |
|
1704 |
* This state object can be used to store, and later restore, the selection |
|
1705 |
* state. Whatever this method returns will be passed back to it in |
|
1706 |
* future calls, as the state parameter. If it wants the DnD system to |
|
1707 |
* continue storing the same state, it must pass it back every time. |
|
1708 |
* Here's how this is used: |
|
1709 |
* <p> |
|
1710 |
* Let's say that on the first call to this method the component decides |
|
1711 |
* to save some state (because it is about to use the selection to show |
|
1712 |
* a drop index). It can return a state object to the caller encapsulating |
|
1713 |
* any saved selection state. On a second call, let's say the drop location |
|
1714 |
* is being changed to something else. The component doesn't need to |
|
1715 |
* restore anything yet, so it simply passes back the same state object |
|
1716 |
* to have the DnD system continue storing it. Finally, let's say this |
|
1717 |
* method is messaged with <code>null</code>. This means DnD |
|
1718 |
* is finished with this component for now, meaning it should restore |
|
1719 |
* state. At this point, it can use the state parameter to restore |
|
1720 |
* said state, and of course return <code>null</code> since there's |
|
1721 |
* no longer anything to store. |
|
1722 |
* |
|
1723 |
* @param location the drop location (as calculated by |
|
1724 |
* <code>dropLocationForPoint</code>) or <code>null</code> |
|
1725 |
* if there's no longer a valid drop location |
|
1726 |
* @param state the state object saved earlier for this component, |
|
1727 |
* or <code>null</code> |
|
1728 |
* @param forDrop whether or not the method is being called because an |
|
1729 |
* actual drop occurred |
|
1730 |
* @return any saved state for this component, or <code>null</code> if none |
|
1731 |
*/ |
|
1732 |
Object setDropLocation(TransferHandler.DropLocation location, |
|
1733 |
Object state, |
|
1734 |
boolean forDrop) { |
|
1735 |
||
1736 |
Object retVal = null; |
|
1737 |
DropLocation tableLocation = (DropLocation)location; |
|
1738 |
||
1739 |
if (dropMode == DropMode.USE_SELECTION) { |
|
1740 |
if (tableLocation == null) { |
|
1741 |
if (!forDrop && state != null) { |
|
1742 |
clearSelection(); |
|
1743 |
||
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1744 |
int[] rows = ((int[][])state)[0]; |
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1745 |
int[] cols = ((int[][])state)[1]; |
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1746 |
int[] anchleads = ((int[][])state)[2]; |
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1747 |
|
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1748 |
for (int row : rows) { |
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1749 |
addRowSelectionInterval(row, row); |
2 | 1750 |
} |
1751 |
||
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1752 |
for (int col : cols) { |
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1753 |
addColumnSelectionInterval(col, col); |
2 | 1754 |
} |
1755 |
||
1756 |
SwingUtilities2.setLeadAnchorWithoutSelection( |
|
1757 |
getSelectionModel(), anchleads[1], anchleads[0]); |
|
1758 |
||
1759 |
SwingUtilities2.setLeadAnchorWithoutSelection( |
|
1760 |
getColumnModel().getSelectionModel(), |
|
1761 |
anchleads[3], anchleads[2]); |
|
1762 |
} |
|
1763 |
} else { |
|
1764 |
if (dropLocation == null) { |
|
1765 |
retVal = new int[][]{ |
|
1766 |
getSelectedRows(), |
|
1767 |
getSelectedColumns(), |
|
1768 |
{getAdjustedIndex(getSelectionModel() |
|
1769 |
.getAnchorSelectionIndex(), true), |
|
1770 |
getAdjustedIndex(getSelectionModel() |
|
1771 |
.getLeadSelectionIndex(), true), |
|
1772 |
getAdjustedIndex(getColumnModel().getSelectionModel() |
|
1773 |
.getAnchorSelectionIndex(), false), |
|
1774 |
getAdjustedIndex(getColumnModel().getSelectionModel() |
|
1775 |
.getLeadSelectionIndex(), false)}}; |
|
1776 |
} else { |
|
1777 |
retVal = state; |
|
1778 |
} |
|
1779 |
||
1780 |
if (tableLocation.getRow() == -1) { |
|
1781 |
clearSelectionAndLeadAnchor(); |
|
1782 |
} else { |
|
1783 |
setRowSelectionInterval(tableLocation.getRow(), |
|
1784 |
tableLocation.getRow()); |
|
1785 |
setColumnSelectionInterval(tableLocation.getColumn(), |
|
1786 |
tableLocation.getColumn()); |
|
1787 |
} |
|
1788 |
} |
|
1789 |
} |
|
1790 |
||
1791 |
DropLocation old = dropLocation; |
|
1792 |
dropLocation = tableLocation; |
|
1793 |
firePropertyChange("dropLocation", old, dropLocation); |
|
1794 |
||
1795 |
return retVal; |
|
1796 |
} |
|
1797 |
||
1798 |
/** |
|
1799 |
* Returns the location that this component should visually indicate |
|
1800 |
* as the drop location during a DnD operation over the component, |
|
1801 |
* or {@code null} if no location is to currently be shown. |
|
1802 |
* <p> |
|
1803 |
* This method is not meant for querying the drop location |
|
1804 |
* from a {@code TransferHandler}, as the drop location is only |
|
1805 |
* set after the {@code TransferHandler}'s <code>canImport</code> |
|
1806 |
* has returned and has allowed for the location to be shown. |
|
1807 |
* <p> |
|
1808 |
* When this property changes, a property change event with |
|
1809 |
* name "dropLocation" is fired by the component. |
|
1810 |
* |
|
1811 |
* @return the drop location |
|
1812 |
* @see #setDropMode |
|
1813 |
* @see TransferHandler#canImport(TransferHandler.TransferSupport) |
|
1814 |
* @since 1.6 |
|
1815 |
*/ |
|
1816 |
public final DropLocation getDropLocation() { |
|
1817 |
return dropLocation; |
|
1818 |
} |
|
1819 |
||
1820 |
/** |
|
1821 |
* Specifies whether a {@code RowSorter} should be created for the |
|
1822 |
* table whenever its model changes. |
|
1823 |
* <p> |
|
1824 |
* When {@code setAutoCreateRowSorter(true)} is invoked, a {@code |
|
1825 |
* TableRowSorter} is immediately created and installed on the |
|
1826 |
* table. While the {@code autoCreateRowSorter} property remains |
|
1827 |
* {@code true}, every time the model is changed, a new {@code |
|
1828 |
* TableRowSorter} is created and set as the table's row sorter. |
|
10868
d134ad3bc135
7100004: javax.swing.JTable.setAutoCreateRowSorter(boolean autoCreateRowSorter) should mention default value
rupashka
parents:
6836
diff
changeset
|
1829 |
* The default value for the {@code autoCreateRowSorter} |
d134ad3bc135
7100004: javax.swing.JTable.setAutoCreateRowSorter(boolean autoCreateRowSorter) should mention default value
rupashka
parents:
6836
diff
changeset
|
1830 |
* property is {@code false}. |
2 | 1831 |
* |
1832 |
* @param autoCreateRowSorter whether or not a {@code RowSorter} |
|
1833 |
* should be automatically created |
|
1834 |
* @see javax.swing.table.TableRowSorter |
|
1835 |
* @beaninfo |
|
1836 |
* bound: true |
|
1837 |
* preferred: true |
|
1838 |
* description: Whether or not to turn on sorting by default. |
|
1839 |
* @since 1.6 |
|
1840 |
*/ |
|
1841 |
public void setAutoCreateRowSorter(boolean autoCreateRowSorter) { |
|
1842 |
boolean oldValue = this.autoCreateRowSorter; |
|
1843 |
this.autoCreateRowSorter = autoCreateRowSorter; |
|
1844 |
if (autoCreateRowSorter) { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
1845 |
setRowSorter(new TableRowSorter<TableModel>(getModel())); |
2 | 1846 |
} |
1847 |
firePropertyChange("autoCreateRowSorter", oldValue, |
|
1848 |
autoCreateRowSorter); |
|
1849 |
} |
|
1850 |
||
1851 |
/** |
|
1852 |
* Returns {@code true} if whenever the model changes, a new |
|
1853 |
* {@code RowSorter} should be created and installed |
|
1854 |
* as the table's sorter; otherwise, returns {@code false}. |
|
1855 |
* |
|
1856 |
* @return true if a {@code RowSorter} should be created when |
|
1857 |
* the model changes |
|
1858 |
* @since 1.6 |
|
1859 |
*/ |
|
1860 |
public boolean getAutoCreateRowSorter() { |
|
1861 |
return autoCreateRowSorter; |
|
1862 |
} |
|
1863 |
||
1864 |
/** |
|
1865 |
* Specifies whether the selection should be updated after sorting. |
|
1866 |
* If true, on sorting the selection is reset such that |
|
1867 |
* the same rows, in terms of the model, remain selected. The default |
|
1868 |
* is true. |
|
1869 |
* |
|
1870 |
* @param update whether or not to update the selection on sorting |
|
1871 |
* @beaninfo |
|
1872 |
* bound: true |
|
1873 |
* expert: true |
|
1874 |
* description: Whether or not to update the selection on sorting |
|
1875 |
* @since 1.6 |
|
1876 |
*/ |
|
1877 |
public void setUpdateSelectionOnSort(boolean update) { |
|
1878 |
if (updateSelectionOnSort != update) { |
|
1879 |
updateSelectionOnSort = update; |
|
1880 |
firePropertyChange("updateSelectionOnSort", !update, update); |
|
1881 |
} |
|
1882 |
} |
|
1883 |
||
1884 |
/** |
|
1885 |
* Returns true if the selection should be updated after sorting. |
|
1886 |
* |
|
1887 |
* @return whether to update the selection on a sort |
|
1888 |
* @since 1.6 |
|
1889 |
*/ |
|
1890 |
public boolean getUpdateSelectionOnSort() { |
|
1891 |
return updateSelectionOnSort; |
|
1892 |
} |
|
1893 |
||
1894 |
/** |
|
1895 |
* Sets the <code>RowSorter</code>. <code>RowSorter</code> is used |
|
1896 |
* to provide sorting and filtering to a <code>JTable</code>. |
|
1897 |
* <p> |
|
1898 |
* This method clears the selection and resets any variable row heights. |
|
1899 |
* <p> |
|
1900 |
* This method fires a <code>PropertyChangeEvent</code> when appropriate, |
|
1901 |
* with the property name <code>"rowSorter"</code>. For |
|
1902 |
* backward-compatibility, this method fires an additional event with the |
|
1903 |
* property name <code>"sorter"</code>. |
|
1904 |
* <p> |
|
1905 |
* If the underlying model of the <code>RowSorter</code> differs from |
|
1906 |
* that of this <code>JTable</code> undefined behavior will result. |
|
1907 |
* |
|
1908 |
* @param sorter the <code>RowSorter</code>; <code>null</code> turns |
|
1909 |
* sorting off |
|
1910 |
* @see javax.swing.table.TableRowSorter |
|
1911 |
* @beaninfo |
|
1912 |
* bound: true |
|
1913 |
* description: The table's RowSorter |
|
1914 |
* @since 1.6 |
|
1915 |
*/ |
|
1916 |
public void setRowSorter(RowSorter<? extends TableModel> sorter) { |
|
1917 |
RowSorter<? extends TableModel> oldRowSorter = null; |
|
1918 |
if (sortManager != null) { |
|
1919 |
oldRowSorter = sortManager.sorter; |
|
1920 |
sortManager.dispose(); |
|
1921 |
sortManager = null; |
|
1922 |
} |
|
1923 |
rowModel = null; |
|
1924 |
clearSelectionAndLeadAnchor(); |
|
1925 |
if (sorter != null) { |
|
1926 |
sortManager = new SortManager(sorter); |
|
1927 |
} |
|
1928 |
resizeAndRepaint(); |
|
1929 |
firePropertyChange("rowSorter", oldRowSorter, sorter); |
|
1930 |
firePropertyChange("sorter", oldRowSorter, sorter); |
|
1931 |
} |
|
1932 |
||
1933 |
/** |
|
1934 |
* Returns the object responsible for sorting. |
|
1935 |
* |
|
1936 |
* @return the object responsible for sorting |
|
1937 |
* @since 1.6 |
|
1938 |
*/ |
|
1939 |
public RowSorter<? extends TableModel> getRowSorter() { |
|
1940 |
return (sortManager != null) ? sortManager.sorter : null; |
|
1941 |
} |
|
1942 |
||
1943 |
// |
|
1944 |
// Selection methods |
|
1945 |
// |
|
1946 |
/** |
|
1947 |
* Sets the table's selection mode to allow only single selections, a single |
|
1948 |
* contiguous interval, or multiple intervals. |
|
1949 |
* <P> |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
1950 |
* <b>Note:</b> |
2 | 1951 |
* <code>JTable</code> provides all the methods for handling |
1952 |
* column and row selection. When setting states, |
|
1953 |
* such as <code>setSelectionMode</code>, it not only |
|
1954 |
* updates the mode for the row selection model but also sets similar |
|
1955 |
* values in the selection model of the <code>columnModel</code>. |
|
1956 |
* If you want to have the row and column selection models operating |
|
1957 |
* in different modes, set them both directly. |
|
1958 |
* <p> |
|
1959 |
* Both the row and column selection models for <code>JTable</code> |
|
1960 |
* default to using a <code>DefaultListSelectionModel</code> |
|
1961 |
* so that <code>JTable</code> works the same way as the |
|
1962 |
* <code>JList</code>. See the <code>setSelectionMode</code> method |
|
1963 |
* in <code>JList</code> for details about the modes. |
|
1964 |
* |
|
1965 |
* @see JList#setSelectionMode |
|
1966 |
* @beaninfo |
|
1967 |
* description: The selection mode used by the row and column selection models. |
|
1968 |
* enum: SINGLE_SELECTION ListSelectionModel.SINGLE_SELECTION |
|
1969 |
* SINGLE_INTERVAL_SELECTION ListSelectionModel.SINGLE_INTERVAL_SELECTION |
|
1970 |
* MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION |
|
1971 |
*/ |
|
1972 |
public void setSelectionMode(int selectionMode) { |
|
1973 |
clearSelection(); |
|
1974 |
getSelectionModel().setSelectionMode(selectionMode); |
|
1975 |
getColumnModel().getSelectionModel().setSelectionMode(selectionMode); |
|
1976 |
} |
|
1977 |
||
1978 |
/** |
|
1979 |
* Sets whether the rows in this model can be selected. |
|
1980 |
* |
|
1981 |
* @param rowSelectionAllowed true if this model will allow row selection |
|
1982 |
* @see #getRowSelectionAllowed |
|
1983 |
* @beaninfo |
|
1984 |
* bound: true |
|
1985 |
* attribute: visualUpdate true |
|
1986 |
* description: If true, an entire row is selected for each selected cell. |
|
1987 |
*/ |
|
1988 |
public void setRowSelectionAllowed(boolean rowSelectionAllowed) { |
|
1989 |
boolean old = this.rowSelectionAllowed; |
|
1990 |
this.rowSelectionAllowed = rowSelectionAllowed; |
|
1991 |
if (old != rowSelectionAllowed) { |
|
1992 |
repaint(); |
|
1993 |
} |
|
1994 |
firePropertyChange("rowSelectionAllowed", old, rowSelectionAllowed); |
|
1995 |
} |
|
1996 |
||
1997 |
/** |
|
1998 |
* Returns true if rows can be selected. |
|
1999 |
* |
|
2000 |
* @return true if rows can be selected, otherwise false |
|
2001 |
* @see #setRowSelectionAllowed |
|
2002 |
*/ |
|
2003 |
public boolean getRowSelectionAllowed() { |
|
2004 |
return rowSelectionAllowed; |
|
2005 |
} |
|
2006 |
||
2007 |
/** |
|
2008 |
* Sets whether the columns in this model can be selected. |
|
2009 |
* |
|
2010 |
* @param columnSelectionAllowed true if this model will allow column selection |
|
2011 |
* @see #getColumnSelectionAllowed |
|
2012 |
* @beaninfo |
|
2013 |
* bound: true |
|
2014 |
* attribute: visualUpdate true |
|
2015 |
* description: If true, an entire column is selected for each selected cell. |
|
2016 |
*/ |
|
2017 |
public void setColumnSelectionAllowed(boolean columnSelectionAllowed) { |
|
2018 |
boolean old = columnModel.getColumnSelectionAllowed(); |
|
2019 |
columnModel.setColumnSelectionAllowed(columnSelectionAllowed); |
|
2020 |
if (old != columnSelectionAllowed) { |
|
2021 |
repaint(); |
|
2022 |
} |
|
2023 |
firePropertyChange("columnSelectionAllowed", old, columnSelectionAllowed); |
|
2024 |
} |
|
2025 |
||
2026 |
/** |
|
2027 |
* Returns true if columns can be selected. |
|
2028 |
* |
|
2029 |
* @return true if columns can be selected, otherwise false |
|
2030 |
* @see #setColumnSelectionAllowed |
|
2031 |
*/ |
|
2032 |
public boolean getColumnSelectionAllowed() { |
|
2033 |
return columnModel.getColumnSelectionAllowed(); |
|
2034 |
} |
|
2035 |
||
2036 |
/** |
|
2037 |
* Sets whether this table allows both a column selection and a |
|
2038 |
* row selection to exist simultaneously. When set, |
|
2039 |
* the table treats the intersection of the row and column selection |
|
2040 |
* models as the selected cells. Override <code>isCellSelected</code> to |
|
2041 |
* change this default behavior. This method is equivalent to setting |
|
2042 |
* both the <code>rowSelectionAllowed</code> property and |
|
2043 |
* <code>columnSelectionAllowed</code> property of the |
|
2044 |
* <code>columnModel</code> to the supplied value. |
|
2045 |
* |
|
2046 |
* @param cellSelectionEnabled true if simultaneous row and column |
|
2047 |
* selection is allowed |
|
2048 |
* @see #getCellSelectionEnabled |
|
2049 |
* @see #isCellSelected |
|
2050 |
* @beaninfo |
|
2051 |
* bound: true |
|
2052 |
* attribute: visualUpdate true |
|
2053 |
* description: Select a rectangular region of cells rather than |
|
2054 |
* rows or columns. |
|
2055 |
*/ |
|
2056 |
public void setCellSelectionEnabled(boolean cellSelectionEnabled) { |
|
2057 |
setRowSelectionAllowed(cellSelectionEnabled); |
|
2058 |
setColumnSelectionAllowed(cellSelectionEnabled); |
|
2059 |
boolean old = this.cellSelectionEnabled; |
|
2060 |
this.cellSelectionEnabled = cellSelectionEnabled; |
|
2061 |
firePropertyChange("cellSelectionEnabled", old, cellSelectionEnabled); |
|
2062 |
} |
|
2063 |
||
2064 |
/** |
|
2065 |
* Returns true if both row and column selection models are enabled. |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
2066 |
* Equivalent to <code>getRowSelectionAllowed() && |
2 | 2067 |
* getColumnSelectionAllowed()</code>. |
2068 |
* |
|
2069 |
* @return true if both row and column selection models are enabled |
|
2070 |
* |
|
2071 |
* @see #setCellSelectionEnabled |
|
2072 |
*/ |
|
2073 |
public boolean getCellSelectionEnabled() { |
|
2074 |
return getRowSelectionAllowed() && getColumnSelectionAllowed(); |
|
2075 |
} |
|
2076 |
||
2077 |
/** |
|
2078 |
* Selects all rows, columns, and cells in the table. |
|
2079 |
*/ |
|
2080 |
public void selectAll() { |
|
2081 |
// If I'm currently editing, then I should stop editing |
|
2082 |
if (isEditing()) { |
|
2083 |
removeEditor(); |
|
2084 |
} |
|
2085 |
if (getRowCount() > 0 && getColumnCount() > 0) { |
|
2086 |
int oldLead; |
|
2087 |
int oldAnchor; |
|
2088 |
ListSelectionModel selModel; |
|
2089 |
||
2090 |
selModel = selectionModel; |
|
2091 |
selModel.setValueIsAdjusting(true); |
|
2092 |
oldLead = getAdjustedIndex(selModel.getLeadSelectionIndex(), true); |
|
2093 |
oldAnchor = getAdjustedIndex(selModel.getAnchorSelectionIndex(), true); |
|
2094 |
||
2095 |
setRowSelectionInterval(0, getRowCount()-1); |
|
2096 |
||
2097 |
// this is done to restore the anchor and lead |
|
2098 |
SwingUtilities2.setLeadAnchorWithoutSelection(selModel, oldLead, oldAnchor); |
|
2099 |
||
2100 |
selModel.setValueIsAdjusting(false); |
|
2101 |
||
2102 |
selModel = columnModel.getSelectionModel(); |
|
2103 |
selModel.setValueIsAdjusting(true); |
|
2104 |
oldLead = getAdjustedIndex(selModel.getLeadSelectionIndex(), false); |
|
2105 |
oldAnchor = getAdjustedIndex(selModel.getAnchorSelectionIndex(), false); |
|
2106 |
||
2107 |
setColumnSelectionInterval(0, getColumnCount()-1); |
|
2108 |
||
2109 |
// this is done to restore the anchor and lead |
|
2110 |
SwingUtilities2.setLeadAnchorWithoutSelection(selModel, oldLead, oldAnchor); |
|
2111 |
||
2112 |
selModel.setValueIsAdjusting(false); |
|
2113 |
} |
|
2114 |
} |
|
2115 |
||
2116 |
/** |
|
2117 |
* Deselects all selected columns and rows. |
|
2118 |
*/ |
|
2119 |
public void clearSelection() { |
|
2120 |
selectionModel.clearSelection(); |
|
2121 |
columnModel.getSelectionModel().clearSelection(); |
|
2122 |
} |
|
2123 |
||
2124 |
private void clearSelectionAndLeadAnchor() { |
|
2125 |
selectionModel.setValueIsAdjusting(true); |
|
2126 |
columnModel.getSelectionModel().setValueIsAdjusting(true); |
|
2127 |
||
2128 |
clearSelection(); |
|
2129 |
||
2130 |
selectionModel.setAnchorSelectionIndex(-1); |
|
2131 |
selectionModel.setLeadSelectionIndex(-1); |
|
2132 |
columnModel.getSelectionModel().setAnchorSelectionIndex(-1); |
|
2133 |
columnModel.getSelectionModel().setLeadSelectionIndex(-1); |
|
2134 |
||
2135 |
selectionModel.setValueIsAdjusting(false); |
|
2136 |
columnModel.getSelectionModel().setValueIsAdjusting(false); |
|
2137 |
} |
|
2138 |
||
2139 |
private int getAdjustedIndex(int index, boolean row) { |
|
2140 |
int compare = row ? getRowCount() : getColumnCount(); |
|
2141 |
return index < compare ? index : -1; |
|
2142 |
} |
|
2143 |
||
2144 |
private int boundRow(int row) throws IllegalArgumentException { |
|
2145 |
if (row < 0 || row >= getRowCount()) { |
|
2146 |
throw new IllegalArgumentException("Row index out of range"); |
|
2147 |
} |
|
2148 |
return row; |
|
2149 |
} |
|
2150 |
||
2151 |
private int boundColumn(int col) { |
|
2152 |
if (col< 0 || col >= getColumnCount()) { |
|
2153 |
throw new IllegalArgumentException("Column index out of range"); |
|
2154 |
} |
|
2155 |
return col; |
|
2156 |
} |
|
2157 |
||
2158 |
/** |
|
2159 |
* Selects the rows from <code>index0</code> to <code>index1</code>, |
|
2160 |
* inclusive. |
|
2161 |
* |
|
2162 |
* @exception IllegalArgumentException if <code>index0</code> or |
|
2163 |
* <code>index1</code> lie outside |
|
2164 |
* [0, <code>getRowCount()</code>-1] |
|
2165 |
* @param index0 one end of the interval |
|
2166 |
* @param index1 the other end of the interval |
|
2167 |
*/ |
|
2168 |
public void setRowSelectionInterval(int index0, int index1) { |
|
2169 |
selectionModel.setSelectionInterval(boundRow(index0), boundRow(index1)); |
|
2170 |
} |
|
2171 |
||
2172 |
/** |
|
2173 |
* Selects the columns from <code>index0</code> to <code>index1</code>, |
|
2174 |
* inclusive. |
|
2175 |
* |
|
2176 |
* @exception IllegalArgumentException if <code>index0</code> or |
|
2177 |
* <code>index1</code> lie outside |
|
2178 |
* [0, <code>getColumnCount()</code>-1] |
|
2179 |
* @param index0 one end of the interval |
|
2180 |
* @param index1 the other end of the interval |
|
2181 |
*/ |
|
2182 |
public void setColumnSelectionInterval(int index0, int index1) { |
|
2183 |
columnModel.getSelectionModel().setSelectionInterval(boundColumn(index0), boundColumn(index1)); |
|
2184 |
} |
|
2185 |
||
2186 |
/** |
|
2187 |
* Adds the rows from <code>index0</code> to <code>index1</code>, inclusive, to |
|
2188 |
* the current selection. |
|
2189 |
* |
|
2190 |
* @exception IllegalArgumentException if <code>index0</code> or <code>index1</code> |
|
2191 |
* lie outside [0, <code>getRowCount()</code>-1] |
|
2192 |
* @param index0 one end of the interval |
|
2193 |
* @param index1 the other end of the interval |
|
2194 |
*/ |
|
2195 |
public void addRowSelectionInterval(int index0, int index1) { |
|
2196 |
selectionModel.addSelectionInterval(boundRow(index0), boundRow(index1)); |
|
2197 |
} |
|
2198 |
||
2199 |
/** |
|
2200 |
* Adds the columns from <code>index0</code> to <code>index1</code>, |
|
2201 |
* inclusive, to the current selection. |
|
2202 |
* |
|
2203 |
* @exception IllegalArgumentException if <code>index0</code> or |
|
2204 |
* <code>index1</code> lie outside |
|
2205 |
* [0, <code>getColumnCount()</code>-1] |
|
2206 |
* @param index0 one end of the interval |
|
2207 |
* @param index1 the other end of the interval |
|
2208 |
*/ |
|
2209 |
public void addColumnSelectionInterval(int index0, int index1) { |
|
2210 |
columnModel.getSelectionModel().addSelectionInterval(boundColumn(index0), boundColumn(index1)); |
|
2211 |
} |
|
2212 |
||
2213 |
/** |
|
2214 |
* Deselects the rows from <code>index0</code> to <code>index1</code>, inclusive. |
|
2215 |
* |
|
2216 |
* @exception IllegalArgumentException if <code>index0</code> or |
|
2217 |
* <code>index1</code> lie outside |
|
2218 |
* [0, <code>getRowCount()</code>-1] |
|
2219 |
* @param index0 one end of the interval |
|
2220 |
* @param index1 the other end of the interval |
|
2221 |
*/ |
|
2222 |
public void removeRowSelectionInterval(int index0, int index1) { |
|
2223 |
selectionModel.removeSelectionInterval(boundRow(index0), boundRow(index1)); |
|
2224 |
} |
|
2225 |
||
2226 |
/** |
|
2227 |
* Deselects the columns from <code>index0</code> to <code>index1</code>, inclusive. |
|
2228 |
* |
|
2229 |
* @exception IllegalArgumentException if <code>index0</code> or |
|
2230 |
* <code>index1</code> lie outside |
|
2231 |
* [0, <code>getColumnCount()</code>-1] |
|
2232 |
* @param index0 one end of the interval |
|
2233 |
* @param index1 the other end of the interval |
|
2234 |
*/ |
|
2235 |
public void removeColumnSelectionInterval(int index0, int index1) { |
|
2236 |
columnModel.getSelectionModel().removeSelectionInterval(boundColumn(index0), boundColumn(index1)); |
|
2237 |
} |
|
2238 |
||
2239 |
/** |
|
2240 |
* Returns the index of the first selected row, -1 if no row is selected. |
|
2241 |
* @return the index of the first selected row |
|
2242 |
*/ |
|
2243 |
public int getSelectedRow() { |
|
2244 |
return selectionModel.getMinSelectionIndex(); |
|
2245 |
} |
|
2246 |
||
2247 |
/** |
|
2248 |
* Returns the index of the first selected column, |
|
2249 |
* -1 if no column is selected. |
|
2250 |
* @return the index of the first selected column |
|
2251 |
*/ |
|
2252 |
public int getSelectedColumn() { |
|
2253 |
return columnModel.getSelectionModel().getMinSelectionIndex(); |
|
2254 |
} |
|
2255 |
||
2256 |
/** |
|
2257 |
* Returns the indices of all selected rows. |
|
2258 |
* |
|
2259 |
* @return an array of integers containing the indices of all selected rows, |
|
2260 |
* or an empty array if no row is selected |
|
2261 |
* @see #getSelectedRow |
|
2262 |
*/ |
|
2263 |
public int[] getSelectedRows() { |
|
2264 |
int iMin = selectionModel.getMinSelectionIndex(); |
|
2265 |
int iMax = selectionModel.getMaxSelectionIndex(); |
|
2266 |
||
2267 |
if ((iMin == -1) || (iMax == -1)) { |
|
2268 |
return new int[0]; |
|
2269 |
} |
|
2270 |
||
2271 |
int[] rvTmp = new int[1+ (iMax - iMin)]; |
|
2272 |
int n = 0; |
|
2273 |
for(int i = iMin; i <= iMax; i++) { |
|
2274 |
if (selectionModel.isSelectedIndex(i)) { |
|
2275 |
rvTmp[n++] = i; |
|
2276 |
} |
|
2277 |
} |
|
2278 |
int[] rv = new int[n]; |
|
2279 |
System.arraycopy(rvTmp, 0, rv, 0, n); |
|
2280 |
return rv; |
|
2281 |
} |
|
2282 |
||
2283 |
/** |
|
2284 |
* Returns the indices of all selected columns. |
|
2285 |
* |
|
2286 |
* @return an array of integers containing the indices of all selected columns, |
|
2287 |
* or an empty array if no column is selected |
|
2288 |
* @see #getSelectedColumn |
|
2289 |
*/ |
|
2290 |
public int[] getSelectedColumns() { |
|
2291 |
return columnModel.getSelectedColumns(); |
|
2292 |
} |
|
2293 |
||
2294 |
/** |
|
2295 |
* Returns the number of selected rows. |
|
2296 |
* |
|
2297 |
* @return the number of selected rows, 0 if no rows are selected |
|
2298 |
*/ |
|
2299 |
public int getSelectedRowCount() { |
|
2300 |
int iMin = selectionModel.getMinSelectionIndex(); |
|
2301 |
int iMax = selectionModel.getMaxSelectionIndex(); |
|
2302 |
int count = 0; |
|
2303 |
||
2304 |
for(int i = iMin; i <= iMax; i++) { |
|
2305 |
if (selectionModel.isSelectedIndex(i)) { |
|
2306 |
count++; |
|
2307 |
} |
|
2308 |
} |
|
2309 |
return count; |
|
2310 |
} |
|
2311 |
||
2312 |
/** |
|
2313 |
* Returns the number of selected columns. |
|
2314 |
* |
|
2315 |
* @return the number of selected columns, 0 if no columns are selected |
|
2316 |
*/ |
|
2317 |
public int getSelectedColumnCount() { |
|
2318 |
return columnModel.getSelectedColumnCount(); |
|
2319 |
} |
|
2320 |
||
2321 |
/** |
|
2322 |
* Returns true if the specified index is in the valid range of rows, |
|
2323 |
* and the row at that index is selected. |
|
2324 |
* |
|
2325 |
* @return true if <code>row</code> is a valid index and the row at |
|
2326 |
* that index is selected (where 0 is the first row) |
|
2327 |
*/ |
|
2328 |
public boolean isRowSelected(int row) { |
|
2329 |
return selectionModel.isSelectedIndex(row); |
|
2330 |
} |
|
2331 |
||
2332 |
/** |
|
2333 |
* Returns true if the specified index is in the valid range of columns, |
|
2334 |
* and the column at that index is selected. |
|
2335 |
* |
|
2336 |
* @param column the column in the column model |
|
2337 |
* @return true if <code>column</code> is a valid index and the column at |
|
2338 |
* that index is selected (where 0 is the first column) |
|
2339 |
*/ |
|
2340 |
public boolean isColumnSelected(int column) { |
|
2341 |
return columnModel.getSelectionModel().isSelectedIndex(column); |
|
2342 |
} |
|
2343 |
||
2344 |
/** |
|
2345 |
* Returns true if the specified indices are in the valid range of rows |
|
2346 |
* and columns and the cell at the specified position is selected. |
|
2347 |
* @param row the row being queried |
|
2348 |
* @param column the column being queried |
|
2349 |
* |
|
2350 |
* @return true if <code>row</code> and <code>column</code> are valid indices |
|
2351 |
* and the cell at index <code>(row, column)</code> is selected, |
|
2352 |
* where the first row and first column are at index 0 |
|
2353 |
*/ |
|
2354 |
public boolean isCellSelected(int row, int column) { |
|
2355 |
if (!getRowSelectionAllowed() && !getColumnSelectionAllowed()) { |
|
2356 |
return false; |
|
2357 |
} |
|
2358 |
return (!getRowSelectionAllowed() || isRowSelected(row)) && |
|
2359 |
(!getColumnSelectionAllowed() || isColumnSelected(column)); |
|
2360 |
} |
|
2361 |
||
2362 |
private void changeSelectionModel(ListSelectionModel sm, int index, |
|
2363 |
boolean toggle, boolean extend, boolean selected, |
|
2364 |
int anchor, boolean anchorSelected) { |
|
2365 |
if (extend) { |
|
2366 |
if (toggle) { |
|
2367 |
if (anchorSelected) { |
|
2368 |
sm.addSelectionInterval(anchor, index); |
|
2369 |
} else { |
|
2370 |
sm.removeSelectionInterval(anchor, index); |
|
2371 |
// this is a Windows-only behavior that we want for file lists |
|
2372 |
if (Boolean.TRUE == getClientProperty("Table.isFileList")) { |
|
2373 |
sm.addSelectionInterval(index, index); |
|
2374 |
sm.setAnchorSelectionIndex(anchor); |
|
2375 |
} |
|
2376 |
} |
|
2377 |
} |
|
2378 |
else { |
|
2379 |
sm.setSelectionInterval(anchor, index); |
|
2380 |
} |
|
2381 |
} |
|
2382 |
else { |
|
2383 |
if (toggle) { |
|
2384 |
if (selected) { |
|
2385 |
sm.removeSelectionInterval(index, index); |
|
2386 |
} |
|
2387 |
else { |
|
2388 |
sm.addSelectionInterval(index, index); |
|
2389 |
} |
|
2390 |
} |
|
2391 |
else { |
|
2392 |
sm.setSelectionInterval(index, index); |
|
2393 |
} |
|
2394 |
} |
|
2395 |
} |
|
2396 |
||
2397 |
/** |
|
2398 |
* Updates the selection models of the table, depending on the state of the |
|
2399 |
* two flags: <code>toggle</code> and <code>extend</code>. Most changes |
|
2400 |
* to the selection that are the result of keyboard or mouse events received |
|
2401 |
* by the UI are channeled through this method so that the behavior may be |
|
2402 |
* overridden by a subclass. Some UIs may need more functionality than |
|
2403 |
* this method provides, such as when manipulating the lead for discontiguous |
|
2404 |
* selection, and may not call into this method for some selection changes. |
|
2405 |
* <p> |
|
2406 |
* This implementation uses the following conventions: |
|
2407 |
* <ul> |
|
2408 |
* <li> <code>toggle</code>: <em>false</em>, <code>extend</code>: <em>false</em>. |
|
2409 |
* Clear the previous selection and ensure the new cell is selected. |
|
2410 |
* <li> <code>toggle</code>: <em>false</em>, <code>extend</code>: <em>true</em>. |
|
2411 |
* Extend the previous selection from the anchor to the specified cell, |
|
2412 |
* clearing all other selections. |
|
2413 |
* <li> <code>toggle</code>: <em>true</em>, <code>extend</code>: <em>false</em>. |
|
2414 |
* If the specified cell is selected, deselect it. If it is not selected, select it. |
|
2415 |
* <li> <code>toggle</code>: <em>true</em>, <code>extend</code>: <em>true</em>. |
|
2416 |
* Apply the selection state of the anchor to all cells between it and the |
|
2417 |
* specified cell. |
|
2418 |
* </ul> |
|
2419 |
* @param rowIndex affects the selection at <code>row</code> |
|
2420 |
* @param columnIndex affects the selection at <code>column</code> |
|
2421 |
* @param toggle see description above |
|
2422 |
* @param extend if true, extend the current selection |
|
2423 |
* |
|
2424 |
* @since 1.3 |
|
2425 |
*/ |
|
2426 |
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) { |
|
2427 |
ListSelectionModel rsm = getSelectionModel(); |
|
2428 |
ListSelectionModel csm = getColumnModel().getSelectionModel(); |
|
2429 |
||
2430 |
int anchorRow = getAdjustedIndex(rsm.getAnchorSelectionIndex(), true); |
|
2431 |
int anchorCol = getAdjustedIndex(csm.getAnchorSelectionIndex(), false); |
|
2432 |
||
2433 |
boolean anchorSelected = true; |
|
2434 |
||
2435 |
if (anchorRow == -1) { |
|
2436 |
if (getRowCount() > 0) { |
|
2437 |
anchorRow = 0; |
|
2438 |
} |
|
2439 |
anchorSelected = false; |
|
2440 |
} |
|
2441 |
||
2442 |
if (anchorCol == -1) { |
|
2443 |
if (getColumnCount() > 0) { |
|
2444 |
anchorCol = 0; |
|
2445 |
} |
|
2446 |
anchorSelected = false; |
|
2447 |
} |
|
2448 |
||
2449 |
// Check the selection here rather than in each selection model. |
|
2450 |
// This is significant in cell selection mode if we are supposed |
|
2451 |
// to be toggling the selection. In this case it is better to |
|
2452 |
// ensure that the cell's selection state will indeed be changed. |
|
2453 |
// If this were done in the code for the selection model it |
|
2454 |
// might leave a cell in selection state if the row was |
|
2455 |
// selected but the column was not - as it would toggle them both. |
|
2456 |
boolean selected = isCellSelected(rowIndex, columnIndex); |
|
2457 |
anchorSelected = anchorSelected && isCellSelected(anchorRow, anchorCol); |
|
2458 |
||
2459 |
changeSelectionModel(csm, columnIndex, toggle, extend, selected, |
|
2460 |
anchorCol, anchorSelected); |
|
2461 |
changeSelectionModel(rsm, rowIndex, toggle, extend, selected, |
|
2462 |
anchorRow, anchorSelected); |
|
2463 |
||
2464 |
// Scroll after changing the selection as blit scrolling is immediate, |
|
2465 |
// so that if we cause the repaint after the scroll we end up painting |
|
2466 |
// everything! |
|
2467 |
if (getAutoscrolls()) { |
|
2468 |
Rectangle cellRect = getCellRect(rowIndex, columnIndex, false); |
|
2469 |
if (cellRect != null) { |
|
2470 |
scrollRectToVisible(cellRect); |
|
2471 |
} |
|
2472 |
} |
|
2473 |
} |
|
2474 |
||
2475 |
/** |
|
2476 |
* Returns the foreground color for selected cells. |
|
2477 |
* |
|
2478 |
* @return the <code>Color</code> object for the foreground property |
|
2479 |
* @see #setSelectionForeground |
|
2480 |
* @see #setSelectionBackground |
|
2481 |
*/ |
|
2482 |
public Color getSelectionForeground() { |
|
2483 |
return selectionForeground; |
|
2484 |
} |
|
2485 |
||
2486 |
/** |
|
2487 |
* Sets the foreground color for selected cells. Cell renderers |
|
2488 |
* can use this color to render text and graphics for selected |
|
2489 |
* cells. |
|
2490 |
* <p> |
|
2491 |
* The default value of this property is defined by the look |
|
2492 |
* and feel implementation. |
|
2493 |
* <p> |
|
20455
f6f9a0c2796b
8020688: Broken links in documentation at http://docs.oracle.com/javase/6/docs/api/index.
mcherkas
parents:
20157
diff
changeset
|
2494 |
* This is a <a href="http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html">JavaBeans</a> bound property. |
2 | 2495 |
* |
2496 |
* @param selectionForeground the <code>Color</code> to use in the foreground |
|
2497 |
* for selected list items |
|
2498 |
* @see #getSelectionForeground |
|
2499 |
* @see #setSelectionBackground |
|
2500 |
* @see #setForeground |
|
2501 |
* @see #setBackground |
|
2502 |
* @see #setFont |
|
2503 |
* @beaninfo |
|
2504 |
* bound: true |
|
2505 |
* description: A default foreground color for selected cells. |
|
2506 |
*/ |
|
2507 |
public void setSelectionForeground(Color selectionForeground) { |
|
2508 |
Color old = this.selectionForeground; |
|
2509 |
this.selectionForeground = selectionForeground; |
|
2510 |
firePropertyChange("selectionForeground", old, selectionForeground); |
|
4967
da853cd502c8
6913768: With default SynthLookAndFeel instance installed new JTable creation leads to throwing NPE
rupashka
parents:
4379
diff
changeset
|
2511 |
repaint(); |
2 | 2512 |
} |
2513 |
||
2514 |
/** |
|
2515 |
* Returns the background color for selected cells. |
|
2516 |
* |
|
2517 |
* @return the <code>Color</code> used for the background of selected list items |
|
2518 |
* @see #setSelectionBackground |
|
2519 |
* @see #setSelectionForeground |
|
2520 |
*/ |
|
2521 |
public Color getSelectionBackground() { |
|
2522 |
return selectionBackground; |
|
2523 |
} |
|
2524 |
||
2525 |
/** |
|
2526 |
* Sets the background color for selected cells. Cell renderers |
|
2527 |
* can use this color to the fill selected cells. |
|
2528 |
* <p> |
|
2529 |
* The default value of this property is defined by the look |
|
2530 |
* and feel implementation. |
|
2531 |
* <p> |
|
20455
f6f9a0c2796b
8020688: Broken links in documentation at http://docs.oracle.com/javase/6/docs/api/index.
mcherkas
parents:
20157
diff
changeset
|
2532 |
* This is a <a href="http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html">JavaBeans</a> bound property. |
2 | 2533 |
* |
2534 |
* @param selectionBackground the <code>Color</code> to use for the background |
|
2535 |
* of selected cells |
|
2536 |
* @see #getSelectionBackground |
|
2537 |
* @see #setSelectionForeground |
|
2538 |
* @see #setForeground |
|
2539 |
* @see #setBackground |
|
2540 |
* @see #setFont |
|
2541 |
* @beaninfo |
|
2542 |
* bound: true |
|
2543 |
* description: A default background color for selected cells. |
|
2544 |
*/ |
|
2545 |
public void setSelectionBackground(Color selectionBackground) { |
|
2546 |
Color old = this.selectionBackground; |
|
2547 |
this.selectionBackground = selectionBackground; |
|
2548 |
firePropertyChange("selectionBackground", old, selectionBackground); |
|
4967
da853cd502c8
6913768: With default SynthLookAndFeel instance installed new JTable creation leads to throwing NPE
rupashka
parents:
4379
diff
changeset
|
2549 |
repaint(); |
2 | 2550 |
} |
2551 |
||
2552 |
/** |
|
2553 |
* Returns the <code>TableColumn</code> object for the column in the table |
|
2554 |
* whose identifier is equal to <code>identifier</code>, when compared using |
|
2555 |
* <code>equals</code>. |
|
2556 |
* |
|
2557 |
* @return the <code>TableColumn</code> object that matches the identifier |
|
2558 |
* @exception IllegalArgumentException if <code>identifier</code> is <code>null</code> or no <code>TableColumn</code> has this identifier |
|
2559 |
* |
|
2560 |
* @param identifier the identifier object |
|
2561 |
*/ |
|
2562 |
public TableColumn getColumn(Object identifier) { |
|
2563 |
TableColumnModel cm = getColumnModel(); |
|
2564 |
int columnIndex = cm.getColumnIndex(identifier); |
|
2565 |
return cm.getColumn(columnIndex); |
|
2566 |
} |
|
2567 |
||
2568 |
// |
|
2569 |
// Informally implement the TableModel interface. |
|
2570 |
// |
|
2571 |
||
2572 |
/** |
|
2573 |
* Maps the index of the column in the view at |
|
2574 |
* <code>viewColumnIndex</code> to the index of the column |
|
2575 |
* in the table model. Returns the index of the corresponding |
|
2576 |
* column in the model. If <code>viewColumnIndex</code> |
|
2577 |
* is less than zero, returns <code>viewColumnIndex</code>. |
|
2578 |
* |
|
2579 |
* @param viewColumnIndex the index of the column in the view |
|
2580 |
* @return the index of the corresponding column in the model |
|
2581 |
* |
|
2582 |
* @see #convertColumnIndexToView |
|
2583 |
*/ |
|
2584 |
public int convertColumnIndexToModel(int viewColumnIndex) { |
|
5590
3ec077d7e893
6884066: JTableHeader listens mouse in disabled state and doesn't work when not attached to a table
alexp
parents:
5449
diff
changeset
|
2585 |
return SwingUtilities2.convertColumnIndexToModel( |
3ec077d7e893
6884066: JTableHeader listens mouse in disabled state and doesn't work when not attached to a table
alexp
parents:
5449
diff
changeset
|
2586 |
getColumnModel(), viewColumnIndex); |
2 | 2587 |
} |
2588 |
||
2589 |
/** |
|
2590 |
* Maps the index of the column in the table model at |
|
2591 |
* <code>modelColumnIndex</code> to the index of the column |
|
2592 |
* in the view. Returns the index of the |
|
2593 |
* corresponding column in the view; returns -1 if this column is not |
|
2594 |
* being displayed. If <code>modelColumnIndex</code> is less than zero, |
|
2595 |
* returns <code>modelColumnIndex</code>. |
|
2596 |
* |
|
2597 |
* @param modelColumnIndex the index of the column in the model |
|
2598 |
* @return the index of the corresponding column in the view |
|
2599 |
* |
|
2600 |
* @see #convertColumnIndexToModel |
|
2601 |
*/ |
|
2602 |
public int convertColumnIndexToView(int modelColumnIndex) { |
|
5590
3ec077d7e893
6884066: JTableHeader listens mouse in disabled state and doesn't work when not attached to a table
alexp
parents:
5449
diff
changeset
|
2603 |
return SwingUtilities2.convertColumnIndexToView( |
3ec077d7e893
6884066: JTableHeader listens mouse in disabled state and doesn't work when not attached to a table
alexp
parents:
5449
diff
changeset
|
2604 |
getColumnModel(), modelColumnIndex); |
2 | 2605 |
} |
2606 |
||
2607 |
/** |
|
2608 |
* Maps the index of the row in terms of the |
|
2609 |
* <code>TableModel</code> to the view. If the contents of the |
|
2610 |
* model are not sorted the model and view indices are the same. |
|
2611 |
* |
|
2612 |
* @param modelRowIndex the index of the row in terms of the model |
|
2613 |
* @return the index of the corresponding row in the view, or -1 if |
|
2614 |
* the row isn't visible |
|
2615 |
* @throws IndexOutOfBoundsException if sorting is enabled and passed an |
|
2616 |
* index outside the number of rows of the <code>TableModel</code> |
|
2617 |
* @see javax.swing.table.TableRowSorter |
|
2618 |
* @since 1.6 |
|
2619 |
*/ |
|
2620 |
public int convertRowIndexToView(int modelRowIndex) { |
|
2621 |
RowSorter sorter = getRowSorter(); |
|
2622 |
if (sorter != null) { |
|
2623 |
return sorter.convertRowIndexToView(modelRowIndex); |
|
2624 |
} |
|
2625 |
return modelRowIndex; |
|
2626 |
} |
|
2627 |
||
2628 |
/** |
|
2629 |
* Maps the index of the row in terms of the view to the |
|
2630 |
* underlying <code>TableModel</code>. If the contents of the |
|
2631 |
* model are not sorted the model and view indices are the same. |
|
2632 |
* |
|
2633 |
* @param viewRowIndex the index of the row in the view |
|
2634 |
* @return the index of the corresponding row in the model |
|
2635 |
* @throws IndexOutOfBoundsException if sorting is enabled and passed an |
|
2636 |
* index outside the range of the <code>JTable</code> as |
|
2637 |
* determined by the method <code>getRowCount</code> |
|
2638 |
* @see javax.swing.table.TableRowSorter |
|
2639 |
* @see #getRowCount |
|
2640 |
* @since 1.6 |
|
2641 |
*/ |
|
2642 |
public int convertRowIndexToModel(int viewRowIndex) { |
|
2643 |
RowSorter sorter = getRowSorter(); |
|
2644 |
if (sorter != null) { |
|
2645 |
return sorter.convertRowIndexToModel(viewRowIndex); |
|
2646 |
} |
|
2647 |
return viewRowIndex; |
|
2648 |
} |
|
2649 |
||
2650 |
/** |
|
2651 |
* Returns the number of rows that can be shown in the |
|
2652 |
* <code>JTable</code>, given unlimited space. If a |
|
2653 |
* <code>RowSorter</code> with a filter has been specified, the |
|
2654 |
* number of rows returned may differ from that of the underlying |
|
2655 |
* <code>TableModel</code>. |
|
2656 |
* |
|
2657 |
* @return the number of rows shown in the <code>JTable</code> |
|
2658 |
* @see #getColumnCount |
|
2659 |
*/ |
|
2660 |
public int getRowCount() { |
|
2661 |
RowSorter sorter = getRowSorter(); |
|
2662 |
if (sorter != null) { |
|
2663 |
return sorter.getViewRowCount(); |
|
2664 |
} |
|
2665 |
return getModel().getRowCount(); |
|
2666 |
} |
|
2667 |
||
2668 |
/** |
|
2669 |
* Returns the number of columns in the column model. Note that this may |
|
2670 |
* be different from the number of columns in the table model. |
|
2671 |
* |
|
2672 |
* @return the number of columns in the table |
|
2673 |
* @see #getRowCount |
|
2674 |
* @see #removeColumn |
|
2675 |
*/ |
|
2676 |
public int getColumnCount() { |
|
2677 |
return getColumnModel().getColumnCount(); |
|
2678 |
} |
|
2679 |
||
2680 |
/** |
|
2681 |
* Returns the name of the column appearing in the view at |
|
2682 |
* column position <code>column</code>. |
|
2683 |
* |
|
2684 |
* @param column the column in the view being queried |
|
2685 |
* @return the name of the column at position <code>column</code> |
|
2686 |
in the view where the first column is column 0 |
|
2687 |
*/ |
|
2688 |
public String getColumnName(int column) { |
|
2689 |
return getModel().getColumnName(convertColumnIndexToModel(column)); |
|
2690 |
} |
|
2691 |
||
2692 |
/** |
|
2693 |
* Returns the type of the column appearing in the view at |
|
2694 |
* column position <code>column</code>. |
|
2695 |
* |
|
2696 |
* @param column the column in the view being queried |
|
2697 |
* @return the type of the column at position <code>column</code> |
|
2698 |
* in the view where the first column is column 0 |
|
2699 |
*/ |
|
2700 |
public Class<?> getColumnClass(int column) { |
|
2701 |
return getModel().getColumnClass(convertColumnIndexToModel(column)); |
|
2702 |
} |
|
2703 |
||
2704 |
/** |
|
2705 |
* Returns the cell value at <code>row</code> and <code>column</code>. |
|
2706 |
* <p> |
|
2707 |
* <b>Note</b>: The column is specified in the table view's display |
|
2708 |
* order, and not in the <code>TableModel</code>'s column |
|
2709 |
* order. This is an important distinction because as the |
|
2710 |
* user rearranges the columns in the table, |
|
2711 |
* the column at a given index in the view will change. |
|
2712 |
* Meanwhile the user's actions never affect the model's |
|
2713 |
* column ordering. |
|
2714 |
* |
|
2715 |
* @param row the row whose value is to be queried |
|
2716 |
* @param column the column whose value is to be queried |
|
2717 |
* @return the Object at the specified cell |
|
2718 |
*/ |
|
2719 |
public Object getValueAt(int row, int column) { |
|
2720 |
return getModel().getValueAt(convertRowIndexToModel(row), |
|
2721 |
convertColumnIndexToModel(column)); |
|
2722 |
} |
|
2723 |
||
2724 |
/** |
|
2725 |
* Sets the value for the cell in the table model at <code>row</code> |
|
2726 |
* and <code>column</code>. |
|
2727 |
* <p> |
|
2728 |
* <b>Note</b>: The column is specified in the table view's display |
|
2729 |
* order, and not in the <code>TableModel</code>'s column |
|
2730 |
* order. This is an important distinction because as the |
|
2731 |
* user rearranges the columns in the table, |
|
2732 |
* the column at a given index in the view will change. |
|
2733 |
* Meanwhile the user's actions never affect the model's |
|
2734 |
* column ordering. |
|
2735 |
* |
|
2736 |
* <code>aValue</code> is the new value. |
|
2737 |
* |
|
2738 |
* @param aValue the new value |
|
2739 |
* @param row the row of the cell to be changed |
|
2740 |
* @param column the column of the cell to be changed |
|
2741 |
* @see #getValueAt |
|
2742 |
*/ |
|
2743 |
public void setValueAt(Object aValue, int row, int column) { |
|
2744 |
getModel().setValueAt(aValue, convertRowIndexToModel(row), |
|
2745 |
convertColumnIndexToModel(column)); |
|
2746 |
} |
|
2747 |
||
2748 |
/** |
|
2749 |
* Returns true if the cell at <code>row</code> and <code>column</code> |
|
2750 |
* is editable. Otherwise, invoking <code>setValueAt</code> on the cell |
|
2751 |
* will have no effect. |
|
2752 |
* <p> |
|
2753 |
* <b>Note</b>: The column is specified in the table view's display |
|
2754 |
* order, and not in the <code>TableModel</code>'s column |
|
2755 |
* order. This is an important distinction because as the |
|
2756 |
* user rearranges the columns in the table, |
|
2757 |
* the column at a given index in the view will change. |
|
2758 |
* Meanwhile the user's actions never affect the model's |
|
2759 |
* column ordering. |
|
2760 |
* |
|
2761 |
* |
|
2762 |
* @param row the row whose value is to be queried |
|
2763 |
* @param column the column whose value is to be queried |
|
2764 |
* @return true if the cell is editable |
|
2765 |
* @see #setValueAt |
|
2766 |
*/ |
|
2767 |
public boolean isCellEditable(int row, int column) { |
|
2768 |
return getModel().isCellEditable(convertRowIndexToModel(row), |
|
2769 |
convertColumnIndexToModel(column)); |
|
2770 |
} |
|
2771 |
// |
|
2772 |
// Adding and removing columns in the view |
|
2773 |
// |
|
2774 |
||
2775 |
/** |
|
2776 |
* Appends <code>aColumn</code> to the end of the array of columns held by |
|
2777 |
* this <code>JTable</code>'s column model. |
|
2778 |
* If the column name of <code>aColumn</code> is <code>null</code>, |
|
2779 |
* sets the column name of <code>aColumn</code> to the name |
|
2780 |
* returned by <code>getModel().getColumnName()</code>. |
|
2781 |
* <p> |
|
2782 |
* To add a column to this <code>JTable</code> to display the |
|
2783 |
* <code>modelColumn</code>'th column of data in the model with a |
|
2784 |
* given <code>width</code>, <code>cellRenderer</code>, |
|
2785 |
* and <code>cellEditor</code> you can use: |
|
2786 |
* <pre> |
|
2787 |
* |
|
2788 |
* addColumn(new TableColumn(modelColumn, width, cellRenderer, cellEditor)); |
|
2789 |
* |
|
2790 |
* </pre> |
|
2791 |
* [Any of the <code>TableColumn</code> constructors can be used |
|
2792 |
* instead of this one.] |
|
2793 |
* The model column number is stored inside the <code>TableColumn</code> |
|
2794 |
* and is used during rendering and editing to locate the appropriates |
|
2795 |
* data values in the model. The model column number does not change |
|
2796 |
* when columns are reordered in the view. |
|
2797 |
* |
|
2798 |
* @param aColumn the <code>TableColumn</code> to be added |
|
2799 |
* @see #removeColumn |
|
2800 |
*/ |
|
2801 |
public void addColumn(TableColumn aColumn) { |
|
2802 |
if (aColumn.getHeaderValue() == null) { |
|
2803 |
int modelColumn = aColumn.getModelIndex(); |
|
2804 |
String columnName = getModel().getColumnName(modelColumn); |
|
2805 |
aColumn.setHeaderValue(columnName); |
|
2806 |
} |
|
2807 |
getColumnModel().addColumn(aColumn); |
|
2808 |
} |
|
2809 |
||
2810 |
/** |
|
2811 |
* Removes <code>aColumn</code> from this <code>JTable</code>'s |
|
2812 |
* array of columns. Note: this method does not remove the column |
|
2813 |
* of data from the model; it just removes the <code>TableColumn</code> |
|
2814 |
* that was responsible for displaying it. |
|
2815 |
* |
|
2816 |
* @param aColumn the <code>TableColumn</code> to be removed |
|
2817 |
* @see #addColumn |
|
2818 |
*/ |
|
2819 |
public void removeColumn(TableColumn aColumn) { |
|
2820 |
getColumnModel().removeColumn(aColumn); |
|
2821 |
} |
|
2822 |
||
2823 |
/** |
|
2824 |
* Moves the column <code>column</code> to the position currently |
|
2825 |
* occupied by the column <code>targetColumn</code> in the view. |
|
2826 |
* The old column at <code>targetColumn</code> is |
|
2827 |
* shifted left or right to make room. |
|
2828 |
* |
|
2829 |
* @param column the index of column to be moved |
|
2830 |
* @param targetColumn the new index of the column |
|
2831 |
*/ |
|
2832 |
public void moveColumn(int column, int targetColumn) { |
|
2833 |
getColumnModel().moveColumn(column, targetColumn); |
|
2834 |
} |
|
2835 |
||
2836 |
// |
|
2837 |
// Cover methods for various models and helper methods |
|
2838 |
// |
|
2839 |
||
2840 |
/** |
|
2841 |
* Returns the index of the column that <code>point</code> lies in, |
|
2842 |
* or -1 if the result is not in the range |
|
2843 |
* [0, <code>getColumnCount()</code>-1]. |
|
2844 |
* |
|
2845 |
* @param point the location of interest |
|
2846 |
* @return the index of the column that <code>point</code> lies in, |
|
2847 |
* or -1 if the result is not in the range |
|
2848 |
* [0, <code>getColumnCount()</code>-1] |
|
2849 |
* @see #rowAtPoint |
|
2850 |
*/ |
|
2851 |
public int columnAtPoint(Point point) { |
|
2852 |
int x = point.x; |
|
2853 |
if( !getComponentOrientation().isLeftToRight() ) { |
|
2854 |
x = getWidth() - x - 1; |
|
2855 |
} |
|
2856 |
return getColumnModel().getColumnIndexAtX(x); |
|
2857 |
} |
|
2858 |
||
2859 |
/** |
|
2860 |
* Returns the index of the row that <code>point</code> lies in, |
|
2861 |
* or -1 if the result is not in the range |
|
2862 |
* [0, <code>getRowCount()</code>-1]. |
|
2863 |
* |
|
2864 |
* @param point the location of interest |
|
2865 |
* @return the index of the row that <code>point</code> lies in, |
|
2866 |
* or -1 if the result is not in the range |
|
2867 |
* [0, <code>getRowCount()</code>-1] |
|
2868 |
* @see #columnAtPoint |
|
2869 |
*/ |
|
2870 |
public int rowAtPoint(Point point) { |
|
2871 |
int y = point.y; |
|
2872 |
int result = (rowModel == null) ? y/getRowHeight() : rowModel.getIndex(y); |
|
2873 |
if (result < 0) { |
|
2874 |
return -1; |
|
2875 |
} |
|
2876 |
else if (result >= getRowCount()) { |
|
2877 |
return -1; |
|
2878 |
} |
|
2879 |
else { |
|
2880 |
return result; |
|
2881 |
} |
|
2882 |
} |
|
2883 |
||
2884 |
/** |
|
2885 |
* Returns a rectangle for the cell that lies at the intersection of |
|
2886 |
* <code>row</code> and <code>column</code>. |
|
2887 |
* If <code>includeSpacing</code> is true then the value returned |
|
2888 |
* has the full height and width of the row and column |
|
2889 |
* specified. If it is false, the returned rectangle is inset by the |
|
2890 |
* intercell spacing to return the true bounds of the rendering or |
|
2891 |
* editing component as it will be set during rendering. |
|
2892 |
* <p> |
|
2893 |
* If the column index is valid but the row index is less |
|
2894 |
* than zero the method returns a rectangle with the |
|
2895 |
* <code>y</code> and <code>height</code> values set appropriately |
|
2896 |
* and the <code>x</code> and <code>width</code> values both set |
|
2897 |
* to zero. In general, when either the row or column indices indicate a |
|
2898 |
* cell outside the appropriate range, the method returns a rectangle |
|
2899 |
* depicting the closest edge of the closest cell that is within |
|
2900 |
* the table's range. When both row and column indices are out |
|
2901 |
* of range the returned rectangle covers the closest |
|
2902 |
* point of the closest cell. |
|
2903 |
* <p> |
|
2904 |
* In all cases, calculations that use this method to calculate |
|
2905 |
* results along one axis will not fail because of anomalies in |
|
2906 |
* calculations along the other axis. When the cell is not valid |
|
2907 |
* the <code>includeSpacing</code> parameter is ignored. |
|
2908 |
* |
|
2909 |
* @param row the row index where the desired cell |
|
2910 |
* is located |
|
2911 |
* @param column the column index where the desired cell |
|
2912 |
* is located in the display; this is not |
|
2913 |
* necessarily the same as the column index |
|
2914 |
* in the data model for the table; the |
|
2915 |
* {@link #convertColumnIndexToView(int)} |
|
2916 |
* method may be used to convert a data |
|
2917 |
* model column index to a display |
|
2918 |
* column index |
|
2919 |
* @param includeSpacing if false, return the true cell bounds - |
|
2920 |
* computed by subtracting the intercell |
|
2921 |
* spacing from the height and widths of |
|
2922 |
* the column and row models |
|
2923 |
* |
|
2924 |
* @return the rectangle containing the cell at location |
|
2925 |
* <code>row</code>,<code>column</code> |
|
2926 |
* @see #getIntercellSpacing |
|
2927 |
*/ |
|
2928 |
public Rectangle getCellRect(int row, int column, boolean includeSpacing) { |
|
2929 |
Rectangle r = new Rectangle(); |
|
2930 |
boolean valid = true; |
|
2931 |
if (row < 0) { |
|
2932 |
// y = height = 0; |
|
2933 |
valid = false; |
|
2934 |
} |
|
2935 |
else if (row >= getRowCount()) { |
|
2936 |
r.y = getHeight(); |
|
2937 |
valid = false; |
|
2938 |
} |
|
2939 |
else { |
|
2940 |
r.height = getRowHeight(row); |
|
2941 |
r.y = (rowModel == null) ? row * r.height : rowModel.getPosition(row); |
|
2942 |
} |
|
2943 |
||
2944 |
if (column < 0) { |
|
2945 |
if( !getComponentOrientation().isLeftToRight() ) { |
|
2946 |
r.x = getWidth(); |
|
2947 |
} |
|
2948 |
// otherwise, x = width = 0; |
|
2949 |
valid = false; |
|
2950 |
} |
|
2951 |
else if (column >= getColumnCount()) { |
|
2952 |
if( getComponentOrientation().isLeftToRight() ) { |
|
2953 |
r.x = getWidth(); |
|
2954 |
} |
|
2955 |
// otherwise, x = width = 0; |
|
2956 |
valid = false; |
|
2957 |
} |
|
2958 |
else { |
|
2959 |
TableColumnModel cm = getColumnModel(); |
|
2960 |
if( getComponentOrientation().isLeftToRight() ) { |
|
2961 |
for(int i = 0; i < column; i++) { |
|
2962 |
r.x += cm.getColumn(i).getWidth(); |
|
2963 |
} |
|
2964 |
} else { |
|
2965 |
for(int i = cm.getColumnCount()-1; i > column; i--) { |
|
2966 |
r.x += cm.getColumn(i).getWidth(); |
|
2967 |
} |
|
2968 |
} |
|
2969 |
r.width = cm.getColumn(column).getWidth(); |
|
2970 |
} |
|
2971 |
||
2972 |
if (valid && !includeSpacing) { |
|
2973 |
// Bound the margins by their associated dimensions to prevent |
|
2974 |
// returning bounds with negative dimensions. |
|
2975 |
int rm = Math.min(getRowMargin(), r.height); |
|
2976 |
int cm = Math.min(getColumnModel().getColumnMargin(), r.width); |
|
2977 |
// This is not the same as grow(), it rounds differently. |
|
2978 |
r.setBounds(r.x + cm/2, r.y + rm/2, r.width - cm, r.height - rm); |
|
2979 |
} |
|
2980 |
return r; |
|
2981 |
} |
|
2982 |
||
2983 |
private int viewIndexForColumn(TableColumn aColumn) { |
|
2984 |
TableColumnModel cm = getColumnModel(); |
|
2985 |
for (int column = 0; column < cm.getColumnCount(); column++) { |
|
2986 |
if (cm.getColumn(column) == aColumn) { |
|
2987 |
return column; |
|
2988 |
} |
|
2989 |
} |
|
2990 |
return -1; |
|
2991 |
} |
|
2992 |
||
2993 |
/** |
|
2994 |
* Causes this table to lay out its rows and columns. Overridden so |
|
21278 | 2995 |
* that columns can be resized to accommodate a change in the size of |
2 | 2996 |
* a containing parent. |
2997 |
* Resizes one or more of the columns in the table |
|
2998 |
* so that the total width of all of this <code>JTable</code>'s |
|
2999 |
* columns is equal to the width of the table. |
|
3000 |
* <p> |
|
3001 |
* Before the layout begins the method gets the |
|
3002 |
* <code>resizingColumn</code> of the <code>tableHeader</code>. |
|
3003 |
* When the method is called as a result of the resizing of an enclosing window, |
|
3004 |
* the <code>resizingColumn</code> is <code>null</code>. This means that resizing |
|
3005 |
* has taken place "outside" the <code>JTable</code> and the change - |
|
3006 |
* or "delta" - should be distributed to all of the columns regardless |
|
3007 |
* of this <code>JTable</code>'s automatic resize mode. |
|
3008 |
* <p> |
|
3009 |
* If the <code>resizingColumn</code> is not <code>null</code>, it is one of |
|
3010 |
* the columns in the table that has changed size rather than |
|
3011 |
* the table itself. In this case the auto-resize modes govern |
|
3012 |
* the way the extra (or deficit) space is distributed |
|
3013 |
* amongst the available columns. |
|
3014 |
* <p> |
|
3015 |
* The modes are: |
|
3016 |
* <ul> |
|
3017 |
* <li> AUTO_RESIZE_OFF: Don't automatically adjust the column's |
|
21278 | 3018 |
* widths at all. Use a horizontal scrollbar to accommodate the |
2 | 3019 |
* columns when their sum exceeds the width of the |
3020 |
* <code>Viewport</code>. If the <code>JTable</code> is not |
|
3021 |
* enclosed in a <code>JScrollPane</code> this may |
|
3022 |
* leave parts of the table invisible. |
|
3023 |
* <li> AUTO_RESIZE_NEXT_COLUMN: Use just the column after the |
|
3024 |
* resizing column. This results in the "boundary" or divider |
|
3025 |
* between adjacent cells being independently adjustable. |
|
3026 |
* <li> AUTO_RESIZE_SUBSEQUENT_COLUMNS: Use all columns after the |
|
3027 |
* one being adjusted to absorb the changes. This is the |
|
3028 |
* default behavior. |
|
3029 |
* <li> AUTO_RESIZE_LAST_COLUMN: Automatically adjust the |
|
3030 |
* size of the last column only. If the bounds of the last column |
|
3031 |
* prevent the desired size from being allocated, set the |
|
3032 |
* width of the last column to the appropriate limit and make |
|
3033 |
* no further adjustments. |
|
3034 |
* <li> AUTO_RESIZE_ALL_COLUMNS: Spread the delta amongst all the columns |
|
3035 |
* in the <code>JTable</code>, including the one that is being |
|
3036 |
* adjusted. |
|
3037 |
* </ul> |
|
3038 |
* <p> |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3039 |
* <b>Note:</b> When a <code>JTable</code> makes adjustments |
2 | 3040 |
* to the widths of the columns it respects their minimum and |
3041 |
* maximum values absolutely. It is therefore possible that, |
|
3042 |
* even after this method is called, the total width of the columns |
|
3043 |
* is still not equal to the width of the table. When this happens |
|
3044 |
* the <code>JTable</code> does not put itself |
|
3045 |
* in AUTO_RESIZE_OFF mode to bring up a scroll bar, or break other |
|
3046 |
* commitments of its current auto-resize mode -- instead it |
|
3047 |
* allows its bounds to be set larger (or smaller) than the total of the |
|
3048 |
* column minimum or maximum, meaning, either that there |
|
3049 |
* will not be enough room to display all of the columns, or that the |
|
3050 |
* columns will not fill the <code>JTable</code>'s bounds. |
|
3051 |
* These respectively, result in the clipping of some columns |
|
3052 |
* or an area being painted in the <code>JTable</code>'s |
|
3053 |
* background color during painting. |
|
3054 |
* <p> |
|
3055 |
* The mechanism for distributing the delta amongst the available |
|
3056 |
* columns is provided in a private method in the <code>JTable</code> |
|
3057 |
* class: |
|
3058 |
* <pre> |
|
3059 |
* adjustSizes(long targetSize, final Resizable3 r, boolean inverse) |
|
3060 |
* </pre> |
|
3061 |
* an explanation of which is provided in the following section. |
|
3062 |
* <code>Resizable3</code> is a private |
|
3063 |
* interface that allows any data structure containing a collection |
|
3064 |
* of elements with a size, preferred size, maximum size and minimum size |
|
3065 |
* to have its elements manipulated by the algorithm. |
|
21982 | 3066 |
* |
2 | 3067 |
* <H3> Distributing the delta </H3> |
21982 | 3068 |
* |
2 | 3069 |
* <H4> Overview </H4> |
3070 |
* <P> |
|
3071 |
* Call "DELTA" the difference between the target size and the |
|
3072 |
* sum of the preferred sizes of the elements in r. The individual |
|
3073 |
* sizes are calculated by taking the original preferred |
|
3074 |
* sizes and adding a share of the DELTA - that share being based on |
|
3075 |
* how far each preferred size is from its limiting bound (minimum or |
|
3076 |
* maximum). |
|
21982 | 3077 |
* |
2 | 3078 |
* <H4>Definition</H4> |
3079 |
* <P> |
|
3080 |
* Call the individual constraints min[i], max[i], and pref[i]. |
|
3081 |
* <p> |
|
3082 |
* Call their respective sums: MIN, MAX, and PREF. |
|
3083 |
* <p> |
|
3084 |
* Each new size will be calculated using: |
|
21982 | 3085 |
* |
2 | 3086 |
* <pre> |
3087 |
* size[i] = pref[i] + delta[i] |
|
3088 |
* </pre> |
|
3089 |
* where each individual delta[i] is calculated according to: |
|
3090 |
* <p> |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3091 |
* If (DELTA < 0) we are in shrink mode where: |
21982 | 3092 |
* |
2 | 3093 |
* <PRE> |
3094 |
* DELTA |
|
3095 |
* delta[i] = ------------ * (pref[i] - min[i]) |
|
3096 |
* (PREF - MIN) |
|
3097 |
* </PRE> |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3098 |
* If (DELTA > 0) we are in expand mode where: |
21982 | 3099 |
* |
2 | 3100 |
* <PRE> |
3101 |
* DELTA |
|
3102 |
* delta[i] = ------------ * (max[i] - pref[i]) |
|
3103 |
* (MAX - PREF) |
|
3104 |
* </PRE> |
|
3105 |
* <P> |
|
3106 |
* The overall effect is that the total size moves that same percentage, |
|
3107 |
* k, towards the total minimum or maximum and that percentage guarantees |
|
21278 | 3108 |
* accommodation of the required space, DELTA. |
2 | 3109 |
* |
3110 |
* <H4>Details</H4> |
|
3111 |
* <P> |
|
3112 |
* Naive evaluation of the formulae presented here would be subject to |
|
3113 |
* the aggregated rounding errors caused by doing this operation in finite |
|
3114 |
* precision (using ints). To deal with this, the multiplying factor above, |
|
3115 |
* is constantly recalculated and this takes account of the rounding |
|
3116 |
* errors in the previous iterations. The result is an algorithm that |
|
3117 |
* produces a set of integers whose values exactly sum to the supplied |
|
3118 |
* <code>targetSize</code>, and does so by spreading the rounding |
|
3119 |
* errors evenly over the given elements. |
|
3120 |
* |
|
3121 |
* <H4>When the MAX and MIN bounds are hit</H4> |
|
3122 |
* <P> |
|
3123 |
* When <code>targetSize</code> is outside the [MIN, MAX] range, |
|
3124 |
* the algorithm sets all sizes to their appropriate limiting value |
|
3125 |
* (maximum or minimum). |
|
3126 |
* |
|
3127 |
*/ |
|
3128 |
public void doLayout() { |
|
3129 |
TableColumn resizingColumn = getResizingColumn(); |
|
3130 |
if (resizingColumn == null) { |
|
3131 |
setWidthsFromPreferredWidths(false); |
|
3132 |
} |
|
3133 |
else { |
|
3134 |
// JTable behaves like a layout manger - but one in which the |
|
3135 |
// user can come along and dictate how big one of the children |
|
3136 |
// (columns) is supposed to be. |
|
3137 |
||
3138 |
// A column has been resized and JTable may need to distribute |
|
3139 |
// any overall delta to other columns, according to the resize mode. |
|
3140 |
int columnIndex = viewIndexForColumn(resizingColumn); |
|
3141 |
int delta = getWidth() - getColumnModel().getTotalColumnWidth(); |
|
3142 |
accommodateDelta(columnIndex, delta); |
|
3143 |
delta = getWidth() - getColumnModel().getTotalColumnWidth(); |
|
3144 |
||
3145 |
// If the delta cannot be completely accomodated, then the |
|
3146 |
// resizing column will have to take any remainder. This means |
|
3147 |
// that the column is not being allowed to take the requested |
|
3148 |
// width. This happens under many circumstances: For example, |
|
3149 |
// AUTO_RESIZE_NEXT_COLUMN specifies that any delta be distributed |
|
3150 |
// to the column after the resizing column. If one were to attempt |
|
3151 |
// to resize the last column of the table, there would be no |
|
3152 |
// columns after it, and hence nowhere to distribute the delta. |
|
3153 |
// It would then be given entirely back to the resizing column, |
|
3154 |
// preventing it from changing size. |
|
3155 |
if (delta != 0) { |
|
3156 |
resizingColumn.setWidth(resizingColumn.getWidth() + delta); |
|
3157 |
} |
|
3158 |
||
3159 |
// At this point the JTable has to work out what preferred sizes |
|
3160 |
// would have resulted in the layout the user has chosen. |
|
3161 |
// Thereafter, during window resizing etc. it has to work off |
|
3162 |
// the preferred sizes as usual - the idea being that, whatever |
|
3163 |
// the user does, everything stays in synch and things don't jump |
|
3164 |
// around. |
|
3165 |
setWidthsFromPreferredWidths(true); |
|
3166 |
} |
|
3167 |
||
3168 |
super.doLayout(); |
|
3169 |
} |
|
3170 |
||
3171 |
private TableColumn getResizingColumn() { |
|
3172 |
return (tableHeader == null) ? null |
|
3173 |
: tableHeader.getResizingColumn(); |
|
3174 |
} |
|
3175 |
||
3176 |
/** |
|
3177 |
* Sizes the table columns to fit the available space. |
|
3178 |
* @deprecated As of Swing version 1.0.3, |
|
3179 |
* replaced by <code>doLayout()</code>. |
|
3180 |
* @see #doLayout |
|
3181 |
*/ |
|
3182 |
@Deprecated |
|
3183 |
public void sizeColumnsToFit(boolean lastColumnOnly) { |
|
3184 |
int oldAutoResizeMode = autoResizeMode; |
|
3185 |
setAutoResizeMode(lastColumnOnly ? AUTO_RESIZE_LAST_COLUMN |
|
3186 |
: AUTO_RESIZE_ALL_COLUMNS); |
|
3187 |
sizeColumnsToFit(-1); |
|
3188 |
setAutoResizeMode(oldAutoResizeMode); |
|
3189 |
} |
|
3190 |
||
3191 |
/** |
|
3192 |
* Obsolete as of Java 2 platform v1.4. Please use the |
|
3193 |
* <code>doLayout()</code> method instead. |
|
3194 |
* @param resizingColumn the column whose resizing made this adjustment |
|
3195 |
* necessary or -1 if there is no such column |
|
3196 |
* @see #doLayout |
|
3197 |
*/ |
|
3198 |
public void sizeColumnsToFit(int resizingColumn) { |
|
3199 |
if (resizingColumn == -1) { |
|
3200 |
setWidthsFromPreferredWidths(false); |
|
3201 |
} |
|
3202 |
else { |
|
3203 |
if (autoResizeMode == AUTO_RESIZE_OFF) { |
|
3204 |
TableColumn aColumn = getColumnModel().getColumn(resizingColumn); |
|
3205 |
aColumn.setPreferredWidth(aColumn.getWidth()); |
|
3206 |
} |
|
3207 |
else { |
|
3208 |
int delta = getWidth() - getColumnModel().getTotalColumnWidth(); |
|
3209 |
accommodateDelta(resizingColumn, delta); |
|
3210 |
setWidthsFromPreferredWidths(true); |
|
3211 |
} |
|
3212 |
} |
|
3213 |
} |
|
3214 |
||
3215 |
private void setWidthsFromPreferredWidths(final boolean inverse) { |
|
3216 |
int totalWidth = getWidth(); |
|
3217 |
int totalPreferred = getPreferredSize().width; |
|
3218 |
int target = !inverse ? totalWidth : totalPreferred; |
|
3219 |
||
3220 |
final TableColumnModel cm = columnModel; |
|
3221 |
Resizable3 r = new Resizable3() { |
|
3222 |
public int getElementCount() { return cm.getColumnCount(); } |
|
3223 |
public int getLowerBoundAt(int i) { return cm.getColumn(i).getMinWidth(); } |
|
3224 |
public int getUpperBoundAt(int i) { return cm.getColumn(i).getMaxWidth(); } |
|
3225 |
public int getMidPointAt(int i) { |
|
3226 |
if (!inverse) { |
|
3227 |
return cm.getColumn(i).getPreferredWidth(); |
|
3228 |
} |
|
3229 |
else { |
|
3230 |
return cm.getColumn(i).getWidth(); |
|
3231 |
} |
|
3232 |
} |
|
3233 |
public void setSizeAt(int s, int i) { |
|
3234 |
if (!inverse) { |
|
3235 |
cm.getColumn(i).setWidth(s); |
|
3236 |
} |
|
3237 |
else { |
|
3238 |
cm.getColumn(i).setPreferredWidth(s); |
|
3239 |
} |
|
3240 |
} |
|
3241 |
}; |
|
3242 |
||
3243 |
adjustSizes(target, r, inverse); |
|
3244 |
} |
|
3245 |
||
3246 |
||
3247 |
// Distribute delta over columns, as indicated by the autoresize mode. |
|
3248 |
private void accommodateDelta(int resizingColumnIndex, int delta) { |
|
3249 |
int columnCount = getColumnCount(); |
|
3250 |
int from = resizingColumnIndex; |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
3251 |
int to; |
2 | 3252 |
|
3253 |
// Use the mode to determine how to absorb the changes. |
|
3254 |
switch(autoResizeMode) { |
|
3255 |
case AUTO_RESIZE_NEXT_COLUMN: |
|
3256 |
from = from + 1; |
|
3257 |
to = Math.min(from + 1, columnCount); break; |
|
3258 |
case AUTO_RESIZE_SUBSEQUENT_COLUMNS: |
|
3259 |
from = from + 1; |
|
3260 |
to = columnCount; break; |
|
3261 |
case AUTO_RESIZE_LAST_COLUMN: |
|
3262 |
from = columnCount - 1; |
|
3263 |
to = from + 1; break; |
|
3264 |
case AUTO_RESIZE_ALL_COLUMNS: |
|
3265 |
from = 0; |
|
3266 |
to = columnCount; break; |
|
3267 |
default: |
|
3268 |
return; |
|
3269 |
} |
|
3270 |
||
3271 |
final int start = from; |
|
3272 |
final int end = to; |
|
3273 |
final TableColumnModel cm = columnModel; |
|
3274 |
Resizable3 r = new Resizable3() { |
|
3275 |
public int getElementCount() { return end-start; } |
|
3276 |
public int getLowerBoundAt(int i) { return cm.getColumn(i+start).getMinWidth(); } |
|
3277 |
public int getUpperBoundAt(int i) { return cm.getColumn(i+start).getMaxWidth(); } |
|
3278 |
public int getMidPointAt(int i) { return cm.getColumn(i+start).getWidth(); } |
|
3279 |
public void setSizeAt(int s, int i) { cm.getColumn(i+start).setWidth(s); } |
|
3280 |
}; |
|
3281 |
||
3282 |
int totalWidth = 0; |
|
3283 |
for(int i = from; i < to; i++) { |
|
3284 |
TableColumn aColumn = columnModel.getColumn(i); |
|
3285 |
int input = aColumn.getWidth(); |
|
3286 |
totalWidth = totalWidth + input; |
|
3287 |
} |
|
3288 |
||
3289 |
adjustSizes(totalWidth + delta, r, false); |
|
3290 |
} |
|
3291 |
||
3292 |
private interface Resizable2 { |
|
3293 |
public int getElementCount(); |
|
3294 |
public int getLowerBoundAt(int i); |
|
3295 |
public int getUpperBoundAt(int i); |
|
3296 |
public void setSizeAt(int newSize, int i); |
|
3297 |
} |
|
3298 |
||
3299 |
private interface Resizable3 extends Resizable2 { |
|
3300 |
public int getMidPointAt(int i); |
|
3301 |
} |
|
3302 |
||
3303 |
||
3304 |
private void adjustSizes(long target, final Resizable3 r, boolean inverse) { |
|
3305 |
int N = r.getElementCount(); |
|
3306 |
long totalPreferred = 0; |
|
3307 |
for(int i = 0; i < N; i++) { |
|
3308 |
totalPreferred += r.getMidPointAt(i); |
|
3309 |
} |
|
3310 |
Resizable2 s; |
|
3311 |
if ((target < totalPreferred) == !inverse) { |
|
3312 |
s = new Resizable2() { |
|
3313 |
public int getElementCount() { return r.getElementCount(); } |
|
3314 |
public int getLowerBoundAt(int i) { return r.getLowerBoundAt(i); } |
|
3315 |
public int getUpperBoundAt(int i) { return r.getMidPointAt(i); } |
|
3316 |
public void setSizeAt(int newSize, int i) { r.setSizeAt(newSize, i); } |
|
3317 |
||
3318 |
}; |
|
3319 |
} |
|
3320 |
else { |
|
3321 |
s = new Resizable2() { |
|
3322 |
public int getElementCount() { return r.getElementCount(); } |
|
3323 |
public int getLowerBoundAt(int i) { return r.getMidPointAt(i); } |
|
3324 |
public int getUpperBoundAt(int i) { return r.getUpperBoundAt(i); } |
|
3325 |
public void setSizeAt(int newSize, int i) { r.setSizeAt(newSize, i); } |
|
3326 |
||
3327 |
}; |
|
3328 |
} |
|
3329 |
adjustSizes(target, s, !inverse); |
|
3330 |
} |
|
3331 |
||
3332 |
private void adjustSizes(long target, Resizable2 r, boolean limitToRange) { |
|
3333 |
long totalLowerBound = 0; |
|
3334 |
long totalUpperBound = 0; |
|
3335 |
for(int i = 0; i < r.getElementCount(); i++) { |
|
3336 |
totalLowerBound += r.getLowerBoundAt(i); |
|
3337 |
totalUpperBound += r.getUpperBoundAt(i); |
|
3338 |
} |
|
3339 |
||
3340 |
if (limitToRange) { |
|
3341 |
target = Math.min(Math.max(totalLowerBound, target), totalUpperBound); |
|
3342 |
} |
|
3343 |
||
3344 |
for(int i = 0; i < r.getElementCount(); i++) { |
|
3345 |
int lowerBound = r.getLowerBoundAt(i); |
|
3346 |
int upperBound = r.getUpperBoundAt(i); |
|
3347 |
// Check for zero. This happens when the distribution of the delta |
|
3348 |
// finishes early due to a series of "fixed" entries at the end. |
|
3349 |
// In this case, lowerBound == upperBound, for all subsequent terms. |
|
3350 |
int newSize; |
|
3351 |
if (totalLowerBound == totalUpperBound) { |
|
3352 |
newSize = lowerBound; |
|
3353 |
} |
|
3354 |
else { |
|
3355 |
double f = (double)(target - totalLowerBound)/(totalUpperBound - totalLowerBound); |
|
3356 |
newSize = (int)Math.round(lowerBound+f*(upperBound - lowerBound)); |
|
3357 |
// We'd need to round manually in an all integer version. |
|
3358 |
// size[i] = (int)(((totalUpperBound - target) * lowerBound + |
|
3359 |
// (target - totalLowerBound) * upperBound)/(totalUpperBound-totalLowerBound)); |
|
3360 |
} |
|
3361 |
r.setSizeAt(newSize, i); |
|
3362 |
target -= newSize; |
|
3363 |
totalLowerBound -= lowerBound; |
|
3364 |
totalUpperBound -= upperBound; |
|
3365 |
} |
|
3366 |
} |
|
3367 |
||
3368 |
/** |
|
3369 |
* Overrides <code>JComponent</code>'s <code>getToolTipText</code> |
|
3370 |
* method in order to allow the renderer's tips to be used |
|
3371 |
* if it has text set. |
|
3372 |
* <p> |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3373 |
* <b>Note:</b> For <code>JTable</code> to properly display |
2 | 3374 |
* tooltips of its renderers |
3375 |
* <code>JTable</code> must be a registered component with the |
|
3376 |
* <code>ToolTipManager</code>. |
|
3377 |
* This is done automatically in <code>initializeLocalVars</code>, |
|
3378 |
* but if at a later point <code>JTable</code> is told |
|
3379 |
* <code>setToolTipText(null)</code> it will unregister the table |
|
3380 |
* component, and no tips from renderers will display anymore. |
|
3381 |
* |
|
3382 |
* @see JComponent#getToolTipText |
|
3383 |
*/ |
|
3384 |
public String getToolTipText(MouseEvent event) { |
|
3385 |
String tip = null; |
|
3386 |
Point p = event.getPoint(); |
|
3387 |
||
3388 |
// Locate the renderer under the event location |
|
3389 |
int hitColumnIndex = columnAtPoint(p); |
|
3390 |
int hitRowIndex = rowAtPoint(p); |
|
3391 |
||
3392 |
if ((hitColumnIndex != -1) && (hitRowIndex != -1)) { |
|
3393 |
TableCellRenderer renderer = getCellRenderer(hitRowIndex, hitColumnIndex); |
|
3394 |
Component component = prepareRenderer(renderer, hitRowIndex, hitColumnIndex); |
|
3395 |
||
3396 |
// Now have to see if the component is a JComponent before |
|
3397 |
// getting the tip |
|
3398 |
if (component instanceof JComponent) { |
|
3399 |
// Convert the event to the renderer's coordinate system |
|
3400 |
Rectangle cellRect = getCellRect(hitRowIndex, hitColumnIndex, false); |
|
3401 |
p.translate(-cellRect.x, -cellRect.y); |
|
3402 |
MouseEvent newEvent = new MouseEvent(component, event.getID(), |
|
3403 |
event.getWhen(), event.getModifiers(), |
|
3404 |
p.x, p.y, |
|
3405 |
event.getXOnScreen(), |
|
3406 |
event.getYOnScreen(), |
|
3407 |
event.getClickCount(), |
|
3408 |
event.isPopupTrigger(), |
|
3409 |
MouseEvent.NOBUTTON); |
|
3410 |
||
3411 |
tip = ((JComponent)component).getToolTipText(newEvent); |
|
3412 |
} |
|
3413 |
} |
|
3414 |
||
3415 |
// No tip from the renderer get our own tip |
|
3416 |
if (tip == null) |
|
3417 |
tip = getToolTipText(); |
|
3418 |
||
3419 |
return tip; |
|
3420 |
} |
|
3421 |
||
3422 |
// |
|
3423 |
// Editing Support |
|
3424 |
// |
|
3425 |
||
3426 |
/** |
|
3427 |
* Sets whether editors in this JTable get the keyboard focus |
|
3428 |
* when an editor is activated as a result of the JTable |
|
3429 |
* forwarding keyboard events for a cell. |
|
3430 |
* By default, this property is false, and the JTable |
|
3431 |
* retains the focus unless the cell is clicked. |
|
3432 |
* |
|
3433 |
* @param surrendersFocusOnKeystroke true if the editor should get the focus |
|
3434 |
* when keystrokes cause the editor to be |
|
3435 |
* activated |
|
3436 |
* |
|
3437 |
* |
|
3438 |
* @see #getSurrendersFocusOnKeystroke |
|
3439 |
* @since 1.4 |
|
3440 |
*/ |
|
3441 |
public void setSurrendersFocusOnKeystroke(boolean surrendersFocusOnKeystroke) { |
|
3442 |
this.surrendersFocusOnKeystroke = surrendersFocusOnKeystroke; |
|
3443 |
} |
|
3444 |
||
3445 |
/** |
|
3446 |
* Returns true if the editor should get the focus |
|
3447 |
* when keystrokes cause the editor to be activated |
|
3448 |
* |
|
3449 |
* @return true if the editor should get the focus |
|
3450 |
* when keystrokes cause the editor to be |
|
3451 |
* activated |
|
3452 |
* |
|
3453 |
* @see #setSurrendersFocusOnKeystroke |
|
3454 |
* @since 1.4 |
|
3455 |
*/ |
|
3456 |
public boolean getSurrendersFocusOnKeystroke() { |
|
3457 |
return surrendersFocusOnKeystroke; |
|
3458 |
} |
|
3459 |
||
3460 |
/** |
|
3461 |
* Programmatically starts editing the cell at <code>row</code> and |
|
3462 |
* <code>column</code>, if those indices are in the valid range, and |
|
3463 |
* the cell at those indices is editable. |
|
3464 |
* Note that this is a convenience method for |
|
3465 |
* <code>editCellAt(int, int, null)</code>. |
|
3466 |
* |
|
3467 |
* @param row the row to be edited |
|
3468 |
* @param column the column to be edited |
|
3469 |
* @return false if for any reason the cell cannot be edited, |
|
3470 |
* or if the indices are invalid |
|
3471 |
*/ |
|
3472 |
public boolean editCellAt(int row, int column) { |
|
3473 |
return editCellAt(row, column, null); |
|
3474 |
} |
|
3475 |
||
3476 |
/** |
|
3477 |
* Programmatically starts editing the cell at <code>row</code> and |
|
3478 |
* <code>column</code>, if those indices are in the valid range, and |
|
3479 |
* the cell at those indices is editable. |
|
3480 |
* To prevent the <code>JTable</code> from |
|
3481 |
* editing a particular table, column or cell value, return false from |
|
3482 |
* the <code>isCellEditable</code> method in the <code>TableModel</code> |
|
3483 |
* interface. |
|
3484 |
* |
|
3485 |
* @param row the row to be edited |
|
3486 |
* @param column the column to be edited |
|
3487 |
* @param e event to pass into <code>shouldSelectCell</code>; |
|
3488 |
* note that as of Java 2 platform v1.2, the call to |
|
3489 |
* <code>shouldSelectCell</code> is no longer made |
|
3490 |
* @return false if for any reason the cell cannot be edited, |
|
3491 |
* or if the indices are invalid |
|
3492 |
*/ |
|
3493 |
public boolean editCellAt(int row, int column, EventObject e){ |
|
3494 |
if (cellEditor != null && !cellEditor.stopCellEditing()) { |
|
3495 |
return false; |
|
3496 |
} |
|
3497 |
||
3498 |
if (row < 0 || row >= getRowCount() || |
|
3499 |
column < 0 || column >= getColumnCount()) { |
|
3500 |
return false; |
|
3501 |
} |
|
3502 |
||
3503 |
if (!isCellEditable(row, column)) |
|
3504 |
return false; |
|
3505 |
||
3506 |
if (editorRemover == null) { |
|
3507 |
KeyboardFocusManager fm = |
|
3508 |
KeyboardFocusManager.getCurrentKeyboardFocusManager(); |
|
3509 |
editorRemover = new CellEditorRemover(fm); |
|
3510 |
fm.addPropertyChangeListener("permanentFocusOwner", editorRemover); |
|
3511 |
} |
|
3512 |
||
3513 |
TableCellEditor editor = getCellEditor(row, column); |
|
3514 |
if (editor != null && editor.isCellEditable(e)) { |
|
3515 |
editorComp = prepareEditor(editor, row, column); |
|
3516 |
if (editorComp == null) { |
|
3517 |
removeEditor(); |
|
3518 |
return false; |
|
3519 |
} |
|
3520 |
editorComp.setBounds(getCellRect(row, column, false)); |
|
3521 |
add(editorComp); |
|
3522 |
editorComp.validate(); |
|
3523 |
editorComp.repaint(); |
|
3524 |
||
3525 |
setCellEditor(editor); |
|
3526 |
setEditingRow(row); |
|
3527 |
setEditingColumn(column); |
|
3528 |
editor.addCellEditorListener(this); |
|
3529 |
||
3530 |
return true; |
|
3531 |
} |
|
3532 |
return false; |
|
3533 |
} |
|
3534 |
||
3535 |
/** |
|
3536 |
* Returns true if a cell is being edited. |
|
3537 |
* |
|
3538 |
* @return true if the table is editing a cell |
|
3539 |
* @see #editingColumn |
|
3540 |
* @see #editingRow |
|
3541 |
*/ |
|
3542 |
public boolean isEditing() { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
3543 |
return cellEditor != null; |
2 | 3544 |
} |
3545 |
||
3546 |
/** |
|
3547 |
* Returns the component that is handling the editing session. |
|
3548 |
* If nothing is being edited, returns null. |
|
3549 |
* |
|
3550 |
* @return Component handling editing session |
|
3551 |
*/ |
|
3552 |
public Component getEditorComponent() { |
|
3553 |
return editorComp; |
|
3554 |
} |
|
3555 |
||
3556 |
/** |
|
3557 |
* Returns the index of the column that contains the cell currently |
|
3558 |
* being edited. If nothing is being edited, returns -1. |
|
3559 |
* |
|
3560 |
* @return the index of the column that contains the cell currently |
|
3561 |
* being edited; returns -1 if nothing being edited |
|
3562 |
* @see #editingRow |
|
3563 |
*/ |
|
3564 |
public int getEditingColumn() { |
|
3565 |
return editingColumn; |
|
3566 |
} |
|
3567 |
||
3568 |
/** |
|
3569 |
* Returns the index of the row that contains the cell currently |
|
3570 |
* being edited. If nothing is being edited, returns -1. |
|
3571 |
* |
|
3572 |
* @return the index of the row that contains the cell currently |
|
3573 |
* being edited; returns -1 if nothing being edited |
|
3574 |
* @see #editingColumn |
|
3575 |
*/ |
|
3576 |
public int getEditingRow() { |
|
3577 |
return editingRow; |
|
3578 |
} |
|
3579 |
||
3580 |
// |
|
3581 |
// Managing TableUI |
|
3582 |
// |
|
3583 |
||
3584 |
/** |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3585 |
* Returns the L&F object that renders this component. |
2 | 3586 |
* |
3587 |
* @return the <code>TableUI</code> object that renders this component |
|
3588 |
*/ |
|
3589 |
public TableUI getUI() { |
|
3590 |
return (TableUI)ui; |
|
3591 |
} |
|
3592 |
||
3593 |
/** |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3594 |
* Sets the L&F object that renders this component and repaints. |
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3595 |
* |
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3596 |
* @param ui the TableUI L&F object |
2 | 3597 |
* @see UIDefaults#getUI |
3598 |
* @beaninfo |
|
3599 |
* bound: true |
|
3600 |
* hidden: true |
|
3601 |
* attribute: visualUpdate true |
|
3602 |
* description: The UI object that implements the Component's LookAndFeel. |
|
3603 |
*/ |
|
3604 |
public void setUI(TableUI ui) { |
|
3605 |
if (this.ui != ui) { |
|
3606 |
super.setUI(ui); |
|
3607 |
repaint(); |
|
3608 |
} |
|
3609 |
} |
|
3610 |
||
3611 |
/** |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3612 |
* Notification from the <code>UIManager</code> that the L&F has changed. |
2 | 3613 |
* Replaces the current UI object with the latest version from the |
3614 |
* <code>UIManager</code>. |
|
3615 |
* |
|
3616 |
* @see JComponent#updateUI |
|
3617 |
*/ |
|
3618 |
public void updateUI() { |
|
3619 |
// Update the UIs of the cell renderers, cell editors and header renderers. |
|
3620 |
TableColumnModel cm = getColumnModel(); |
|
3621 |
for(int column = 0; column < cm.getColumnCount(); column++) { |
|
3622 |
TableColumn aColumn = cm.getColumn(column); |
|
3623 |
SwingUtilities.updateRendererOrEditorUI(aColumn.getCellRenderer()); |
|
3624 |
SwingUtilities.updateRendererOrEditorUI(aColumn.getCellEditor()); |
|
3625 |
SwingUtilities.updateRendererOrEditorUI(aColumn.getHeaderRenderer()); |
|
3626 |
} |
|
3627 |
||
3628 |
// Update the UIs of all the default renderers. |
|
3629 |
Enumeration defaultRenderers = defaultRenderersByColumnClass.elements(); |
|
3630 |
while (defaultRenderers.hasMoreElements()) { |
|
3631 |
SwingUtilities.updateRendererOrEditorUI(defaultRenderers.nextElement()); |
|
3632 |
} |
|
3633 |
||
3634 |
// Update the UIs of all the default editors. |
|
3635 |
Enumeration defaultEditors = defaultEditorsByColumnClass.elements(); |
|
3636 |
while (defaultEditors.hasMoreElements()) { |
|
3637 |
SwingUtilities.updateRendererOrEditorUI(defaultEditors.nextElement()); |
|
3638 |
} |
|
3639 |
||
3640 |
// Update the UI of the table header |
|
3641 |
if (tableHeader != null && tableHeader.getParent() == null) { |
|
3642 |
tableHeader.updateUI(); |
|
3643 |
} |
|
3644 |
||
2658 | 3645 |
// Update UI applied to parent ScrollPane |
3646 |
configureEnclosingScrollPaneUI(); |
|
3647 |
||
2 | 3648 |
setUI((TableUI)UIManager.getUI(this)); |
3649 |
} |
|
3650 |
||
3651 |
/** |
|
20157
cafca01a8e28
8025230: [cleanup] some more javadoc formatting fixes for swing
yan
parents:
16100
diff
changeset
|
3652 |
* Returns the suffix used to construct the name of the L&F class used to |
2 | 3653 |
* render this component. |
3654 |
* |
|
3655 |
* @return the string "TableUI" |
|
3656 |
* @see JComponent#getUIClassID |
|
3657 |
* @see UIDefaults#getUI |
|
3658 |
*/ |
|
3659 |
public String getUIClassID() { |
|
3660 |
return uiClassID; |
|
3661 |
} |
|
3662 |
||
3663 |
||
3664 |
// |
|
3665 |
// Managing models |
|
3666 |
// |
|
3667 |
||
3668 |
/** |
|
3669 |
* Sets the data model for this table to <code>newModel</code> and registers |
|
3670 |
* with it for listener notifications from the new data model. |
|
3671 |
* |
|
3672 |
* @param dataModel the new data source for this table |
|
3673 |
* @exception IllegalArgumentException if <code>newModel</code> is <code>null</code> |
|
3674 |
* @see #getModel |
|
3675 |
* @beaninfo |
|
3676 |
* bound: true |
|
3677 |
* description: The model that is the source of the data for this view. |
|
3678 |
*/ |
|
3679 |
public void setModel(TableModel dataModel) { |
|
3680 |
if (dataModel == null) { |
|
3681 |
throw new IllegalArgumentException("Cannot set a null TableModel"); |
|
3682 |
} |
|
3683 |
if (this.dataModel != dataModel) { |
|
3684 |
TableModel old = this.dataModel; |
|
3685 |
if (old != null) { |
|
3686 |
old.removeTableModelListener(this); |
|
3687 |
} |
|
3688 |
this.dataModel = dataModel; |
|
3689 |
dataModel.addTableModelListener(this); |
|
3690 |
||
3691 |
tableChanged(new TableModelEvent(dataModel, TableModelEvent.HEADER_ROW)); |
|
3692 |
||
3693 |
firePropertyChange("model", old, dataModel); |
|
3694 |
||
3695 |
if (getAutoCreateRowSorter()) { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
3696 |
setRowSorter(new TableRowSorter<TableModel>(dataModel)); |
2 | 3697 |
} |
3698 |
} |
|
3699 |
} |
|
3700 |
||
3701 |
/** |
|
3702 |
* Returns the <code>TableModel</code> that provides the data displayed by this |
|
3703 |
* <code>JTable</code>. |
|
3704 |
* |
|
3705 |
* @return the <code>TableModel</code> that provides the data displayed by this <code>JTable</code> |
|
3706 |
* @see #setModel |
|
3707 |
*/ |
|
3708 |
public TableModel getModel() { |
|
3709 |
return dataModel; |
|
3710 |
} |
|
3711 |
||
3712 |
/** |
|
3713 |
* Sets the column model for this table to <code>newModel</code> and registers |
|
3714 |
* for listener notifications from the new column model. Also sets |
|
3715 |
* the column model of the <code>JTableHeader</code> to <code>columnModel</code>. |
|
3716 |
* |
|
3717 |
* @param columnModel the new data source for this table |
|
3718 |
* @exception IllegalArgumentException if <code>columnModel</code> is <code>null</code> |
|
3719 |
* @see #getColumnModel |
|
3720 |
* @beaninfo |
|
3721 |
* bound: true |
|
3722 |
* description: The object governing the way columns appear in the view. |
|
3723 |
*/ |
|
3724 |
public void setColumnModel(TableColumnModel columnModel) { |
|
3725 |
if (columnModel == null) { |
|
3726 |
throw new IllegalArgumentException("Cannot set a null ColumnModel"); |
|
3727 |
} |
|
3728 |
TableColumnModel old = this.columnModel; |
|
3729 |
if (columnModel != old) { |
|
3730 |
if (old != null) { |
|
3731 |
old.removeColumnModelListener(this); |
|
3732 |
} |
|
3733 |
this.columnModel = columnModel; |
|
3734 |
columnModel.addColumnModelListener(this); |
|
3735 |
||
3736 |
// Set the column model of the header as well. |
|
3737 |
if (tableHeader != null) { |
|
3738 |
tableHeader.setColumnModel(columnModel); |
|
3739 |
} |
|
3740 |
||
3741 |
firePropertyChange("columnModel", old, columnModel); |
|
3742 |
resizeAndRepaint(); |
|
3743 |
} |
|
3744 |
} |
|
3745 |
||
3746 |
/** |
|
3747 |
* Returns the <code>TableColumnModel</code> that contains all column information |
|
3748 |
* of this table. |
|
3749 |
* |
|
3750 |
* @return the object that provides the column state of the table |
|
3751 |
* @see #setColumnModel |
|
3752 |
*/ |
|
3753 |
public TableColumnModel getColumnModel() { |
|
3754 |
return columnModel; |
|
3755 |
} |
|
3756 |
||
3757 |
/** |
|
3758 |
* Sets the row selection model for this table to <code>newModel</code> |
|
3759 |
* and registers for listener notifications from the new selection model. |
|
3760 |
* |
|
3761 |
* @param newModel the new selection model |
|
3762 |
* @exception IllegalArgumentException if <code>newModel</code> is <code>null</code> |
|
3763 |
* @see #getSelectionModel |
|
3764 |
* @beaninfo |
|
3765 |
* bound: true |
|
3766 |
* description: The selection model for rows. |
|
3767 |
*/ |
|
3768 |
public void setSelectionModel(ListSelectionModel newModel) { |
|
3769 |
if (newModel == null) { |
|
3770 |
throw new IllegalArgumentException("Cannot set a null SelectionModel"); |
|
3771 |
} |
|
3772 |
||
3773 |
ListSelectionModel oldModel = selectionModel; |
|
3774 |
||
3775 |
if (newModel != oldModel) { |
|
3776 |
if (oldModel != null) { |
|
3777 |
oldModel.removeListSelectionListener(this); |
|
3778 |
} |
|
3779 |
||
3780 |
selectionModel = newModel; |
|
3781 |
newModel.addListSelectionListener(this); |
|
3782 |
||
3783 |
firePropertyChange("selectionModel", oldModel, newModel); |
|
3784 |
repaint(); |
|
3785 |
} |
|
3786 |
} |
|
3787 |
||
3788 |
/** |
|
3789 |
* Returns the <code>ListSelectionModel</code> that is used to maintain row |
|
3790 |
* selection state. |
|
3791 |
* |
|
3792 |
* @return the object that provides row selection state, <code>null</code> |
|
3793 |
* if row selection is not allowed |
|
3794 |
* @see #setSelectionModel |
|
3795 |
*/ |
|
3796 |
public ListSelectionModel getSelectionModel() { |
|
3797 |
return selectionModel; |
|
3798 |
} |
|
3799 |
||
3800 |
// |
|
3801 |
// RowSorterListener |
|
3802 |
// |
|
3803 |
||
3804 |
/** |
|
3805 |
* <code>RowSorterListener</code> notification that the |
|
3806 |
* <code>RowSorter</code> has changed in some way. |
|
3807 |
* |
|
3808 |
* @param e the <code>RowSorterEvent</code> describing the change |
|
3809 |
* @throws NullPointerException if <code>e</code> is <code>null</code> |
|
3810 |
* @since 1.6 |
|
3811 |
*/ |
|
3812 |
public void sorterChanged(RowSorterEvent e) { |
|
3813 |
if (e.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) { |
|
3814 |
JTableHeader header = getTableHeader(); |
|
3815 |
if (header != null) { |
|
3816 |
header.repaint(); |
|
3817 |
} |
|
3818 |
} |
|
3819 |
else if (e.getType() == RowSorterEvent.Type.SORTED) { |
|
3820 |
sorterChanged = true; |
|
3821 |
if (!ignoreSortChange) { |
|
3822 |
sortedTableChanged(e, null); |
|
3823 |
} |
|
3824 |
} |
|
3825 |
} |
|
3826 |
||
3827 |
||
3828 |
/** |
|
3829 |
* SortManager provides support for managing the selection and variable |
|
3830 |
* row heights when sorting is enabled. This information is encapsulated |
|
3831 |
* into a class to avoid bulking up JTable. |
|
3832 |
*/ |
|
3833 |
private final class SortManager { |
|
3834 |
RowSorter<? extends TableModel> sorter; |
|
3835 |
||
3836 |
// Selection, in terms of the model. This is lazily created |
|
3837 |
// as needed. |
|
3838 |
private ListSelectionModel modelSelection; |
|
3839 |
private int modelLeadIndex; |
|
3840 |
// Set to true while in the process of changing the selection. |
|
3841 |
// If this is true the selection change is ignored. |
|
3842 |
private boolean syncingSelection; |
|
3843 |
// Temporary cache of selection, in terms of model. This is only used |
|
3844 |
// if we don't need the full weight of modelSelection. |
|
3845 |
private int[] lastModelSelection; |
|
3846 |
||
3847 |
// Heights of the rows in terms of the model. |
|
3848 |
private SizeSequence modelRowSizes; |
|
3849 |
||
3850 |
||
3851 |
SortManager(RowSorter<? extends TableModel> sorter) { |
|
3852 |
this.sorter = sorter; |
|
3853 |
sorter.addRowSorterListener(JTable.this); |
|
3854 |
} |
|
3855 |
||
3856 |
/** |
|
3857 |
* Disposes any resources used by this SortManager. |
|
3858 |
*/ |
|
3859 |
public void dispose() { |
|
3860 |
if (sorter != null) { |
|
3861 |
sorter.removeRowSorterListener(JTable.this); |
|
3862 |
} |
|
3863 |
} |
|
3864 |
||
3865 |
/** |
|
3866 |
* Sets the height for a row at a specified index. |
|
3867 |
*/ |
|
3868 |
public void setViewRowHeight(int viewIndex, int rowHeight) { |
|
3869 |
if (modelRowSizes == null) { |
|
3870 |
modelRowSizes = new SizeSequence(getModel().getRowCount(), |
|
3871 |
getRowHeight()); |
|
3872 |
} |
|
3873 |
modelRowSizes.setSize(convertRowIndexToModel(viewIndex),rowHeight); |
|
3874 |
} |
|
3875 |
||
3876 |
/** |
|
3877 |
* Invoked when the underlying model has completely changed. |
|
3878 |
*/ |
|
3879 |
public void allChanged() { |
|
3880 |
modelLeadIndex = -1; |
|
3881 |
modelSelection = null; |
|
3882 |
modelRowSizes = null; |
|
3883 |
} |
|
3884 |
||
3885 |
/** |
|
3886 |
* Invoked when the selection, on the view, has changed. |
|
3887 |
*/ |
|
3888 |
public void viewSelectionChanged(ListSelectionEvent e) { |
|
3889 |
if (!syncingSelection && modelSelection != null) { |
|
3890 |
modelSelection = null; |
|
3891 |
} |
|
3892 |
} |
|
3893 |
||
3894 |
/** |
|
3895 |
* Invoked when either the table model has changed, or the RowSorter |
|
3896 |
* has changed. This is invoked prior to notifying the sorter of the |
|
3897 |
* change. |
|
3898 |
*/ |
|
3899 |
public void prepareForChange(RowSorterEvent sortEvent, |
|
3900 |
ModelChange change) { |
|
3901 |
if (getUpdateSelectionOnSort()) { |
|
3902 |
cacheSelection(sortEvent, change); |
|
3903 |
} |
|
3904 |
} |
|
3905 |
||
3906 |
/** |
|
3907 |
* Updates the internal cache of the selection based on the change. |
|
3908 |
*/ |
|
3909 |
private void cacheSelection(RowSorterEvent sortEvent, |
|
3910 |
ModelChange change) { |
|
3911 |
if (sortEvent != null) { |
|
3912 |
// sort order changed. If modelSelection is null and filtering |
|
3913 |
// is enabled we need to cache the selection in terms of the |
|
3914 |
// underlying model, this will allow us to correctly restore |
|
3915 |
// the selection even if rows are filtered out. |
|
3916 |
if (modelSelection == null && |
|
3917 |
sorter.getViewRowCount() != getModel().getRowCount()) { |
|
3918 |
modelSelection = new DefaultListSelectionModel(); |
|
3919 |
ListSelectionModel viewSelection = getSelectionModel(); |
|
3920 |
int min = viewSelection.getMinSelectionIndex(); |
|
3921 |
int max = viewSelection.getMaxSelectionIndex(); |
|
3922 |
int modelIndex; |
|
3923 |
for (int viewIndex = min; viewIndex <= max; viewIndex++) { |
|
3924 |
if (viewSelection.isSelectedIndex(viewIndex)) { |
|
3925 |
modelIndex = convertRowIndexToModel( |
|
3926 |
sortEvent, viewIndex); |
|
3927 |
if (modelIndex != -1) { |
|
3928 |
modelSelection.addSelectionInterval( |
|
3929 |
modelIndex, modelIndex); |
|
3930 |
} |
|
3931 |
} |
|
3932 |
} |
|
3933 |
modelIndex = convertRowIndexToModel(sortEvent, |
|
3934 |
viewSelection.getLeadSelectionIndex()); |
|
3935 |
SwingUtilities2.setLeadAnchorWithoutSelection( |
|
3936 |
modelSelection, modelIndex, modelIndex); |
|
3937 |
} else if (modelSelection == null) { |
|
3938 |
// Sorting changed, haven't cached selection in terms |
|
3939 |
// of model and no filtering. Temporarily cache selection. |
|
3940 |
cacheModelSelection(sortEvent); |
|
3941 |
} |
|
3942 |
} else if (change.allRowsChanged) { |
|
3943 |
// All the rows have changed, chuck any cached selection. |
|
3944 |
modelSelection = null; |
|
3945 |
} else if (modelSelection != null) { |
|
3946 |
// Table changed, reflect changes in cached selection model. |
|
3947 |
switch(change.type) { |
|
3948 |
case TableModelEvent.DELETE: |
|
3949 |
modelSelection.removeIndexInterval(change.startModelIndex, |
|
3950 |
change.endModelIndex); |
|
3951 |
break; |
|
3952 |
case TableModelEvent.INSERT: |
|
3953 |
modelSelection.insertIndexInterval(change.startModelIndex, |
|
14992
e9db4be29324
8005019: JTable passes row index instead of length when inserts selection interval
alexsch
parents:
13546
diff
changeset
|
3954 |
change.length, |
2 | 3955 |
true); |
3956 |
break; |
|
3957 |
default: |
|
3958 |
break; |
|
3959 |
} |
|
3960 |
} else { |
|
3961 |
// table changed, but haven't cached rows, temporarily |
|
3962 |
// cache them. |
|
3963 |
cacheModelSelection(null); |
|
3964 |
} |
|
3965 |
} |
|
3966 |
||
3967 |
private void cacheModelSelection(RowSorterEvent sortEvent) { |
|
3968 |
lastModelSelection = convertSelectionToModel(sortEvent); |
|
3969 |
modelLeadIndex = convertRowIndexToModel(sortEvent, |
|
3970 |
selectionModel.getLeadSelectionIndex()); |
|
3971 |
} |
|
3972 |
||
3973 |
/** |
|
3974 |
* Inovked when either the table has changed or the sorter has changed |
|
3975 |
* and after the sorter has been notified. If necessary this will |
|
3976 |
* reapply the selection and variable row heights. |
|
3977 |
*/ |
|
3978 |
public void processChange(RowSorterEvent sortEvent, |
|
3979 |
ModelChange change, |
|
3980 |
boolean sorterChanged) { |
|
3981 |
if (change != null) { |
|
3982 |
if (change.allRowsChanged) { |
|
3983 |
modelRowSizes = null; |
|
3984 |
rowModel = null; |
|
3985 |
} else if (modelRowSizes != null) { |
|
3986 |
if (change.type == TableModelEvent.INSERT) { |
|
3987 |
modelRowSizes.insertEntries(change.startModelIndex, |
|
3988 |
change.endModelIndex - |
|
3989 |
change.startModelIndex + 1, |
|
3990 |
getRowHeight()); |
|
3991 |
} else if (change.type == TableModelEvent.DELETE) { |
|
3992 |
modelRowSizes.removeEntries(change.startModelIndex, |
|
3993 |
change.endModelIndex - |
|
3994 |
change.startModelIndex +1 ); |
|
3995 |
} |
|
3996 |
} |
|
3997 |
} |
|
3998 |
if (sorterChanged) { |
|
3999 |
setViewRowHeightsFromModel(); |
|
4000 |
restoreSelection(change); |
|
4001 |
} |
|
4002 |
} |
|
4003 |
||
4004 |
/** |
|
4005 |
* Resets the variable row heights in terms of the view from |
|
4006 |
* that of the variable row heights in terms of the model. |
|
4007 |
*/ |
|
4008 |
private void setViewRowHeightsFromModel() { |
|
4009 |
if (modelRowSizes != null) { |
|
4010 |
rowModel.setSizes(getRowCount(), getRowHeight()); |
|
4011 |
for (int viewIndex = getRowCount() - 1; viewIndex >= 0; |
|
4012 |
viewIndex--) { |
|
4013 |
int modelIndex = convertRowIndexToModel(viewIndex); |
|
4014 |
rowModel.setSize(viewIndex, |
|
4015 |
modelRowSizes.getSize(modelIndex)); |
|
4016 |
} |
|
4017 |
} |
|
4018 |
} |
|
4019 |
||
4020 |
/** |
|
4021 |
* Restores the selection from that in terms of the model. |
|
4022 |
*/ |
|
4023 |
private void restoreSelection(ModelChange change) { |
|
4024 |
syncingSelection = true; |
|
4025 |
if (lastModelSelection != null) { |
|
4026 |
restoreSortingSelection(lastModelSelection, |
|
4027 |
modelLeadIndex, change); |
|
4028 |
lastModelSelection = null; |
|
4029 |
} else if (modelSelection != null) { |
|
4030 |
ListSelectionModel viewSelection = getSelectionModel(); |
|
4031 |
viewSelection.setValueIsAdjusting(true); |
|
4032 |
viewSelection.clearSelection(); |
|
4033 |
int min = modelSelection.getMinSelectionIndex(); |
|
4034 |
int max = modelSelection.getMaxSelectionIndex(); |
|
4035 |
int viewIndex; |
|
4036 |
for (int modelIndex = min; modelIndex <= max; modelIndex++) { |
|
4037 |
if (modelSelection.isSelectedIndex(modelIndex)) { |
|
4038 |
viewIndex = convertRowIndexToView(modelIndex); |
|
4039 |
if (viewIndex != -1) { |
|
4040 |
viewSelection.addSelectionInterval(viewIndex, |
|
4041 |
viewIndex); |
|
4042 |
} |
|
4043 |
} |
|
4044 |
} |
|
4045 |
// Restore the lead |
|
4046 |
int viewLeadIndex = modelSelection.getLeadSelectionIndex(); |
|
4047 |
if (viewLeadIndex != -1) { |
|
4048 |
viewLeadIndex = convertRowIndexToView(viewLeadIndex); |
|
4049 |
} |
|
4050 |
SwingUtilities2.setLeadAnchorWithoutSelection( |
|
4051 |
viewSelection, viewLeadIndex, viewLeadIndex); |
|
4052 |
viewSelection.setValueIsAdjusting(false); |
|
4053 |
} |
|
4054 |
syncingSelection = false; |
|
4055 |
} |
|
4056 |
} |
|
4057 |
||
4058 |
||
4059 |
/** |
|
4060 |
* ModelChange is used when sorting to restore state, it corresponds |
|
4061 |
* to data from a TableModelEvent. The values are precalculated as |
|
4062 |
* they are used extensively. |
|
4063 |
*/ |
|
4064 |
private final class ModelChange { |
|
4065 |
// Starting index of the change, in terms of the model |
|
4066 |
int startModelIndex; |
|
4067 |
||
4068 |
// Ending index of the change, in terms of the model |
|
4069 |
int endModelIndex; |
|
4070 |
||
4071 |
// Type of change |
|
4072 |
int type; |
|
4073 |
||
4074 |
// Number of rows in the model |
|
4075 |
int modelRowCount; |
|
4076 |
||
4077 |
// The event that triggered this. |
|
4078 |
TableModelEvent event; |
|
4079 |
||
4080 |
// Length of the change (end - start + 1) |
|
4081 |
int length; |
|
4082 |
||
4083 |
// True if the event indicates all the contents have changed |
|
4084 |
boolean allRowsChanged; |
|
4085 |
||
4086 |
ModelChange(TableModelEvent e) { |
|
4087 |
startModelIndex = Math.max(0, e.getFirstRow()); |
|
4088 |
endModelIndex = e.getLastRow(); |
|
4089 |
modelRowCount = getModel().getRowCount(); |
|
4090 |
if (endModelIndex < 0) { |
|
4091 |
endModelIndex = Math.max(0, modelRowCount - 1); |
|
4092 |
} |
|
4093 |
length = endModelIndex - startModelIndex + 1; |
|
4094 |
type = e.getType(); |
|
4095 |
event = e; |
|
4096 |
allRowsChanged = (e.getLastRow() == Integer.MAX_VALUE); |
|
4097 |
} |
|
4098 |
} |
|
4099 |
||
4100 |
/** |
|
4101 |
* Invoked when <code>sorterChanged</code> is invoked, or |
|
4102 |
* when <code>tableChanged</code> is invoked and sorting is enabled. |
|
4103 |
*/ |
|
4104 |
private void sortedTableChanged(RowSorterEvent sortedEvent, |
|
4105 |
TableModelEvent e) { |
|
4106 |
int editingModelIndex = -1; |
|
4107 |
ModelChange change = (e != null) ? new ModelChange(e) : null; |
|
4108 |
||
4109 |
if ((change == null || !change.allRowsChanged) && |
|
4110 |
this.editingRow != -1) { |
|
4111 |
editingModelIndex = convertRowIndexToModel(sortedEvent, |
|
4112 |
this.editingRow); |
|
4113 |
} |
|
4114 |
||
4115 |
sortManager.prepareForChange(sortedEvent, change); |
|
4116 |
||
4117 |
if (e != null) { |
|
4118 |
if (change.type == TableModelEvent.UPDATE) { |
|
4119 |
repaintSortedRows(change); |
|
4120 |
} |
|
4121 |
notifySorter(change); |
|
4122 |
if (change.type != TableModelEvent.UPDATE) { |
|
4123 |
// If the Sorter is unsorted we will not have received |
|
4124 |
// notification, force treating insert/delete as a change. |
|
4125 |
sorterChanged = true; |
|
4126 |
} |
|
4127 |
} |
|
4128 |
else { |
|
4129 |
sorterChanged = true; |
|
4130 |
} |
|
4131 |
||
4132 |
sortManager.processChange(sortedEvent, change, sorterChanged); |
|
4133 |
||
4134 |
if (sorterChanged) { |
|
4135 |
// Update the editing row |
|
4136 |
if (this.editingRow != -1) { |
|
4137 |
int newIndex = (editingModelIndex == -1) ? -1 : |
|
4138 |
convertRowIndexToView(editingModelIndex,change); |
|
4139 |
restoreSortingEditingRow(newIndex); |
|
4140 |
} |
|
4141 |
||
4142 |
// And handle the appropriate repainting. |
|
4143 |
if (e == null || change.type != TableModelEvent.UPDATE) { |
|
4144 |
resizeAndRepaint(); |
|
4145 |
} |
|
4146 |
} |
|
4147 |
||
4148 |
// Check if lead/anchor need to be reset. |
|
4149 |
if (change != null && change.allRowsChanged) { |
|
4150 |
clearSelectionAndLeadAnchor(); |
|
4151 |
resizeAndRepaint(); |
|
4152 |
} |
|
4153 |
} |
|
4154 |
||
4155 |
/** |
|
4156 |
* Repaints the sort of sorted rows in response to a TableModelEvent. |
|
4157 |
*/ |
|
4158 |
private void repaintSortedRows(ModelChange change) { |
|
4159 |
if (change.startModelIndex > change.endModelIndex || |
|
4160 |
change.startModelIndex + 10 < change.endModelIndex) { |
|
4161 |
// Too much has changed, punt |
|
4162 |
repaint(); |
|
4163 |
return; |
|
4164 |
} |
|
4165 |
int eventColumn = change.event.getColumn(); |
|
4166 |
int columnViewIndex = eventColumn; |
|
4167 |
if (columnViewIndex == TableModelEvent.ALL_COLUMNS) { |
|
4168 |
columnViewIndex = 0; |
|
4169 |
} |
|
4170 |
else { |
|
4171 |
columnViewIndex = convertColumnIndexToView(columnViewIndex); |
|
4172 |
if (columnViewIndex == -1) { |
|
4173 |
return; |
|
4174 |
} |
|
4175 |
} |
|
4176 |
int modelIndex = change.startModelIndex; |
|
4177 |
while (modelIndex <= change.endModelIndex) { |
|
4178 |
int viewIndex = convertRowIndexToView(modelIndex++); |
|
4179 |
if (viewIndex != -1) { |
|
4180 |
Rectangle dirty = getCellRect(viewIndex, columnViewIndex, |
|
4181 |
false); |
|
4182 |
int x = dirty.x; |
|
4183 |
int w = dirty.width; |
|
4184 |
if (eventColumn == TableModelEvent.ALL_COLUMNS) { |
|
4185 |
x = 0; |
|
4186 |
w = getWidth(); |
|
4187 |
} |
|
4188 |
repaint(x, dirty.y, w, dirty.height); |
|
4189 |
} |
|
4190 |
} |
|
4191 |
} |
|
4192 |
||
4193 |
/** |
|
4194 |
* Restores the selection after a model event/sort order changes. |
|
4195 |
* All coordinates are in terms of the model. |
|
4196 |
*/ |
|
4197 |
private void restoreSortingSelection(int[] selection, int lead, |
|
4198 |
ModelChange change) { |
|
4199 |
// Convert the selection from model to view |
|
4200 |
for (int i = selection.length - 1; i >= 0; i--) { |
|
4201 |
selection[i] = convertRowIndexToView(selection[i], change); |
|
4202 |
} |
|
4203 |
lead = convertRowIndexToView(lead, change); |
|
4204 |
||
4205 |
// Check for the common case of no change in selection for 1 row |
|
4206 |
if (selection.length == 0 || |
|
4207 |
(selection.length == 1 && selection[0] == getSelectedRow())) { |
|
4208 |
return; |
|
4209 |
} |
|
4210 |
||
4211 |
// And apply the new selection |
|
4212 |
selectionModel.setValueIsAdjusting(true); |
|
4213 |
selectionModel.clearSelection(); |
|
4214 |
for (int i = selection.length - 1; i >= 0; i--) { |
|
4215 |
if (selection[i] != -1) { |
|
4216 |
selectionModel.addSelectionInterval(selection[i], |
|
4217 |
selection[i]); |
|
4218 |
} |
|
4219 |
} |
|
4220 |
SwingUtilities2.setLeadAnchorWithoutSelection( |
|
4221 |
selectionModel, lead, lead); |
|
4222 |
selectionModel.setValueIsAdjusting(false); |
|
4223 |
} |
|
4224 |
||
4225 |
/** |
|
4226 |
* Restores the editing row after a model event/sort order change. |
|
4227 |
* |
|
4228 |
* @param editingRow new index of the editingRow, in terms of the view |
|
4229 |
*/ |
|
4230 |
private void restoreSortingEditingRow(int editingRow) { |
|
4231 |
if (editingRow == -1) { |
|
4232 |
// Editing row no longer being shown, cancel editing |
|
4233 |
TableCellEditor editor = getCellEditor(); |
|
4234 |
if (editor != null) { |
|
4235 |
// First try and cancel |
|
4236 |
editor.cancelCellEditing(); |
|
4237 |
if (getCellEditor() != null) { |
|
4238 |
// CellEditor didn't cede control, forcefully |
|
4239 |
// remove it |
|
4240 |
removeEditor(); |
|
4241 |
} |
|
4242 |
} |
|
4243 |
} |
|
4244 |
else { |
|
4245 |
// Repositioning handled in BasicTableUI |
|
4246 |
this.editingRow = editingRow; |
|
4247 |
repaint(); |
|
4248 |
} |
|
4249 |
} |
|
4250 |
||
4251 |
/** |
|
4252 |
* Notifies the sorter of a change in the underlying model. |
|
4253 |
*/ |
|
4254 |
private void notifySorter(ModelChange change) { |
|
4255 |
try { |
|
4256 |
ignoreSortChange = true; |
|
4257 |
sorterChanged = false; |
|
4258 |
switch(change.type) { |
|
4259 |
case TableModelEvent.UPDATE: |
|
4260 |
if (change.event.getLastRow() == Integer.MAX_VALUE) { |
|
4261 |
sortManager.sorter.allRowsChanged(); |
|
4262 |
} else if (change.event.getColumn() == |
|
4263 |
TableModelEvent.ALL_COLUMNS) { |
|
4264 |
sortManager.sorter.rowsUpdated(change.startModelIndex, |
|
4265 |
change.endModelIndex); |
|
4266 |
} else { |
|
4267 |
sortManager.sorter.rowsUpdated(change.startModelIndex, |
|
4268 |
change.endModelIndex, |
|
4269 |
change.event.getColumn()); |
|
4270 |
} |
|
4271 |
break; |
|
4272 |
case TableModelEvent.INSERT: |
|
4273 |
sortManager.sorter.rowsInserted(change.startModelIndex, |
|
4274 |
change.endModelIndex); |
|
4275 |
break; |
|
4276 |
case TableModelEvent.DELETE: |
|
4277 |
sortManager.sorter.rowsDeleted(change.startModelIndex, |
|
4278 |
change.endModelIndex); |
|
4279 |
break; |
|
4280 |
} |
|
4281 |
} finally { |
|
4282 |
ignoreSortChange = false; |
|
4283 |
} |
|
4284 |
} |
|
4285 |
||
4286 |
/** |
|
4287 |
* Converts a model index to view index. This is called when the |
|
4288 |
* sorter or model changes and sorting is enabled. |
|
4289 |
* |
|
4290 |
* @param change describes the TableModelEvent that initiated the change; |
|
4291 |
* will be null if called as the result of a sort |
|
4292 |
*/ |
|
4293 |
private int convertRowIndexToView(int modelIndex, ModelChange change) { |
|
4294 |
if (modelIndex < 0) { |
|
4295 |
return -1; |
|
4296 |
} |
|
4297 |
if (change != null && modelIndex >= change.startModelIndex) { |
|
4298 |
if (change.type == TableModelEvent.INSERT) { |
|
4299 |
if (modelIndex + change.length >= change.modelRowCount) { |
|
4300 |
return -1; |
|
4301 |
} |
|
4302 |
return sortManager.sorter.convertRowIndexToView( |
|
4303 |
modelIndex + change.length); |
|
4304 |
} |
|
4305 |
else if (change.type == TableModelEvent.DELETE) { |
|
4306 |
if (modelIndex <= change.endModelIndex) { |
|
4307 |
// deleted |
|
4308 |
return -1; |
|
4309 |
} |
|
4310 |
else { |
|
4311 |
if (modelIndex - change.length >= change.modelRowCount) { |
|
4312 |
return -1; |
|
4313 |
} |
|
4314 |
return sortManager.sorter.convertRowIndexToView( |
|
4315 |
modelIndex - change.length); |
|
4316 |
} |
|
4317 |
} |
|
4318 |
// else, updated |
|
4319 |
} |
|
4320 |
if (modelIndex >= getModel().getRowCount()) { |
|
4321 |
return -1; |
|
4322 |
} |
|
4323 |
return sortManager.sorter.convertRowIndexToView(modelIndex); |
|
4324 |
} |
|
4325 |
||
4326 |
/** |
|
4327 |
* Converts the selection to model coordinates. This is used when |
|
4328 |
* the model changes or the sorter changes. |
|
4329 |
*/ |
|
4330 |
private int[] convertSelectionToModel(RowSorterEvent e) { |
|
4331 |
int[] selection = getSelectedRows(); |
|
4332 |
for (int i = selection.length - 1; i >= 0; i--) { |
|
4333 |
selection[i] = convertRowIndexToModel(e, selection[i]); |
|
4334 |
} |
|
4335 |
return selection; |
|
4336 |
} |
|
4337 |
||
4338 |
private int convertRowIndexToModel(RowSorterEvent e, int viewIndex) { |
|
4339 |
if (e != null) { |
|
4340 |
if (e.getPreviousRowCount() == 0) { |
|
4341 |
return viewIndex; |
|
4342 |
} |
|
4343 |
// range checking handled by RowSorterEvent |
|
4344 |
return e.convertPreviousRowIndexToModel(viewIndex); |
|
4345 |
} |
|
4346 |
// Make sure the viewIndex is valid |
|
4347 |
if (viewIndex < 0 || viewIndex >= getRowCount()) { |
|
4348 |
return -1; |
|
4349 |
} |
|
4350 |
return convertRowIndexToModel(viewIndex); |
|
4351 |
} |
|
4352 |
||
4353 |
// |
|
4354 |
// Implementing TableModelListener interface |
|
4355 |
// |
|
4356 |
||
4357 |
/** |
|
4358 |
* Invoked when this table's <code>TableModel</code> generates |
|
4359 |
* a <code>TableModelEvent</code>. |
|
4360 |
* The <code>TableModelEvent</code> should be constructed in the |
|
4361 |
* coordinate system of the model; the appropriate mapping to the |
|
4362 |
* view coordinate system is performed by this <code>JTable</code> |
|
4363 |
* when it receives the event. |
|
4364 |
* <p> |
|
4365 |
* Application code will not use these methods explicitly, they |
|
4366 |
* are used internally by <code>JTable</code>. |
|
4367 |
* <p> |
|
4368 |
* Note that as of 1.3, this method clears the selection, if any. |
|
4369 |
*/ |
|
4370 |
public void tableChanged(TableModelEvent e) { |
|
4371 |
if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW) { |
|
4372 |
// The whole thing changed |
|
4373 |
clearSelectionAndLeadAnchor(); |
|
4374 |
||
4375 |
rowModel = null; |
|
4376 |
||
4377 |
if (sortManager != null) { |
|
4378 |
try { |
|
4379 |
ignoreSortChange = true; |
|
4380 |
sortManager.sorter.modelStructureChanged(); |
|
4381 |
} finally { |
|
4382 |
ignoreSortChange = false; |
|
4383 |
} |
|
4384 |
sortManager.allChanged(); |
|
4385 |
} |
|
4386 |
||
4387 |
if (getAutoCreateColumnsFromModel()) { |
|
4388 |
// This will effect invalidation of the JTable and JTableHeader. |
|
4389 |
createDefaultColumnsFromModel(); |
|
4390 |
return; |
|
4391 |
} |
|
4392 |
||
4393 |
resizeAndRepaint(); |
|
4394 |
return; |
|
4395 |
} |
|
4396 |
||
4397 |
if (sortManager != null) { |
|
4398 |
sortedTableChanged(null, e); |
|
4399 |
return; |
|
4400 |
} |
|
4401 |
||
4402 |
// The totalRowHeight calculated below will be incorrect if |
|
4403 |
// there are variable height rows. Repaint the visible region, |
|
4404 |
// but don't return as a revalidate may be necessary as well. |
|
4405 |
if (rowModel != null) { |
|
4406 |
repaint(); |
|
4407 |
} |
|
4408 |
||
4409 |
if (e.getType() == TableModelEvent.INSERT) { |
|
4410 |
tableRowsInserted(e); |
|
4411 |
return; |
|
4412 |
} |
|
4413 |
||
4414 |
if (e.getType() == TableModelEvent.DELETE) { |
|
4415 |
tableRowsDeleted(e); |
|
4416 |
return; |
|
4417 |
} |
|
4418 |
||
4419 |
int modelColumn = e.getColumn(); |
|
4420 |
int start = e.getFirstRow(); |
|
4421 |
int end = e.getLastRow(); |
|
4422 |
||
4423 |
Rectangle dirtyRegion; |
|
4424 |
if (modelColumn == TableModelEvent.ALL_COLUMNS) { |
|
4425 |
// 1 or more rows changed |
|
4426 |
dirtyRegion = new Rectangle(0, start * getRowHeight(), |
|
4427 |
getColumnModel().getTotalColumnWidth(), 0); |
|
4428 |
} |
|
4429 |
else { |
|
4430 |
// A cell or column of cells has changed. |
|
4431 |
// Unlike the rest of the methods in the JTable, the TableModelEvent |
|
4432 |
// uses the coordinate system of the model instead of the view. |
|
4433 |
// This is the only place in the JTable where this "reverse mapping" |
|
4434 |
// is used. |
|
4435 |
int column = convertColumnIndexToView(modelColumn); |
|
4436 |
dirtyRegion = getCellRect(start, column, false); |
|
4437 |
} |
|
4438 |
||
4439 |
// Now adjust the height of the dirty region according to the value of "end". |
|
4440 |
// Check for Integer.MAX_VALUE as this will cause an overflow. |
|
4441 |
if (end != Integer.MAX_VALUE) { |
|
4442 |
dirtyRegion.height = (end-start+1)*getRowHeight(); |
|
4443 |
repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height); |
|
4444 |
} |
|
4445 |
// In fact, if the end is Integer.MAX_VALUE we need to revalidate anyway |
|
4446 |
// because the scrollbar may need repainting. |
|
4447 |
else { |
|
4448 |
clearSelectionAndLeadAnchor(); |
|
4449 |
resizeAndRepaint(); |
|
4450 |
rowModel = null; |
|
4451 |
} |
|
4452 |
} |
|
4453 |
||
4454 |
/* |
|
4455 |
* Invoked when rows have been inserted into the table. |
|
4456 |
* <p> |
|
4457 |
* Application code will not use these methods explicitly, they |
|
4458 |
* are used internally by JTable. |
|
4459 |
* |
|
4460 |
* @param e the TableModelEvent encapsulating the insertion |
|
4461 |
*/ |
|
4462 |
private void tableRowsInserted(TableModelEvent e) { |
|
4463 |
int start = e.getFirstRow(); |
|
4464 |
int end = e.getLastRow(); |
|
4465 |
if (start < 0) { |
|
4466 |
start = 0; |
|
4467 |
} |
|
4468 |
if (end < 0) { |
|
4469 |
end = getRowCount()-1; |
|
4470 |
} |
|
4471 |
||
4472 |
// Adjust the selection to account for the new rows. |
|
4473 |
int length = end - start + 1; |
|
4474 |
selectionModel.insertIndexInterval(start, length, true); |
|
4475 |
||
4476 |
// If we have variable height rows, adjust the row model. |
|
4477 |
if (rowModel != null) { |
|
4478 |
rowModel.insertEntries(start, length, getRowHeight()); |
|
4479 |
} |
|
4480 |
int rh = getRowHeight() ; |
|
4481 |
Rectangle drawRect = new Rectangle(0, start * rh, |
|
4482 |
getColumnModel().getTotalColumnWidth(), |
|
4483 |
(getRowCount()-start) * rh); |
|
4484 |
||
4485 |
revalidate(); |
|
4486 |
// PENDING(milne) revalidate calls repaint() if parent is a ScrollPane |
|
4487 |
// repaint still required in the unusual case where there is no ScrollPane |
|
4488 |
repaint(drawRect); |
|
4489 |
} |
|
4490 |
||
4491 |
/* |
|
4492 |
* Invoked when rows have been removed from the table. |
|
4493 |
* <p> |
|
4494 |
* Application code will not use these methods explicitly, they |
|
4495 |
* are used internally by JTable. |
|
4496 |
* |
|
4497 |
* @param e the TableModelEvent encapsulating the deletion |
|
4498 |
*/ |
|
4499 |
private void tableRowsDeleted(TableModelEvent e) { |
|
4500 |
int start = e.getFirstRow(); |
|
4501 |
int end = e.getLastRow(); |
|
4502 |
if (start < 0) { |
|
4503 |
start = 0; |
|
4504 |
} |
|
4505 |
if (end < 0) { |
|
4506 |
end = getRowCount()-1; |
|
4507 |
} |
|
4508 |
||
4509 |
int deletedCount = end - start + 1; |
|
4510 |
int previousRowCount = getRowCount() + deletedCount; |
|
4511 |
// Adjust the selection to account for the new rows |
|
4512 |
selectionModel.removeIndexInterval(start, end); |
|
4513 |
||
4514 |
// If we have variable height rows, adjust the row model. |
|
4515 |
if (rowModel != null) { |
|
4516 |
rowModel.removeEntries(start, deletedCount); |
|
4517 |
} |
|
4518 |
||
4519 |
int rh = getRowHeight(); |
|
4520 |
Rectangle drawRect = new Rectangle(0, start * rh, |
|
4521 |
getColumnModel().getTotalColumnWidth(), |
|
4522 |
(previousRowCount - start) * rh); |
|
4523 |
||
4524 |
revalidate(); |
|
4525 |
// PENDING(milne) revalidate calls repaint() if parent is a ScrollPane |
|
4526 |
// repaint still required in the unusual case where there is no ScrollPane |
|
4527 |
repaint(drawRect); |
|
4528 |
} |
|
4529 |
||
4530 |
// |
|
4531 |
// Implementing TableColumnModelListener interface |
|
4532 |
// |
|
4533 |
||
4534 |
/** |
|
4535 |
* Invoked when a column is added to the table column model. |
|
4536 |
* <p> |
|
4537 |
* Application code will not use these methods explicitly, they |
|
4538 |
* are used internally by JTable. |
|
4539 |
* |
|
4540 |
* @see TableColumnModelListener |
|
4541 |
*/ |
|
4542 |
public void columnAdded(TableColumnModelEvent e) { |
|
4543 |
// If I'm currently editing, then I should stop editing |
|
4544 |
if (isEditing()) { |
|
4545 |
removeEditor(); |
|
4546 |
} |
|
4547 |
resizeAndRepaint(); |
|
4548 |
} |
|
4549 |
||
4550 |
/** |
|
4551 |
* Invoked when a column is removed from the table column model. |
|
4552 |
* <p> |
|
4553 |
* Application code will not use these methods explicitly, they |
|
4554 |
* are used internally by JTable. |
|
4555 |
* |
|
4556 |
* @see TableColumnModelListener |
|
4557 |
*/ |
|
4558 |
public void columnRemoved(TableColumnModelEvent e) { |
|
4559 |
// If I'm currently editing, then I should stop editing |
|
4560 |
if (isEditing()) { |
|
4561 |
removeEditor(); |
|
4562 |
} |
|
4563 |
resizeAndRepaint(); |
|
4564 |
} |
|
4565 |
||
4566 |
/** |
|
4567 |
* Invoked when a column is repositioned. If a cell is being |
|
4568 |
* edited, then editing is stopped and the cell is redrawn. |
|
4569 |
* <p> |
|
4570 |
* Application code will not use these methods explicitly, they |
|
4571 |
* are used internally by JTable. |
|
4572 |
* |
|
4573 |
* @param e the event received |
|
4574 |
* @see TableColumnModelListener |
|
4575 |
*/ |
|
4576 |
public void columnMoved(TableColumnModelEvent e) { |
|
6651
f3f6465a128e
4330950: Lost newly entered data in the cell when resizing column width
alexp
parents:
6288
diff
changeset
|
4577 |
if (isEditing() && !getCellEditor().stopCellEditing()) { |
f3f6465a128e
4330950: Lost newly entered data in the cell when resizing column width
alexp
parents:
6288
diff
changeset
|
4578 |
getCellEditor().cancelCellEditing(); |
2 | 4579 |
} |
4580 |
repaint(); |
|
4581 |
} |
|
4582 |
||
4583 |
/** |
|
4584 |
* Invoked when a column is moved due to a margin change. |
|
4585 |
* If a cell is being edited, then editing is stopped and the cell |
|
4586 |
* is redrawn. |
|
4587 |
* <p> |
|
4588 |
* Application code will not use these methods explicitly, they |
|
4589 |
* are used internally by JTable. |
|
4590 |
* |
|
4591 |
* @param e the event received |
|
4592 |
* @see TableColumnModelListener |
|
4593 |
*/ |
|
4594 |
public void columnMarginChanged(ChangeEvent e) { |
|
6651
f3f6465a128e
4330950: Lost newly entered data in the cell when resizing column width
alexp
parents:
6288
diff
changeset
|
4595 |
if (isEditing() && !getCellEditor().stopCellEditing()) { |
f3f6465a128e
4330950: Lost newly entered data in the cell when resizing column width
alexp
parents:
6288
diff
changeset
|
4596 |
getCellEditor().cancelCellEditing(); |
2 | 4597 |
} |
4598 |
TableColumn resizingColumn = getResizingColumn(); |
|
4599 |
// Need to do this here, before the parent's |
|
4600 |
// layout manager calls getPreferredSize(). |
|
4601 |
if (resizingColumn != null && autoResizeMode == AUTO_RESIZE_OFF) { |
|
4602 |
resizingColumn.setPreferredWidth(resizingColumn.getWidth()); |
|
4603 |
} |
|
4604 |
resizeAndRepaint(); |
|
4605 |
} |
|
4606 |
||
4607 |
private int limit(int i, int a, int b) { |
|
4608 |
return Math.min(b, Math.max(i, a)); |
|
4609 |
} |
|
4610 |
||
4611 |
/** |
|
4612 |
* Invoked when the selection model of the <code>TableColumnModel</code> |
|
4613 |
* is changed. |
|
4614 |
* <p> |
|
4615 |
* Application code will not use these methods explicitly, they |
|
4616 |
* are used internally by JTable. |
|
4617 |
* |
|
4618 |
* @param e the event received |
|
4619 |
* @see TableColumnModelListener |
|
4620 |
*/ |
|
4621 |
public void columnSelectionChanged(ListSelectionEvent e) { |
|
4622 |
boolean isAdjusting = e.getValueIsAdjusting(); |
|
4623 |
if (columnSelectionAdjusting && !isAdjusting) { |
|
4624 |
// The assumption is that when the model is no longer adjusting |
|
4625 |
// we will have already gotten all the changes, and therefore |
|
4626 |
// don't need to do an additional paint. |
|
4627 |
columnSelectionAdjusting = false; |
|
4628 |
return; |
|
4629 |
} |
|
4630 |
columnSelectionAdjusting = isAdjusting; |
|
4631 |
// The getCellRect() call will fail unless there is at least one row. |
|
4632 |
if (getRowCount() <= 0 || getColumnCount() <= 0) { |
|
4633 |
return; |
|
4634 |
} |
|
4635 |
int firstIndex = limit(e.getFirstIndex(), 0, getColumnCount()-1); |
|
4636 |
int lastIndex = limit(e.getLastIndex(), 0, getColumnCount()-1); |
|
4637 |
int minRow = 0; |
|
4638 |
int maxRow = getRowCount() - 1; |
|
4639 |
if (getRowSelectionAllowed()) { |
|
4640 |
minRow = selectionModel.getMinSelectionIndex(); |
|
4641 |
maxRow = selectionModel.getMaxSelectionIndex(); |
|
4642 |
int leadRow = getAdjustedIndex(selectionModel.getLeadSelectionIndex(), true); |
|
4643 |
||
4644 |
if (minRow == -1 || maxRow == -1) { |
|
4645 |
if (leadRow == -1) { |
|
4646 |
// nothing to repaint, return |
|
4647 |
return; |
|
4648 |
} |
|
4649 |
||
4650 |
// only thing to repaint is the lead |
|
4651 |
minRow = maxRow = leadRow; |
|
4652 |
} else { |
|
4653 |
// We need to consider more than just the range between |
|
4654 |
// the min and max selected index. The lead row, which could |
|
4655 |
// be outside this range, should be considered also. |
|
4656 |
if (leadRow != -1) { |
|
4657 |
minRow = Math.min(minRow, leadRow); |
|
4658 |
maxRow = Math.max(maxRow, leadRow); |
|
4659 |
} |
|
4660 |
} |
|
4661 |
} |
|
4662 |
Rectangle firstColumnRect = getCellRect(minRow, firstIndex, false); |
|
4663 |
Rectangle lastColumnRect = getCellRect(maxRow, lastIndex, false); |
|
4664 |
Rectangle dirtyRegion = firstColumnRect.union(lastColumnRect); |
|
4665 |
repaint(dirtyRegion); |
|
4666 |
} |
|
4667 |
||
4668 |
// |
|
4669 |
// Implementing ListSelectionListener interface |
|
4670 |
// |
|
4671 |
||
4672 |
/** |
|
4673 |
* Invoked when the row selection changes -- repaints to show the new |
|
4674 |
* selection. |
|
4675 |
* <p> |
|
4676 |
* Application code will not use these methods explicitly, they |
|
4677 |
* are used internally by JTable. |
|
4678 |
* |
|
4679 |
* @param e the event received |
|
4680 |
* @see ListSelectionListener |
|
4681 |
*/ |
|
4682 |
public void valueChanged(ListSelectionEvent e) { |
|
4683 |
if (sortManager != null) { |
|
4684 |
sortManager.viewSelectionChanged(e); |
|
4685 |
} |
|
4686 |
boolean isAdjusting = e.getValueIsAdjusting(); |
|
4687 |
if (rowSelectionAdjusting && !isAdjusting) { |
|
4688 |
// The assumption is that when the model is no longer adjusting |
|
4689 |
// we will have already gotten all the changes, and therefore |
|
4690 |
// don't need to do an additional paint. |
|
4691 |
rowSelectionAdjusting = false; |
|
4692 |
return; |
|
4693 |
} |
|
4694 |
rowSelectionAdjusting = isAdjusting; |
|
4695 |
// The getCellRect() calls will fail unless there is at least one column. |
|
4696 |
if (getRowCount() <= 0 || getColumnCount() <= 0) { |
|
4697 |
return; |
|
4698 |
} |
|
4699 |
int firstIndex = limit(e.getFirstIndex(), 0, getRowCount()-1); |
|
4700 |
int lastIndex = limit(e.getLastIndex(), 0, getRowCount()-1); |
|
4701 |
Rectangle firstRowRect = getCellRect(firstIndex, 0, false); |
|
4702 |
Rectangle lastRowRect = getCellRect(lastIndex, getColumnCount()-1, false); |
|
4703 |
Rectangle dirtyRegion = firstRowRect.union(lastRowRect); |
|
4704 |
repaint(dirtyRegion); |
|
4705 |
} |
|
4706 |
||
4707 |
// |
|
4708 |
// Implementing the CellEditorListener interface |
|
4709 |
// |
|
4710 |
||
4711 |
/** |
|
4712 |
* Invoked when editing is finished. The changes are saved and the |
|
4713 |
* editor is discarded. |
|
4714 |
* <p> |
|
4715 |
* Application code will not use these methods explicitly, they |
|
4716 |
* are used internally by JTable. |
|
4717 |
* |
|
4718 |
* @param e the event received |
|
4719 |
* @see CellEditorListener |
|
4720 |
*/ |
|
4721 |
public void editingStopped(ChangeEvent e) { |
|
4722 |
// Take in the new value |
|
4723 |
TableCellEditor editor = getCellEditor(); |
|
4724 |
if (editor != null) { |
|
4725 |
Object value = editor.getCellEditorValue(); |
|
4726 |
setValueAt(value, editingRow, editingColumn); |
|
4727 |
removeEditor(); |
|
4728 |
} |
|
4729 |
} |
|
4730 |
||
4731 |
/** |
|
4732 |
* Invoked when editing is canceled. The editor object is discarded |
|
4733 |
* and the cell is rendered once again. |
|
4734 |
* <p> |
|
4735 |
* Application code will not use these methods explicitly, they |
|
4736 |
* are used internally by JTable. |
|
4737 |
* |
|
4738 |
* @param e the event received |
|
4739 |
* @see CellEditorListener |
|
4740 |
*/ |
|
4741 |
public void editingCanceled(ChangeEvent e) { |
|
4742 |
removeEditor(); |
|
4743 |
} |
|
4744 |
||
4745 |
// |
|
4746 |
// Implementing the Scrollable interface |
|
4747 |
// |
|
4748 |
||
4749 |
/** |
|
4750 |
* Sets the preferred size of the viewport for this table. |
|
4751 |
* |
|
4752 |
* @param size a <code>Dimension</code> object specifying the <code>preferredSize</code> of a |
|
4753 |
* <code>JViewport</code> whose view is this table |
|
4754 |
* @see Scrollable#getPreferredScrollableViewportSize |
|
4755 |
* @beaninfo |
|
4756 |
* description: The preferred size of the viewport. |
|
4757 |
*/ |
|
4758 |
public void setPreferredScrollableViewportSize(Dimension size) { |
|
4759 |
preferredViewportSize = size; |
|
4760 |
} |
|
4761 |
||
4762 |
/** |
|
4763 |
* Returns the preferred size of the viewport for this table. |
|
4764 |
* |
|
4765 |
* @return a <code>Dimension</code> object containing the <code>preferredSize</code> of the <code>JViewport</code> |
|
4766 |
* which displays this table |
|
4767 |
* @see Scrollable#getPreferredScrollableViewportSize |
|
4768 |
*/ |
|
4769 |
public Dimension getPreferredScrollableViewportSize() { |
|
4770 |
return preferredViewportSize; |
|
4771 |
} |
|
4772 |
||
4773 |
/** |
|
4774 |
* Returns the scroll increment (in pixels) that completely exposes one new |
|
4775 |
* row or column (depending on the orientation). |
|
4776 |
* <p> |
|
4777 |
* This method is called each time the user requests a unit scroll. |
|
4778 |
* |
|
4779 |
* @param visibleRect the view area visible within the viewport |
|
4780 |
* @param orientation either <code>SwingConstants.VERTICAL</code> |
|
4781 |
* or <code>SwingConstants.HORIZONTAL</code> |
|
4782 |
* @param direction less than zero to scroll up/left, |
|
4783 |
* greater than zero for down/right |
|
4784 |
* @return the "unit" increment for scrolling in the specified direction |
|
4785 |
* @see Scrollable#getScrollableUnitIncrement |
|
4786 |
*/ |
|
4787 |
public int getScrollableUnitIncrement(Rectangle visibleRect, |
|
4788 |
int orientation, |
|
4789 |
int direction) { |
|
4790 |
int leadingRow; |
|
4791 |
int leadingCol; |
|
4792 |
Rectangle leadingCellRect; |
|
4793 |
||
4794 |
int leadingVisibleEdge; |
|
4795 |
int leadingCellEdge; |
|
4796 |
int leadingCellSize; |
|
4797 |
||
4798 |
leadingRow = getLeadingRow(visibleRect); |
|
4799 |
leadingCol = getLeadingCol(visibleRect); |
|
4800 |
if (orientation == SwingConstants.VERTICAL && leadingRow < 0) { |
|
4801 |
// Couldn't find leading row - return some default value |
|
4802 |
return getRowHeight(); |
|
4803 |
} |
|
4804 |
else if (orientation == SwingConstants.HORIZONTAL && leadingCol < 0) { |
|
4805 |
// Couldn't find leading col - return some default value |
|
4806 |
return 100; |
|
4807 |
} |
|
4808 |
||
4809 |
// Note that it's possible for one of leadingCol or leadingRow to be |
|
4810 |
// -1, depending on the orientation. This is okay, as getCellRect() |
|
4811 |
// still provides enough information to calculate the unit increment. |
|
4812 |
leadingCellRect = getCellRect(leadingRow, leadingCol, true); |
|
4813 |
leadingVisibleEdge = leadingEdge(visibleRect, orientation); |
|
4814 |
leadingCellEdge = leadingEdge(leadingCellRect, orientation); |
|
4815 |
||
4816 |
if (orientation == SwingConstants.VERTICAL) { |
|
4817 |
leadingCellSize = leadingCellRect.height; |
|
4818 |
||
4819 |
} |
|
4820 |
else { |
|
4821 |
leadingCellSize = leadingCellRect.width; |
|
4822 |
} |
|
4823 |
||
4824 |
// 4 cases: |
|
4825 |
// #1: Leading cell fully visible, reveal next cell |
|
4826 |
// #2: Leading cell fully visible, hide leading cell |
|
4827 |
// #3: Leading cell partially visible, hide rest of leading cell |
|
4828 |
// #4: Leading cell partially visible, reveal rest of leading cell |
|
4829 |
||
4830 |
if (leadingVisibleEdge == leadingCellEdge) { // Leading cell is fully |
|
4831 |
// visible |
|
4832 |
// Case #1: Reveal previous cell |
|
4833 |
if (direction < 0) { |
|
4834 |
int retVal = 0; |
|
4835 |
||
4836 |
if (orientation == SwingConstants.VERTICAL) { |
|
4837 |
// Loop past any zero-height rows |
|
4838 |
while (--leadingRow >= 0) { |
|
4839 |
retVal = getRowHeight(leadingRow); |
|
4840 |
if (retVal != 0) { |
|
4841 |
break; |
|
4842 |
} |
|
4843 |
} |
|
4844 |
} |
|
4845 |
else { // HORIZONTAL |
|
4846 |
// Loop past any zero-width cols |
|
4847 |
while (--leadingCol >= 0) { |
|
4848 |
retVal = getCellRect(leadingRow, leadingCol, true).width; |
|
4849 |
if (retVal != 0) { |
|
4850 |
break; |
|
4851 |
} |
|
4852 |
} |
|
4853 |
} |
|
4854 |
return retVal; |
|
4855 |
} |
|
4856 |
else { // Case #2: hide leading cell |
|
4857 |
return leadingCellSize; |
|
4858 |
} |
|
4859 |
} |
|
4860 |
else { // Leading cell is partially hidden |
|
4861 |
// Compute visible, hidden portions |
|
4862 |
int hiddenAmt = Math.abs(leadingVisibleEdge - leadingCellEdge); |
|
4863 |
int visibleAmt = leadingCellSize - hiddenAmt; |
|
4864 |
||
4865 |
if (direction > 0) { |
|
4866 |
// Case #3: hide showing portion of leading cell |
|
4867 |
return visibleAmt; |
|
4868 |
} |
|
4869 |
else { // Case #4: reveal hidden portion of leading cell |
|
4870 |
return hiddenAmt; |
|
4871 |
} |
|
4872 |
} |
|
4873 |
} |
|
4874 |
||
4875 |
/** |
|
4876 |
* Returns <code>visibleRect.height</code> or |
|
4877 |
* <code>visibleRect.width</code>, |
|
4878 |
* depending on this table's orientation. Note that as of Swing 1.1.1 |
|
4879 |
* (Java 2 v 1.2.2) the value |
|
4880 |
* returned will ensure that the viewport is cleanly aligned on |
|
4881 |
* a row boundary. |
|
4882 |
* |
|
4883 |
* @return <code>visibleRect.height</code> or |
|
4884 |
* <code>visibleRect.width</code> |
|
4885 |
* per the orientation |
|
4886 |
* @see Scrollable#getScrollableBlockIncrement |
|
4887 |
*/ |
|
4888 |
public int getScrollableBlockIncrement(Rectangle visibleRect, |
|
4889 |
int orientation, int direction) { |
|
4890 |
||
4891 |
if (getRowCount() == 0) { |
|
4892 |
// Short-circuit empty table model |
|
4893 |
if (SwingConstants.VERTICAL == orientation) { |
|
4894 |
int rh = getRowHeight(); |
|
4895 |
return (rh > 0) ? Math.max(rh, (visibleRect.height / rh) * rh) : |
|
4896 |
visibleRect.height; |
|
4897 |
} |
|
4898 |
else { |
|
4899 |
return visibleRect.width; |
|
4900 |
} |
|
4901 |
} |
|
4902 |
// Shortcut for vertical scrolling of a table w/ uniform row height |
|
4903 |
if (null == rowModel && SwingConstants.VERTICAL == orientation) { |
|
4904 |
int row = rowAtPoint(visibleRect.getLocation()); |
|
4905 |
assert row != -1; |
|
4906 |
int col = columnAtPoint(visibleRect.getLocation()); |
|
4907 |
Rectangle cellRect = getCellRect(row, col, true); |
|
4908 |
||
4909 |
if (cellRect.y == visibleRect.y) { |
|
4910 |
int rh = getRowHeight(); |
|
4911 |
assert rh > 0; |
|
4912 |
return Math.max(rh, (visibleRect.height / rh) * rh); |
|
4913 |
} |
|
4914 |
} |
|
4915 |
if (direction < 0) { |
|
4916 |
return getPreviousBlockIncrement(visibleRect, orientation); |
|
4917 |
} |
|
4918 |
else { |
|
4919 |
return getNextBlockIncrement(visibleRect, orientation); |
|
4920 |
} |
|
4921 |
} |
|
4922 |
||
4923 |
/** |
|
4924 |
* Called to get the block increment for upward scrolling in cases of |
|
4925 |
* horizontal scrolling, or for vertical scrolling of a table with |
|
4926 |
* variable row heights. |
|
4927 |
*/ |
|
4928 |
private int getPreviousBlockIncrement(Rectangle visibleRect, |
|
4929 |
int orientation) { |
|
4930 |
// Measure back from visible leading edge |
|
4931 |
// If we hit the cell on its leading edge, it becomes the leading cell. |
|
4932 |
// Else, use following cell |
|
4933 |
||
4934 |
int row; |
|
4935 |
int col; |
|
4936 |
||
4937 |
int newEdge; |
|
4938 |
Point newCellLoc; |
|
4939 |
||
4940 |
int visibleLeadingEdge = leadingEdge(visibleRect, orientation); |
|
4941 |
boolean leftToRight = getComponentOrientation().isLeftToRight(); |
|
4942 |
int newLeadingEdge; |
|
4943 |
||
4944 |
// Roughly determine the new leading edge by measuring back from the |
|
4945 |
// leading visible edge by the size of the visible rect, and find the |
|
4946 |
// cell there. |
|
4947 |
if (orientation == SwingConstants.VERTICAL) { |
|
4948 |
newEdge = visibleLeadingEdge - visibleRect.height; |
|
4949 |
int x = visibleRect.x + (leftToRight ? 0 : visibleRect.width); |
|
4950 |
newCellLoc = new Point(x, newEdge); |
|
4951 |
} |
|
4952 |
else if (leftToRight) { |
|
4953 |
newEdge = visibleLeadingEdge - visibleRect.width; |
|
4954 |
newCellLoc = new Point(newEdge, visibleRect.y); |
|
4955 |
} |
|
4956 |
else { // Horizontal, right-to-left |
|
4957 |
newEdge = visibleLeadingEdge + visibleRect.width; |
|
4958 |
newCellLoc = new Point(newEdge - 1, visibleRect.y); |
|
4959 |
} |
|
4960 |
row = rowAtPoint(newCellLoc); |
|
4961 |
col = columnAtPoint(newCellLoc); |
|
4962 |
||
4963 |
// If we're measuring past the beginning of the table, we get an invalid |
|
4964 |
// cell. Just go to the beginning of the table in this case. |
|
4965 |
if (orientation == SwingConstants.VERTICAL & row < 0) { |
|
4966 |
newLeadingEdge = 0; |
|
4967 |
} |
|
4968 |
else if (orientation == SwingConstants.HORIZONTAL & col < 0) { |
|
4969 |
if (leftToRight) { |
|
4970 |
newLeadingEdge = 0; |
|
4971 |
} |
|
4972 |
else { |
|
4973 |
newLeadingEdge = getWidth(); |
|
4974 |
} |
|
4975 |
} |
|
4976 |
else { |
|
4977 |
// Refine our measurement |
|
4978 |
Rectangle newCellRect = getCellRect(row, col, true); |
|
4979 |
int newCellLeadingEdge = leadingEdge(newCellRect, orientation); |
|
4980 |
int newCellTrailingEdge = trailingEdge(newCellRect, orientation); |
|
4981 |
||
4982 |
// Usually, we hit in the middle of newCell, and want to scroll to |
|
4983 |
// the beginning of the cell after newCell. But there are a |
|
4984 |
// couple corner cases where we want to scroll to the beginning of |
|
4985 |
// newCell itself. These cases are: |
|
4986 |
// 1) newCell is so large that it ends at or extends into the |
|
4987 |
// visibleRect (newCell is the leading cell, or is adjacent to |
|
4988 |
// the leading cell) |
|
4989 |
// 2) newEdge happens to fall right on the beginning of a cell |
|
4990 |
||
4991 |
// Case 1 |
|
4992 |
if ((orientation == SwingConstants.VERTICAL || leftToRight) && |
|
4993 |
(newCellTrailingEdge >= visibleLeadingEdge)) { |
|
4994 |
newLeadingEdge = newCellLeadingEdge; |
|
4995 |
} |
|
4996 |
else if (orientation == SwingConstants.HORIZONTAL && |
|
4997 |
!leftToRight && |
|
4998 |
newCellTrailingEdge <= visibleLeadingEdge) { |
|
4999 |
newLeadingEdge = newCellLeadingEdge; |
|
5000 |
} |
|
5001 |
// Case 2: |
|
5002 |
else if (newEdge == newCellLeadingEdge) { |
|
5003 |
newLeadingEdge = newCellLeadingEdge; |
|
5004 |
} |
|
5005 |
// Common case: scroll to cell after newCell |
|
5006 |
else { |
|
5007 |
newLeadingEdge = newCellTrailingEdge; |
|
5008 |
} |
|
5009 |
} |
|
5010 |
return Math.abs(visibleLeadingEdge - newLeadingEdge); |
|
5011 |
} |
|
5012 |
||
5013 |
/** |
|
5014 |
* Called to get the block increment for downward scrolling in cases of |
|
5015 |
* horizontal scrolling, or for vertical scrolling of a table with |
|
5016 |
* variable row heights. |
|
5017 |
*/ |
|
5018 |
private int getNextBlockIncrement(Rectangle visibleRect, |
|
5019 |
int orientation) { |
|
5020 |
// Find the cell at the trailing edge. Return the distance to put |
|
5021 |
// that cell at the leading edge. |
|
5022 |
int trailingRow = getTrailingRow(visibleRect); |
|
5023 |
int trailingCol = getTrailingCol(visibleRect); |
|
5024 |
||
5025 |
Rectangle cellRect; |
|
5026 |
boolean cellFillsVis; |
|
5027 |
||
5028 |
int cellLeadingEdge; |
|
5029 |
int cellTrailingEdge; |
|
5030 |
int newLeadingEdge; |
|
5031 |
int visibleLeadingEdge = leadingEdge(visibleRect, orientation); |
|
5032 |
||
5033 |
// If we couldn't find trailing cell, just return the size of the |
|
5034 |
// visibleRect. Note that, for instance, we don't need the |
|
5035 |
// trailingCol to proceed if we're scrolling vertically, because |
|
5036 |
// cellRect will still fill in the required dimensions. This would |
|
5037 |
// happen if we're scrolling vertically, and the table is not wide |
|
5038 |
// enough to fill the visibleRect. |
|
5039 |
if (orientation == SwingConstants.VERTICAL && trailingRow < 0) { |
|
5040 |
return visibleRect.height; |
|
5041 |
} |
|
5042 |
else if (orientation == SwingConstants.HORIZONTAL && trailingCol < 0) { |
|
5043 |
return visibleRect.width; |
|
5044 |
} |
|
5045 |
cellRect = getCellRect(trailingRow, trailingCol, true); |
|
5046 |
cellLeadingEdge = leadingEdge(cellRect, orientation); |
|
5047 |
cellTrailingEdge = trailingEdge(cellRect, orientation); |
|
5048 |
||
5049 |
if (orientation == SwingConstants.VERTICAL || |
|
5050 |
getComponentOrientation().isLeftToRight()) { |
|
5051 |
cellFillsVis = cellLeadingEdge <= visibleLeadingEdge; |
|
5052 |
} |
|
5053 |
else { // Horizontal, right-to-left |
|
5054 |
cellFillsVis = cellLeadingEdge >= visibleLeadingEdge; |
|
5055 |
} |
|
5056 |
||
5057 |
if (cellFillsVis) { |
|
5058 |
// The visibleRect contains a single large cell. Scroll to the end |
|
5059 |
// of this cell, so the following cell is the first cell. |
|
5060 |
newLeadingEdge = cellTrailingEdge; |
|
5061 |
} |
|
5062 |
else if (cellTrailingEdge == trailingEdge(visibleRect, orientation)) { |
|
5063 |
// The trailing cell happens to end right at the end of the |
|
5064 |
// visibleRect. Again, scroll to the beginning of the next cell. |
|
5065 |
newLeadingEdge = cellTrailingEdge; |
|
5066 |
} |
|
5067 |
else { |
|
5068 |
// Common case: the trailing cell is partially visible, and isn't |
|
5069 |
// big enough to take up the entire visibleRect. Scroll so it |
|
5070 |
// becomes the leading cell. |
|
5071 |
newLeadingEdge = cellLeadingEdge; |
|
5072 |
} |
|
5073 |
return Math.abs(newLeadingEdge - visibleLeadingEdge); |
|
5074 |
} |
|
5075 |
||
5076 |
/* |
|
5077 |
* Return the row at the top of the visibleRect |
|
5078 |
* |
|
5079 |
* May return -1 |
|
5080 |
*/ |
|
5081 |
private int getLeadingRow(Rectangle visibleRect) { |
|
5082 |
Point leadingPoint; |
|
5083 |
||
5084 |
if (getComponentOrientation().isLeftToRight()) { |
|
5085 |
leadingPoint = new Point(visibleRect.x, visibleRect.y); |
|
5086 |
} |
|
5087 |
else { |
|
5088 |
leadingPoint = new Point(visibleRect.x + visibleRect.width - 1, |
|
5089 |
visibleRect.y); |
|
5090 |
} |
|
5091 |
return rowAtPoint(leadingPoint); |
|
5092 |
} |
|
5093 |
||
5094 |
/* |
|
5095 |
* Return the column at the leading edge of the visibleRect. |
|
5096 |
* |
|
5097 |
* May return -1 |
|
5098 |
*/ |
|
5099 |
private int getLeadingCol(Rectangle visibleRect) { |
|
5100 |
Point leadingPoint; |
|
5101 |
||
5102 |
if (getComponentOrientation().isLeftToRight()) { |
|
5103 |
leadingPoint = new Point(visibleRect.x, visibleRect.y); |
|
5104 |
} |
|
5105 |
else { |
|
5106 |
leadingPoint = new Point(visibleRect.x + visibleRect.width - 1, |
|
5107 |
visibleRect.y); |
|
5108 |
} |
|
5109 |
return columnAtPoint(leadingPoint); |
|
5110 |
} |
|
5111 |
||
5112 |
/* |
|
5113 |
* Return the row at the bottom of the visibleRect. |
|
5114 |
* |
|
5115 |
* May return -1 |
|
5116 |
*/ |
|
5117 |
private int getTrailingRow(Rectangle visibleRect) { |
|
5118 |
Point trailingPoint; |
|
5119 |
||
5120 |
if (getComponentOrientation().isLeftToRight()) { |
|
5121 |
trailingPoint = new Point(visibleRect.x, |
|
5122 |
visibleRect.y + visibleRect.height - 1); |
|
5123 |
} |
|
5124 |
else { |
|
5125 |
trailingPoint = new Point(visibleRect.x + visibleRect.width - 1, |
|
5126 |
visibleRect.y + visibleRect.height - 1); |
|
5127 |
} |
|
5128 |
return rowAtPoint(trailingPoint); |
|
5129 |
} |
|
5130 |
||
5131 |
/* |
|
5132 |
* Return the column at the trailing edge of the visibleRect. |
|
5133 |
* |
|
5134 |
* May return -1 |
|
5135 |
*/ |
|
5136 |
private int getTrailingCol(Rectangle visibleRect) { |
|
5137 |
Point trailingPoint; |
|
5138 |
||
5139 |
if (getComponentOrientation().isLeftToRight()) { |
|
5140 |
trailingPoint = new Point(visibleRect.x + visibleRect.width - 1, |
|
5141 |
visibleRect.y); |
|
5142 |
} |
|
5143 |
else { |
|
5144 |
trailingPoint = new Point(visibleRect.x, visibleRect.y); |
|
5145 |
} |
|
5146 |
return columnAtPoint(trailingPoint); |
|
5147 |
} |
|
5148 |
||
5149 |
/* |
|
5150 |
* Returns the leading edge ("beginning") of the given Rectangle. |
|
5151 |
* For VERTICAL, this is the top, for left-to-right, the left side, and for |
|
5152 |
* right-to-left, the right side. |
|
5153 |
*/ |
|
5154 |
private int leadingEdge(Rectangle rect, int orientation) { |
|
5155 |
if (orientation == SwingConstants.VERTICAL) { |
|
5156 |
return rect.y; |
|
5157 |
} |
|
5158 |
else if (getComponentOrientation().isLeftToRight()) { |
|
5159 |
return rect.x; |
|
5160 |
} |
|
5161 |
else { // Horizontal, right-to-left |
|
5162 |
return rect.x + rect.width; |
|
5163 |
} |
|
5164 |
} |
|
5165 |
||
5166 |
/* |
|
5167 |
* Returns the trailing edge ("end") of the given Rectangle. |
|
5168 |
* For VERTICAL, this is the bottom, for left-to-right, the right side, and |
|
5169 |
* for right-to-left, the left side. |
|
5170 |
*/ |
|
5171 |
private int trailingEdge(Rectangle rect, int orientation) { |
|
5172 |
if (orientation == SwingConstants.VERTICAL) { |
|
5173 |
return rect.y + rect.height; |
|
5174 |
} |
|
5175 |
else if (getComponentOrientation().isLeftToRight()) { |
|
5176 |
return rect.x + rect.width; |
|
5177 |
} |
|
5178 |
else { // Horizontal, right-to-left |
|
5179 |
return rect.x; |
|
5180 |
} |
|
5181 |
} |
|
5182 |
||
5183 |
/** |
|
5184 |
* Returns false if <code>autoResizeMode</code> is set to |
|
5185 |
* <code>AUTO_RESIZE_OFF</code>, which indicates that the |
|
5186 |
* width of the viewport does not determine the width |
|
5187 |
* of the table. Otherwise returns true. |
|
5188 |
* |
|
5189 |
* @return false if <code>autoResizeMode</code> is set |
|
5190 |
* to <code>AUTO_RESIZE_OFF</code>, otherwise returns true |
|
5191 |
* @see Scrollable#getScrollableTracksViewportWidth |
|
5192 |
*/ |
|
5193 |
public boolean getScrollableTracksViewportWidth() { |
|
5194 |
return !(autoResizeMode == AUTO_RESIZE_OFF); |
|
5195 |
} |
|
5196 |
||
5197 |
/** |
|
5198 |
* Returns {@code false} to indicate that the height of the viewport does |
|
5199 |
* not determine the height of the table, unless |
|
5200 |
* {@code getFillsViewportHeight} is {@code true} and the preferred height |
|
5201 |
* of the table is smaller than the viewport's height. |
|
5202 |
* |
|
5203 |
* @return {@code false} unless {@code getFillsViewportHeight} is |
|
5204 |
* {@code true} and the table needs to be stretched to fill |
|
5205 |
* the viewport |
|
5206 |
* @see Scrollable#getScrollableTracksViewportHeight |
|
5207 |
* @see #setFillsViewportHeight |
|
5208 |
* @see #getFillsViewportHeight |
|
5209 |
*/ |
|
5210 |
public boolean getScrollableTracksViewportHeight() { |
|
5449 | 5211 |
Container parent = SwingUtilities.getUnwrappedParent(this); |
2 | 5212 |
return getFillsViewportHeight() |
5449 | 5213 |
&& parent instanceof JViewport |
5214 |
&& parent.getHeight() > getPreferredSize().height; |
|
2 | 5215 |
} |
5216 |
||
5217 |
/** |
|
5218 |
* Sets whether or not this table is always made large enough |
|
5219 |
* to fill the height of an enclosing viewport. If the preferred |
|
5220 |
* height of the table is smaller than the viewport, then the table |
|
5221 |
* will be stretched to fill the viewport. In other words, this |
|
5222 |
* ensures the table is never smaller than the viewport. |
|
5223 |
* The default for this property is {@code false}. |
|
5224 |
* |
|
5225 |
* @param fillsViewportHeight whether or not this table is always |
|
5226 |
* made large enough to fill the height of an enclosing |
|
5227 |
* viewport |
|
5228 |
* @see #getFillsViewportHeight |
|
5229 |
* @see #getScrollableTracksViewportHeight |
|
5230 |
* @since 1.6 |
|
5231 |
* @beaninfo |
|
5232 |
* bound: true |
|
5233 |
* description: Whether or not this table is always made large enough |
|
5234 |
* to fill the height of an enclosing viewport |
|
5235 |
*/ |
|
5236 |
public void setFillsViewportHeight(boolean fillsViewportHeight) { |
|
5237 |
boolean old = this.fillsViewportHeight; |
|
5238 |
this.fillsViewportHeight = fillsViewportHeight; |
|
5239 |
resizeAndRepaint(); |
|
5240 |
firePropertyChange("fillsViewportHeight", old, fillsViewportHeight); |
|
5241 |
} |
|
5242 |
||
5243 |
/** |
|
5244 |
* Returns whether or not this table is always made large enough |
|
5245 |
* to fill the height of an enclosing viewport. |
|
5246 |
* |
|
5247 |
* @return whether or not this table is always made large enough |
|
5248 |
* to fill the height of an enclosing viewport |
|
5249 |
* @see #setFillsViewportHeight |
|
5250 |
* @since 1.6 |
|
5251 |
*/ |
|
5252 |
public boolean getFillsViewportHeight() { |
|
5253 |
return fillsViewportHeight; |
|
5254 |
} |
|
5255 |
||
5256 |
// |
|
5257 |
// Protected Methods |
|
5258 |
// |
|
5259 |
||
5260 |
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, |
|
5261 |
int condition, boolean pressed) { |
|
5262 |
boolean retValue = super.processKeyBinding(ks, e, condition, pressed); |
|
5263 |
||
5264 |
// Start editing when a key is typed. UI classes can disable this behavior |
|
5265 |
// by setting the client property JTable.autoStartsEdit to Boolean.FALSE. |
|
5266 |
if (!retValue && condition == WHEN_ANCESTOR_OF_FOCUSED_COMPONENT && |
|
5267 |
isFocusOwner() && |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
5268 |
!Boolean.FALSE.equals(getClientProperty("JTable.autoStartsEdit"))) { |
2 | 5269 |
// We do not have a binding for the event. |
5270 |
Component editorComponent = getEditorComponent(); |
|
5271 |
if (editorComponent == null) { |
|
5272 |
// Only attempt to install the editor on a KEY_PRESSED, |
|
5273 |
if (e == null || e.getID() != KeyEvent.KEY_PRESSED) { |
|
5274 |
return false; |
|
5275 |
} |
|
5276 |
// Don't start when just a modifier is pressed |
|
5277 |
int code = e.getKeyCode(); |
|
5278 |
if (code == KeyEvent.VK_SHIFT || code == KeyEvent.VK_CONTROL || |
|
5279 |
code == KeyEvent.VK_ALT) { |
|
5280 |
return false; |
|
5281 |
} |
|
5282 |
// Try to install the editor |
|
5283 |
int leadRow = getSelectionModel().getLeadSelectionIndex(); |
|
5284 |
int leadColumn = getColumnModel().getSelectionModel(). |
|
5285 |
getLeadSelectionIndex(); |
|
5286 |
if (leadRow != -1 && leadColumn != -1 && !isEditing()) { |
|
5287 |
if (!editCellAt(leadRow, leadColumn, e)) { |
|
5288 |
return false; |
|
5289 |
} |
|
5290 |
} |
|
5291 |
editorComponent = getEditorComponent(); |
|
5292 |
if (editorComponent == null) { |
|
5293 |
return false; |
|
5294 |
} |
|
5295 |
} |
|
5296 |
// If the editorComponent is a JComponent, pass the event to it. |
|
5297 |
if (editorComponent instanceof JComponent) { |
|
5298 |
retValue = ((JComponent)editorComponent).processKeyBinding |
|
5299 |
(ks, e, WHEN_FOCUSED, pressed); |
|
5300 |
// If we have started an editor as a result of the user |
|
5301 |
// pressing a key and the surrendersFocusOnKeystroke property |
|
5302 |
// is true, give the focus to the new editor. |
|
5303 |
if (getSurrendersFocusOnKeystroke()) { |
|
5304 |
editorComponent.requestFocus(); |
|
5305 |
} |
|
5306 |
} |
|
5307 |
} |
|
5308 |
return retValue; |
|
5309 |
} |
|
5310 |
||
5311 |
private void setLazyValue(Hashtable h, Class c, String s) { |
|
4272
f4742294ef29
6795356: Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc
alexp
parents:
3737
diff
changeset
|
5312 |
h.put(c, new SwingLazyValue(s)); |
2 | 5313 |
} |
5314 |
||
5315 |
private void setLazyRenderer(Class c, String s) { |
|
5316 |
setLazyValue(defaultRenderersByColumnClass, c, s); |
|
5317 |
} |
|
5318 |
||
5319 |
/** |
|
5320 |
* Creates default cell renderers for objects, numbers, doubles, dates, |
|
5321 |
* booleans, and icons. |
|
5322 |
* @see javax.swing.table.DefaultTableCellRenderer |
|
5323 |
* |
|
5324 |
*/ |
|
5325 |
protected void createDefaultRenderers() { |
|
5326 |
defaultRenderersByColumnClass = new UIDefaults(8, 0.75f); |
|
5327 |
||
5328 |
// Objects |
|
5329 |
setLazyRenderer(Object.class, "javax.swing.table.DefaultTableCellRenderer$UIResource"); |
|
5330 |
||
5331 |
// Numbers |
|
5332 |
setLazyRenderer(Number.class, "javax.swing.JTable$NumberRenderer"); |
|
5333 |
||
5334 |
// Doubles and Floats |
|
5335 |
setLazyRenderer(Float.class, "javax.swing.JTable$DoubleRenderer"); |
|
5336 |
setLazyRenderer(Double.class, "javax.swing.JTable$DoubleRenderer"); |
|
5337 |
||
5338 |
// Dates |
|
5339 |
setLazyRenderer(Date.class, "javax.swing.JTable$DateRenderer"); |
|
5340 |
||
5341 |
// Icons and ImageIcons |
|
5342 |
setLazyRenderer(Icon.class, "javax.swing.JTable$IconRenderer"); |
|
5343 |
setLazyRenderer(ImageIcon.class, "javax.swing.JTable$IconRenderer"); |
|
5344 |
||
5345 |
// Booleans |
|
5346 |
setLazyRenderer(Boolean.class, "javax.swing.JTable$BooleanRenderer"); |
|
5347 |
} |
|
5348 |
||
5349 |
/** |
|
5350 |
* Default Renderers |
|
5351 |
**/ |
|
5352 |
static class NumberRenderer extends DefaultTableCellRenderer.UIResource { |
|
5353 |
public NumberRenderer() { |
|
5354 |
super(); |
|
5355 |
setHorizontalAlignment(JLabel.RIGHT); |
|
5356 |
} |
|
5357 |
} |
|
5358 |
||
5359 |
static class DoubleRenderer extends NumberRenderer { |
|
5360 |
NumberFormat formatter; |
|
5361 |
public DoubleRenderer() { super(); } |
|
5362 |
||
5363 |
public void setValue(Object value) { |
|
5364 |
if (formatter == null) { |
|
5365 |
formatter = NumberFormat.getInstance(); |
|
5366 |
} |
|
5367 |
setText((value == null) ? "" : formatter.format(value)); |
|
5368 |
} |
|
5369 |
} |
|
5370 |
||
5371 |
static class DateRenderer extends DefaultTableCellRenderer.UIResource { |
|
5372 |
DateFormat formatter; |
|
5373 |
public DateRenderer() { super(); } |
|
5374 |
||
5375 |
public void setValue(Object value) { |
|
5376 |
if (formatter==null) { |
|
5377 |
formatter = DateFormat.getDateInstance(); |
|
5378 |
} |
|
5379 |
setText((value == null) ? "" : formatter.format(value)); |
|
5380 |
} |
|
5381 |
} |
|
5382 |
||
5383 |
static class IconRenderer extends DefaultTableCellRenderer.UIResource { |
|
5384 |
public IconRenderer() { |
|
5385 |
super(); |
|
5386 |
setHorizontalAlignment(JLabel.CENTER); |
|
5387 |
} |
|
5388 |
public void setValue(Object value) { setIcon((value instanceof Icon) ? (Icon)value : null); } |
|
5389 |
} |
|
5390 |
||
5391 |
||
5392 |
static class BooleanRenderer extends JCheckBox implements TableCellRenderer, UIResource |
|
5393 |
{ |
|
5394 |
private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); |
|
5395 |
||
5396 |
public BooleanRenderer() { |
|
5397 |
super(); |
|
5398 |
setHorizontalAlignment(JLabel.CENTER); |
|
5399 |
setBorderPainted(true); |
|
5400 |
} |
|
5401 |
||
5402 |
public Component getTableCellRendererComponent(JTable table, Object value, |
|
5403 |
boolean isSelected, boolean hasFocus, int row, int column) { |
|
5404 |
if (isSelected) { |
|
5405 |
setForeground(table.getSelectionForeground()); |
|
5406 |
super.setBackground(table.getSelectionBackground()); |
|
5407 |
} |
|
5408 |
else { |
|
5409 |
setForeground(table.getForeground()); |
|
5410 |
setBackground(table.getBackground()); |
|
5411 |
} |
|
5412 |
setSelected((value != null && ((Boolean)value).booleanValue())); |
|
5413 |
||
5414 |
if (hasFocus) { |
|
5415 |
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); |
|
5416 |
} else { |
|
5417 |
setBorder(noFocusBorder); |
|
5418 |
} |
|
5419 |
||
5420 |
return this; |
|
5421 |
} |
|
5422 |
} |
|
5423 |
||
5424 |
private void setLazyEditor(Class c, String s) { |
|
5425 |
setLazyValue(defaultEditorsByColumnClass, c, s); |
|
5426 |
} |
|
5427 |
||
5428 |
/** |
|
5429 |
* Creates default cell editors for objects, numbers, and boolean values. |
|
5430 |
* @see DefaultCellEditor |
|
5431 |
*/ |
|
5432 |
protected void createDefaultEditors() { |
|
5433 |
defaultEditorsByColumnClass = new UIDefaults(3, 0.75f); |
|
5434 |
||
5435 |
// Objects |
|
5436 |
setLazyEditor(Object.class, "javax.swing.JTable$GenericEditor"); |
|
5437 |
||
5438 |
// Numbers |
|
5439 |
setLazyEditor(Number.class, "javax.swing.JTable$NumberEditor"); |
|
5440 |
||
5441 |
// Booleans |
|
5442 |
setLazyEditor(Boolean.class, "javax.swing.JTable$BooleanEditor"); |
|
5443 |
} |
|
5444 |
||
5445 |
/** |
|
5446 |
* Default Editors |
|
5447 |
*/ |
|
5448 |
static class GenericEditor extends DefaultCellEditor { |
|
5449 |
||
5450 |
Class[] argTypes = new Class[]{String.class}; |
|
5451 |
java.lang.reflect.Constructor constructor; |
|
5452 |
Object value; |
|
5453 |
||
5454 |
public GenericEditor() { |
|
5455 |
super(new JTextField()); |
|
5456 |
getComponent().setName("Table.editor"); |
|
5457 |
} |
|
5458 |
||
5459 |
public boolean stopCellEditing() { |
|
5460 |
String s = (String)super.getCellEditorValue(); |
|
5461 |
// Here we are dealing with the case where a user |
|
5462 |
// has deleted the string value in a cell, possibly |
|
5463 |
// after a failed validation. Return null, so that |
|
5464 |
// they have the option to replace the value with |
|
5465 |
// null or use escape to restore the original. |
|
5466 |
// For Strings, return "" for backward compatibility. |
|
5467 |
try { |
|
20800 | 5468 |
if ("".equals(s)) { |
5469 |
if (constructor.getDeclaringClass() == String.class) { |
|
5470 |
value = s; |
|
5471 |
} |
|
5472 |
return super.stopCellEditing(); |
|
5473 |
} |
|
5474 |
||
5475 |
SwingUtilities2.checkAccess(constructor.getModifiers()); |
|
2 | 5476 |
value = constructor.newInstance(new Object[]{s}); |
5477 |
} |
|
5478 |
catch (Exception e) { |
|
5479 |
((JComponent)getComponent()).setBorder(new LineBorder(Color.red)); |
|
5480 |
return false; |
|
5481 |
} |
|
5482 |
return super.stopCellEditing(); |
|
5483 |
} |
|
5484 |
||
5485 |
public Component getTableCellEditorComponent(JTable table, Object value, |
|
5486 |
boolean isSelected, |
|
5487 |
int row, int column) { |
|
5488 |
this.value = null; |
|
5489 |
((JComponent)getComponent()).setBorder(new LineBorder(Color.black)); |
|
5490 |
try { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
5491 |
Class<?> type = table.getColumnClass(column); |
2 | 5492 |
// Since our obligation is to produce a value which is |
5493 |
// assignable for the required type it is OK to use the |
|
5494 |
// String constructor for columns which are declared |
|
5495 |
// to contain Objects. A String is an Object. |
|
5496 |
if (type == Object.class) { |
|
5497 |
type = String.class; |
|
5498 |
} |
|
20800 | 5499 |
ReflectUtil.checkPackageAccess(type); |
5500 |
SwingUtilities2.checkAccess(type.getModifiers()); |
|
2 | 5501 |
constructor = type.getConstructor(argTypes); |
5502 |
} |
|
5503 |
catch (Exception e) { |
|
5504 |
return null; |
|
5505 |
} |
|
5506 |
return super.getTableCellEditorComponent(table, value, isSelected, row, column); |
|
5507 |
} |
|
5508 |
||
5509 |
public Object getCellEditorValue() { |
|
5510 |
return value; |
|
5511 |
} |
|
5512 |
} |
|
5513 |
||
5514 |
static class NumberEditor extends GenericEditor { |
|
5515 |
||
5516 |
public NumberEditor() { |
|
5517 |
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT); |
|
5518 |
} |
|
5519 |
} |
|
5520 |
||
5521 |
static class BooleanEditor extends DefaultCellEditor { |
|
5522 |
public BooleanEditor() { |
|
5523 |
super(new JCheckBox()); |
|
5524 |
JCheckBox checkBox = (JCheckBox)getComponent(); |
|
5525 |
checkBox.setHorizontalAlignment(JCheckBox.CENTER); |
|
5526 |
} |
|
5527 |
} |
|
5528 |
||
5529 |
/** |
|
5530 |
* Initializes table properties to their default values. |
|
5531 |
*/ |
|
5532 |
protected void initializeLocalVars() { |
|
5533 |
updateSelectionOnSort = true; |
|
5534 |
setOpaque(true); |
|
5535 |
createDefaultRenderers(); |
|
5536 |
createDefaultEditors(); |
|
5537 |
||
5538 |
setTableHeader(createDefaultTableHeader()); |
|
5539 |
||
5540 |
setShowGrid(true); |
|
5541 |
setAutoResizeMode(AUTO_RESIZE_SUBSEQUENT_COLUMNS); |
|
5542 |
setRowHeight(16); |
|
5543 |
isRowHeightSet = false; |
|
5544 |
setRowMargin(1); |
|
5545 |
setRowSelectionAllowed(true); |
|
5546 |
setCellEditor(null); |
|
5547 |
setEditingColumn(-1); |
|
5548 |
setEditingRow(-1); |
|
5549 |
setSurrendersFocusOnKeystroke(false); |
|
5550 |
setPreferredScrollableViewportSize(new Dimension(450, 400)); |
|
5551 |
||
5552 |
// I'm registered to do tool tips so we can draw tips for the renderers |
|
5553 |
ToolTipManager toolTipManager = ToolTipManager.sharedInstance(); |
|
5554 |
toolTipManager.registerComponent(this); |
|
5555 |
||
5556 |
setAutoscrolls(true); |
|
5557 |
} |
|
5558 |
||
5559 |
/** |
|
5560 |
* Returns the default table model object, which is |
|
5561 |
* a <code>DefaultTableModel</code>. A subclass can override this |
|
5562 |
* method to return a different table model object. |
|
5563 |
* |
|
5564 |
* @return the default table model object |
|
5565 |
* @see javax.swing.table.DefaultTableModel |
|
5566 |
*/ |
|
5567 |
protected TableModel createDefaultDataModel() { |
|
5568 |
return new DefaultTableModel(); |
|
5569 |
} |
|
5570 |
||
5571 |
/** |
|
5572 |
* Returns the default column model object, which is |
|
5573 |
* a <code>DefaultTableColumnModel</code>. A subclass can override this |
|
5574 |
* method to return a different column model object. |
|
5575 |
* |
|
5576 |
* @return the default column model object |
|
5577 |
* @see javax.swing.table.DefaultTableColumnModel |
|
5578 |
*/ |
|
5579 |
protected TableColumnModel createDefaultColumnModel() { |
|
5580 |
return new DefaultTableColumnModel(); |
|
5581 |
} |
|
5582 |
||
5583 |
/** |
|
5584 |
* Returns the default selection model object, which is |
|
5585 |
* a <code>DefaultListSelectionModel</code>. A subclass can override this |
|
5586 |
* method to return a different selection model object. |
|
5587 |
* |
|
5588 |
* @return the default selection model object |
|
5589 |
* @see javax.swing.DefaultListSelectionModel |
|
5590 |
*/ |
|
5591 |
protected ListSelectionModel createDefaultSelectionModel() { |
|
5592 |
return new DefaultListSelectionModel(); |
|
5593 |
} |
|
5594 |
||
5595 |
/** |
|
5596 |
* Returns the default table header object, which is |
|
5597 |
* a <code>JTableHeader</code>. A subclass can override this |
|
5598 |
* method to return a different table header object. |
|
5599 |
* |
|
5600 |
* @return the default table header object |
|
5601 |
* @see javax.swing.table.JTableHeader |
|
5602 |
*/ |
|
5603 |
protected JTableHeader createDefaultTableHeader() { |
|
5604 |
return new JTableHeader(columnModel); |
|
5605 |
} |
|
5606 |
||
5607 |
/** |
|
5608 |
* Equivalent to <code>revalidate</code> followed by <code>repaint</code>. |
|
5609 |
*/ |
|
5610 |
protected void resizeAndRepaint() { |
|
5611 |
revalidate(); |
|
5612 |
repaint(); |
|
5613 |
} |
|
5614 |
||
5615 |
/** |
|
5616 |
* Returns the active cell editor, which is {@code null} if the table |
|
5617 |
* is not currently editing. |
|
5618 |
* |
|
5619 |
* @return the {@code TableCellEditor} that does the editing, |
|
5620 |
* or {@code null} if the table is not currently editing. |
|
5621 |
* @see #cellEditor |
|
5622 |
* @see #getCellEditor(int, int) |
|
5623 |
*/ |
|
5624 |
public TableCellEditor getCellEditor() { |
|
5625 |
return cellEditor; |
|
5626 |
} |
|
5627 |
||
5628 |
/** |
|
5629 |
* Sets the active cell editor. |
|
5630 |
* |
|
5631 |
* @param anEditor the active cell editor |
|
5632 |
* @see #cellEditor |
|
5633 |
* @beaninfo |
|
5634 |
* bound: true |
|
5635 |
* description: The table's active cell editor. |
|
5636 |
*/ |
|
5637 |
public void setCellEditor(TableCellEditor anEditor) { |
|
5638 |
TableCellEditor oldEditor = cellEditor; |
|
5639 |
cellEditor = anEditor; |
|
5640 |
firePropertyChange("tableCellEditor", oldEditor, anEditor); |
|
5641 |
} |
|
5642 |
||
5643 |
/** |
|
5644 |
* Sets the <code>editingColumn</code> variable. |
|
5645 |
* @param aColumn the column of the cell to be edited |
|
5646 |
* |
|
5647 |
* @see #editingColumn |
|
5648 |
*/ |
|
5649 |
public void setEditingColumn(int aColumn) { |
|
5650 |
editingColumn = aColumn; |
|
5651 |
} |
|
5652 |
||
5653 |
/** |
|
5654 |
* Sets the <code>editingRow</code> variable. |
|
5655 |
* @param aRow the row of the cell to be edited |
|
5656 |
* |
|
5657 |
* @see #editingRow |
|
5658 |
*/ |
|
5659 |
public void setEditingRow(int aRow) { |
|
5660 |
editingRow = aRow; |
|
5661 |
} |
|
5662 |
||
5663 |
/** |
|
5664 |
* Returns an appropriate renderer for the cell specified by this row and |
|
5665 |
* column. If the <code>TableColumn</code> for this column has a non-null |
|
5666 |
* renderer, returns that. If not, finds the class of the data in |
|
5667 |
* this column (using <code>getColumnClass</code>) |
|
5668 |
* and returns the default renderer for this type of data. |
|
5669 |
* <p> |
|
5670 |
* <b>Note:</b> |
|
5671 |
* Throughout the table package, the internal implementations always |
|
5672 |
* use this method to provide renderers so that this default behavior |
|
5673 |
* can be safely overridden by a subclass. |
|
5674 |
* |
|
5675 |
* @param row the row of the cell to render, where 0 is the first row |
|
5676 |
* @param column the column of the cell to render, |
|
5677 |
* where 0 is the first column |
|
5678 |
* @return the assigned renderer; if <code>null</code> |
|
5679 |
* returns the default renderer |
|
5680 |
* for this type of object |
|
5681 |
* @see javax.swing.table.DefaultTableCellRenderer |
|
5682 |
* @see javax.swing.table.TableColumn#setCellRenderer |
|
5683 |
* @see #setDefaultRenderer |
|
5684 |
*/ |
|
5685 |
public TableCellRenderer getCellRenderer(int row, int column) { |
|
5686 |
TableColumn tableColumn = getColumnModel().getColumn(column); |
|
5687 |
TableCellRenderer renderer = tableColumn.getCellRenderer(); |
|
5688 |
if (renderer == null) { |
|
5689 |
renderer = getDefaultRenderer(getColumnClass(column)); |
|
5690 |
} |
|
5691 |
return renderer; |
|
5692 |
} |
|
5693 |
||
5694 |
/** |
|
5695 |
* Prepares the renderer by querying the data model for the |
|
5696 |
* value and selection state |
|
5697 |
* of the cell at <code>row</code>, <code>column</code>. |
|
5698 |
* Returns the component (may be a <code>Component</code> |
|
5699 |
* or a <code>JComponent</code>) under the event location. |
|
5700 |
* <p> |
|
5701 |
* During a printing operation, this method will configure the |
|
5702 |
* renderer without indicating selection or focus, to prevent |
|
5703 |
* them from appearing in the printed output. To do other |
|
5704 |
* customizations based on whether or not the table is being |
|
5705 |
* printed, you can check the value of |
|
5706 |
* {@link javax.swing.JComponent#isPaintingForPrint()}, either here |
|
5707 |
* or within custom renderers. |
|
5708 |
* <p> |
|
5709 |
* <b>Note:</b> |
|
5710 |
* Throughout the table package, the internal implementations always |
|
5711 |
* use this method to prepare renderers so that this default behavior |
|
5712 |
* can be safely overridden by a subclass. |
|
5713 |
* |
|
5714 |
* @param renderer the <code>TableCellRenderer</code> to prepare |
|
5715 |
* @param row the row of the cell to render, where 0 is the first row |
|
5716 |
* @param column the column of the cell to render, |
|
5717 |
* where 0 is the first column |
|
5718 |
* @return the <code>Component</code> under the event location |
|
5719 |
*/ |
|
5720 |
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { |
|
5721 |
Object value = getValueAt(row, column); |
|
5722 |
||
5723 |
boolean isSelected = false; |
|
5724 |
boolean hasFocus = false; |
|
5725 |
||
5726 |
// Only indicate the selection and focused cell if not printing |
|
5727 |
if (!isPaintingForPrint()) { |
|
5728 |
isSelected = isCellSelected(row, column); |
|
5729 |
||
5730 |
boolean rowIsLead = |
|
5731 |
(selectionModel.getLeadSelectionIndex() == row); |
|
5732 |
boolean colIsLead = |
|
5733 |
(columnModel.getSelectionModel().getLeadSelectionIndex() == column); |
|
5734 |
||
5735 |
hasFocus = (rowIsLead && colIsLead) && isFocusOwner(); |
|
5736 |
} |
|
5737 |
||
5738 |
return renderer.getTableCellRendererComponent(this, value, |
|
5739 |
isSelected, hasFocus, |
|
5740 |
row, column); |
|
5741 |
} |
|
5742 |
||
5743 |
/** |
|
5744 |
* Returns an appropriate editor for the cell specified by |
|
5745 |
* <code>row</code> and <code>column</code>. If the |
|
5746 |
* <code>TableColumn</code> for this column has a non-null editor, |
|
5747 |
* returns that. If not, finds the class of the data in this |
|
5748 |
* column (using <code>getColumnClass</code>) |
|
5749 |
* and returns the default editor for this type of data. |
|
5750 |
* <p> |
|
5751 |
* <b>Note:</b> |
|
5752 |
* Throughout the table package, the internal implementations always |
|
5753 |
* use this method to provide editors so that this default behavior |
|
5754 |
* can be safely overridden by a subclass. |
|
5755 |
* |
|
5756 |
* @param row the row of the cell to edit, where 0 is the first row |
|
5757 |
* @param column the column of the cell to edit, |
|
5758 |
* where 0 is the first column |
|
5759 |
* @return the editor for this cell; |
|
5760 |
* if <code>null</code> return the default editor for |
|
5761 |
* this type of cell |
|
5762 |
* @see DefaultCellEditor |
|
5763 |
*/ |
|
5764 |
public TableCellEditor getCellEditor(int row, int column) { |
|
5765 |
TableColumn tableColumn = getColumnModel().getColumn(column); |
|
5766 |
TableCellEditor editor = tableColumn.getCellEditor(); |
|
5767 |
if (editor == null) { |
|
5768 |
editor = getDefaultEditor(getColumnClass(column)); |
|
5769 |
} |
|
5770 |
return editor; |
|
5771 |
} |
|
5772 |
||
5773 |
||
5774 |
/** |
|
5775 |
* Prepares the editor by querying the data model for the value and |
|
5776 |
* selection state of the cell at <code>row</code>, <code>column</code>. |
|
5777 |
* <p> |
|
5778 |
* <b>Note:</b> |
|
5779 |
* Throughout the table package, the internal implementations always |
|
5780 |
* use this method to prepare editors so that this default behavior |
|
5781 |
* can be safely overridden by a subclass. |
|
5782 |
* |
|
5783 |
* @param editor the <code>TableCellEditor</code> to set up |
|
5784 |
* @param row the row of the cell to edit, |
|
5785 |
* where 0 is the first row |
|
5786 |
* @param column the column of the cell to edit, |
|
5787 |
* where 0 is the first column |
|
5788 |
* @return the <code>Component</code> being edited |
|
5789 |
*/ |
|
5790 |
public Component prepareEditor(TableCellEditor editor, int row, int column) { |
|
5791 |
Object value = getValueAt(row, column); |
|
5792 |
boolean isSelected = isCellSelected(row, column); |
|
5793 |
Component comp = editor.getTableCellEditorComponent(this, value, isSelected, |
|
5794 |
row, column); |
|
5795 |
if (comp instanceof JComponent) { |
|
5796 |
JComponent jComp = (JComponent)comp; |
|
5797 |
if (jComp.getNextFocusableComponent() == null) { |
|
5798 |
jComp.setNextFocusableComponent(this); |
|
5799 |
} |
|
5800 |
} |
|
5801 |
return comp; |
|
5802 |
} |
|
5803 |
||
5804 |
/** |
|
5805 |
* Discards the editor object and frees the real estate it used for |
|
5806 |
* cell rendering. |
|
5807 |
*/ |
|
5808 |
public void removeEditor() { |
|
5809 |
KeyboardFocusManager.getCurrentKeyboardFocusManager(). |
|
5810 |
removePropertyChangeListener("permanentFocusOwner", editorRemover); |
|
5811 |
editorRemover = null; |
|
5812 |
||
5813 |
TableCellEditor editor = getCellEditor(); |
|
5814 |
if(editor != null) { |
|
5815 |
editor.removeCellEditorListener(this); |
|
5816 |
if (editorComp != null) { |
|
5817 |
Component focusOwner = |
|
5818 |
KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); |
|
5819 |
boolean isFocusOwnerInTheTable = focusOwner != null? |
|
5820 |
SwingUtilities.isDescendingFrom(focusOwner, this):false; |
|
5821 |
remove(editorComp); |
|
5822 |
if(isFocusOwnerInTheTable) { |
|
5823 |
requestFocusInWindow(); |
|
5824 |
} |
|
5825 |
} |
|
5826 |
||
5827 |
Rectangle cellRect = getCellRect(editingRow, editingColumn, false); |
|
5828 |
||
5829 |
setCellEditor(null); |
|
5830 |
setEditingColumn(-1); |
|
5831 |
setEditingRow(-1); |
|
5832 |
editorComp = null; |
|
5833 |
||
5834 |
repaint(cellRect); |
|
5835 |
} |
|
5836 |
} |
|
5837 |
||
5838 |
// |
|
5839 |
// Serialization |
|
5840 |
// |
|
5841 |
||
5842 |
/** |
|
5843 |
* See readObject() and writeObject() in JComponent for more |
|
5844 |
* information about serialization in Swing. |
|
5845 |
*/ |
|
5846 |
private void writeObject(ObjectOutputStream s) throws IOException { |
|
5847 |
s.defaultWriteObject(); |
|
5848 |
if (getUIClassID().equals(uiClassID)) { |
|
5849 |
byte count = JComponent.getWriteObjCounter(this); |
|
5850 |
JComponent.setWriteObjCounter(this, --count); |
|
5851 |
if (count == 0 && ui != null) { |
|
5852 |
ui.installUI(this); |
|
5853 |
} |
|
5854 |
} |
|
5855 |
} |
|
5856 |
||
5857 |
private void readObject(ObjectInputStream s) |
|
5858 |
throws IOException, ClassNotFoundException |
|
5859 |
{ |
|
5860 |
s.defaultReadObject(); |
|
5861 |
if ((ui != null) && (getUIClassID().equals(uiClassID))) { |
|
5862 |
ui.installUI(this); |
|
5863 |
} |
|
5864 |
createDefaultRenderers(); |
|
5865 |
createDefaultEditors(); |
|
5866 |
||
5867 |
// If ToolTipText != null, then the tooltip has already been |
|
5868 |
// registered by JComponent.readObject() and we don't want |
|
5869 |
// to re-register here |
|
5870 |
if (getToolTipText() == null) { |
|
5871 |
ToolTipManager.sharedInstance().registerComponent(this); |
|
5872 |
} |
|
5873 |
} |
|
5874 |
||
5875 |
/* Called from the JComponent's EnableSerializationFocusListener to |
|
5876 |
* do any Swing-specific pre-serialization configuration. |
|
5877 |
*/ |
|
5878 |
void compWriteObjectNotify() { |
|
5879 |
super.compWriteObjectNotify(); |
|
5880 |
// If ToolTipText != null, then the tooltip has already been |
|
5881 |
// unregistered by JComponent.compWriteObjectNotify() |
|
5882 |
if (getToolTipText() == null) { |
|
5883 |
ToolTipManager.sharedInstance().unregisterComponent(this); |
|
5884 |
} |
|
5885 |
} |
|
5886 |
||
5887 |
/** |
|
5888 |
* Returns a string representation of this table. This method |
|
5889 |
* is intended to be used only for debugging purposes, and the |
|
5890 |
* content and format of the returned string may vary between |
|
5891 |
* implementations. The returned string may be empty but may not |
|
5892 |
* be <code>null</code>. |
|
5893 |
* |
|
5894 |
* @return a string representation of this table |
|
5895 |
*/ |
|
5896 |
protected String paramString() { |
|
5897 |
String gridColorString = (gridColor != null ? |
|
5898 |
gridColor.toString() : ""); |
|
5899 |
String showHorizontalLinesString = (showHorizontalLines ? |
|
5900 |
"true" : "false"); |
|
5901 |
String showVerticalLinesString = (showVerticalLines ? |
|
5902 |
"true" : "false"); |
|
5903 |
String autoResizeModeString; |
|
5904 |
if (autoResizeMode == AUTO_RESIZE_OFF) { |
|
5905 |
autoResizeModeString = "AUTO_RESIZE_OFF"; |
|
5906 |
} else if (autoResizeMode == AUTO_RESIZE_NEXT_COLUMN) { |
|
5907 |
autoResizeModeString = "AUTO_RESIZE_NEXT_COLUMN"; |
|
5908 |
} else if (autoResizeMode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) { |
|
5909 |
autoResizeModeString = "AUTO_RESIZE_SUBSEQUENT_COLUMNS"; |
|
5910 |
} else if (autoResizeMode == AUTO_RESIZE_LAST_COLUMN) { |
|
5911 |
autoResizeModeString = "AUTO_RESIZE_LAST_COLUMN"; |
|
5912 |
} else if (autoResizeMode == AUTO_RESIZE_ALL_COLUMNS) { |
|
5913 |
autoResizeModeString = "AUTO_RESIZE_ALL_COLUMNS"; |
|
5914 |
} else autoResizeModeString = ""; |
|
5915 |
String autoCreateColumnsFromModelString = (autoCreateColumnsFromModel ? |
|
5916 |
"true" : "false"); |
|
5917 |
String preferredViewportSizeString = (preferredViewportSize != null ? |
|
5918 |
preferredViewportSize.toString() |
|
5919 |
: ""); |
|
5920 |
String rowSelectionAllowedString = (rowSelectionAllowed ? |
|
5921 |
"true" : "false"); |
|
5922 |
String cellSelectionEnabledString = (cellSelectionEnabled ? |
|
5923 |
"true" : "false"); |
|
5924 |
String selectionForegroundString = (selectionForeground != null ? |
|
5925 |
selectionForeground.toString() : |
|
5926 |
""); |
|
5927 |
String selectionBackgroundString = (selectionBackground != null ? |
|
5928 |
selectionBackground.toString() : |
|
5929 |
""); |
|
5930 |
||
5931 |
return super.paramString() + |
|
5932 |
",autoCreateColumnsFromModel=" + autoCreateColumnsFromModelString + |
|
5933 |
",autoResizeMode=" + autoResizeModeString + |
|
5934 |
",cellSelectionEnabled=" + cellSelectionEnabledString + |
|
5935 |
",editingColumn=" + editingColumn + |
|
5936 |
",editingRow=" + editingRow + |
|
5937 |
",gridColor=" + gridColorString + |
|
5938 |
",preferredViewportSize=" + preferredViewportSizeString + |
|
5939 |
",rowHeight=" + rowHeight + |
|
5940 |
",rowMargin=" + rowMargin + |
|
5941 |
",rowSelectionAllowed=" + rowSelectionAllowedString + |
|
5942 |
",selectionBackground=" + selectionBackgroundString + |
|
5943 |
",selectionForeground=" + selectionForegroundString + |
|
5944 |
",showHorizontalLines=" + showHorizontalLinesString + |
|
5945 |
",showVerticalLines=" + showVerticalLinesString; |
|
5946 |
} |
|
5947 |
||
5948 |
// This class tracks changes in the keyboard focus state. It is used |
|
5949 |
// when the JTable is editing to determine when to cancel the edit. |
|
5950 |
// If focus switches to a component outside of the jtable, but in the |
|
5951 |
// same window, this will cancel editing. |
|
5952 |
class CellEditorRemover implements PropertyChangeListener { |
|
5953 |
KeyboardFocusManager focusManager; |
|
5954 |
||
5955 |
public CellEditorRemover(KeyboardFocusManager fm) { |
|
5956 |
this.focusManager = fm; |
|
5957 |
} |
|
5958 |
||
5959 |
public void propertyChange(PropertyChangeEvent ev) { |
|
5960 |
if (!isEditing() || getClientProperty("terminateEditOnFocusLost") != Boolean.TRUE) { |
|
5961 |
return; |
|
5962 |
} |
|
5963 |
||
5964 |
Component c = focusManager.getPermanentFocusOwner(); |
|
5965 |
while (c != null) { |
|
5966 |
if (c == JTable.this) { |
|
5967 |
// focus remains inside the table |
|
5968 |
return; |
|
5969 |
} else if ((c instanceof Window) || |
|
5970 |
(c instanceof Applet && c.getParent() == null)) { |
|
5971 |
if (c == SwingUtilities.getRoot(JTable.this)) { |
|
5972 |
if (!getCellEditor().stopCellEditing()) { |
|
5973 |
getCellEditor().cancelCellEditing(); |
|
5974 |
} |
|
5975 |
} |
|
5976 |
break; |
|
5977 |
} |
|
5978 |
c = c.getParent(); |
|
5979 |
} |
|
5980 |
} |
|
5981 |
} |
|
5982 |
||
5983 |
///////////////// |
|
5984 |
// Printing Support |
|
5985 |
///////////////// |
|
5986 |
||
5987 |
/** |
|
5988 |
* A convenience method that displays a printing dialog, and then prints |
|
5989 |
* this <code>JTable</code> in mode <code>PrintMode.FIT_WIDTH</code>, |
|
5990 |
* with no header or footer text. A modal progress dialog, with an abort |
|
5991 |
* option, will be shown for the duration of printing. |
|
5992 |
* <p> |
|
5993 |
* Note: In headless mode, no dialogs are shown and printing |
|
5994 |
* occurs on the default printer. |
|
5995 |
* |
|
5996 |
* @return true, unless printing is cancelled by the user |
|
5997 |
* @throws SecurityException if this thread is not allowed to |
|
5998 |
* initiate a print job request |
|
5999 |
* @throws PrinterException if an error in the print system causes the job |
|
6000 |
* to be aborted |
|
6001 |
* @see #print(JTable.PrintMode, MessageFormat, MessageFormat, |
|
6002 |
* boolean, PrintRequestAttributeSet, boolean, PrintService) |
|
6003 |
* @see #getPrintable |
|
6004 |
* |
|
6005 |
* @since 1.5 |
|
6006 |
*/ |
|
6007 |
public boolean print() throws PrinterException { |
|
6008 |
||
6009 |
return print(PrintMode.FIT_WIDTH); |
|
6010 |
} |
|
6011 |
||
6012 |
/** |
|
6013 |
* A convenience method that displays a printing dialog, and then prints |
|
6014 |
* this <code>JTable</code> in the given printing mode, |
|
6015 |
* with no header or footer text. A modal progress dialog, with an abort |
|
6016 |
* option, will be shown for the duration of printing. |
|
6017 |
* <p> |
|
6018 |
* Note: In headless mode, no dialogs are shown and printing |
|
6019 |
* occurs on the default printer. |
|
6020 |
* |
|
6021 |
* @param printMode the printing mode that the printable should use |
|
6022 |
* @return true, unless printing is cancelled by the user |
|
6023 |
* @throws SecurityException if this thread is not allowed to |
|
6024 |
* initiate a print job request |
|
6025 |
* @throws PrinterException if an error in the print system causes the job |
|
6026 |
* to be aborted |
|
6027 |
* @see #print(JTable.PrintMode, MessageFormat, MessageFormat, |
|
6028 |
* boolean, PrintRequestAttributeSet, boolean, PrintService) |
|
6029 |
* @see #getPrintable |
|
6030 |
* |
|
6031 |
* @since 1.5 |
|
6032 |
*/ |
|
6033 |
public boolean print(PrintMode printMode) throws PrinterException { |
|
6034 |
||
6035 |
return print(printMode, null, null); |
|
6036 |
} |
|
6037 |
||
6038 |
/** |
|
6039 |
* A convenience method that displays a printing dialog, and then prints |
|
6040 |
* this <code>JTable</code> in the given printing mode, |
|
6041 |
* with the specified header and footer text. A modal progress dialog, |
|
6042 |
* with an abort option, will be shown for the duration of printing. |
|
6043 |
* <p> |
|
6044 |
* Note: In headless mode, no dialogs are shown and printing |
|
6045 |
* occurs on the default printer. |
|
6046 |
* |
|
6047 |
* @param printMode the printing mode that the printable should use |
|
6048 |
* @param headerFormat a <code>MessageFormat</code> specifying the text |
|
6049 |
* to be used in printing a header, |
|
6050 |
* or null for none |
|
6051 |
* @param footerFormat a <code>MessageFormat</code> specifying the text |
|
6052 |
* to be used in printing a footer, |
|
6053 |
* or null for none |
|
6054 |
* @return true, unless printing is cancelled by the user |
|
6055 |
* @throws SecurityException if this thread is not allowed to |
|
6056 |
* initiate a print job request |
|
6057 |
* @throws PrinterException if an error in the print system causes the job |
|
6058 |
* to be aborted |
|
6059 |
* @see #print(JTable.PrintMode, MessageFormat, MessageFormat, |
|
6060 |
* boolean, PrintRequestAttributeSet, boolean, PrintService) |
|
6061 |
* @see #getPrintable |
|
6062 |
* |
|
6063 |
* @since 1.5 |
|
6064 |
*/ |
|
6065 |
public boolean print(PrintMode printMode, |
|
6066 |
MessageFormat headerFormat, |
|
6067 |
MessageFormat footerFormat) throws PrinterException { |
|
6068 |
||
6069 |
boolean showDialogs = !GraphicsEnvironment.isHeadless(); |
|
6070 |
return print(printMode, headerFormat, footerFormat, |
|
6071 |
showDialogs, null, showDialogs); |
|
6072 |
} |
|
6073 |
||
6074 |
/** |
|
6075 |
* Prints this table, as specified by the fully featured |
|
6076 |
* {@link #print(JTable.PrintMode, MessageFormat, MessageFormat, |
|
6077 |
* boolean, PrintRequestAttributeSet, boolean, PrintService) print} |
|
6078 |
* method, with the default printer specified as the print service. |
|
6079 |
* |
|
6080 |
* @param printMode the printing mode that the printable should use |
|
6081 |
* @param headerFormat a <code>MessageFormat</code> specifying the text |
|
6082 |
* to be used in printing a header, |
|
6083 |
* or <code>null</code> for none |
|
6084 |
* @param footerFormat a <code>MessageFormat</code> specifying the text |
|
6085 |
* to be used in printing a footer, |
|
6086 |
* or <code>null</code> for none |
|
6087 |
* @param showPrintDialog whether or not to display a print dialog |
|
6088 |
* @param attr a <code>PrintRequestAttributeSet</code> |
|
6089 |
* specifying any printing attributes, |
|
6090 |
* or <code>null</code> for none |
|
6091 |
* @param interactive whether or not to print in an interactive mode |
|
6092 |
* @return true, unless printing is cancelled by the user |
|
6093 |
* @throws HeadlessException if the method is asked to show a printing |
|
6094 |
* dialog or run interactively, and |
|
6095 |
* <code>GraphicsEnvironment.isHeadless</code> |
|
6096 |
* returns <code>true</code> |
|
6097 |
* @throws SecurityException if this thread is not allowed to |
|
6098 |
* initiate a print job request |
|
6099 |
* @throws PrinterException if an error in the print system causes the job |
|
6100 |
* to be aborted |
|
6101 |
* @see #print(JTable.PrintMode, MessageFormat, MessageFormat, |
|
6102 |
* boolean, PrintRequestAttributeSet, boolean, PrintService) |
|
6103 |
* @see #getPrintable |
|
6104 |
* |
|
6105 |
* @since 1.5 |
|
6106 |
*/ |
|
6107 |
public boolean print(PrintMode printMode, |
|
6108 |
MessageFormat headerFormat, |
|
6109 |
MessageFormat footerFormat, |
|
6110 |
boolean showPrintDialog, |
|
6111 |
PrintRequestAttributeSet attr, |
|
6112 |
boolean interactive) throws PrinterException, |
|
6113 |
HeadlessException { |
|
6114 |
||
6115 |
return print(printMode, |
|
6116 |
headerFormat, |
|
6117 |
footerFormat, |
|
6118 |
showPrintDialog, |
|
6119 |
attr, |
|
6120 |
interactive, |
|
6121 |
null); |
|
6122 |
} |
|
6123 |
||
6124 |
/** |
|
6125 |
* Prints this <code>JTable</code>. Takes steps that the majority of |
|
6126 |
* developers would take in order to print a <code>JTable</code>. |
|
6127 |
* In short, it prepares the table, calls <code>getPrintable</code> to |
|
6128 |
* fetch an appropriate <code>Printable</code>, and then sends it to the |
|
6129 |
* printer. |
|
6130 |
* <p> |
|
6131 |
* A <code>boolean</code> parameter allows you to specify whether or not |
|
6132 |
* a printing dialog is displayed to the user. When it is, the user may |
|
6133 |
* use the dialog to change the destination printer or printing attributes, |
|
6134 |
* or even to cancel the print. Another two parameters allow for a |
|
6135 |
* <code>PrintService</code> and printing attributes to be specified. |
|
6136 |
* These parameters can be used either to provide initial values for the |
|
6137 |
* print dialog, or to specify values when the dialog is not shown. |
|
6138 |
* <p> |
|
6139 |
* A second <code>boolean</code> parameter allows you to specify whether |
|
6140 |
* or not to perform printing in an interactive mode. If <code>true</code>, |
|
6141 |
* a modal progress dialog, with an abort option, is displayed for the |
|
6142 |
* duration of printing . This dialog also prevents any user action which |
|
6143 |
* may affect the table. However, it can not prevent the table from being |
|
6144 |
* modified by code (for example, another thread that posts updates using |
|
6145 |
* <code>SwingUtilities.invokeLater</code>). It is therefore the |
|
6146 |
* responsibility of the developer to ensure that no other code modifies |
|
6147 |
* the table in any way during printing (invalid modifications include |
|
6148 |
* changes in: size, renderers, or underlying data). Printing behavior is |
|
6149 |
* undefined when the table is changed during printing. |
|
6150 |
* <p> |
|
6151 |
* If <code>false</code> is specified for this parameter, no dialog will |
|
6152 |
* be displayed and printing will begin immediately on the event-dispatch |
|
6153 |
* thread. This blocks any other events, including repaints, from being |
|
6154 |
* processed until printing is complete. Although this effectively prevents |
|
6155 |
* the table from being changed, it doesn't provide a good user experience. |
|
6156 |
* For this reason, specifying <code>false</code> is only recommended when |
|
6157 |
* printing from an application with no visible GUI. |
|
6158 |
* <p> |
|
6159 |
* Note: Attempting to show the printing dialog or run interactively, while |
|
6160 |
* in headless mode, will result in a <code>HeadlessException</code>. |
|
6161 |
* <p> |
|
6162 |
* Before fetching the printable, this method will gracefully terminate |
|
6163 |
* editing, if necessary, to prevent an editor from showing in the printed |
|
6164 |
* result. Additionally, <code>JTable</code> will prepare its renderers |
|
6165 |
* during printing such that selection and focus are not indicated. |
|
6166 |
* As far as customizing further how the table looks in the printout, |
|
6167 |
* developers can provide custom renderers or paint code that conditionalize |
|
6168 |
* on the value of {@link javax.swing.JComponent#isPaintingForPrint()}. |
|
6169 |
* <p> |
|
6170 |
* See {@link #getPrintable} for more description on how the table is |
|
6171 |
* printed. |
|
6172 |
* |
|
6173 |
* @param printMode the printing mode that the printable should use |
|
6174 |
* @param headerFormat a <code>MessageFormat</code> specifying the text |
|
6175 |
* to be used in printing a header, |
|
6176 |
* or <code>null</code> for none |
|
6177 |
* @param footerFormat a <code>MessageFormat</code> specifying the text |
|
6178 |
* to be used in printing a footer, |
|
6179 |
* or <code>null</code> for none |
|
6180 |
* @param showPrintDialog whether or not to display a print dialog |
|
6181 |
* @param attr a <code>PrintRequestAttributeSet</code> |
|
6182 |
* specifying any printing attributes, |
|
6183 |
* or <code>null</code> for none |
|
6184 |
* @param interactive whether or not to print in an interactive mode |
|
6185 |
* @param service the destination <code>PrintService</code>, |
|
6186 |
* or <code>null</code> to use the default printer |
|
6187 |
* @return true, unless printing is cancelled by the user |
|
6188 |
* @throws HeadlessException if the method is asked to show a printing |
|
6189 |
* dialog or run interactively, and |
|
6190 |
* <code>GraphicsEnvironment.isHeadless</code> |
|
6191 |
* returns <code>true</code> |
|
6192 |
* @throws SecurityException if a security manager exists and its |
|
6193 |
* {@link java.lang.SecurityManager#checkPrintJobAccess} |
|
6194 |
* method disallows this thread from creating a print job request |
|
6195 |
* @throws PrinterException if an error in the print system causes the job |
|
6196 |
* to be aborted |
|
6197 |
* @see #getPrintable |
|
6198 |
* @see java.awt.GraphicsEnvironment#isHeadless |
|
6199 |
* |
|
6200 |
* @since 1.6 |
|
6201 |
*/ |
|
6202 |
public boolean print(PrintMode printMode, |
|
6203 |
MessageFormat headerFormat, |
|
6204 |
MessageFormat footerFormat, |
|
6205 |
boolean showPrintDialog, |
|
6206 |
PrintRequestAttributeSet attr, |
|
6207 |
boolean interactive, |
|
6208 |
PrintService service) throws PrinterException, |
|
6209 |
HeadlessException { |
|
6210 |
||
6211 |
// complain early if an invalid parameter is specified for headless mode |
|
6212 |
boolean isHeadless = GraphicsEnvironment.isHeadless(); |
|
6213 |
if (isHeadless) { |
|
6214 |
if (showPrintDialog) { |
|
6215 |
throw new HeadlessException("Can't show print dialog."); |
|
6216 |
} |
|
6217 |
||
6218 |
if (interactive) { |
|
6219 |
throw new HeadlessException("Can't run interactively."); |
|
6220 |
} |
|
6221 |
} |
|
6222 |
||
6223 |
// Get a PrinterJob. |
|
6224 |
// Do this before anything with side-effects since it may throw a |
|
6225 |
// security exception - in which case we don't want to do anything else. |
|
6226 |
final PrinterJob job = PrinterJob.getPrinterJob(); |
|
6227 |
||
6228 |
if (isEditing()) { |
|
6229 |
// try to stop cell editing, and failing that, cancel it |
|
6230 |
if (!getCellEditor().stopCellEditing()) { |
|
6231 |
getCellEditor().cancelCellEditing(); |
|
6232 |
} |
|
6233 |
} |
|
6234 |
||
6235 |
if (attr == null) { |
|
6236 |
attr = new HashPrintRequestAttributeSet(); |
|
6237 |
} |
|
6238 |
||
6239 |
final PrintingStatus printingStatus; |
|
6240 |
||
6241 |
// fetch the Printable |
|
6242 |
Printable printable = |
|
6243 |
getPrintable(printMode, headerFormat, footerFormat); |
|
6244 |
||
6245 |
if (interactive) { |
|
6246 |
// wrap the Printable so that we can print on another thread |
|
6247 |
printable = new ThreadSafePrintable(printable); |
|
6248 |
printingStatus = PrintingStatus.createPrintingStatus(this, job); |
|
6249 |
printable = printingStatus.createNotificationPrintable(printable); |
|
6250 |
} else { |
|
6251 |
// to please compiler |
|
6252 |
printingStatus = null; |
|
6253 |
} |
|
6254 |
||
6255 |
// set the printable on the PrinterJob |
|
6256 |
job.setPrintable(printable); |
|
6257 |
||
6258 |
// if specified, set the PrintService on the PrinterJob |
|
6259 |
if (service != null) { |
|
6260 |
job.setPrintService(service); |
|
6261 |
} |
|
6262 |
||
6263 |
// if requested, show the print dialog |
|
6264 |
if (showPrintDialog && !job.printDialog(attr)) { |
|
6265 |
// the user cancelled the print dialog |
|
6266 |
return false; |
|
6267 |
} |
|
6268 |
||
6269 |
// if not interactive, just print on this thread (no dialog) |
|
6270 |
if (!interactive) { |
|
6271 |
// do the printing |
|
6272 |
job.print(attr); |
|
6273 |
||
6274 |
// we're done |
|
6275 |
return true; |
|
6276 |
} |
|
6277 |
||
6278 |
// make sure this is clear since we'll check it after |
|
6279 |
printError = null; |
|
6280 |
||
6281 |
// to synchronize on |
|
6282 |
final Object lock = new Object(); |
|
6283 |
||
6284 |
// copied so we can access from the inner class |
|
6285 |
final PrintRequestAttributeSet copyAttr = attr; |
|
6286 |
||
6287 |
// this runnable will be used to do the printing |
|
6288 |
// (and save any throwables) on another thread |
|
6289 |
Runnable runnable = new Runnable() { |
|
6290 |
public void run() { |
|
6291 |
try { |
|
6292 |
// do the printing |
|
6293 |
job.print(copyAttr); |
|
6294 |
} catch (Throwable t) { |
|
6295 |
// save any Throwable to be rethrown |
|
6296 |
synchronized(lock) { |
|
6297 |
printError = t; |
|
6298 |
} |
|
6299 |
} finally { |
|
6300 |
// we're finished - hide the dialog |
|
6301 |
printingStatus.dispose(); |
|
6302 |
} |
|
6303 |
} |
|
6304 |
}; |
|
6305 |
||
6306 |
// start printing on another thread |
|
6307 |
Thread th = new Thread(runnable); |
|
6308 |
th.start(); |
|
6309 |
||
6310 |
printingStatus.showModal(true); |
|
6311 |
||
6312 |
// look for any error that the printing may have generated |
|
6313 |
Throwable pe; |
|
6314 |
synchronized(lock) { |
|
6315 |
pe = printError; |
|
6316 |
printError = null; |
|
6317 |
} |
|
6318 |
||
6319 |
// check the type of error and handle it |
|
6320 |
if (pe != null) { |
|
6321 |
// a subclass of PrinterException meaning the job was aborted, |
|
6322 |
// in this case, by the user |
|
6323 |
if (pe instanceof PrinterAbortException) { |
|
6324 |
return false; |
|
6325 |
} else if (pe instanceof PrinterException) { |
|
6326 |
throw (PrinterException)pe; |
|
6327 |
} else if (pe instanceof RuntimeException) { |
|
6328 |
throw (RuntimeException)pe; |
|
6329 |
} else if (pe instanceof Error) { |
|
6330 |
throw (Error)pe; |
|
6331 |
} |
|
6332 |
||
6333 |
// can not happen |
|
6334 |
throw new AssertionError(pe); |
|
6335 |
} |
|
6336 |
||
6337 |
return true; |
|
6338 |
} |
|
6339 |
||
6340 |
/** |
|
6341 |
* Return a <code>Printable</code> for use in printing this JTable. |
|
6342 |
* <p> |
|
6343 |
* This method is meant for those wishing to customize the default |
|
6344 |
* <code>Printable</code> implementation used by <code>JTable</code>'s |
|
6345 |
* <code>print</code> methods. Developers wanting simply to print the table |
|
6346 |
* should use one of those methods directly. |
|
6347 |
* <p> |
|
6348 |
* The <code>Printable</code> can be requested in one of two printing modes. |
|
6349 |
* In both modes, it spreads table rows naturally in sequence across |
|
6350 |
* multiple pages, fitting as many rows as possible per page. |
|
6351 |
* <code>PrintMode.NORMAL</code> specifies that the table be |
|
6352 |
* printed at its current size. In this mode, there may be a need to spread |
|
6353 |
* columns across pages in a similar manner to that of the rows. When the |
|
6354 |
* need arises, columns are distributed in an order consistent with the |
|
6355 |
* table's <code>ComponentOrientation</code>. |
|
6356 |
* <code>PrintMode.FIT_WIDTH</code> specifies that the output be |
|
6357 |
* scaled smaller, if necessary, to fit the table's entire width |
|
6358 |
* (and thereby all columns) on each page. Width and height are scaled |
|
6359 |
* equally, maintaining the aspect ratio of the output. |
|
6360 |
* <p> |
|
6361 |
* The <code>Printable</code> heads the portion of table on each page |
|
6362 |
* with the appropriate section from the table's <code>JTableHeader</code>, |
|
6363 |
* if it has one. |
|
6364 |
* <p> |
|
6365 |
* Header and footer text can be added to the output by providing |
|
6366 |
* <code>MessageFormat</code> arguments. The printing code requests |
|
6367 |
* Strings from the formats, providing a single item which may be included |
|
6368 |
* in the formatted string: an <code>Integer</code> representing the current |
|
6369 |
* page number. |
|
6370 |
* <p> |
|
6371 |
* You are encouraged to read the documentation for |
|
6372 |
* <code>MessageFormat</code> as some characters, such as single-quote, |
|
6373 |
* are special and need to be escaped. |
|
6374 |
* <p> |
|
6375 |
* Here's an example of creating a <code>MessageFormat</code> that can be |
|
6376 |
* used to print "Duke's Table: Page - " and the current page number: |
|
21982 | 6377 |
* |
2 | 6378 |
* <pre> |
6379 |
* // notice the escaping of the single quote |
|
6380 |
* // notice how the page number is included with "{0}" |
|
6381 |
* MessageFormat format = new MessageFormat("Duke''s Table: Page - {0}"); |
|
6382 |
* </pre> |
|
6383 |
* <p> |
|
6384 |
* The <code>Printable</code> constrains what it draws to the printable |
|
6385 |
* area of each page that it prints. Under certain circumstances, it may |
|
6386 |
* find it impossible to fit all of a page's content into that area. In |
|
6387 |
* these cases the output may be clipped, but the implementation |
|
6388 |
* makes an effort to do something reasonable. Here are a few situations |
|
6389 |
* where this is known to occur, and how they may be handled by this |
|
6390 |
* particular implementation: |
|
6391 |
* <ul> |
|
6392 |
* <li>In any mode, when the header or footer text is too wide to fit |
|
6393 |
* completely in the printable area -- print as much of the text as |
|
6394 |
* possible starting from the beginning, as determined by the table's |
|
6395 |
* <code>ComponentOrientation</code>. |
|
6396 |
* <li>In any mode, when a row is too tall to fit in the |
|
6397 |
* printable area -- print the upper-most portion of the row |
|
6398 |
* and paint no lower border on the table. |
|
6399 |
* <li>In <code>PrintMode.NORMAL</code> when a column |
|
6400 |
* is too wide to fit in the printable area -- print the center |
|
6401 |
* portion of the column and leave the left and right borders |
|
6402 |
* off the table. |
|
6403 |
* </ul> |
|
6404 |
* <p> |
|
6405 |
* It is entirely valid for this <code>Printable</code> to be wrapped |
|
6406 |
* inside another in order to create complex reports and documents. You may |
|
6407 |
* even request that different pages be rendered into different sized |
|
6408 |
* printable areas. The implementation must be prepared to handle this |
|
6409 |
* (possibly by doing its layout calculations on the fly). However, |
|
6410 |
* providing different heights to each page will likely not work well |
|
6411 |
* with <code>PrintMode.NORMAL</code> when it has to spread columns |
|
6412 |
* across pages. |
|
6413 |
* <p> |
|
6414 |
* As far as customizing how the table looks in the printed result, |
|
6415 |
* <code>JTable</code> itself will take care of hiding the selection |
|
6416 |
* and focus during printing. For additional customizations, your |
|
6417 |
* renderers or painting code can customize the look based on the value |
|
6418 |
* of {@link javax.swing.JComponent#isPaintingForPrint()} |
|
6419 |
* <p> |
|
6420 |
* Also, <i>before</i> calling this method you may wish to <i>first</i> |
|
6421 |
* modify the state of the table, such as to cancel cell editing or |
|
6422 |
* have the user size the table appropriately. However, you must not |
|
6423 |
* modify the state of the table <i>after</i> this <code>Printable</code> |
|
6424 |
* has been fetched (invalid modifications include changes in size or |
|
6425 |
* underlying data). The behavior of the returned <code>Printable</code> |
|
6426 |
* is undefined once the table has been changed. |
|
6427 |
* |
|
6428 |
* @param printMode the printing mode that the printable should use |
|
6429 |
* @param headerFormat a <code>MessageFormat</code> specifying the text to |
|
6430 |
* be used in printing a header, or null for none |
|
6431 |
* @param footerFormat a <code>MessageFormat</code> specifying the text to |
|
6432 |
* be used in printing a footer, or null for none |
|
6433 |
* @return a <code>Printable</code> for printing this JTable |
|
6434 |
* @see #print(JTable.PrintMode, MessageFormat, MessageFormat, |
|
6435 |
* boolean, PrintRequestAttributeSet, boolean) |
|
6436 |
* @see Printable |
|
6437 |
* @see PrinterJob |
|
6438 |
* |
|
6439 |
* @since 1.5 |
|
6440 |
*/ |
|
6441 |
public Printable getPrintable(PrintMode printMode, |
|
6442 |
MessageFormat headerFormat, |
|
6443 |
MessageFormat footerFormat) { |
|
6444 |
||
6445 |
return new TablePrintable(this, printMode, headerFormat, footerFormat); |
|
6446 |
} |
|
6447 |
||
6448 |
||
6449 |
/** |
|
6450 |
* A <code>Printable</code> implementation that wraps another |
|
6451 |
* <code>Printable</code>, making it safe for printing on another thread. |
|
6452 |
*/ |
|
6453 |
private class ThreadSafePrintable implements Printable { |
|
6454 |
||
6455 |
/** The delegate <code>Printable</code>. */ |
|
6456 |
private Printable printDelegate; |
|
6457 |
||
6458 |
/** |
|
6459 |
* To communicate any return value when delegating. |
|
6460 |
*/ |
|
6461 |
private int retVal; |
|
6462 |
||
6463 |
/** |
|
6464 |
* To communicate any <code>Throwable</code> when delegating. |
|
6465 |
*/ |
|
6466 |
private Throwable retThrowable; |
|
6467 |
||
6468 |
/** |
|
6469 |
* Construct a <code>ThreadSafePrintable</code> around the given |
|
6470 |
* delegate. |
|
6471 |
* |
|
6472 |
* @param printDelegate the <code>Printable</code> to delegate to |
|
6473 |
*/ |
|
6474 |
public ThreadSafePrintable(Printable printDelegate) { |
|
6475 |
this.printDelegate = printDelegate; |
|
6476 |
} |
|
6477 |
||
6478 |
/** |
|
6479 |
* Prints the specified page into the given {@link Graphics} |
|
6480 |
* context, in the specified format. |
|
6481 |
* <p> |
|
6482 |
* Regardless of what thread this method is called on, all calls into |
|
6483 |
* the delegate will be done on the event-dispatch thread. |
|
6484 |
* |
|
6485 |
* @param graphics the context into which the page is drawn |
|
6486 |
* @param pageFormat the size and orientation of the page being drawn |
|
6487 |
* @param pageIndex the zero based index of the page to be drawn |
|
6488 |
* @return PAGE_EXISTS if the page is rendered successfully, or |
|
6489 |
* NO_SUCH_PAGE if a non-existent page index is specified |
|
6490 |
* @throws PrinterException if an error causes printing to be aborted |
|
6491 |
*/ |
|
6492 |
public int print(final Graphics graphics, |
|
6493 |
final PageFormat pageFormat, |
|
6494 |
final int pageIndex) throws PrinterException { |
|
6495 |
||
6496 |
// We'll use this Runnable |
|
6497 |
Runnable runnable = new Runnable() { |
|
6498 |
public synchronized void run() { |
|
6499 |
try { |
|
6500 |
// call into the delegate and save the return value |
|
6501 |
retVal = printDelegate.print(graphics, pageFormat, pageIndex); |
|
6502 |
} catch (Throwable throwable) { |
|
6503 |
// save any Throwable to be rethrown |
|
6504 |
retThrowable = throwable; |
|
6505 |
} finally { |
|
6506 |
// notify the caller that we're done |
|
6507 |
notifyAll(); |
|
6508 |
} |
|
6509 |
} |
|
6510 |
}; |
|
6511 |
||
6512 |
synchronized(runnable) { |
|
6513 |
// make sure these are initialized |
|
6514 |
retVal = -1; |
|
6515 |
retThrowable = null; |
|
6516 |
||
6517 |
// call into the EDT |
|
6518 |
SwingUtilities.invokeLater(runnable); |
|
6519 |
||
6520 |
// wait for the runnable to finish |
|
6521 |
while (retVal == -1 && retThrowable == null) { |
|
6522 |
try { |
|
6523 |
runnable.wait(); |
|
6524 |
} catch (InterruptedException ie) { |
|
6525 |
// short process, safe to ignore interrupts |
|
6526 |
} |
|
6527 |
} |
|
6528 |
||
6529 |
// if the delegate threw a throwable, rethrow it here |
|
6530 |
if (retThrowable != null) { |
|
6531 |
if (retThrowable instanceof PrinterException) { |
|
6532 |
throw (PrinterException)retThrowable; |
|
6533 |
} else if (retThrowable instanceof RuntimeException) { |
|
6534 |
throw (RuntimeException)retThrowable; |
|
6535 |
} else if (retThrowable instanceof Error) { |
|
6536 |
throw (Error)retThrowable; |
|
6537 |
} |
|
6538 |
||
6539 |
// can not happen |
|
6540 |
throw new AssertionError(retThrowable); |
|
6541 |
} |
|
6542 |
||
6543 |
return retVal; |
|
6544 |
} |
|
6545 |
} |
|
6546 |
} |
|
6547 |
||
6548 |
||
6549 |
///////////////// |
|
6550 |
// Accessibility support |
|
6551 |
//////////////// |
|
6552 |
||
6553 |
/** |
|
6554 |
* Gets the AccessibleContext associated with this JTable. |
|
6555 |
* For tables, the AccessibleContext takes the form of an |
|
6556 |
* AccessibleJTable. |
|
6557 |
* A new AccessibleJTable instance is created if necessary. |
|
6558 |
* |
|
6559 |
* @return an AccessibleJTable that serves as the |
|
6560 |
* AccessibleContext of this JTable |
|
6561 |
*/ |
|
6562 |
public AccessibleContext getAccessibleContext() { |
|
6563 |
if (accessibleContext == null) { |
|
6564 |
accessibleContext = new AccessibleJTable(); |
|
6565 |
} |
|
6566 |
return accessibleContext; |
|
6567 |
} |
|
6568 |
||
6569 |
// |
|
6570 |
// *** should also implement AccessibleSelection? |
|
6571 |
// *** and what's up with keyboard navigation/manipulation? |
|
6572 |
// |
|
6573 |
/** |
|
6574 |
* This class implements accessibility support for the |
|
6575 |
* <code>JTable</code> class. It provides an implementation of the |
|
6576 |
* Java Accessibility API appropriate to table user-interface elements. |
|
6577 |
* <p> |
|
6578 |
* <strong>Warning:</strong> |
|
6579 |
* Serialized objects of this class will not be compatible with |
|
6580 |
* future Swing releases. The current serialization support is |
|
6581 |
* appropriate for short term storage or RMI between applications running |
|
6582 |
* the same version of Swing. As of 1.4, support for long term storage |
|
20458 | 6583 |
* of all JavaBeans™ |
2 | 6584 |
* has been added to the <code>java.beans</code> package. |
6585 |
* Please see {@link java.beans.XMLEncoder}. |
|
6586 |
*/ |
|
22574
7f8ce0c8c20a
8032627: Add @SuppressWarnings("serial") to appropriate javax.swing classes
darcy
parents:
21982
diff
changeset
|
6587 |
@SuppressWarnings("serial") // Same-version serialization only |
2 | 6588 |
protected class AccessibleJTable extends AccessibleJComponent |
6589 |
implements AccessibleSelection, ListSelectionListener, TableModelListener, |
|
6590 |
TableColumnModelListener, CellEditorListener, PropertyChangeListener, |
|
6591 |
AccessibleExtendedTable { |
|
6592 |
||
6593 |
int lastSelectedRow; |
|
6594 |
int lastSelectedCol; |
|
6595 |
||
6596 |
/** |
|
6597 |
* AccessibleJTable constructor |
|
6598 |
* |
|
6599 |
* @since 1.5 |
|
6600 |
*/ |
|
6601 |
protected AccessibleJTable() { |
|
6602 |
super(); |
|
6603 |
JTable.this.addPropertyChangeListener(this); |
|
6604 |
JTable.this.getSelectionModel().addListSelectionListener(this); |
|
6605 |
TableColumnModel tcm = JTable.this.getColumnModel(); |
|
6606 |
tcm.addColumnModelListener(this); |
|
6607 |
tcm.getSelectionModel().addListSelectionListener(this); |
|
6608 |
JTable.this.getModel().addTableModelListener(this); |
|
6609 |
lastSelectedRow = JTable.this.getSelectedRow(); |
|
6610 |
lastSelectedCol = JTable.this.getSelectedColumn(); |
|
6611 |
} |
|
6612 |
||
6613 |
// Listeners to track model, etc. changes to as to re-place the other |
|
6614 |
// listeners |
|
6615 |
||
6616 |
/** |
|
6617 |
* Track changes to selection model, column model, etc. so as to |
|
6618 |
* be able to re-place listeners on those in order to pass on |
|
6619 |
* information to the Accessibility PropertyChange mechanism |
|
6620 |
*/ |
|
6621 |
public void propertyChange(PropertyChangeEvent e) { |
|
6622 |
String name = e.getPropertyName(); |
|
6623 |
Object oldValue = e.getOldValue(); |
|
6624 |
Object newValue = e.getNewValue(); |
|
6625 |
||
6626 |
// re-set tableModel listeners |
|
6627 |
if (name.compareTo("model") == 0) { |
|
6628 |
||
6629 |
if (oldValue != null && oldValue instanceof TableModel) { |
|
6630 |
((TableModel) oldValue).removeTableModelListener(this); |
|
6631 |
} |
|
6632 |
if (newValue != null && newValue instanceof TableModel) { |
|
6633 |
((TableModel) newValue).addTableModelListener(this); |
|
6634 |
} |
|
6635 |
||
6636 |
// re-set selectionModel listeners |
|
6637 |
} else if (name.compareTo("selectionModel") == 0) { |
|
6638 |
||
6639 |
Object source = e.getSource(); |
|
6640 |
if (source == JTable.this) { // row selection model |
|
6641 |
||
6642 |
if (oldValue != null && |
|
6643 |
oldValue instanceof ListSelectionModel) { |
|
6644 |
((ListSelectionModel) oldValue).removeListSelectionListener(this); |
|
6645 |
} |
|
6646 |
if (newValue != null && |
|
6647 |
newValue instanceof ListSelectionModel) { |
|
6648 |
((ListSelectionModel) newValue).addListSelectionListener(this); |
|
6649 |
} |
|
6650 |
||
6651 |
} else if (source == JTable.this.getColumnModel()) { |
|
6652 |
||
6653 |
if (oldValue != null && |
|
6654 |
oldValue instanceof ListSelectionModel) { |
|
6655 |
((ListSelectionModel) oldValue).removeListSelectionListener(this); |
|
6656 |
} |
|
6657 |
if (newValue != null && |
|
6658 |
newValue instanceof ListSelectionModel) { |
|
6659 |
((ListSelectionModel) newValue).addListSelectionListener(this); |
|
6660 |
} |
|
6661 |
||
6662 |
} else { |
|
6663 |
// System.out.println("!!! Bug in source of selectionModel propertyChangeEvent"); |
|
6664 |
} |
|
6665 |
||
6666 |
// re-set columnModel listeners |
|
6667 |
// and column's selection property listener as well |
|
6668 |
} else if (name.compareTo("columnModel") == 0) { |
|
6669 |
||
6670 |
if (oldValue != null && oldValue instanceof TableColumnModel) { |
|
6671 |
TableColumnModel tcm = (TableColumnModel) oldValue; |
|
6672 |
tcm.removeColumnModelListener(this); |
|
6673 |
tcm.getSelectionModel().removeListSelectionListener(this); |
|
6674 |
} |
|
6675 |
if (newValue != null && newValue instanceof TableColumnModel) { |
|
6676 |
TableColumnModel tcm = (TableColumnModel) newValue; |
|
6677 |
tcm.addColumnModelListener(this); |
|
6678 |
tcm.getSelectionModel().addListSelectionListener(this); |
|
6679 |
} |
|
6680 |
||
6681 |
// re-se cellEditor listeners |
|
6682 |
} else if (name.compareTo("tableCellEditor") == 0) { |
|
6683 |
||
6684 |
if (oldValue != null && oldValue instanceof TableCellEditor) { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
6685 |
((TableCellEditor) oldValue).removeCellEditorListener(this); |
2 | 6686 |
} |
6687 |
if (newValue != null && newValue instanceof TableCellEditor) { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
6688 |
((TableCellEditor) newValue).addCellEditorListener(this); |
2 | 6689 |
} |
6690 |
} |
|
6691 |
} |
|
6692 |
||
6693 |
||
6694 |
// Listeners to echo changes to the AccessiblePropertyChange mechanism |
|
6695 |
||
6696 |
/* |
|
6697 |
* Describes a change in the accessible table model. |
|
6698 |
*/ |
|
6699 |
protected class AccessibleJTableModelChange |
|
6700 |
implements AccessibleTableModelChange { |
|
6701 |
||
6702 |
protected int type; |
|
6703 |
protected int firstRow; |
|
6704 |
protected int lastRow; |
|
6705 |
protected int firstColumn; |
|
6706 |
protected int lastColumn; |
|
6707 |
||
6708 |
protected AccessibleJTableModelChange(int type, int firstRow, |
|
6709 |
int lastRow, int firstColumn, |
|
6710 |
int lastColumn) { |
|
6711 |
this.type = type; |
|
6712 |
this.firstRow = firstRow; |
|
6713 |
this.lastRow = lastRow; |
|
6714 |
this.firstColumn = firstColumn; |
|
6715 |
this.lastColumn = lastColumn; |
|
6716 |
} |
|
6717 |
||
6718 |
public int getType() { |
|
6719 |
return type; |
|
6720 |
} |
|
6721 |
||
6722 |
public int getFirstRow() { |
|
6723 |
return firstRow; |
|
6724 |
} |
|
6725 |
||
6726 |
public int getLastRow() { |
|
6727 |
return lastRow; |
|
6728 |
} |
|
6729 |
||
6730 |
public int getFirstColumn() { |
|
6731 |
return firstColumn; |
|
6732 |
} |
|
6733 |
||
6734 |
public int getLastColumn() { |
|
6735 |
return lastColumn; |
|
6736 |
} |
|
6737 |
} |
|
6738 |
||
6739 |
/** |
|
6740 |
* Track changes to the table contents |
|
6741 |
*/ |
|
6742 |
public void tableChanged(TableModelEvent e) { |
|
6743 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6744 |
null, null); |
|
6745 |
if (e != null) { |
|
6746 |
int firstColumn = e.getColumn(); |
|
6747 |
int lastColumn = e.getColumn(); |
|
6748 |
if (firstColumn == TableModelEvent.ALL_COLUMNS) { |
|
6749 |
firstColumn = 0; |
|
6750 |
lastColumn = getColumnCount() - 1; |
|
6751 |
} |
|
6752 |
||
6753 |
// Fire a property change event indicating the table model |
|
6754 |
// has changed. |
|
6755 |
AccessibleJTableModelChange change = |
|
6756 |
new AccessibleJTableModelChange(e.getType(), |
|
6757 |
e.getFirstRow(), |
|
6758 |
e.getLastRow(), |
|
6759 |
firstColumn, |
|
6760 |
lastColumn); |
|
6761 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED, |
|
6762 |
null, change); |
|
6763 |
} |
|
6764 |
} |
|
6765 |
||
6766 |
/** |
|
6767 |
* Track changes to the table contents (row insertions) |
|
6768 |
*/ |
|
6769 |
public void tableRowsInserted(TableModelEvent e) { |
|
6770 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6771 |
null, null); |
|
6772 |
||
6773 |
// Fire a property change event indicating the table model |
|
6774 |
// has changed. |
|
6775 |
int firstColumn = e.getColumn(); |
|
6776 |
int lastColumn = e.getColumn(); |
|
6777 |
if (firstColumn == TableModelEvent.ALL_COLUMNS) { |
|
6778 |
firstColumn = 0; |
|
6779 |
lastColumn = getColumnCount() - 1; |
|
6780 |
} |
|
6781 |
AccessibleJTableModelChange change = |
|
6782 |
new AccessibleJTableModelChange(e.getType(), |
|
6783 |
e.getFirstRow(), |
|
6784 |
e.getLastRow(), |
|
6785 |
firstColumn, |
|
6786 |
lastColumn); |
|
6787 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED, |
|
6788 |
null, change); |
|
6789 |
} |
|
6790 |
||
6791 |
/** |
|
6792 |
* Track changes to the table contents (row deletions) |
|
6793 |
*/ |
|
6794 |
public void tableRowsDeleted(TableModelEvent e) { |
|
6795 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6796 |
null, null); |
|
6797 |
||
6798 |
// Fire a property change event indicating the table model |
|
6799 |
// has changed. |
|
6800 |
int firstColumn = e.getColumn(); |
|
6801 |
int lastColumn = e.getColumn(); |
|
6802 |
if (firstColumn == TableModelEvent.ALL_COLUMNS) { |
|
6803 |
firstColumn = 0; |
|
6804 |
lastColumn = getColumnCount() - 1; |
|
6805 |
} |
|
6806 |
AccessibleJTableModelChange change = |
|
6807 |
new AccessibleJTableModelChange(e.getType(), |
|
6808 |
e.getFirstRow(), |
|
6809 |
e.getLastRow(), |
|
6810 |
firstColumn, |
|
6811 |
lastColumn); |
|
6812 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED, |
|
6813 |
null, change); |
|
6814 |
} |
|
6815 |
||
6816 |
/** |
|
6817 |
* Track changes to the table contents (column insertions) |
|
6818 |
*/ |
|
6819 |
public void columnAdded(TableColumnModelEvent e) { |
|
6820 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6821 |
null, null); |
|
6822 |
||
6823 |
// Fire a property change event indicating the table model |
|
6824 |
// has changed. |
|
6825 |
int type = AccessibleTableModelChange.INSERT; |
|
6826 |
AccessibleJTableModelChange change = |
|
6827 |
new AccessibleJTableModelChange(type, |
|
6828 |
0, |
|
6829 |
0, |
|
6830 |
e.getFromIndex(), |
|
6831 |
e.getToIndex()); |
|
6832 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED, |
|
6833 |
null, change); |
|
6834 |
} |
|
6835 |
||
6836 |
/** |
|
6837 |
* Track changes to the table contents (column deletions) |
|
6838 |
*/ |
|
6839 |
public void columnRemoved(TableColumnModelEvent e) { |
|
6840 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6841 |
null, null); |
|
6842 |
// Fire a property change event indicating the table model |
|
6843 |
// has changed. |
|
6844 |
int type = AccessibleTableModelChange.DELETE; |
|
6845 |
AccessibleJTableModelChange change = |
|
6846 |
new AccessibleJTableModelChange(type, |
|
6847 |
0, |
|
6848 |
0, |
|
6849 |
e.getFromIndex(), |
|
6850 |
e.getToIndex()); |
|
6851 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED, |
|
6852 |
null, change); |
|
6853 |
} |
|
6854 |
||
6855 |
/** |
|
6856 |
* Track changes of a column repositioning. |
|
6857 |
* |
|
6858 |
* @see TableColumnModelListener |
|
6859 |
*/ |
|
6860 |
public void columnMoved(TableColumnModelEvent e) { |
|
6861 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6862 |
null, null); |
|
6863 |
||
6864 |
// Fire property change events indicating the table model |
|
6865 |
// has changed. |
|
6866 |
int type = AccessibleTableModelChange.DELETE; |
|
6867 |
AccessibleJTableModelChange change = |
|
6868 |
new AccessibleJTableModelChange(type, |
|
6869 |
0, |
|
6870 |
0, |
|
6871 |
e.getFromIndex(), |
|
6872 |
e.getFromIndex()); |
|
6873 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED, |
|
6874 |
null, change); |
|
6875 |
||
6876 |
int type2 = AccessibleTableModelChange.INSERT; |
|
6877 |
AccessibleJTableModelChange change2 = |
|
6878 |
new AccessibleJTableModelChange(type2, |
|
6879 |
0, |
|
6880 |
0, |
|
6881 |
e.getToIndex(), |
|
6882 |
e.getToIndex()); |
|
6883 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_MODEL_CHANGED, |
|
6884 |
null, change2); |
|
6885 |
} |
|
6886 |
||
6887 |
/** |
|
6888 |
* Track changes of a column moving due to margin changes. |
|
6889 |
* |
|
6890 |
* @see TableColumnModelListener |
|
6891 |
*/ |
|
6892 |
public void columnMarginChanged(ChangeEvent e) { |
|
6893 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6894 |
null, null); |
|
6895 |
} |
|
6896 |
||
6897 |
/** |
|
6898 |
* Track that the selection model of the TableColumnModel changed. |
|
6899 |
* |
|
6900 |
* @see TableColumnModelListener |
|
6901 |
*/ |
|
6902 |
public void columnSelectionChanged(ListSelectionEvent e) { |
|
6903 |
// we should now re-place our TableColumn listener |
|
6904 |
} |
|
6905 |
||
6906 |
/** |
|
6907 |
* Track changes to a cell's contents. |
|
6908 |
* |
|
6909 |
* Invoked when editing is finished. The changes are saved, the |
|
6910 |
* editor object is discarded, and the cell is rendered once again. |
|
6911 |
* |
|
6912 |
* @see CellEditorListener |
|
6913 |
*/ |
|
6914 |
public void editingStopped(ChangeEvent e) { |
|
6915 |
// it'd be great if we could figure out which cell, and pass that |
|
6916 |
// somehow as a parameter |
|
6917 |
firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, |
|
6918 |
null, null); |
|
6919 |
} |
|
6920 |
||
6921 |
/** |
|
6922 |
* Invoked when editing is canceled. The editor object is discarded |
|
6923 |
* and the cell is rendered once again. |
|
6924 |
* |
|
6925 |
* @see CellEditorListener |
|
6926 |
*/ |
|
6927 |
public void editingCanceled(ChangeEvent e) { |
|
6928 |
// nothing to report, 'cause nothing changed |
|
6929 |
} |
|
6930 |
||
6931 |
/** |
|
6932 |
* Track changes to table cell selections |
|
6933 |
*/ |
|
6934 |
public void valueChanged(ListSelectionEvent e) { |
|
6935 |
firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, |
|
6936 |
Boolean.valueOf(false), Boolean.valueOf(true)); |
|
6937 |
||
6938 |
int selectedRow = JTable.this.getSelectedRow(); |
|
6939 |
int selectedCol = JTable.this.getSelectedColumn(); |
|
6940 |
if (selectedRow != lastSelectedRow || |
|
6941 |
selectedCol != lastSelectedCol) { |
|
6942 |
Accessible oldA = getAccessibleAt(lastSelectedRow, |
|
6943 |
lastSelectedCol); |
|
6944 |
Accessible newA = getAccessibleAt(selectedRow, selectedCol); |
|
6945 |
firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY, |
|
6946 |
oldA, newA); |
|
6947 |
lastSelectedRow = selectedRow; |
|
6948 |
lastSelectedCol = selectedCol; |
|
6949 |
} |
|
6950 |
} |
|
6951 |
||
6952 |
||
6953 |
||
6954 |
||
6955 |
// AccessibleContext support |
|
6956 |
||
6957 |
/** |
|
6958 |
* Get the AccessibleSelection associated with this object. In the |
|
6959 |
* implementation of the Java Accessibility API for this class, |
|
6960 |
* return this object, which is responsible for implementing the |
|
6961 |
* AccessibleSelection interface on behalf of itself. |
|
6962 |
* |
|
6963 |
* @return this object |
|
6964 |
*/ |
|
6965 |
public AccessibleSelection getAccessibleSelection() { |
|
6966 |
return this; |
|
6967 |
} |
|
6968 |
||
6969 |
/** |
|
6970 |
* Gets the role of this object. |
|
6971 |
* |
|
6972 |
* @return an instance of AccessibleRole describing the role of the |
|
6973 |
* object |
|
6974 |
* @see AccessibleRole |
|
6975 |
*/ |
|
6976 |
public AccessibleRole getAccessibleRole() { |
|
6977 |
return AccessibleRole.TABLE; |
|
6978 |
} |
|
6979 |
||
6980 |
/** |
|
6981 |
* Returns the <code>Accessible</code> child, if one exists, |
|
6982 |
* contained at the local coordinate <code>Point</code>. |
|
6983 |
* |
|
6984 |
* @param p the point defining the top-left corner of the |
|
6985 |
* <code>Accessible</code>, given in the coordinate space |
|
6986 |
* of the object's parent |
|
6987 |
* @return the <code>Accessible</code>, if it exists, |
|
6988 |
* at the specified location; else <code>null</code> |
|
6989 |
*/ |
|
6990 |
public Accessible getAccessibleAt(Point p) { |
|
6991 |
int column = columnAtPoint(p); |
|
6992 |
int row = rowAtPoint(p); |
|
6993 |
||
6994 |
if ((column != -1) && (row != -1)) { |
|
6995 |
TableColumn aColumn = getColumnModel().getColumn(column); |
|
6996 |
TableCellRenderer renderer = aColumn.getCellRenderer(); |
|
6997 |
if (renderer == null) { |
|
6998 |
Class<?> columnClass = getColumnClass(column); |
|
6999 |
renderer = getDefaultRenderer(columnClass); |
|
7000 |
} |
|
7001 |
Component component = renderer.getTableCellRendererComponent( |
|
7002 |
JTable.this, null, false, false, |
|
7003 |
row, column); |
|
7004 |
return new AccessibleJTableCell(JTable.this, row, column, |
|
7005 |
getAccessibleIndexAt(row, column)); |
|
7006 |
} |
|
7007 |
return null; |
|
7008 |
} |
|
7009 |
||
7010 |
/** |
|
7011 |
* Returns the number of accessible children in the object. If all |
|
7012 |
* of the children of this object implement <code>Accessible</code>, |
|
7013 |
* then this method should return the number of children of this object. |
|
7014 |
* |
|
7015 |
* @return the number of accessible children in the object |
|
7016 |
*/ |
|
7017 |
public int getAccessibleChildrenCount() { |
|
7018 |
return (JTable.this.getColumnCount() * JTable.this.getRowCount()); |
|
7019 |
} |
|
7020 |
||
7021 |
/** |
|
7022 |
* Returns the nth <code>Accessible</code> child of the object. |
|
7023 |
* |
|
7024 |
* @param i zero-based index of child |
|
7025 |
* @return the nth Accessible child of the object |
|
7026 |
*/ |
|
7027 |
public Accessible getAccessibleChild(int i) { |
|
7028 |
if (i < 0 || i >= getAccessibleChildrenCount()) { |
|
7029 |
return null; |
|
7030 |
} else { |
|
7031 |
// children increase across, and then down, for tables |
|
7032 |
// (arbitrary decision) |
|
7033 |
int column = getAccessibleColumnAtIndex(i); |
|
7034 |
int row = getAccessibleRowAtIndex(i); |
|
7035 |
||
7036 |
TableColumn aColumn = getColumnModel().getColumn(column); |
|
7037 |
TableCellRenderer renderer = aColumn.getCellRenderer(); |
|
7038 |
if (renderer == null) { |
|
7039 |
Class<?> columnClass = getColumnClass(column); |
|
7040 |
renderer = getDefaultRenderer(columnClass); |
|
7041 |
} |
|
7042 |
Component component = renderer.getTableCellRendererComponent( |
|
7043 |
JTable.this, null, false, false, |
|
7044 |
row, column); |
|
7045 |
return new AccessibleJTableCell(JTable.this, row, column, |
|
7046 |
getAccessibleIndexAt(row, column)); |
|
7047 |
} |
|
7048 |
} |
|
7049 |
||
7050 |
// AccessibleSelection support |
|
7051 |
||
7052 |
/** |
|
7053 |
* Returns the number of <code>Accessible</code> children |
|
7054 |
* currently selected. |
|
7055 |
* If no children are selected, the return value will be 0. |
|
7056 |
* |
|
7057 |
* @return the number of items currently selected |
|
7058 |
*/ |
|
7059 |
public int getAccessibleSelectionCount() { |
|
7060 |
int rowsSel = JTable.this.getSelectedRowCount(); |
|
7061 |
int colsSel = JTable.this.getSelectedColumnCount(); |
|
7062 |
||
7063 |
if (JTable.this.cellSelectionEnabled) { // a contiguous block |
|
7064 |
return rowsSel * colsSel; |
|
7065 |
||
7066 |
} else { |
|
7067 |
// a column swath and a row swath, with a shared block |
|
7068 |
if (JTable.this.getRowSelectionAllowed() && |
|
7069 |
JTable.this.getColumnSelectionAllowed()) { |
|
7070 |
return rowsSel * JTable.this.getColumnCount() + |
|
7071 |
colsSel * JTable.this.getRowCount() - |
|
7072 |
rowsSel * colsSel; |
|
7073 |
||
7074 |
// just one or more rows in selection |
|
7075 |
} else if (JTable.this.getRowSelectionAllowed()) { |
|
7076 |
return rowsSel * JTable.this.getColumnCount(); |
|
7077 |
||
7078 |
// just one or more rows in selection |
|
7079 |
} else if (JTable.this.getColumnSelectionAllowed()) { |
|
7080 |
return colsSel * JTable.this.getRowCount(); |
|
7081 |
||
7082 |
} else { |
|
7083 |
return 0; // JTable doesn't allow selections |
|
7084 |
} |
|
7085 |
} |
|
7086 |
} |
|
7087 |
||
7088 |
/** |
|
7089 |
* Returns an <code>Accessible</code> representing the |
|
7090 |
* specified selected child in the object. If there |
|
7091 |
* isn't a selection, or there are fewer children selected |
|
7092 |
* than the integer passed in, the return |
|
7093 |
* value will be <code>null</code>. |
|
7094 |
* <p>Note that the index represents the i-th selected child, which |
|
7095 |
* is different from the i-th child. |
|
7096 |
* |
|
7097 |
* @param i the zero-based index of selected children |
|
7098 |
* @return the i-th selected child |
|
7099 |
* @see #getAccessibleSelectionCount |
|
7100 |
*/ |
|
7101 |
public Accessible getAccessibleSelection(int i) { |
|
7102 |
if (i < 0 || i > getAccessibleSelectionCount()) { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
7103 |
return null; |
2 | 7104 |
} |
7105 |
||
7106 |
int rowsSel = JTable.this.getSelectedRowCount(); |
|
7107 |
int colsSel = JTable.this.getSelectedColumnCount(); |
|
7108 |
int rowIndicies[] = getSelectedRows(); |
|
7109 |
int colIndicies[] = getSelectedColumns(); |
|
7110 |
int ttlCols = JTable.this.getColumnCount(); |
|
7111 |
int ttlRows = JTable.this.getRowCount(); |
|
7112 |
int r; |
|
7113 |
int c; |
|
7114 |
||
7115 |
if (JTable.this.cellSelectionEnabled) { // a contiguous block |
|
7116 |
r = rowIndicies[i / colsSel]; |
|
7117 |
c = colIndicies[i % colsSel]; |
|
7118 |
return getAccessibleChild((r * ttlCols) + c); |
|
7119 |
} else { |
|
7120 |
||
7121 |
// a column swath and a row swath, with a shared block |
|
7122 |
if (JTable.this.getRowSelectionAllowed() && |
|
7123 |
JTable.this.getColumnSelectionAllowed()) { |
|
7124 |
||
7125 |
// Situation: |
|
7126 |
// We have a table, like the 6x3 table below, |
|
7127 |
// wherein three colums and one row selected |
|
7128 |
// (selected cells marked with "*", unselected "0"): |
|
7129 |
// |
|
7130 |
// 0 * 0 * * 0 |
|
7131 |
// * * * * * * |
|
7132 |
// 0 * 0 * * 0 |
|
7133 |
// |
|
7134 |
||
7135 |
// State machine below walks through the array of |
|
7136 |
// selected rows in two states: in a selected row, |
|
7137 |
// and not in one; continuing until we are in a row |
|
7138 |
// in which the ith selection exists. Then we return |
|
7139 |
// the appropriate cell. In the state machine, we |
|
7140 |
// always do rows above the "current" selected row first, |
|
7141 |
// then the cells in the selected row. If we're done |
|
7142 |
// with the state machine before finding the requested |
|
7143 |
// selected child, we handle the rows below the last |
|
7144 |
// selected row at the end. |
|
7145 |
// |
|
7146 |
int curIndex = i; |
|
7147 |
final int IN_ROW = 0; |
|
7148 |
final int NOT_IN_ROW = 1; |
|
7149 |
int state = (rowIndicies[0] == 0 ? IN_ROW : NOT_IN_ROW); |
|
7150 |
int j = 0; |
|
7151 |
int prevRow = -1; |
|
7152 |
while (j < rowIndicies.length) { |
|
7153 |
switch (state) { |
|
7154 |
||
7155 |
case IN_ROW: // on individual row full of selections |
|
7156 |
if (curIndex < ttlCols) { // it's here! |
|
7157 |
c = curIndex % ttlCols; |
|
7158 |
r = rowIndicies[j]; |
|
7159 |
return getAccessibleChild((r * ttlCols) + c); |
|
7160 |
} else { // not here |
|
7161 |
curIndex -= ttlCols; |
|
7162 |
} |
|
7163 |
// is the next row in table selected or not? |
|
7164 |
if (j + 1 == rowIndicies.length || |
|
7165 |
rowIndicies[j] != rowIndicies[j+1] - 1) { |
|
7166 |
state = NOT_IN_ROW; |
|
7167 |
prevRow = rowIndicies[j]; |
|
7168 |
} |
|
7169 |
j++; // we didn't return earlier, so go to next row |
|
7170 |
break; |
|
7171 |
||
7172 |
case NOT_IN_ROW: // sparse bunch of rows of selections |
|
7173 |
if (curIndex < |
|
7174 |
(colsSel * (rowIndicies[j] - |
|
7175 |
(prevRow == -1 ? 0 : (prevRow + 1))))) { |
|
7176 |
||
7177 |
// it's here! |
|
7178 |
c = colIndicies[curIndex % colsSel]; |
|
7179 |
r = (j > 0 ? rowIndicies[j-1] + 1 : 0) |
|
7180 |
+ curIndex / colsSel; |
|
7181 |
return getAccessibleChild((r * ttlCols) + c); |
|
7182 |
} else { // not here |
|
7183 |
curIndex -= colsSel * (rowIndicies[j] - |
|
7184 |
(prevRow == -1 ? 0 : (prevRow + 1))); |
|
7185 |
} |
|
7186 |
state = IN_ROW; |
|
7187 |
break; |
|
7188 |
} |
|
7189 |
} |
|
7190 |
// we got here, so we didn't find it yet; find it in |
|
7191 |
// the last sparse bunch of rows |
|
7192 |
if (curIndex < |
|
7193 |
(colsSel * (ttlRows - |
|
7194 |
(prevRow == -1 ? 0 : (prevRow + 1))))) { // it's here! |
|
7195 |
c = colIndicies[curIndex % colsSel]; |
|
7196 |
r = rowIndicies[j-1] + curIndex / colsSel + 1; |
|
7197 |
return getAccessibleChild((r * ttlCols) + c); |
|
7198 |
} else { // not here |
|
7199 |
// we shouldn't get to this spot in the code! |
|
7200 |
// System.out.println("Bug in AccessibleJTable.getAccessibleSelection()"); |
|
7201 |
} |
|
7202 |
||
7203 |
// one or more rows selected |
|
7204 |
} else if (JTable.this.getRowSelectionAllowed()) { |
|
7205 |
c = i % ttlCols; |
|
7206 |
r = rowIndicies[i / ttlCols]; |
|
7207 |
return getAccessibleChild((r * ttlCols) + c); |
|
7208 |
||
7209 |
// one or more columns selected |
|
7210 |
} else if (JTable.this.getColumnSelectionAllowed()) { |
|
7211 |
c = colIndicies[i % colsSel]; |
|
7212 |
r = i / colsSel; |
|
7213 |
return getAccessibleChild((r * ttlCols) + c); |
|
7214 |
} |
|
7215 |
} |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
7216 |
return null; |
2 | 7217 |
} |
7218 |
||
7219 |
/** |
|
7220 |
* Determines if the current child of this object is selected. |
|
7221 |
* |
|
7222 |
* @param i the zero-based index of the child in this |
|
7223 |
* <code>Accessible</code> object |
|
7224 |
* @return true if the current child of this object is selected |
|
7225 |
* @see AccessibleContext#getAccessibleChild |
|
7226 |
*/ |
|
7227 |
public boolean isAccessibleChildSelected(int i) { |
|
7228 |
int column = getAccessibleColumnAtIndex(i); |
|
7229 |
int row = getAccessibleRowAtIndex(i); |
|
7230 |
return JTable.this.isCellSelected(row, column); |
|
7231 |
} |
|
7232 |
||
7233 |
/** |
|
7234 |
* Adds the specified <code>Accessible</code> child of the |
|
7235 |
* object to the object's selection. If the object supports |
|
7236 |
* multiple selections, the specified child is added to |
|
7237 |
* any existing selection, otherwise |
|
7238 |
* it replaces any existing selection in the object. If the |
|
7239 |
* specified child is already selected, this method has no effect. |
|
7240 |
* <p> |
|
7241 |
* This method only works on <code>JTable</code>s which have |
|
7242 |
* individual cell selection enabled. |
|
7243 |
* |
|
7244 |
* @param i the zero-based index of the child |
|
7245 |
* @see AccessibleContext#getAccessibleChild |
|
7246 |
*/ |
|
7247 |
public void addAccessibleSelection(int i) { |
|
7248 |
// TIGER - 4495286 |
|
7249 |
int column = getAccessibleColumnAtIndex(i); |
|
7250 |
int row = getAccessibleRowAtIndex(i); |
|
7251 |
JTable.this.changeSelection(row, column, true, false); |
|
7252 |
} |
|
7253 |
||
7254 |
/** |
|
7255 |
* Removes the specified child of the object from the object's |
|
7256 |
* selection. If the specified item isn't currently selected, this |
|
7257 |
* method has no effect. |
|
7258 |
* <p> |
|
7259 |
* This method only works on <code>JTables</code> which have |
|
7260 |
* individual cell selection enabled. |
|
7261 |
* |
|
7262 |
* @param i the zero-based index of the child |
|
7263 |
* @see AccessibleContext#getAccessibleChild |
|
7264 |
*/ |
|
7265 |
public void removeAccessibleSelection(int i) { |
|
7266 |
if (JTable.this.cellSelectionEnabled) { |
|
7267 |
int column = getAccessibleColumnAtIndex(i); |
|
7268 |
int row = getAccessibleRowAtIndex(i); |
|
7269 |
JTable.this.removeRowSelectionInterval(row, row); |
|
7270 |
JTable.this.removeColumnSelectionInterval(column, column); |
|
7271 |
} |
|
7272 |
} |
|
7273 |
||
7274 |
/** |
|
7275 |
* Clears the selection in the object, so that no children in the |
|
7276 |
* object are selected. |
|
7277 |
*/ |
|
7278 |
public void clearAccessibleSelection() { |
|
7279 |
JTable.this.clearSelection(); |
|
7280 |
} |
|
7281 |
||
7282 |
/** |
|
7283 |
* Causes every child of the object to be selected, but only |
|
7284 |
* if the <code>JTable</code> supports multiple selections, |
|
7285 |
* and if individual cell selection is enabled. |
|
7286 |
*/ |
|
7287 |
public void selectAllAccessibleSelection() { |
|
7288 |
if (JTable.this.cellSelectionEnabled) { |
|
7289 |
JTable.this.selectAll(); |
|
7290 |
} |
|
7291 |
} |
|
7292 |
||
7293 |
// begin AccessibleExtendedTable implementation ------------- |
|
7294 |
||
7295 |
/** |
|
7296 |
* Returns the row number of an index in the table. |
|
7297 |
* |
|
7298 |
* @param index the zero-based index in the table |
|
7299 |
* @return the zero-based row of the table if one exists; |
|
7300 |
* otherwise -1. |
|
7301 |
* @since 1.4 |
|
7302 |
*/ |
|
7303 |
public int getAccessibleRow(int index) { |
|
7304 |
return getAccessibleRowAtIndex(index); |
|
7305 |
} |
|
7306 |
||
7307 |
/** |
|
7308 |
* Returns the column number of an index in the table. |
|
7309 |
* |
|
7310 |
* @param index the zero-based index in the table |
|
7311 |
* @return the zero-based column of the table if one exists; |
|
7312 |
* otherwise -1. |
|
7313 |
* @since 1.4 |
|
7314 |
*/ |
|
7315 |
public int getAccessibleColumn(int index) { |
|
7316 |
return getAccessibleColumnAtIndex(index); |
|
7317 |
} |
|
7318 |
||
7319 |
/** |
|
7320 |
* Returns the index at a row and column in the table. |
|
7321 |
* |
|
7322 |
* @param r zero-based row of the table |
|
7323 |
* @param c zero-based column of the table |
|
7324 |
* @return the zero-based index in the table if one exists; |
|
7325 |
* otherwise -1. |
|
7326 |
* @since 1.4 |
|
7327 |
*/ |
|
7328 |
public int getAccessibleIndex(int r, int c) { |
|
7329 |
return getAccessibleIndexAt(r, c); |
|
7330 |
} |
|
7331 |
||
7332 |
// end of AccessibleExtendedTable implementation ------------ |
|
7333 |
||
7334 |
// start of AccessibleTable implementation ------------------ |
|
7335 |
||
7336 |
private Accessible caption; |
|
7337 |
private Accessible summary; |
|
7338 |
private Accessible [] rowDescription; |
|
7339 |
private Accessible [] columnDescription; |
|
7340 |
||
7341 |
/** |
|
7342 |
* Gets the <code>AccessibleTable</code> associated with this |
|
7343 |
* object. In the implementation of the Java Accessibility |
|
7344 |
* API for this class, return this object, which is responsible |
|
7345 |
* for implementing the <code>AccessibleTables</code> interface |
|
7346 |
* on behalf of itself. |
|
7347 |
* |
|
7348 |
* @return this object |
|
7349 |
* @since 1.3 |
|
7350 |
*/ |
|
7351 |
public AccessibleTable getAccessibleTable() { |
|
7352 |
return this; |
|
7353 |
} |
|
7354 |
||
7355 |
/** |
|
7356 |
* Returns the caption for the table. |
|
7357 |
* |
|
7358 |
* @return the caption for the table |
|
7359 |
* @since 1.3 |
|
7360 |
*/ |
|
7361 |
public Accessible getAccessibleCaption() { |
|
7362 |
return this.caption; |
|
7363 |
} |
|
7364 |
||
7365 |
/** |
|
7366 |
* Sets the caption for the table. |
|
7367 |
* |
|
7368 |
* @param a the caption for the table |
|
7369 |
* @since 1.3 |
|
7370 |
*/ |
|
7371 |
public void setAccessibleCaption(Accessible a) { |
|
7372 |
Accessible oldCaption = caption; |
|
7373 |
this.caption = a; |
|
7374 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_CAPTION_CHANGED, |
|
7375 |
oldCaption, this.caption); |
|
7376 |
} |
|
7377 |
||
7378 |
/** |
|
7379 |
* Returns the summary description of the table. |
|
7380 |
* |
|
7381 |
* @return the summary description of the table |
|
7382 |
* @since 1.3 |
|
7383 |
*/ |
|
7384 |
public Accessible getAccessibleSummary() { |
|
7385 |
return this.summary; |
|
7386 |
} |
|
7387 |
||
7388 |
/** |
|
7389 |
* Sets the summary description of the table. |
|
7390 |
* |
|
7391 |
* @param a the summary description of the table |
|
7392 |
* @since 1.3 |
|
7393 |
*/ |
|
7394 |
public void setAccessibleSummary(Accessible a) { |
|
7395 |
Accessible oldSummary = summary; |
|
7396 |
this.summary = a; |
|
7397 |
firePropertyChange(AccessibleContext.ACCESSIBLE_TABLE_SUMMARY_CHANGED, |
|
7398 |
oldSummary, this.summary); |
|
7399 |
} |
|
7400 |
||
7401 |
/* |
|
7402 |
* Returns the total number of rows in this table. |
|
7403 |
* |
|
7404 |
* @return the total number of rows in this table |
|
7405 |
*/ |
|
7406 |
public int getAccessibleRowCount() { |
|
7407 |
return JTable.this.getRowCount(); |
|
7408 |
} |
|
7409 |
||
7410 |
/* |
|
7411 |
* Returns the total number of columns in the table. |
|
7412 |
* |
|
7413 |
* @return the total number of columns in the table |
|
7414 |
*/ |
|
7415 |
public int getAccessibleColumnCount() { |
|
7416 |
return JTable.this.getColumnCount(); |
|
7417 |
} |
|
7418 |
||
7419 |
/* |
|
7420 |
* Returns the <code>Accessible</code> at a specified row |
|
7421 |
* and column in the table. |
|
7422 |
* |
|
7423 |
* @param r zero-based row of the table |
|
7424 |
* @param c zero-based column of the table |
|
7425 |
* @return the <code>Accessible</code> at the specified row and column |
|
7426 |
* in the table |
|
7427 |
*/ |
|
7428 |
public Accessible getAccessibleAt(int r, int c) { |
|
7429 |
return getAccessibleChild((r * getAccessibleColumnCount()) + c); |
|
7430 |
} |
|
7431 |
||
7432 |
/** |
|
7433 |
* Returns the number of rows occupied by the <code>Accessible</code> |
|
7434 |
* at a specified row and column in the table. |
|
7435 |
* |
|
7436 |
* @return the number of rows occupied by the <code>Accessible</code> |
|
7437 |
* at a specified row and column in the table |
|
7438 |
* @since 1.3 |
|
7439 |
*/ |
|
7440 |
public int getAccessibleRowExtentAt(int r, int c) { |
|
7441 |
return 1; |
|
7442 |
} |
|
7443 |
||
7444 |
/** |
|
7445 |
* Returns the number of columns occupied by the |
|
7446 |
* <code>Accessible</code> at a given (row, column). |
|
7447 |
* |
|
7448 |
* @return the number of columns occupied by the <code>Accessible</code> |
|
7449 |
* at a specified row and column in the table |
|
7450 |
* @since 1.3 |
|
7451 |
*/ |
|
7452 |
public int getAccessibleColumnExtentAt(int r, int c) { |
|
7453 |
return 1; |
|
7454 |
} |
|
7455 |
||
7456 |
/** |
|
7457 |
* Returns the row headers as an <code>AccessibleTable</code>. |
|
7458 |
* |
|
7459 |
* @return an <code>AccessibleTable</code> representing the row |
|
7460 |
* headers |
|
7461 |
* @since 1.3 |
|
7462 |
*/ |
|
7463 |
public AccessibleTable getAccessibleRowHeader() { |
|
7464 |
// row headers are not supported |
|
7465 |
return null; |
|
7466 |
} |
|
7467 |
||
7468 |
/** |
|
7469 |
* Sets the row headers as an <code>AccessibleTable</code>. |
|
7470 |
* |
|
7471 |
* @param a an <code>AccessibleTable</code> representing the row |
|
7472 |
* headers |
|
7473 |
* @since 1.3 |
|
7474 |
*/ |
|
7475 |
public void setAccessibleRowHeader(AccessibleTable a) { |
|
7476 |
// row headers are not supported |
|
7477 |
} |
|
7478 |
||
7479 |
/** |
|
7480 |
* Returns the column headers as an <code>AccessibleTable</code>. |
|
7481 |
* |
|
7482 |
* @return an <code>AccessibleTable</code> representing the column |
|
7483 |
* headers, or <code>null</code> if the table header is |
|
7484 |
* <code>null</code> |
|
7485 |
* @since 1.3 |
|
7486 |
*/ |
|
7487 |
public AccessibleTable getAccessibleColumnHeader() { |
|
7488 |
JTableHeader header = JTable.this.getTableHeader(); |
|
7489 |
return header == null ? null : new AccessibleTableHeader(header); |
|
7490 |
} |
|
7491 |
||
7492 |
/* |
|
7493 |
* Private class representing a table column header |
|
7494 |
*/ |
|
7495 |
private class AccessibleTableHeader implements AccessibleTable { |
|
7496 |
private JTableHeader header; |
|
7497 |
private TableColumnModel headerModel; |
|
7498 |
||
7499 |
AccessibleTableHeader(JTableHeader header) { |
|
7500 |
this.header = header; |
|
7501 |
this.headerModel = header.getColumnModel(); |
|
7502 |
} |
|
7503 |
||
7504 |
/** |
|
7505 |
* Returns the caption for the table. |
|
7506 |
* |
|
7507 |
* @return the caption for the table |
|
7508 |
*/ |
|
7509 |
public Accessible getAccessibleCaption() { return null; } |
|
7510 |
||
7511 |
||
7512 |
/** |
|
7513 |
* Sets the caption for the table. |
|
7514 |
* |
|
7515 |
* @param a the caption for the table |
|
7516 |
*/ |
|
7517 |
public void setAccessibleCaption(Accessible a) {} |
|
7518 |
||
7519 |
/** |
|
7520 |
* Returns the summary description of the table. |
|
7521 |
* |
|
7522 |
* @return the summary description of the table |
|
7523 |
*/ |
|
7524 |
public Accessible getAccessibleSummary() { return null; } |
|
7525 |
||
7526 |
/** |
|
7527 |
* Sets the summary description of the table |
|
7528 |
* |
|
7529 |
* @param a the summary description of the table |
|
7530 |
*/ |
|
7531 |
public void setAccessibleSummary(Accessible a) {} |
|
7532 |
||
7533 |
/** |
|
7534 |
* Returns the number of rows in the table. |
|
7535 |
* |
|
7536 |
* @return the number of rows in the table |
|
7537 |
*/ |
|
7538 |
public int getAccessibleRowCount() { return 1; } |
|
7539 |
||
7540 |
/** |
|
7541 |
* Returns the number of columns in the table. |
|
7542 |
* |
|
7543 |
* @return the number of columns in the table |
|
7544 |
*/ |
|
7545 |
public int getAccessibleColumnCount() { |
|
7546 |
return headerModel.getColumnCount(); |
|
7547 |
} |
|
7548 |
||
7549 |
/** |
|
7550 |
* Returns the Accessible at a specified row and column |
|
7551 |
* in the table. |
|
7552 |
* |
|
7553 |
* @param row zero-based row of the table |
|
7554 |
* @param column zero-based column of the table |
|
7555 |
* @return the Accessible at the specified row and column |
|
7556 |
*/ |
|
7557 |
public Accessible getAccessibleAt(int row, int column) { |
|
7558 |
||
7559 |
||
7560 |
// TIGER - 4715503 |
|
7561 |
TableColumn aColumn = headerModel.getColumn(column); |
|
7562 |
TableCellRenderer renderer = aColumn.getHeaderRenderer(); |
|
7563 |
if (renderer == null) { |
|
7564 |
renderer = header.getDefaultRenderer(); |
|
7565 |
} |
|
7566 |
Component component = renderer.getTableCellRendererComponent( |
|
7567 |
header.getTable(), |
|
7568 |
aColumn.getHeaderValue(), false, false, |
|
7569 |
-1, column); |
|
7570 |
||
7571 |
return new AccessibleJTableHeaderCell(row, column, |
|
7572 |
JTable.this.getTableHeader(), |
|
7573 |
component); |
|
7574 |
} |
|
7575 |
||
7576 |
/** |
|
7577 |
* Returns the number of rows occupied by the Accessible at |
|
7578 |
* a specified row and column in the table. |
|
7579 |
* |
|
7580 |
* @return the number of rows occupied by the Accessible at a |
|
7581 |
* given specified (row, column) |
|
7582 |
*/ |
|
7583 |
public int getAccessibleRowExtentAt(int r, int c) { return 1; } |
|
7584 |
||
7585 |
/** |
|
7586 |
* Returns the number of columns occupied by the Accessible at |
|
7587 |
* a specified row and column in the table. |
|
7588 |
* |
|
7589 |
* @return the number of columns occupied by the Accessible at a |
|
7590 |
* given specified row and column |
|
7591 |
*/ |
|
7592 |
public int getAccessibleColumnExtentAt(int r, int c) { return 1; } |
|
7593 |
||
7594 |
/** |
|
7595 |
* Returns the row headers as an AccessibleTable. |
|
7596 |
* |
|
7597 |
* @return an AccessibleTable representing the row |
|
7598 |
* headers |
|
7599 |
*/ |
|
7600 |
public AccessibleTable getAccessibleRowHeader() { return null; } |
|
7601 |
||
7602 |
/** |
|
7603 |
* Sets the row headers. |
|
7604 |
* |
|
7605 |
* @param table an AccessibleTable representing the |
|
7606 |
* row headers |
|
7607 |
*/ |
|
7608 |
public void setAccessibleRowHeader(AccessibleTable table) {} |
|
7609 |
||
7610 |
/** |
|
7611 |
* Returns the column headers as an AccessibleTable. |
|
7612 |
* |
|
7613 |
* @return an AccessibleTable representing the column |
|
7614 |
* headers |
|
7615 |
*/ |
|
7616 |
public AccessibleTable getAccessibleColumnHeader() { return null; } |
|
7617 |
||
7618 |
/** |
|
7619 |
* Sets the column headers. |
|
7620 |
* |
|
7621 |
* @param table an AccessibleTable representing the |
|
7622 |
* column headers |
|
7623 |
* @since 1.3 |
|
7624 |
*/ |
|
7625 |
public void setAccessibleColumnHeader(AccessibleTable table) {} |
|
7626 |
||
7627 |
/** |
|
7628 |
* Returns the description of the specified row in the table. |
|
7629 |
* |
|
7630 |
* @param r zero-based row of the table |
|
7631 |
* @return the description of the row |
|
7632 |
* @since 1.3 |
|
7633 |
*/ |
|
7634 |
public Accessible getAccessibleRowDescription(int r) { return null; } |
|
7635 |
||
7636 |
/** |
|
7637 |
* Sets the description text of the specified row of the table. |
|
7638 |
* |
|
7639 |
* @param r zero-based row of the table |
|
7640 |
* @param a the description of the row |
|
7641 |
* @since 1.3 |
|
7642 |
*/ |
|
7643 |
public void setAccessibleRowDescription(int r, Accessible a) {} |
|
7644 |
||
7645 |
/** |
|
7646 |
* Returns the description text of the specified column in the table. |
|
7647 |
* |
|
7648 |
* @param c zero-based column of the table |
|
7649 |
* @return the text description of the column |
|
7650 |
* @since 1.3 |
|
7651 |
*/ |
|
7652 |
public Accessible getAccessibleColumnDescription(int c) { return null; } |
|
7653 |
||
7654 |
/** |
|
7655 |
* Sets the description text of the specified column in the table. |
|
7656 |
* |
|
7657 |
* @param c zero-based column of the table |
|
7658 |
* @param a the text description of the column |
|
7659 |
* @since 1.3 |
|
7660 |
*/ |
|
7661 |
public void setAccessibleColumnDescription(int c, Accessible a) {} |
|
7662 |
||
7663 |
/** |
|
7664 |
* Returns a boolean value indicating whether the accessible at |
|
7665 |
* a specified row and column is selected. |
|
7666 |
* |
|
7667 |
* @param r zero-based row of the table |
|
7668 |
* @param c zero-based column of the table |
|
7669 |
* @return the boolean value true if the accessible at the |
|
7670 |
* row and column is selected. Otherwise, the boolean value |
|
7671 |
* false |
|
7672 |
* @since 1.3 |
|
7673 |
*/ |
|
7674 |
public boolean isAccessibleSelected(int r, int c) { return false; } |
|
7675 |
||
7676 |
/** |
|
7677 |
* Returns a boolean value indicating whether the specified row |
|
7678 |
* is selected. |
|
7679 |
* |
|
7680 |
* @param r zero-based row of the table |
|
7681 |
* @return the boolean value true if the specified row is selected. |
|
7682 |
* Otherwise, false. |
|
7683 |
* @since 1.3 |
|
7684 |
*/ |
|
7685 |
public boolean isAccessibleRowSelected(int r) { return false; } |
|
7686 |
||
7687 |
/** |
|
7688 |
* Returns a boolean value indicating whether the specified column |
|
7689 |
* is selected. |
|
7690 |
* |
|
21982 | 7691 |
* @param c zero-based column of the table |
2 | 7692 |
* @return the boolean value true if the specified column is selected. |
7693 |
* Otherwise, false. |
|
7694 |
* @since 1.3 |
|
7695 |
*/ |
|
7696 |
public boolean isAccessibleColumnSelected(int c) { return false; } |
|
7697 |
||
7698 |
/** |
|
7699 |
* Returns the selected rows in a table. |
|
7700 |
* |
|
7701 |
* @return an array of selected rows where each element is a |
|
7702 |
* zero-based row of the table |
|
7703 |
* @since 1.3 |
|
7704 |
*/ |
|
7705 |
public int [] getSelectedAccessibleRows() { return new int[0]; } |
|
7706 |
||
7707 |
/** |
|
7708 |
* Returns the selected columns in a table. |
|
7709 |
* |
|
7710 |
* @return an array of selected columns where each element is a |
|
7711 |
* zero-based column of the table |
|
7712 |
* @since 1.3 |
|
7713 |
*/ |
|
7714 |
public int [] getSelectedAccessibleColumns() { return new int[0]; } |
|
7715 |
} |
|
7716 |
||
7717 |
||
7718 |
/** |
|
7719 |
* Sets the column headers as an <code>AccessibleTable</code>. |
|
7720 |
* |
|
7721 |
* @param a an <code>AccessibleTable</code> representing the |
|
7722 |
* column headers |
|
7723 |
* @since 1.3 |
|
7724 |
*/ |
|
7725 |
public void setAccessibleColumnHeader(AccessibleTable a) { |
|
7726 |
// XXX not implemented |
|
7727 |
} |
|
7728 |
||
7729 |
/** |
|
7730 |
* Returns the description of the specified row in the table. |
|
7731 |
* |
|
7732 |
* @param r zero-based row of the table |
|
7733 |
* @return the description of the row |
|
7734 |
* @since 1.3 |
|
7735 |
*/ |
|
7736 |
public Accessible getAccessibleRowDescription(int r) { |
|
7737 |
if (r < 0 || r >= getAccessibleRowCount()) { |
|
438
2ae294e4518c
6613529: Avoid duplicate object creation within JDK packages
dav
parents:
2
diff
changeset
|
7738 |
throw new IllegalArgumentException(Integer.toString(r)); |
2 | 7739 |
} |
7740 |
if (rowDescription == null) { |
|
7741 |
return null; |
|
7742 |
} else { |
|
7743 |
return rowDescription[r]; |
|
7744 |
} |
|
7745 |
} |
|
7746 |
||
7747 |
/** |
|
7748 |
* Sets the description text of the specified row of the table. |
|
7749 |
* |
|
7750 |
* @param r zero-based row of the table |
|
7751 |
* @param a the description of the row |
|
7752 |
* @since 1.3 |
|
7753 |
*/ |
|
7754 |
public void setAccessibleRowDescription(int r, Accessible a) { |
|
7755 |
if (r < 0 || r >= getAccessibleRowCount()) { |
|
438
2ae294e4518c
6613529: Avoid duplicate object creation within JDK packages
dav
parents:
2
diff
changeset
|
7756 |
throw new IllegalArgumentException(Integer.toString(r)); |
2 | 7757 |
} |
7758 |
if (rowDescription == null) { |
|
7759 |
int numRows = getAccessibleRowCount(); |
|
7760 |
rowDescription = new Accessible[numRows]; |
|
7761 |
} |
|
7762 |
rowDescription[r] = a; |
|
7763 |
} |
|
7764 |
||
7765 |
/** |
|
7766 |
* Returns the description of the specified column in the table. |
|
7767 |
* |
|
7768 |
* @param c zero-based column of the table |
|
7769 |
* @return the description of the column |
|
7770 |
* @since 1.3 |
|
7771 |
*/ |
|
7772 |
public Accessible getAccessibleColumnDescription(int c) { |
|
7773 |
if (c < 0 || c >= getAccessibleColumnCount()) { |
|
438
2ae294e4518c
6613529: Avoid duplicate object creation within JDK packages
dav
parents:
2
diff
changeset
|
7774 |
throw new IllegalArgumentException(Integer.toString(c)); |
2 | 7775 |
} |
7776 |
if (columnDescription == null) { |
|
7777 |
return null; |
|
7778 |
} else { |
|
7779 |
return columnDescription[c]; |
|
7780 |
} |
|
7781 |
} |
|
7782 |
||
7783 |
/** |
|
7784 |
* Sets the description text of the specified column of the table. |
|
7785 |
* |
|
7786 |
* @param c zero-based column of the table |
|
7787 |
* @param a the description of the column |
|
7788 |
* @since 1.3 |
|
7789 |
*/ |
|
7790 |
public void setAccessibleColumnDescription(int c, Accessible a) { |
|
7791 |
if (c < 0 || c >= getAccessibleColumnCount()) { |
|
438
2ae294e4518c
6613529: Avoid duplicate object creation within JDK packages
dav
parents:
2
diff
changeset
|
7792 |
throw new IllegalArgumentException(Integer.toString(c)); |
2 | 7793 |
} |
7794 |
if (columnDescription == null) { |
|
7795 |
int numColumns = getAccessibleColumnCount(); |
|
7796 |
columnDescription = new Accessible[numColumns]; |
|
7797 |
} |
|
7798 |
columnDescription[c] = a; |
|
7799 |
} |
|
7800 |
||
7801 |
/** |
|
7802 |
* Returns a boolean value indicating whether the accessible at a |
|
7803 |
* given (row, column) is selected. |
|
7804 |
* |
|
7805 |
* @param r zero-based row of the table |
|
7806 |
* @param c zero-based column of the table |
|
7807 |
* @return the boolean value true if the accessible at (row, column) |
|
7808 |
* is selected; otherwise, the boolean value false |
|
7809 |
* @since 1.3 |
|
7810 |
*/ |
|
7811 |
public boolean isAccessibleSelected(int r, int c) { |
|
7812 |
return JTable.this.isCellSelected(r, c); |
|
7813 |
} |
|
7814 |
||
7815 |
/** |
|
7816 |
* Returns a boolean value indicating whether the specified row |
|
7817 |
* is selected. |
|
7818 |
* |
|
7819 |
* @param r zero-based row of the table |
|
7820 |
* @return the boolean value true if the specified row is selected; |
|
7821 |
* otherwise, false |
|
7822 |
* @since 1.3 |
|
7823 |
*/ |
|
7824 |
public boolean isAccessibleRowSelected(int r) { |
|
7825 |
return JTable.this.isRowSelected(r); |
|
7826 |
} |
|
7827 |
||
7828 |
/** |
|
7829 |
* Returns a boolean value indicating whether the specified column |
|
7830 |
* is selected. |
|
7831 |
* |
|
7832 |
* @param c zero-based column of the table |
|
7833 |
* @return the boolean value true if the specified column is selected; |
|
7834 |
* otherwise, false |
|
7835 |
* @since 1.3 |
|
7836 |
*/ |
|
7837 |
public boolean isAccessibleColumnSelected(int c) { |
|
7838 |
return JTable.this.isColumnSelected(c); |
|
7839 |
} |
|
7840 |
||
7841 |
/** |
|
7842 |
* Returns the selected rows in a table. |
|
7843 |
* |
|
7844 |
* @return an array of selected rows where each element is a |
|
7845 |
* zero-based row of the table |
|
7846 |
* @since 1.3 |
|
7847 |
*/ |
|
7848 |
public int [] getSelectedAccessibleRows() { |
|
7849 |
return JTable.this.getSelectedRows(); |
|
7850 |
} |
|
7851 |
||
7852 |
/** |
|
7853 |
* Returns the selected columns in a table. |
|
7854 |
* |
|
7855 |
* @return an array of selected columns where each element is a |
|
7856 |
* zero-based column of the table |
|
7857 |
* @since 1.3 |
|
7858 |
*/ |
|
7859 |
public int [] getSelectedAccessibleColumns() { |
|
7860 |
return JTable.this.getSelectedColumns(); |
|
7861 |
} |
|
7862 |
||
7863 |
/** |
|
7864 |
* Returns the row at a given index into the table. |
|
7865 |
* |
|
7866 |
* @param i zero-based index into the table |
|
7867 |
* @return the row at a given index |
|
7868 |
* @since 1.3 |
|
7869 |
*/ |
|
7870 |
public int getAccessibleRowAtIndex(int i) { |
|
7871 |
int columnCount = getAccessibleColumnCount(); |
|
7872 |
if (columnCount == 0) { |
|
7873 |
return -1; |
|
7874 |
} else { |
|
7875 |
return (i / columnCount); |
|
7876 |
} |
|
7877 |
} |
|
7878 |
||
7879 |
/** |
|
7880 |
* Returns the column at a given index into the table. |
|
7881 |
* |
|
7882 |
* @param i zero-based index into the table |
|
7883 |
* @return the column at a given index |
|
7884 |
* @since 1.3 |
|
7885 |
*/ |
|
7886 |
public int getAccessibleColumnAtIndex(int i) { |
|
7887 |
int columnCount = getAccessibleColumnCount(); |
|
7888 |
if (columnCount == 0) { |
|
7889 |
return -1; |
|
7890 |
} else { |
|
7891 |
return (i % columnCount); |
|
7892 |
} |
|
7893 |
} |
|
7894 |
||
7895 |
/** |
|
7896 |
* Returns the index at a given (row, column) in the table. |
|
7897 |
* |
|
7898 |
* @param r zero-based row of the table |
|
7899 |
* @param c zero-based column of the table |
|
7900 |
* @return the index into the table |
|
7901 |
* @since 1.3 |
|
7902 |
*/ |
|
7903 |
public int getAccessibleIndexAt(int r, int c) { |
|
7904 |
return ((r * getAccessibleColumnCount()) + c); |
|
7905 |
} |
|
7906 |
||
7907 |
// end of AccessibleTable implementation -------------------- |
|
7908 |
||
7909 |
/** |
|
7910 |
* The class provides an implementation of the Java Accessibility |
|
7911 |
* API appropriate to table cells. |
|
7912 |
*/ |
|
7913 |
protected class AccessibleJTableCell extends AccessibleContext |
|
7914 |
implements Accessible, AccessibleComponent { |
|
7915 |
||
7916 |
private JTable parent; |
|
7917 |
private int row; |
|
7918 |
private int column; |
|
7919 |
private int index; |
|
7920 |
||
7921 |
/** |
|
7922 |
* Constructs an <code>AccessibleJTableHeaderEntry</code>. |
|
7923 |
* @since 1.4 |
|
7924 |
*/ |
|
7925 |
public AccessibleJTableCell(JTable t, int r, int c, int i) { |
|
7926 |
parent = t; |
|
7927 |
row = r; |
|
7928 |
column = c; |
|
7929 |
index = i; |
|
7930 |
this.setAccessibleParent(parent); |
|
7931 |
} |
|
7932 |
||
7933 |
/** |
|
7934 |
* Gets the <code>AccessibleContext</code> associated with this |
|
7935 |
* component. In the implementation of the Java Accessibility |
|
7936 |
* API for this class, return this object, which is its own |
|
7937 |
* <code>AccessibleContext</code>. |
|
7938 |
* |
|
7939 |
* @return this object |
|
7940 |
*/ |
|
7941 |
public AccessibleContext getAccessibleContext() { |
|
7942 |
return this; |
|
7943 |
} |
|
7944 |
||
7945 |
/** |
|
7946 |
* Gets the AccessibleContext for the table cell renderer. |
|
7947 |
* |
|
7948 |
* @return the <code>AccessibleContext</code> for the table |
|
7949 |
* cell renderer if one exists; |
|
7950 |
* otherwise, returns <code>null</code>. |
|
7951 |
* @since 1.6 |
|
7952 |
*/ |
|
7953 |
protected AccessibleContext getCurrentAccessibleContext() { |
|
7954 |
TableColumn aColumn = getColumnModel().getColumn(column); |
|
7955 |
TableCellRenderer renderer = aColumn.getCellRenderer(); |
|
7956 |
if (renderer == null) { |
|
7957 |
Class<?> columnClass = getColumnClass(column); |
|
7958 |
renderer = getDefaultRenderer(columnClass); |
|
7959 |
} |
|
7960 |
Component component = renderer.getTableCellRendererComponent( |
|
7961 |
JTable.this, getValueAt(row, column), |
|
7962 |
false, false, row, column); |
|
7963 |
if (component instanceof Accessible) { |
|
1301
15e81207e1f2
6727662: Code improvement and warnings removing from swing packages
rupashka
parents:
715
diff
changeset
|
7964 |
return component.getAccessibleContext(); |
2 | 7965 |
} else { |
7966 |
return null; |
|
7967 |
} |
|
7968 |
} |
|
7969 |
||
7970 |
/** |
|
7971 |
* Gets the table cell renderer component. |
|
7972 |
* |
|
7973 |
* @return the table cell renderer component if one exists; |
|
7974 |
* otherwise, returns <code>null</code>. |
|
7975 |
* @since 1.6 |
|
7976 |
*/ |
|
7977 |
protected Component getCurrentComponent() { |
|
7978 |
TableColumn aColumn = getColumnModel().getColumn(column); |
|
7979 |
TableCellRenderer renderer = aColumn.getCellRenderer(); |
|
7980 |
if (renderer == null) { |
|
7981 |
Class<?> columnClass = getColumnClass(column); |
|
7982 |
renderer = getDefaultRenderer(columnClass); |
|
7983 |
} |
|
7984 |
return renderer.getTableCellRendererComponent( |
|
7985 |
JTable.this, null, false, false, |
|
7986 |
row, column); |
|
7987 |
} |
|
7988 |
||
7989 |
// AccessibleContext methods |
|
7990 |
||
7991 |
/** |
|
7992 |
* Gets the accessible name of this object. |
|
7993 |
* |
|
7994 |
* @return the localized name of the object; <code>null</code> |
|
7995 |
* if this object does not have a name |
|
7996 |
*/ |
|
7997 |
public String getAccessibleName() { |
|
7998 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
7999 |
if (ac != null) { |
|
8000 |
String name = ac.getAccessibleName(); |
|
8001 |
if ((name != null) && (name != "")) { |
|
8002 |
// return the cell renderer's AccessibleName |
|
8003 |
return name; |
|
8004 |
} |
|
8005 |
} |
|
8006 |
if ((accessibleName != null) && (accessibleName != "")) { |
|
8007 |
return accessibleName; |
|
8008 |
} else { |
|
8009 |
// fall back to the client property |
|
8010 |
return (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY); |
|
8011 |
} |
|
8012 |
} |
|
8013 |
||
8014 |
/** |
|
8015 |
* Sets the localized accessible name of this object. |
|
8016 |
* |
|
8017 |
* @param s the new localized name of the object |
|
8018 |
*/ |
|
8019 |
public void setAccessibleName(String s) { |
|
8020 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8021 |
if (ac != null) { |
|
8022 |
ac.setAccessibleName(s); |
|
8023 |
} else { |
|
8024 |
super.setAccessibleName(s); |
|
8025 |
} |
|
8026 |
} |
|
8027 |
||
8028 |
// |
|
8029 |
// *** should check toolTip text for desc. (needs MouseEvent) |
|
8030 |
// |
|
8031 |
/** |
|
8032 |
* Gets the accessible description of this object. |
|
8033 |
* |
|
8034 |
* @return the localized description of the object; |
|
8035 |
* <code>null</code> if this object does not have |
|
8036 |
* a description |
|
8037 |
*/ |
|
8038 |
public String getAccessibleDescription() { |
|
8039 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8040 |
if (ac != null) { |
|
8041 |
return ac.getAccessibleDescription(); |
|
8042 |
} else { |
|
8043 |
return super.getAccessibleDescription(); |
|
8044 |
} |
|
8045 |
} |
|
8046 |
||
8047 |
/** |
|
8048 |
* Sets the accessible description of this object. |
|
8049 |
* |
|
8050 |
* @param s the new localized description of the object |
|
8051 |
*/ |
|
8052 |
public void setAccessibleDescription(String s) { |
|
8053 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8054 |
if (ac != null) { |
|
8055 |
ac.setAccessibleDescription(s); |
|
8056 |
} else { |
|
8057 |
super.setAccessibleDescription(s); |
|
8058 |
} |
|
8059 |
} |
|
8060 |
||
8061 |
/** |
|
8062 |
* Gets the role of this object. |
|
8063 |
* |
|
8064 |
* @return an instance of <code>AccessibleRole</code> |
|
8065 |
* describing the role of the object |
|
8066 |
* @see AccessibleRole |
|
8067 |
*/ |
|
8068 |
public AccessibleRole getAccessibleRole() { |
|
8069 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8070 |
if (ac != null) { |
|
8071 |
return ac.getAccessibleRole(); |
|
8072 |
} else { |
|
8073 |
return AccessibleRole.UNKNOWN; |
|
8074 |
} |
|
8075 |
} |
|
8076 |
||
8077 |
/** |
|
8078 |
* Gets the state set of this object. |
|
8079 |
* |
|
8080 |
* @return an instance of <code>AccessibleStateSet</code> |
|
8081 |
* containing the current state set of the object |
|
8082 |
* @see AccessibleState |
|
8083 |
*/ |
|
8084 |
public AccessibleStateSet getAccessibleStateSet() { |
|
8085 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8086 |
AccessibleStateSet as = null; |
|
8087 |
||
8088 |
if (ac != null) { |
|
8089 |
as = ac.getAccessibleStateSet(); |
|
8090 |
} |
|
8091 |
if (as == null) { |
|
8092 |
as = new AccessibleStateSet(); |
|
8093 |
} |
|
8094 |
Rectangle rjt = JTable.this.getVisibleRect(); |
|
8095 |
Rectangle rcell = JTable.this.getCellRect(row, column, false); |
|
8096 |
if (rjt.intersects(rcell)) { |
|
8097 |
as.add(AccessibleState.SHOWING); |
|
8098 |
} else { |
|
8099 |
if (as.contains(AccessibleState.SHOWING)) { |
|
8100 |
as.remove(AccessibleState.SHOWING); |
|
8101 |
} |
|
8102 |
} |
|
8103 |
if (parent.isCellSelected(row, column)) { |
|
8104 |
as.add(AccessibleState.SELECTED); |
|
8105 |
} else if (as.contains(AccessibleState.SELECTED)) { |
|
8106 |
as.remove(AccessibleState.SELECTED); |
|
8107 |
} |
|
8108 |
if ((row == getSelectedRow()) && (column == getSelectedColumn())) { |
|
8109 |
as.add(AccessibleState.ACTIVE); |
|
8110 |
} |
|
8111 |
as.add(AccessibleState.TRANSIENT); |
|
8112 |
return as; |
|
8113 |
} |
|
8114 |
||
8115 |
/** |
|
8116 |
* Gets the <code>Accessible</code> parent of this object. |
|
8117 |
* |
|
8118 |
* @return the Accessible parent of this object; |
|
8119 |
* <code>null</code> if this object does not |
|
8120 |
* have an <code>Accessible</code> parent |
|
8121 |
*/ |
|
8122 |
public Accessible getAccessibleParent() { |
|
8123 |
return parent; |
|
8124 |
} |
|
8125 |
||
8126 |
/** |
|
8127 |
* Gets the index of this object in its accessible parent. |
|
8128 |
* |
|
8129 |
* @return the index of this object in its parent; -1 if this |
|
8130 |
* object does not have an accessible parent |
|
8131 |
* @see #getAccessibleParent |
|
8132 |
*/ |
|
8133 |
public int getAccessibleIndexInParent() { |
|
8134 |
return index; |
|
8135 |
} |
|
8136 |
||
8137 |
/** |
|
8138 |
* Returns the number of accessible children in the object. |
|
8139 |
* |
|
8140 |
* @return the number of accessible children in the object |
|
8141 |
*/ |
|
8142 |
public int getAccessibleChildrenCount() { |
|
8143 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8144 |
if (ac != null) { |
|
8145 |
return ac.getAccessibleChildrenCount(); |
|
8146 |
} else { |
|
8147 |
return 0; |
|
8148 |
} |
|
8149 |
} |
|
8150 |
||
8151 |
/** |
|
8152 |
* Returns the specified <code>Accessible</code> child of the |
|
8153 |
* object. |
|
8154 |
* |
|
8155 |
* @param i zero-based index of child |
|
8156 |
* @return the <code>Accessible</code> child of the object |
|
8157 |
*/ |
|
8158 |
public Accessible getAccessibleChild(int i) { |
|
8159 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8160 |
if (ac != null) { |
|
8161 |
Accessible accessibleChild = ac.getAccessibleChild(i); |
|
8162 |
ac.setAccessibleParent(this); |
|
8163 |
return accessibleChild; |
|
8164 |
} else { |
|
8165 |
return null; |
|
8166 |
} |
|
8167 |
} |
|
8168 |
||
8169 |
/** |
|
8170 |
* Gets the locale of the component. If the component |
|
8171 |
* does not have a locale, then the locale of its parent |
|
8172 |
* is returned. |
|
8173 |
* |
|
8174 |
* @return this component's locale; if this component does |
|
8175 |
* not have a locale, the locale of its parent is returned |
|
8176 |
* @exception IllegalComponentStateException if the |
|
8177 |
* <code>Component</code> does not have its own locale |
|
8178 |
* and has not yet been added to a containment hierarchy |
|
8179 |
* such that the locale can be determined from the |
|
8180 |
* containing parent |
|
8181 |
* @see #setLocale |
|
8182 |
*/ |
|
8183 |
public Locale getLocale() { |
|
8184 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8185 |
if (ac != null) { |
|
8186 |
return ac.getLocale(); |
|
8187 |
} else { |
|
8188 |
return null; |
|
8189 |
} |
|
8190 |
} |
|
8191 |
||
8192 |
/** |
|
8193 |
* Adds a <code>PropertyChangeListener</code> to the listener list. |
|
8194 |
* The listener is registered for all properties. |
|
8195 |
* |
|
8196 |
* @param l the <code>PropertyChangeListener</code> |
|
8197 |
* to be added |
|
8198 |
*/ |
|
8199 |
public void addPropertyChangeListener(PropertyChangeListener l) { |
|
8200 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8201 |
if (ac != null) { |
|
8202 |
ac.addPropertyChangeListener(l); |
|
8203 |
} else { |
|
8204 |
super.addPropertyChangeListener(l); |
|
8205 |
} |
|
8206 |
} |
|
8207 |
||
8208 |
/** |
|
8209 |
* Removes a <code>PropertyChangeListener</code> from the |
|
8210 |
* listener list. This removes a <code>PropertyChangeListener</code> |
|
8211 |
* that was registered for all properties. |
|
8212 |
* |
|
8213 |
* @param l the <code>PropertyChangeListener</code> |
|
8214 |
* to be removed |
|
8215 |
*/ |
|
8216 |
public void removePropertyChangeListener(PropertyChangeListener l) { |
|
8217 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8218 |
if (ac != null) { |
|
8219 |
ac.removePropertyChangeListener(l); |
|
8220 |
} else { |
|
8221 |
super.removePropertyChangeListener(l); |
|
8222 |
} |
|
8223 |
} |
|
8224 |
||
8225 |
/** |
|
8226 |
* Gets the <code>AccessibleAction</code> associated with this |
|
8227 |
* object if one exists. Otherwise returns <code>null</code>. |
|
8228 |
* |
|
8229 |
* @return the <code>AccessibleAction</code>, or <code>null</code> |
|
8230 |
*/ |
|
8231 |
public AccessibleAction getAccessibleAction() { |
|
8232 |
return getCurrentAccessibleContext().getAccessibleAction(); |
|
8233 |
} |
|
8234 |
||
8235 |
/** |
|
8236 |
* Gets the <code>AccessibleComponent</code> associated with |
|
8237 |
* this object if one exists. Otherwise returns <code>null</code>. |
|
8238 |
* |
|
8239 |
* @return the <code>AccessibleComponent</code>, or |
|
8240 |
* <code>null</code> |
|
8241 |
*/ |
|
8242 |
public AccessibleComponent getAccessibleComponent() { |
|
8243 |
return this; // to override getBounds() |
|
8244 |
} |
|
8245 |
||
8246 |
/** |
|
8247 |
* Gets the <code>AccessibleSelection</code> associated with |
|
8248 |
* this object if one exists. Otherwise returns <code>null</code>. |
|
8249 |
* |
|
8250 |
* @return the <code>AccessibleSelection</code>, or |
|
8251 |
* <code>null</code> |
|
8252 |
*/ |
|
8253 |
public AccessibleSelection getAccessibleSelection() { |
|
8254 |
return getCurrentAccessibleContext().getAccessibleSelection(); |
|
8255 |
} |
|
8256 |
||
8257 |
/** |
|
8258 |
* Gets the <code>AccessibleText</code> associated with this |
|
8259 |
* object if one exists. Otherwise returns <code>null</code>. |
|
8260 |
* |
|
8261 |
* @return the <code>AccessibleText</code>, or <code>null</code> |
|
8262 |
*/ |
|
8263 |
public AccessibleText getAccessibleText() { |
|
8264 |
return getCurrentAccessibleContext().getAccessibleText(); |
|
8265 |
} |
|
8266 |
||
8267 |
/** |
|
8268 |
* Gets the <code>AccessibleValue</code> associated with |
|
8269 |
* this object if one exists. Otherwise returns <code>null</code>. |
|
8270 |
* |
|
8271 |
* @return the <code>AccessibleValue</code>, or <code>null</code> |
|
8272 |
*/ |
|
8273 |
public AccessibleValue getAccessibleValue() { |
|
8274 |
return getCurrentAccessibleContext().getAccessibleValue(); |
|
8275 |
} |
|
8276 |
||
8277 |
||
8278 |
// AccessibleComponent methods |
|
8279 |
||
8280 |
/** |
|
8281 |
* Gets the background color of this object. |
|
8282 |
* |
|
8283 |
* @return the background color, if supported, of the object; |
|
8284 |
* otherwise, <code>null</code> |
|
8285 |
*/ |
|
8286 |
public Color getBackground() { |
|
8287 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8288 |
if (ac instanceof AccessibleComponent) { |
|
8289 |
return ((AccessibleComponent) ac).getBackground(); |
|
8290 |
} else { |
|
8291 |
Component c = getCurrentComponent(); |
|
8292 |
if (c != null) { |
|
8293 |
return c.getBackground(); |
|
8294 |
} else { |
|
8295 |
return null; |
|
8296 |
} |
|
8297 |
} |
|
8298 |
} |
|
8299 |
||
8300 |
/** |
|
8301 |
* Sets the background color of this object. |
|
8302 |
* |
|
8303 |
* @param c the new <code>Color</code> for the background |
|
8304 |
*/ |
|
8305 |
public void setBackground(Color c) { |
|
8306 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8307 |
if (ac instanceof AccessibleComponent) { |
|
8308 |
((AccessibleComponent) ac).setBackground(c); |
|
8309 |
} else { |
|
8310 |
Component cp = getCurrentComponent(); |
|
8311 |
if (cp != null) { |
|
8312 |
cp.setBackground(c); |
|
8313 |
} |
|
8314 |
} |
|
8315 |
} |
|
8316 |
||
8317 |
/** |
|
8318 |
* Gets the foreground color of this object. |
|
8319 |
* |
|
8320 |
* @return the foreground color, if supported, of the object; |
|
8321 |
* otherwise, <code>null</code> |
|
8322 |
*/ |
|
8323 |
public Color getForeground() { |
|
8324 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8325 |
if (ac instanceof AccessibleComponent) { |
|
8326 |
return ((AccessibleComponent) ac).getForeground(); |
|
8327 |
} else { |
|
8328 |
Component c = getCurrentComponent(); |
|
8329 |
if (c != null) { |
|
8330 |
return c.getForeground(); |
|
8331 |
} else { |
|
8332 |
return null; |
|
8333 |
} |
|
8334 |
} |
|
8335 |
} |
|
8336 |
||
8337 |
/** |
|
8338 |
* Sets the foreground color of this object. |
|
8339 |
* |
|
8340 |
* @param c the new <code>Color</code> for the foreground |
|
8341 |
*/ |
|
8342 |
public void setForeground(Color c) { |
|
8343 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8344 |
if (ac instanceof AccessibleComponent) { |
|
8345 |
((AccessibleComponent) ac).setForeground(c); |
|
8346 |
} else { |
|
8347 |
Component cp = getCurrentComponent(); |
|
8348 |
if (cp != null) { |
|
8349 |
cp.setForeground(c); |
|
8350 |
} |
|
8351 |
} |
|
8352 |
} |
|
8353 |
||
8354 |
/** |
|
8355 |
* Gets the <code>Cursor</code> of this object. |
|
8356 |
* |
|
8357 |
* @return the <code>Cursor</code>, if supported, |
|
8358 |
* of the object; otherwise, <code>null</code> |
|
8359 |
*/ |
|
8360 |
public Cursor getCursor() { |
|
8361 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8362 |
if (ac instanceof AccessibleComponent) { |
|
8363 |
return ((AccessibleComponent) ac).getCursor(); |
|
8364 |
} else { |
|
8365 |
Component c = getCurrentComponent(); |
|
8366 |
if (c != null) { |
|
8367 |
return c.getCursor(); |
|
8368 |
} else { |
|
8369 |
Accessible ap = getAccessibleParent(); |
|
8370 |
if (ap instanceof AccessibleComponent) { |
|
8371 |
return ((AccessibleComponent) ap).getCursor(); |
|
8372 |
} else { |
|
8373 |
return null; |
|
8374 |
} |
|
8375 |
} |
|
8376 |
} |
|
8377 |
} |
|
8378 |
||
8379 |
/** |
|
8380 |
* Sets the <code>Cursor</code> of this object. |
|
8381 |
* |
|
8382 |
* @param c the new <code>Cursor</code> for the object |
|
8383 |
*/ |
|
8384 |
public void setCursor(Cursor c) { |
|
8385 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8386 |
if (ac instanceof AccessibleComponent) { |
|
8387 |
((AccessibleComponent) ac).setCursor(c); |
|
8388 |
} else { |
|
8389 |
Component cp = getCurrentComponent(); |
|
8390 |
if (cp != null) { |
|
8391 |
cp.setCursor(c); |
|
8392 |
} |
|
8393 |
} |
|
8394 |
} |
|
8395 |
||
8396 |
/** |
|
8397 |
* Gets the <code>Font</code> of this object. |
|
8398 |
* |
|
8399 |
* @return the <code>Font</code>,if supported, |
|
8400 |
* for the object; otherwise, <code>null</code> |
|
8401 |
*/ |
|
8402 |
public Font getFont() { |
|
8403 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8404 |
if (ac instanceof AccessibleComponent) { |
|
8405 |
return ((AccessibleComponent) ac).getFont(); |
|
8406 |
} else { |
|
8407 |
Component c = getCurrentComponent(); |
|
8408 |
if (c != null) { |
|
8409 |
return c.getFont(); |
|
8410 |
} else { |
|
8411 |
return null; |
|
8412 |
} |
|
8413 |
} |
|
8414 |
} |
|
8415 |
||
8416 |
/** |
|
8417 |
* Sets the <code>Font</code> of this object. |
|
8418 |
* |
|
8419 |
* @param f the new <code>Font</code> for the object |
|
8420 |
*/ |
|
8421 |
public void setFont(Font f) { |
|
8422 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8423 |
if (ac instanceof AccessibleComponent) { |
|
8424 |
((AccessibleComponent) ac).setFont(f); |
|
8425 |
} else { |
|
8426 |
Component c = getCurrentComponent(); |
|
8427 |
if (c != null) { |
|
8428 |
c.setFont(f); |
|
8429 |
} |
|
8430 |
} |
|
8431 |
} |
|
8432 |
||
8433 |
/** |
|
8434 |
* Gets the <code>FontMetrics</code> of this object. |
|
8435 |
* |
|
8436 |
* @param f the <code>Font</code> |
|
8437 |
* @return the <code>FontMetrics</code> object, if supported; |
|
8438 |
* otherwise <code>null</code> |
|
8439 |
* @see #getFont |
|
8440 |
*/ |
|
8441 |
public FontMetrics getFontMetrics(Font f) { |
|
8442 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8443 |
if (ac instanceof AccessibleComponent) { |
|
8444 |
return ((AccessibleComponent) ac).getFontMetrics(f); |
|
8445 |
} else { |
|
8446 |
Component c = getCurrentComponent(); |
|
8447 |
if (c != null) { |
|
8448 |
return c.getFontMetrics(f); |
|
8449 |
} else { |
|
8450 |
return null; |
|
8451 |
} |
|
8452 |
} |
|
8453 |
} |
|
8454 |
||
8455 |
/** |
|
8456 |
* Determines if the object is enabled. |
|
8457 |
* |
|
8458 |
* @return true if object is enabled; otherwise, false |
|
8459 |
*/ |
|
8460 |
public boolean isEnabled() { |
|
8461 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8462 |
if (ac instanceof AccessibleComponent) { |
|
8463 |
return ((AccessibleComponent) ac).isEnabled(); |
|
8464 |
} else { |
|
8465 |
Component c = getCurrentComponent(); |
|
8466 |
if (c != null) { |
|
8467 |
return c.isEnabled(); |
|
8468 |
} else { |
|
8469 |
return false; |
|
8470 |
} |
|
8471 |
} |
|
8472 |
} |
|
8473 |
||
8474 |
/** |
|
8475 |
* Sets the enabled state of the object. |
|
8476 |
* |
|
8477 |
* @param b if true, enables this object; otherwise, disables it |
|
8478 |
*/ |
|
8479 |
public void setEnabled(boolean b) { |
|
8480 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8481 |
if (ac instanceof AccessibleComponent) { |
|
8482 |
((AccessibleComponent) ac).setEnabled(b); |
|
8483 |
} else { |
|
8484 |
Component c = getCurrentComponent(); |
|
8485 |
if (c != null) { |
|
8486 |
c.setEnabled(b); |
|
8487 |
} |
|
8488 |
} |
|
8489 |
} |
|
8490 |
||
8491 |
/** |
|
8492 |
* Determines if this object is visible. Note: this means that the |
|
8493 |
* object intends to be visible; however, it may not in fact be |
|
8494 |
* showing on the screen because one of the objects that this object |
|
8495 |
* is contained by is not visible. To determine if an object is |
|
8496 |
* showing on the screen, use <code>isShowing</code>. |
|
8497 |
* |
|
8498 |
* @return true if object is visible; otherwise, false |
|
8499 |
*/ |
|
8500 |
public boolean isVisible() { |
|
8501 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8502 |
if (ac instanceof AccessibleComponent) { |
|
8503 |
return ((AccessibleComponent) ac).isVisible(); |
|
8504 |
} else { |
|
8505 |
Component c = getCurrentComponent(); |
|
8506 |
if (c != null) { |
|
8507 |
return c.isVisible(); |
|
8508 |
} else { |
|
8509 |
return false; |
|
8510 |
} |
|
8511 |
} |
|
8512 |
} |
|
8513 |
||
8514 |
/** |
|
8515 |
* Sets the visible state of the object. |
|
8516 |
* |
|
8517 |
* @param b if true, shows this object; otherwise, hides it |
|
8518 |
*/ |
|
8519 |
public void setVisible(boolean b) { |
|
8520 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8521 |
if (ac instanceof AccessibleComponent) { |
|
8522 |
((AccessibleComponent) ac).setVisible(b); |
|
8523 |
} else { |
|
8524 |
Component c = getCurrentComponent(); |
|
8525 |
if (c != null) { |
|
8526 |
c.setVisible(b); |
|
8527 |
} |
|
8528 |
} |
|
8529 |
} |
|
8530 |
||
8531 |
/** |
|
8532 |
* Determines if the object is showing. This is determined |
|
8533 |
* by checking the visibility of the object and ancestors |
|
8534 |
* of the object. Note: this will return true even if the |
|
8535 |
* object is obscured by another (for example, |
|
8536 |
* it happens to be underneath a menu that was pulled down). |
|
8537 |
* |
|
8538 |
* @return true if the object is showing; otherwise, false |
|
8539 |
*/ |
|
8540 |
public boolean isShowing() { |
|
8541 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8542 |
if (ac instanceof AccessibleComponent) { |
|
8543 |
if (ac.getAccessibleParent() != null) { |
|
8544 |
return ((AccessibleComponent) ac).isShowing(); |
|
8545 |
} else { |
|
8546 |
// Fixes 4529616 - AccessibleJTableCell.isShowing() |
|
8547 |
// returns false when the cell on the screen |
|
8548 |
// if no parent |
|
8549 |
return isVisible(); |
|
8550 |
} |
|
8551 |
} else { |
|
8552 |
Component c = getCurrentComponent(); |
|
8553 |
if (c != null) { |
|
8554 |
return c.isShowing(); |
|
8555 |
} else { |
|
8556 |
return false; |
|
8557 |
} |
|
8558 |
} |
|
8559 |
} |
|
8560 |
||
8561 |
/** |
|
8562 |
* Checks whether the specified point is within this |
|
8563 |
* object's bounds, where the point's x and y coordinates |
|
8564 |
* are defined to be relative to the coordinate system of |
|
8565 |
* the object. |
|
8566 |
* |
|
8567 |
* @param p the <code>Point</code> relative to the |
|
8568 |
* coordinate system of the object |
|
8569 |
* @return true if object contains <code>Point</code>; |
|
8570 |
* otherwise false |
|
8571 |
*/ |
|
8572 |
public boolean contains(Point p) { |
|
8573 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8574 |
if (ac instanceof AccessibleComponent) { |
|
8575 |
Rectangle r = ((AccessibleComponent) ac).getBounds(); |
|
8576 |
return r.contains(p); |
|
8577 |
} else { |
|
8578 |
Component c = getCurrentComponent(); |
|
8579 |
if (c != null) { |
|
8580 |
Rectangle r = c.getBounds(); |
|
8581 |
return r.contains(p); |
|
8582 |
} else { |
|
8583 |
return getBounds().contains(p); |
|
8584 |
} |
|
8585 |
} |
|
8586 |
} |
|
8587 |
||
8588 |
/** |
|
8589 |
* Returns the location of the object on the screen. |
|
8590 |
* |
|
8591 |
* @return location of object on screen -- can be |
|
8592 |
* <code>null</code> if this object is not on the screen |
|
8593 |
*/ |
|
8594 |
public Point getLocationOnScreen() { |
|
13546
8c7270c4ce42
7188612: JTable's AccessibleJTable throws IllegalComponentStateException instead of null
dingxmin
parents:
12524
diff
changeset
|
8595 |
if (parent != null && parent.isShowing()) { |
2 | 8596 |
Point parentLocation = parent.getLocationOnScreen(); |
8597 |
Point componentLocation = getLocation(); |
|
8598 |
componentLocation.translate(parentLocation.x, parentLocation.y); |
|
8599 |
return componentLocation; |
|
8600 |
} else { |
|
8601 |
return null; |
|
8602 |
} |
|
8603 |
} |
|
8604 |
||
8605 |
/** |
|
8606 |
* Gets the location of the object relative to the parent |
|
8607 |
* in the form of a point specifying the object's |
|
8608 |
* top-left corner in the screen's coordinate space. |
|
8609 |
* |
|
8610 |
* @return an instance of <code>Point</code> representing |
|
8611 |
* the top-left corner of the object's bounds in the |
|
8612 |
* coordinate space of the screen; <code>null</code> if |
|
8613 |
* this object or its parent are not on the screen |
|
8614 |
*/ |
|
8615 |
public Point getLocation() { |
|
8616 |
if (parent != null) { |
|
8617 |
Rectangle r = parent.getCellRect(row, column, false); |
|
8618 |
if (r != null) { |
|
8619 |
return r.getLocation(); |
|
8620 |
} |
|
8621 |
} |
|
8622 |
return null; |
|
8623 |
} |
|
8624 |
||
8625 |
/** |
|
8626 |
* Sets the location of the object relative to the parent. |
|
8627 |
*/ |
|
8628 |
public void setLocation(Point p) { |
|
8629 |
// if ((parent != null) && (parent.contains(p))) { |
|
8630 |
// ensureIndexIsVisible(indexInParent); |
|
8631 |
// } |
|
8632 |
} |
|
8633 |
||
8634 |
public Rectangle getBounds() { |
|
8635 |
if (parent != null) { |
|
8636 |
return parent.getCellRect(row, column, false); |
|
8637 |
} else { |
|
8638 |
return null; |
|
8639 |
} |
|
8640 |
} |
|
8641 |
||
8642 |
public void setBounds(Rectangle r) { |
|
8643 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8644 |
if (ac instanceof AccessibleComponent) { |
|
8645 |
((AccessibleComponent) ac).setBounds(r); |
|
8646 |
} else { |
|
8647 |
Component c = getCurrentComponent(); |
|
8648 |
if (c != null) { |
|
8649 |
c.setBounds(r); |
|
8650 |
} |
|
8651 |
} |
|
8652 |
} |
|
8653 |
||
8654 |
public Dimension getSize() { |
|
8655 |
if (parent != null) { |
|
8656 |
Rectangle r = parent.getCellRect(row, column, false); |
|
8657 |
if (r != null) { |
|
8658 |
return r.getSize(); |
|
8659 |
} |
|
8660 |
} |
|
8661 |
return null; |
|
8662 |
} |
|
8663 |
||
8664 |
public void setSize (Dimension d) { |
|
8665 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8666 |
if (ac instanceof AccessibleComponent) { |
|
8667 |
((AccessibleComponent) ac).setSize(d); |
|
8668 |
} else { |
|
8669 |
Component c = getCurrentComponent(); |
|
8670 |
if (c != null) { |
|
8671 |
c.setSize(d); |
|
8672 |
} |
|
8673 |
} |
|
8674 |
} |
|
8675 |
||
8676 |
public Accessible getAccessibleAt(Point p) { |
|
8677 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8678 |
if (ac instanceof AccessibleComponent) { |
|
8679 |
return ((AccessibleComponent) ac).getAccessibleAt(p); |
|
8680 |
} else { |
|
8681 |
return null; |
|
8682 |
} |
|
8683 |
} |
|
8684 |
||
8685 |
public boolean isFocusTraversable() { |
|
8686 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8687 |
if (ac instanceof AccessibleComponent) { |
|
8688 |
return ((AccessibleComponent) ac).isFocusTraversable(); |
|
8689 |
} else { |
|
8690 |
Component c = getCurrentComponent(); |
|
8691 |
if (c != null) { |
|
8692 |
return c.isFocusTraversable(); |
|
8693 |
} else { |
|
8694 |
return false; |
|
8695 |
} |
|
8696 |
} |
|
8697 |
} |
|
8698 |
||
8699 |
public void requestFocus() { |
|
8700 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8701 |
if (ac instanceof AccessibleComponent) { |
|
8702 |
((AccessibleComponent) ac).requestFocus(); |
|
8703 |
} else { |
|
8704 |
Component c = getCurrentComponent(); |
|
8705 |
if (c != null) { |
|
8706 |
c.requestFocus(); |
|
8707 |
} |
|
8708 |
} |
|
8709 |
} |
|
8710 |
||
8711 |
public void addFocusListener(FocusListener l) { |
|
8712 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8713 |
if (ac instanceof AccessibleComponent) { |
|
8714 |
((AccessibleComponent) ac).addFocusListener(l); |
|
8715 |
} else { |
|
8716 |
Component c = getCurrentComponent(); |
|
8717 |
if (c != null) { |
|
8718 |
c.addFocusListener(l); |
|
8719 |
} |
|
8720 |
} |
|
8721 |
} |
|
8722 |
||
8723 |
public void removeFocusListener(FocusListener l) { |
|
8724 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8725 |
if (ac instanceof AccessibleComponent) { |
|
8726 |
((AccessibleComponent) ac).removeFocusListener(l); |
|
8727 |
} else { |
|
8728 |
Component c = getCurrentComponent(); |
|
8729 |
if (c != null) { |
|
8730 |
c.removeFocusListener(l); |
|
8731 |
} |
|
8732 |
} |
|
8733 |
} |
|
8734 |
||
8735 |
} // inner class AccessibleJTableCell |
|
8736 |
||
8737 |
// Begin AccessibleJTableHeader ========== // TIGER - 4715503 |
|
8738 |
||
8739 |
/** |
|
8740 |
* This class implements accessibility for JTable header cells. |
|
8741 |
*/ |
|
8742 |
private class AccessibleJTableHeaderCell extends AccessibleContext |
|
8743 |
implements Accessible, AccessibleComponent { |
|
8744 |
||
8745 |
private int row; |
|
8746 |
private int column; |
|
8747 |
private JTableHeader parent; |
|
8748 |
private Component rendererComponent; |
|
8749 |
||
8750 |
/** |
|
8751 |
* Constructs an <code>AccessibleJTableHeaderEntry</code> instance. |
|
8752 |
* |
|
8753 |
* @param row header cell row index |
|
8754 |
* @param column header cell column index |
|
8755 |
* @param parent header cell parent |
|
8756 |
* @param rendererComponent component that renders the header cell |
|
8757 |
*/ |
|
8758 |
public AccessibleJTableHeaderCell(int row, int column, |
|
8759 |
JTableHeader parent, |
|
8760 |
Component rendererComponent) { |
|
8761 |
this.row = row; |
|
8762 |
this.column = column; |
|
8763 |
this.parent = parent; |
|
8764 |
this.rendererComponent = rendererComponent; |
|
8765 |
this.setAccessibleParent(parent); |
|
8766 |
} |
|
8767 |
||
8768 |
/** |
|
8769 |
* Gets the <code>AccessibleContext</code> associated with this |
|
8770 |
* component. In the implementation of the Java Accessibility |
|
8771 |
* API for this class, return this object, which is its own |
|
8772 |
* <code>AccessibleContext</code>. |
|
8773 |
* |
|
8774 |
* @return this object |
|
8775 |
*/ |
|
8776 |
public AccessibleContext getAccessibleContext() { |
|
8777 |
return this; |
|
8778 |
} |
|
8779 |
||
8780 |
/* |
|
8781 |
* Returns the AccessibleContext for the header cell |
|
8782 |
* renderer. |
|
8783 |
*/ |
|
8784 |
private AccessibleContext getCurrentAccessibleContext() { |
|
8785 |
return rendererComponent.getAccessibleContext(); |
|
8786 |
} |
|
8787 |
||
8788 |
/* |
|
8789 |
* Returns the component that renders the header cell. |
|
8790 |
*/ |
|
8791 |
private Component getCurrentComponent() { |
|
8792 |
return rendererComponent; |
|
8793 |
} |
|
8794 |
||
8795 |
// AccessibleContext methods ========== |
|
8796 |
||
8797 |
/** |
|
8798 |
* Gets the accessible name of this object. |
|
8799 |
* |
|
8800 |
* @return the localized name of the object; <code>null</code> |
|
8801 |
* if this object does not have a name |
|
8802 |
*/ |
|
8803 |
public String getAccessibleName() { |
|
8804 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8805 |
if (ac != null) { |
|
8806 |
String name = ac.getAccessibleName(); |
|
8807 |
if ((name != null) && (name != "")) { |
|
8808 |
return ac.getAccessibleName(); |
|
8809 |
} |
|
8810 |
} |
|
8811 |
if ((accessibleName != null) && (accessibleName != "")) { |
|
8812 |
return accessibleName; |
|
8813 |
} else { |
|
8814 |
return null; |
|
8815 |
} |
|
8816 |
} |
|
8817 |
||
8818 |
/** |
|
8819 |
* Sets the localized accessible name of this object. |
|
8820 |
* |
|
8821 |
* @param s the new localized name of the object |
|
8822 |
*/ |
|
8823 |
public void setAccessibleName(String s) { |
|
8824 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8825 |
if (ac != null) { |
|
8826 |
ac.setAccessibleName(s); |
|
8827 |
} else { |
|
8828 |
super.setAccessibleName(s); |
|
8829 |
} |
|
8830 |
} |
|
8831 |
||
8832 |
/** |
|
8833 |
* Gets the accessible description of this object. |
|
8834 |
* |
|
8835 |
* @return the localized description of the object; |
|
8836 |
* <code>null</code> if this object does not have |
|
8837 |
* a description |
|
8838 |
*/ |
|
8839 |
public String getAccessibleDescription() { |
|
8840 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8841 |
if (ac != null) { |
|
8842 |
return ac.getAccessibleDescription(); |
|
8843 |
} else { |
|
8844 |
return super.getAccessibleDescription(); |
|
8845 |
} |
|
8846 |
} |
|
8847 |
||
8848 |
/** |
|
8849 |
* Sets the accessible description of this object. |
|
8850 |
* |
|
8851 |
* @param s the new localized description of the object |
|
8852 |
*/ |
|
8853 |
public void setAccessibleDescription(String s) { |
|
8854 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8855 |
if (ac != null) { |
|
8856 |
ac.setAccessibleDescription(s); |
|
8857 |
} else { |
|
8858 |
super.setAccessibleDescription(s); |
|
8859 |
} |
|
8860 |
} |
|
8861 |
||
8862 |
/** |
|
8863 |
* Gets the role of this object. |
|
8864 |
* |
|
8865 |
* @return an instance of <code>AccessibleRole</code> |
|
8866 |
* describing the role of the object |
|
8867 |
* @see AccessibleRole |
|
8868 |
*/ |
|
8869 |
public AccessibleRole getAccessibleRole() { |
|
8870 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8871 |
if (ac != null) { |
|
8872 |
return ac.getAccessibleRole(); |
|
8873 |
} else { |
|
8874 |
return AccessibleRole.UNKNOWN; |
|
8875 |
} |
|
8876 |
} |
|
8877 |
||
8878 |
/** |
|
8879 |
* Gets the state set of this object. |
|
8880 |
* |
|
8881 |
* @return an instance of <code>AccessibleStateSet</code> |
|
8882 |
* containing the current state set of the object |
|
8883 |
* @see AccessibleState |
|
8884 |
*/ |
|
8885 |
public AccessibleStateSet getAccessibleStateSet() { |
|
8886 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8887 |
AccessibleStateSet as = null; |
|
8888 |
||
8889 |
if (ac != null) { |
|
8890 |
as = ac.getAccessibleStateSet(); |
|
8891 |
} |
|
8892 |
if (as == null) { |
|
8893 |
as = new AccessibleStateSet(); |
|
8894 |
} |
|
8895 |
Rectangle rjt = JTable.this.getVisibleRect(); |
|
8896 |
Rectangle rcell = JTable.this.getCellRect(row, column, false); |
|
8897 |
if (rjt.intersects(rcell)) { |
|
8898 |
as.add(AccessibleState.SHOWING); |
|
8899 |
} else { |
|
8900 |
if (as.contains(AccessibleState.SHOWING)) { |
|
8901 |
as.remove(AccessibleState.SHOWING); |
|
8902 |
} |
|
8903 |
} |
|
8904 |
if (JTable.this.isCellSelected(row, column)) { |
|
8905 |
as.add(AccessibleState.SELECTED); |
|
8906 |
} else if (as.contains(AccessibleState.SELECTED)) { |
|
8907 |
as.remove(AccessibleState.SELECTED); |
|
8908 |
} |
|
8909 |
if ((row == getSelectedRow()) && (column == getSelectedColumn())) { |
|
8910 |
as.add(AccessibleState.ACTIVE); |
|
8911 |
} |
|
8912 |
as.add(AccessibleState.TRANSIENT); |
|
8913 |
return as; |
|
8914 |
} |
|
8915 |
||
8916 |
/** |
|
8917 |
* Gets the <code>Accessible</code> parent of this object. |
|
8918 |
* |
|
8919 |
* @return the Accessible parent of this object; |
|
8920 |
* <code>null</code> if this object does not |
|
8921 |
* have an <code>Accessible</code> parent |
|
8922 |
*/ |
|
8923 |
public Accessible getAccessibleParent() { |
|
8924 |
return parent; |
|
8925 |
} |
|
8926 |
||
8927 |
/** |
|
8928 |
* Gets the index of this object in its accessible parent. |
|
8929 |
* |
|
8930 |
* @return the index of this object in its parent; -1 if this |
|
8931 |
* object does not have an accessible parent |
|
8932 |
* @see #getAccessibleParent |
|
8933 |
*/ |
|
8934 |
public int getAccessibleIndexInParent() { |
|
8935 |
return column; |
|
8936 |
} |
|
8937 |
||
8938 |
/** |
|
8939 |
* Returns the number of accessible children in the object. |
|
8940 |
* |
|
8941 |
* @return the number of accessible children in the object |
|
8942 |
*/ |
|
8943 |
public int getAccessibleChildrenCount() { |
|
8944 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8945 |
if (ac != null) { |
|
8946 |
return ac.getAccessibleChildrenCount(); |
|
8947 |
} else { |
|
8948 |
return 0; |
|
8949 |
} |
|
8950 |
} |
|
8951 |
||
8952 |
/** |
|
8953 |
* Returns the specified <code>Accessible</code> child of the |
|
8954 |
* object. |
|
8955 |
* |
|
8956 |
* @param i zero-based index of child |
|
8957 |
* @return the <code>Accessible</code> child of the object |
|
8958 |
*/ |
|
8959 |
public Accessible getAccessibleChild(int i) { |
|
8960 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8961 |
if (ac != null) { |
|
8962 |
Accessible accessibleChild = ac.getAccessibleChild(i); |
|
8963 |
ac.setAccessibleParent(this); |
|
8964 |
return accessibleChild; |
|
8965 |
} else { |
|
8966 |
return null; |
|
8967 |
} |
|
8968 |
} |
|
8969 |
||
8970 |
/** |
|
8971 |
* Gets the locale of the component. If the component |
|
8972 |
* does not have a locale, then the locale of its parent |
|
8973 |
* is returned. |
|
8974 |
* |
|
8975 |
* @return this component's locale; if this component does |
|
8976 |
* not have a locale, the locale of its parent is returned |
|
8977 |
* @exception IllegalComponentStateException if the |
|
8978 |
* <code>Component</code> does not have its own locale |
|
8979 |
* and has not yet been added to a containment hierarchy |
|
8980 |
* such that the locale can be determined from the |
|
8981 |
* containing parent |
|
8982 |
* @see #setLocale |
|
8983 |
*/ |
|
8984 |
public Locale getLocale() { |
|
8985 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
8986 |
if (ac != null) { |
|
8987 |
return ac.getLocale(); |
|
8988 |
} else { |
|
8989 |
return null; |
|
8990 |
} |
|
8991 |
} |
|
8992 |
||
8993 |
/** |
|
8994 |
* Adds a <code>PropertyChangeListener</code> to the listener list. |
|
8995 |
* The listener is registered for all properties. |
|
8996 |
* |
|
8997 |
* @param l the <code>PropertyChangeListener</code> |
|
8998 |
* to be added |
|
8999 |
*/ |
|
9000 |
public void addPropertyChangeListener(PropertyChangeListener l) { |
|
9001 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9002 |
if (ac != null) { |
|
9003 |
ac.addPropertyChangeListener(l); |
|
9004 |
} else { |
|
9005 |
super.addPropertyChangeListener(l); |
|
9006 |
} |
|
9007 |
} |
|
9008 |
||
9009 |
/** |
|
9010 |
* Removes a <code>PropertyChangeListener</code> from the |
|
9011 |
* listener list. This removes a <code>PropertyChangeListener</code> |
|
9012 |
* that was registered for all properties. |
|
9013 |
* |
|
9014 |
* @param l the <code>PropertyChangeListener</code> |
|
9015 |
* to be removed |
|
9016 |
*/ |
|
9017 |
public void removePropertyChangeListener(PropertyChangeListener l) { |
|
9018 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9019 |
if (ac != null) { |
|
9020 |
ac.removePropertyChangeListener(l); |
|
9021 |
} else { |
|
9022 |
super.removePropertyChangeListener(l); |
|
9023 |
} |
|
9024 |
} |
|
9025 |
||
9026 |
/** |
|
9027 |
* Gets the <code>AccessibleAction</code> associated with this |
|
9028 |
* object if one exists. Otherwise returns <code>null</code>. |
|
9029 |
* |
|
9030 |
* @return the <code>AccessibleAction</code>, or <code>null</code> |
|
9031 |
*/ |
|
9032 |
public AccessibleAction getAccessibleAction() { |
|
9033 |
return getCurrentAccessibleContext().getAccessibleAction(); |
|
9034 |
} |
|
9035 |
||
9036 |
/** |
|
9037 |
* Gets the <code>AccessibleComponent</code> associated with |
|
9038 |
* this object if one exists. Otherwise returns <code>null</code>. |
|
9039 |
* |
|
9040 |
* @return the <code>AccessibleComponent</code>, or |
|
9041 |
* <code>null</code> |
|
9042 |
*/ |
|
9043 |
public AccessibleComponent getAccessibleComponent() { |
|
9044 |
return this; // to override getBounds() |
|
9045 |
} |
|
9046 |
||
9047 |
/** |
|
9048 |
* Gets the <code>AccessibleSelection</code> associated with |
|
9049 |
* this object if one exists. Otherwise returns <code>null</code>. |
|
9050 |
* |
|
9051 |
* @return the <code>AccessibleSelection</code>, or |
|
9052 |
* <code>null</code> |
|
9053 |
*/ |
|
9054 |
public AccessibleSelection getAccessibleSelection() { |
|
9055 |
return getCurrentAccessibleContext().getAccessibleSelection(); |
|
9056 |
} |
|
9057 |
||
9058 |
/** |
|
9059 |
* Gets the <code>AccessibleText</code> associated with this |
|
9060 |
* object if one exists. Otherwise returns <code>null</code>. |
|
9061 |
* |
|
9062 |
* @return the <code>AccessibleText</code>, or <code>null</code> |
|
9063 |
*/ |
|
9064 |
public AccessibleText getAccessibleText() { |
|
9065 |
return getCurrentAccessibleContext().getAccessibleText(); |
|
9066 |
} |
|
9067 |
||
9068 |
/** |
|
9069 |
* Gets the <code>AccessibleValue</code> associated with |
|
9070 |
* this object if one exists. Otherwise returns <code>null</code>. |
|
9071 |
* |
|
9072 |
* @return the <code>AccessibleValue</code>, or <code>null</code> |
|
9073 |
*/ |
|
9074 |
public AccessibleValue getAccessibleValue() { |
|
9075 |
return getCurrentAccessibleContext().getAccessibleValue(); |
|
9076 |
} |
|
9077 |
||
9078 |
||
9079 |
// AccessibleComponent methods ========== |
|
9080 |
||
9081 |
/** |
|
9082 |
* Gets the background color of this object. |
|
9083 |
* |
|
9084 |
* @return the background color, if supported, of the object; |
|
9085 |
* otherwise, <code>null</code> |
|
9086 |
*/ |
|
9087 |
public Color getBackground() { |
|
9088 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9089 |
if (ac instanceof AccessibleComponent) { |
|
9090 |
return ((AccessibleComponent) ac).getBackground(); |
|
9091 |
} else { |
|
9092 |
Component c = getCurrentComponent(); |
|
9093 |
if (c != null) { |
|
9094 |
return c.getBackground(); |
|
9095 |
} else { |
|
9096 |
return null; |
|
9097 |
} |
|
9098 |
} |
|
9099 |
} |
|
9100 |
||
9101 |
/** |
|
9102 |
* Sets the background color of this object. |
|
9103 |
* |
|
9104 |
* @param c the new <code>Color</code> for the background |
|
9105 |
*/ |
|
9106 |
public void setBackground(Color c) { |
|
9107 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9108 |
if (ac instanceof AccessibleComponent) { |
|
9109 |
((AccessibleComponent) ac).setBackground(c); |
|
9110 |
} else { |
|
9111 |
Component cp = getCurrentComponent(); |
|
9112 |
if (cp != null) { |
|
9113 |
cp.setBackground(c); |
|
9114 |
} |
|
9115 |
} |
|
9116 |
} |
|
9117 |
||
9118 |
/** |
|
9119 |
* Gets the foreground color of this object. |
|
9120 |
* |
|
9121 |
* @return the foreground color, if supported, of the object; |
|
9122 |
* otherwise, <code>null</code> |
|
9123 |
*/ |
|
9124 |
public Color getForeground() { |
|
9125 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9126 |
if (ac instanceof AccessibleComponent) { |
|
9127 |
return ((AccessibleComponent) ac).getForeground(); |
|
9128 |
} else { |
|
9129 |
Component c = getCurrentComponent(); |
|
9130 |
if (c != null) { |
|
9131 |
return c.getForeground(); |
|
9132 |
} else { |
|
9133 |
return null; |
|
9134 |
} |
|
9135 |
} |
|
9136 |
} |
|
9137 |
||
9138 |
/** |
|
9139 |
* Sets the foreground color of this object. |
|
9140 |
* |
|
9141 |
* @param c the new <code>Color</code> for the foreground |
|
9142 |
*/ |
|
9143 |
public void setForeground(Color c) { |
|
9144 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9145 |
if (ac instanceof AccessibleComponent) { |
|
9146 |
((AccessibleComponent) ac).setForeground(c); |
|
9147 |
} else { |
|
9148 |
Component cp = getCurrentComponent(); |
|
9149 |
if (cp != null) { |
|
9150 |
cp.setForeground(c); |
|
9151 |
} |
|
9152 |
} |
|
9153 |
} |
|
9154 |
||
9155 |
/** |
|
9156 |
* Gets the <code>Cursor</code> of this object. |
|
9157 |
* |
|
9158 |
* @return the <code>Cursor</code>, if supported, |
|
9159 |
* of the object; otherwise, <code>null</code> |
|
9160 |
*/ |
|
9161 |
public Cursor getCursor() { |
|
9162 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9163 |
if (ac instanceof AccessibleComponent) { |
|
9164 |
return ((AccessibleComponent) ac).getCursor(); |
|
9165 |
} else { |
|
9166 |
Component c = getCurrentComponent(); |
|
9167 |
if (c != null) { |
|
9168 |
return c.getCursor(); |
|
9169 |
} else { |
|
9170 |
Accessible ap = getAccessibleParent(); |
|
9171 |
if (ap instanceof AccessibleComponent) { |
|
9172 |
return ((AccessibleComponent) ap).getCursor(); |
|
9173 |
} else { |
|
9174 |
return null; |
|
9175 |
} |
|
9176 |
} |
|
9177 |
} |
|
9178 |
} |
|
9179 |
||
9180 |
/** |
|
9181 |
* Sets the <code>Cursor</code> of this object. |
|
9182 |
* |
|
9183 |
* @param c the new <code>Cursor</code> for the object |
|
9184 |
*/ |
|
9185 |
public void setCursor(Cursor c) { |
|
9186 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9187 |
if (ac instanceof AccessibleComponent) { |
|
9188 |
((AccessibleComponent) ac).setCursor(c); |
|
9189 |
} else { |
|
9190 |
Component cp = getCurrentComponent(); |
|
9191 |
if (cp != null) { |
|
9192 |
cp.setCursor(c); |
|
9193 |
} |
|
9194 |
} |
|
9195 |
} |
|
9196 |
||
9197 |
/** |
|
9198 |
* Gets the <code>Font</code> of this object. |
|
9199 |
* |
|
9200 |
* @return the <code>Font</code>,if supported, |
|
9201 |
* for the object; otherwise, <code>null</code> |
|
9202 |
*/ |
|
9203 |
public Font getFont() { |
|
9204 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9205 |
if (ac instanceof AccessibleComponent) { |
|
9206 |
return ((AccessibleComponent) ac).getFont(); |
|
9207 |
} else { |
|
9208 |
Component c = getCurrentComponent(); |
|
9209 |
if (c != null) { |
|
9210 |
return c.getFont(); |
|
9211 |
} else { |
|
9212 |
return null; |
|
9213 |
} |
|
9214 |
} |
|
9215 |
} |
|
9216 |
||
9217 |
/** |
|
9218 |
* Sets the <code>Font</code> of this object. |
|
9219 |
* |
|
9220 |
* @param f the new <code>Font</code> for the object |
|
9221 |
*/ |
|
9222 |
public void setFont(Font f) { |
|
9223 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9224 |
if (ac instanceof AccessibleComponent) { |
|
9225 |
((AccessibleComponent) ac).setFont(f); |
|
9226 |
} else { |
|
9227 |
Component c = getCurrentComponent(); |
|
9228 |
if (c != null) { |
|
9229 |
c.setFont(f); |
|
9230 |
} |
|
9231 |
} |
|
9232 |
} |
|
9233 |
||
9234 |
/** |
|
9235 |
* Gets the <code>FontMetrics</code> of this object. |
|
9236 |
* |
|
9237 |
* @param f the <code>Font</code> |
|
9238 |
* @return the <code>FontMetrics</code> object, if supported; |
|
9239 |
* otherwise <code>null</code> |
|
9240 |
* @see #getFont |
|
9241 |
*/ |
|
9242 |
public FontMetrics getFontMetrics(Font f) { |
|
9243 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9244 |
if (ac instanceof AccessibleComponent) { |
|
9245 |
return ((AccessibleComponent) ac).getFontMetrics(f); |
|
9246 |
} else { |
|
9247 |
Component c = getCurrentComponent(); |
|
9248 |
if (c != null) { |
|
9249 |
return c.getFontMetrics(f); |
|
9250 |
} else { |
|
9251 |
return null; |
|
9252 |
} |
|
9253 |
} |
|
9254 |
} |
|
9255 |
||
9256 |
/** |
|
9257 |
* Determines if the object is enabled. |
|
9258 |
* |
|
9259 |
* @return true if object is enabled; otherwise, false |
|
9260 |
*/ |
|
9261 |
public boolean isEnabled() { |
|
9262 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9263 |
if (ac instanceof AccessibleComponent) { |
|
9264 |
return ((AccessibleComponent) ac).isEnabled(); |
|
9265 |
} else { |
|
9266 |
Component c = getCurrentComponent(); |
|
9267 |
if (c != null) { |
|
9268 |
return c.isEnabled(); |
|
9269 |
} else { |
|
9270 |
return false; |
|
9271 |
} |
|
9272 |
} |
|
9273 |
} |
|
9274 |
||
9275 |
/** |
|
9276 |
* Sets the enabled state of the object. |
|
9277 |
* |
|
9278 |
* @param b if true, enables this object; otherwise, disables it |
|
9279 |
*/ |
|
9280 |
public void setEnabled(boolean b) { |
|
9281 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9282 |
if (ac instanceof AccessibleComponent) { |
|
9283 |
((AccessibleComponent) ac).setEnabled(b); |
|
9284 |
} else { |
|
9285 |
Component c = getCurrentComponent(); |
|
9286 |
if (c != null) { |
|
9287 |
c.setEnabled(b); |
|
9288 |
} |
|
9289 |
} |
|
9290 |
} |
|
9291 |
||
9292 |
/** |
|
9293 |
* Determines if this object is visible. Note: this means that the |
|
9294 |
* object intends to be visible; however, it may not in fact be |
|
9295 |
* showing on the screen because one of the objects that this object |
|
9296 |
* is contained by is not visible. To determine if an object is |
|
9297 |
* showing on the screen, use <code>isShowing</code>. |
|
9298 |
* |
|
9299 |
* @return true if object is visible; otherwise, false |
|
9300 |
*/ |
|
9301 |
public boolean isVisible() { |
|
9302 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9303 |
if (ac instanceof AccessibleComponent) { |
|
9304 |
return ((AccessibleComponent) ac).isVisible(); |
|
9305 |
} else { |
|
9306 |
Component c = getCurrentComponent(); |
|
9307 |
if (c != null) { |
|
9308 |
return c.isVisible(); |
|
9309 |
} else { |
|
9310 |
return false; |
|
9311 |
} |
|
9312 |
} |
|
9313 |
} |
|
9314 |
||
9315 |
/** |
|
9316 |
* Sets the visible state of the object. |
|
9317 |
* |
|
9318 |
* @param b if true, shows this object; otherwise, hides it |
|
9319 |
*/ |
|
9320 |
public void setVisible(boolean b) { |
|
9321 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9322 |
if (ac instanceof AccessibleComponent) { |
|
9323 |
((AccessibleComponent) ac).setVisible(b); |
|
9324 |
} else { |
|
9325 |
Component c = getCurrentComponent(); |
|
9326 |
if (c != null) { |
|
9327 |
c.setVisible(b); |
|
9328 |
} |
|
9329 |
} |
|
9330 |
} |
|
9331 |
||
9332 |
/** |
|
9333 |
* Determines if the object is showing. This is determined |
|
9334 |
* by checking the visibility of the object and ancestors |
|
9335 |
* of the object. Note: this will return true even if the |
|
9336 |
* object is obscured by another (for example, |
|
9337 |
* it happens to be underneath a menu that was pulled down). |
|
9338 |
* |
|
9339 |
* @return true if the object is showing; otherwise, false |
|
9340 |
*/ |
|
9341 |
public boolean isShowing() { |
|
9342 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9343 |
if (ac instanceof AccessibleComponent) { |
|
9344 |
if (ac.getAccessibleParent() != null) { |
|
9345 |
return ((AccessibleComponent) ac).isShowing(); |
|
9346 |
} else { |
|
9347 |
// Fixes 4529616 - AccessibleJTableCell.isShowing() |
|
9348 |
// returns false when the cell on the screen |
|
9349 |
// if no parent |
|
9350 |
return isVisible(); |
|
9351 |
} |
|
9352 |
} else { |
|
9353 |
Component c = getCurrentComponent(); |
|
9354 |
if (c != null) { |
|
9355 |
return c.isShowing(); |
|
9356 |
} else { |
|
9357 |
return false; |
|
9358 |
} |
|
9359 |
} |
|
9360 |
} |
|
9361 |
||
9362 |
/** |
|
9363 |
* Checks whether the specified point is within this |
|
9364 |
* object's bounds, where the point's x and y coordinates |
|
9365 |
* are defined to be relative to the coordinate system of |
|
9366 |
* the object. |
|
9367 |
* |
|
9368 |
* @param p the <code>Point</code> relative to the |
|
9369 |
* coordinate system of the object |
|
9370 |
* @return true if object contains <code>Point</code>; |
|
9371 |
* otherwise false |
|
9372 |
*/ |
|
9373 |
public boolean contains(Point p) { |
|
9374 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9375 |
if (ac instanceof AccessibleComponent) { |
|
9376 |
Rectangle r = ((AccessibleComponent) ac).getBounds(); |
|
9377 |
return r.contains(p); |
|
9378 |
} else { |
|
9379 |
Component c = getCurrentComponent(); |
|
9380 |
if (c != null) { |
|
9381 |
Rectangle r = c.getBounds(); |
|
9382 |
return r.contains(p); |
|
9383 |
} else { |
|
9384 |
return getBounds().contains(p); |
|
9385 |
} |
|
9386 |
} |
|
9387 |
} |
|
9388 |
||
9389 |
/** |
|
9390 |
* Returns the location of the object on the screen. |
|
9391 |
* |
|
9392 |
* @return location of object on screen -- can be |
|
9393 |
* <code>null</code> if this object is not on the screen |
|
9394 |
*/ |
|
9395 |
public Point getLocationOnScreen() { |
|
13546
8c7270c4ce42
7188612: JTable's AccessibleJTable throws IllegalComponentStateException instead of null
dingxmin
parents:
12524
diff
changeset
|
9396 |
if (parent != null && parent.isShowing()) { |
2 | 9397 |
Point parentLocation = parent.getLocationOnScreen(); |
9398 |
Point componentLocation = getLocation(); |
|
9399 |
componentLocation.translate(parentLocation.x, parentLocation.y); |
|
9400 |
return componentLocation; |
|
9401 |
} else { |
|
9402 |
return null; |
|
9403 |
} |
|
9404 |
} |
|
9405 |
||
9406 |
/** |
|
9407 |
* Gets the location of the object relative to the parent |
|
9408 |
* in the form of a point specifying the object's |
|
9409 |
* top-left corner in the screen's coordinate space. |
|
9410 |
* |
|
9411 |
* @return an instance of <code>Point</code> representing |
|
9412 |
* the top-left corner of the object's bounds in the |
|
9413 |
* coordinate space of the screen; <code>null</code> if |
|
9414 |
* this object or its parent are not on the screen |
|
9415 |
*/ |
|
9416 |
public Point getLocation() { |
|
9417 |
if (parent != null) { |
|
9418 |
Rectangle r = parent.getHeaderRect(column); |
|
9419 |
if (r != null) { |
|
9420 |
return r.getLocation(); |
|
9421 |
} |
|
9422 |
} |
|
9423 |
return null; |
|
9424 |
} |
|
9425 |
||
9426 |
/** |
|
9427 |
* Sets the location of the object relative to the parent. |
|
9428 |
* @param p the new position for the top-left corner |
|
9429 |
* @see #getLocation |
|
9430 |
*/ |
|
9431 |
public void setLocation(Point p) { |
|
9432 |
} |
|
9433 |
||
9434 |
/** |
|
9435 |
* Gets the bounds of this object in the form of a Rectangle object. |
|
9436 |
* The bounds specify this object's width, height, and location |
|
9437 |
* relative to its parent. |
|
9438 |
* |
|
9439 |
* @return A rectangle indicating this component's bounds; null if |
|
9440 |
* this object is not on the screen. |
|
9441 |
* @see #contains |
|
9442 |
*/ |
|
9443 |
public Rectangle getBounds() { |
|
9444 |
if (parent != null) { |
|
9445 |
return parent.getHeaderRect(column); |
|
9446 |
} else { |
|
9447 |
return null; |
|
9448 |
} |
|
9449 |
} |
|
9450 |
||
9451 |
/** |
|
9452 |
* Sets the bounds of this object in the form of a Rectangle object. |
|
9453 |
* The bounds specify this object's width, height, and location |
|
9454 |
* relative to its parent. |
|
9455 |
* |
|
9456 |
* @param r rectangle indicating this component's bounds |
|
9457 |
* @see #getBounds |
|
9458 |
*/ |
|
9459 |
public void setBounds(Rectangle r) { |
|
9460 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9461 |
if (ac instanceof AccessibleComponent) { |
|
9462 |
((AccessibleComponent) ac).setBounds(r); |
|
9463 |
} else { |
|
9464 |
Component c = getCurrentComponent(); |
|
9465 |
if (c != null) { |
|
9466 |
c.setBounds(r); |
|
9467 |
} |
|
9468 |
} |
|
9469 |
} |
|
9470 |
||
9471 |
/** |
|
9472 |
* Returns the size of this object in the form of a Dimension object. |
|
9473 |
* The height field of the Dimension object contains this object's |
|
9474 |
* height, and the width field of the Dimension object contains this |
|
9475 |
* object's width. |
|
9476 |
* |
|
9477 |
* @return A Dimension object that indicates the size of this component; |
|
9478 |
* null if this object is not on the screen |
|
9479 |
* @see #setSize |
|
9480 |
*/ |
|
9481 |
public Dimension getSize() { |
|
9482 |
if (parent != null) { |
|
9483 |
Rectangle r = parent.getHeaderRect(column); |
|
9484 |
if (r != null) { |
|
9485 |
return r.getSize(); |
|
9486 |
} |
|
9487 |
} |
|
9488 |
return null; |
|
9489 |
} |
|
9490 |
||
9491 |
/** |
|
9492 |
* Resizes this object so that it has width and height. |
|
9493 |
* |
|
9494 |
* @param d The dimension specifying the new size of the object. |
|
9495 |
* @see #getSize |
|
9496 |
*/ |
|
9497 |
public void setSize (Dimension d) { |
|
9498 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9499 |
if (ac instanceof AccessibleComponent) { |
|
9500 |
((AccessibleComponent) ac).setSize(d); |
|
9501 |
} else { |
|
9502 |
Component c = getCurrentComponent(); |
|
9503 |
if (c != null) { |
|
9504 |
c.setSize(d); |
|
9505 |
} |
|
9506 |
} |
|
9507 |
} |
|
9508 |
||
9509 |
/** |
|
9510 |
* Returns the Accessible child, if one exists, contained at the local |
|
9511 |
* coordinate Point. |
|
9512 |
* |
|
9513 |
* @param p The point relative to the coordinate system of this object. |
|
9514 |
* @return the Accessible, if it exists, at the specified location; |
|
9515 |
* otherwise null |
|
9516 |
*/ |
|
9517 |
public Accessible getAccessibleAt(Point p) { |
|
9518 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9519 |
if (ac instanceof AccessibleComponent) { |
|
9520 |
return ((AccessibleComponent) ac).getAccessibleAt(p); |
|
9521 |
} else { |
|
9522 |
return null; |
|
9523 |
} |
|
9524 |
} |
|
9525 |
||
9526 |
/** |
|
9527 |
* Returns whether this object can accept focus or not. Objects that |
|
9528 |
* can accept focus will also have the AccessibleState.FOCUSABLE state |
|
9529 |
* set in their AccessibleStateSets. |
|
9530 |
* |
|
9531 |
* @return true if object can accept focus; otherwise false |
|
9532 |
* @see AccessibleContext#getAccessibleStateSet |
|
9533 |
* @see AccessibleState#FOCUSABLE |
|
9534 |
* @see AccessibleState#FOCUSED |
|
9535 |
* @see AccessibleStateSet |
|
9536 |
*/ |
|
9537 |
public boolean isFocusTraversable() { |
|
9538 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9539 |
if (ac instanceof AccessibleComponent) { |
|
9540 |
return ((AccessibleComponent) ac).isFocusTraversable(); |
|
9541 |
} else { |
|
9542 |
Component c = getCurrentComponent(); |
|
9543 |
if (c != null) { |
|
9544 |
return c.isFocusTraversable(); |
|
9545 |
} else { |
|
9546 |
return false; |
|
9547 |
} |
|
9548 |
} |
|
9549 |
} |
|
9550 |
||
9551 |
/** |
|
9552 |
* Requests focus for this object. If this object cannot accept focus, |
|
9553 |
* nothing will happen. Otherwise, the object will attempt to take |
|
9554 |
* focus. |
|
9555 |
* @see #isFocusTraversable |
|
9556 |
*/ |
|
9557 |
public void requestFocus() { |
|
9558 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9559 |
if (ac instanceof AccessibleComponent) { |
|
9560 |
((AccessibleComponent) ac).requestFocus(); |
|
9561 |
} else { |
|
9562 |
Component c = getCurrentComponent(); |
|
9563 |
if (c != null) { |
|
9564 |
c.requestFocus(); |
|
9565 |
} |
|
9566 |
} |
|
9567 |
} |
|
9568 |
||
9569 |
/** |
|
9570 |
* Adds the specified focus listener to receive focus events from this |
|
9571 |
* component. |
|
9572 |
* |
|
9573 |
* @param l the focus listener |
|
9574 |
* @see #removeFocusListener |
|
9575 |
*/ |
|
9576 |
public void addFocusListener(FocusListener l) { |
|
9577 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9578 |
if (ac instanceof AccessibleComponent) { |
|
9579 |
((AccessibleComponent) ac).addFocusListener(l); |
|
9580 |
} else { |
|
9581 |
Component c = getCurrentComponent(); |
|
9582 |
if (c != null) { |
|
9583 |
c.addFocusListener(l); |
|
9584 |
} |
|
9585 |
} |
|
9586 |
} |
|
9587 |
||
9588 |
/** |
|
9589 |
* Removes the specified focus listener so it no longer receives focus |
|
9590 |
* events from this component. |
|
9591 |
* |
|
9592 |
* @param l the focus listener |
|
9593 |
* @see #addFocusListener |
|
9594 |
*/ |
|
9595 |
public void removeFocusListener(FocusListener l) { |
|
9596 |
AccessibleContext ac = getCurrentAccessibleContext(); |
|
9597 |
if (ac instanceof AccessibleComponent) { |
|
9598 |
((AccessibleComponent) ac).removeFocusListener(l); |
|
9599 |
} else { |
|
9600 |
Component c = getCurrentComponent(); |
|
9601 |
if (c != null) { |
|
9602 |
c.removeFocusListener(l); |
|
9603 |
} |
|
9604 |
} |
|
9605 |
} |
|
9606 |
||
9607 |
} // inner class AccessibleJTableHeaderCell |
|
9608 |
||
9609 |
} // inner class AccessibleJTable |
|
9610 |
||
9611 |
} // End of Class JTable |