1 /*
2 * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
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
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
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 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package javax.swing.table;
27
28 import javax.swing;
29 import javax.swing.table.TableCellRenderer;
30 import javax.swing.border;
31
32 import java.awt.Component;
33 import java.awt.Color;
34 import java.awt.Rectangle;
35
36 import java.io.Serializable;
37
38
39 /**
40 * The standard class for rendering (displaying) individual cells
41 * in a <code>JTable</code>.
42 * <p>
43 *
44 * <strong><a name="override">Implementation Note:</a></strong>
45 * This class inherits from <code>JLabel</code>, a standard component class.
46 * However <code>JTable</code> employs a unique mechanism for rendering
47 * its cells and therefore requires some slightly modified behavior
48 * from its cell renderer.
49 * The table class defines a single cell renderer and uses it as a
50 * as a rubber-stamp for rendering all cells in the table;
51 * it renders the first cell,
52 * changes the contents of that cell renderer,
53 * shifts the origin to the new location, re-draws it, and so on.
54 * The standard <code>JLabel</code> component was not
55 * designed to be used this way and we want to avoid
56 * triggering a <code>revalidate</code> each time the
57 * cell is drawn. This would greatly decrease performance because the
58 * <code>revalidate</code> message would be
59 * passed up the hierarchy of the container to determine whether any other
60 * components would be affected.
61 * As the renderer is only parented for the lifetime of a painting operation
62 * we similarly want to avoid the overhead associated with walking the
63 * hierarchy for painting operations.
64 * So this class
65 * overrides the <code>validate</code>, <code>invalidate</code>,
66 * <code>revalidate</code>, <code>repaint</code>, and
67 * <code>firePropertyChange</code> methods to be
68 * no-ops and override the <code>isOpaque</code> method solely to improve
69 * performance. If you write your own renderer,
70 * please keep this performance consideration in mind.
71 * <p>
72 *
73 * <strong>Warning:</strong>
74 * Serialized objects of this class will not be compatible with
75 * future Swing releases. The current serialization support is
76 * appropriate for short term storage or RMI between applications running
77 * the same version of Swing. As of 1.4, support for long term storage
78 * of all JavaBeans<sup><font size="-2">TM</font></sup>
79 * has been added to the <code>java.beans</code> package.
80 * Please see {@link java.beans.XMLEncoder}.
81 *
82 * @author Philip Milne
83 * @see JTable
84 */
85 public class DefaultTableCellRenderer extends JLabel
86 implements TableCellRenderer, Serializable
87 {
88
89 /**
90 * An empty <code>Border</code>. This field might not be used. To change the
91 * <code>Border</code> used by this renderer override the
92 * <code>getTableCellRendererComponent</code> method and set the border
93 * of the returned component directly.
94 */
95 protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
96 private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1);
97
98 // We need a place to store the color the JLabel should be returned
99 // to after its foreground and background colors have been set
100 // to the selection background color.
101 // These ivars will be made protected when their names are finalized.
102 private Color unselectedForeground;
103 private Color unselectedBackground;
104
105 /**
106 * Creates a default table cell renderer.
107 */
108 public DefaultTableCellRenderer() {
109 super();
110 setOpaque(true);
111 setBorder(getNoFocusBorder());
112 }
113
114 private static Border getNoFocusBorder() {
115 if (System.getSecurityManager() != null) {
116 return SAFE_NO_FOCUS_BORDER;
117 } else {
118 return noFocusBorder;
119 }
120 }
121
122 /**
123 * Overrides <code>JComponent.setForeground</code> to assign
124 * the unselected-foreground color to the specified color.
125 *
126 * @param c set the foreground color to this value
127 */
128 public void setForeground(Color c) {
129 super.setForeground(c);
130 unselectedForeground = c;
131 }
132
133 /**
134 * Overrides <code>JComponent.setBackground</code> to assign
135 * the unselected-background color to the specified color.
136 *
137 * @param c set the background color to this value
138 */
139 public void setBackground(Color c) {
140 super.setBackground(c);
141 unselectedBackground = c;
142 }
143
144 /**
145 * Notification from the <code>UIManager</code> that the look and feel
146 * [L&F] has changed.
147 * Replaces the current UI object with the latest version from the
148 * <code>UIManager</code>.
149 *
150 * @see JComponent#updateUI
151 */
152 public void updateUI() {
153 super.updateUI();
154 setForeground(null);
155 setBackground(null);
156 }
157
158 // implements javax.swing.table.TableCellRenderer
159 /**
160 *
161 * Returns the default table cell renderer.
162 * <p>
163 * During a printing operation, this method will be called with
164 * <code>isSelected</code> and <code>hasFocus</code> values of
165 * <code>false</code> to prevent selection and focus from appearing
166 * in the printed output. To do other customization based on whether
167 * or not the table is being printed, check the return value from
168 * {@link javax.swing.JComponent#isPaintingForPrint()}.
169 *
170 * @param table the <code>JTable</code>
171 * @param value the value to assign to the cell at
172 * <code>[row, column]</code>
173 * @param isSelected true if cell is selected
174 * @param hasFocus true if cell has focus
175 * @param row the row of the cell to render
176 * @param column the column of the cell to render
177 * @return the default table cell renderer
178 * @see javax.swing.JComponent#isPaintingForPrint()
179 */
180 public Component getTableCellRendererComponent(JTable table, Object value,
181 boolean isSelected, boolean hasFocus, int row, int column) {
182
183 Color fg = null;
184 Color bg = null;
185
186 JTable.DropLocation dropLocation = table.getDropLocation();
187 if (dropLocation != null
188 && !dropLocation.isInsertRow()
189 && !dropLocation.isInsertColumn()
190 && dropLocation.getRow() == row
191 && dropLocation.getColumn() == column) {
192
193 fg = UIManager.getColor("Table.dropCellForeground");
194 bg = UIManager.getColor("Table.dropCellBackground");
195
196 isSelected = true;
197 }
198
199 if (isSelected) {
200 super.setForeground(fg == null ? table.getSelectionForeground()
201 : fg);
202 super.setBackground(bg == null ? table.getSelectionBackground()
203 : bg);
204 } else {
205 super.setForeground(unselectedForeground != null
206 ? unselectedForeground
207 : table.getForeground());
208 super.setBackground(unselectedBackground != null
209 ? unselectedBackground
210 : table.getBackground());
211 }
212
213 setFont(table.getFont());
214
215 if (hasFocus) {
216 Border border = null;
217 if (isSelected) {
218 border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder");
219 }
220 if (border == null) {
221 border = UIManager.getBorder("Table.focusCellHighlightBorder");
222 }
223 setBorder(border);
224
225 if (!isSelected && table.isCellEditable(row, column)) {
226 Color col;
227 col = UIManager.getColor("Table.focusCellForeground");
228 if (col != null) {
229 super.setForeground(col);
230 }
231 col = UIManager.getColor("Table.focusCellBackground");
232 if (col != null) {
233 super.setBackground(col);
234 }
235 }
236 } else {
237 setBorder(getNoFocusBorder());
238 }
239
240 setValue(value);
241
242 return this;
243 }
244
245 /*
246 * The following methods are overridden as a performance measure to
247 * to prune code-paths are often called in the case of renders
248 * but which we know are unnecessary. Great care should be taken
249 * when writing your own renderer to weigh the benefits and
250 * drawbacks of overriding methods like these.
251 */
252
253 /**
254 * Overridden for performance reasons.
255 * See the <a href="#override">Implementation Note</a>
256 * for more information.
257 */
258 public boolean isOpaque() {
259 Color back = getBackground();
260 Component p = getParent();
261 if (p != null) {
262 p = p.getParent();
263 }
264 // p should now be the JTable.
265 boolean colorMatch = (back != null) && (p != null) &&
266 back.equals(p.getBackground()) &&
267 p.isOpaque();
268 return !colorMatch && super.isOpaque();
269 }
270
271 /**
272 * Overridden for performance reasons.
273 * See the <a href="#override">Implementation Note</a>
274 * for more information.
275 *
276 * @since 1.5
277 */
278 public void invalidate() {}
279
280 /**
281 * Overridden for performance reasons.
282 * See the <a href="#override">Implementation Note</a>
283 * for more information.
284 */
285 public void validate() {}
286
287 /**
288 * Overridden for performance reasons.
289 * See the <a href="#override">Implementation Note</a>
290 * for more information.
291 */
292 public void revalidate() {}
293
294 /**
295 * Overridden for performance reasons.
296 * See the <a href="#override">Implementation Note</a>
297 * for more information.
298 */
299 public void repaint(long tm, int x, int y, int width, int height) {}
300
301 /**
302 * Overridden for performance reasons.
303 * See the <a href="#override">Implementation Note</a>
304 * for more information.
305 */
306 public void repaint(Rectangle r) { }
307
308 /**
309 * Overridden for performance reasons.
310 * See the <a href="#override">Implementation Note</a>
311 * for more information.
312 *
313 * @since 1.5
314 */
315 public void repaint() {
316 }
317
318 /**
319 * Overridden for performance reasons.
320 * See the <a href="#override">Implementation Note</a>
321 * for more information.
322 */
323 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
324 // Strings get interned...
325 if (propertyName=="text"
326 || propertyName == "labelFor"
327 || propertyName == "displayedMnemonic"
328 || ((propertyName == "font" || propertyName == "foreground")
329 && oldValue != newValue
330 && getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey) != null)) {
331
332 super.firePropertyChange(propertyName, oldValue, newValue);
333 }
334 }
335
336 /**
337 * Overridden for performance reasons.
338 * See the <a href="#override">Implementation Note</a>
339 * for more information.
340 */
341 public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { }
342
343
344 /**
345 * Sets the <code>String</code> object for the cell being rendered to
346 * <code>value</code>.
347 *
348 * @param value the string value for this cell; if value is
349 * <code>null</code> it sets the text value to an empty string
350 * @see JLabel#setText
351 *
352 */
353 protected void setValue(Object value) {
354 setText((value == null) ? "" : value.toString());
355 }
356
357
358 /**
359 * A subclass of <code>DefaultTableCellRenderer</code> that
360 * implements <code>UIResource</code>.
361 * <code>DefaultTableCellRenderer</code> doesn't implement
362 * <code>UIResource</code>
363 * directly so that applications can safely override the
364 * <code>cellRenderer</code> property with
365 * <code>DefaultTableCellRenderer</code> subclasses.
366 * <p>
367 * <strong>Warning:</strong>
368 * Serialized objects of this class will not be compatible with
369 * future Swing releases. The current serialization support is
370 * appropriate for short term storage or RMI between applications running
371 * the same version of Swing. As of 1.4, support for long term storage
372 * of all JavaBeans<sup><font size="-2">TM</font></sup>
373 * has been added to the <code>java.beans</code> package.
374 * Please see {@link java.beans.XMLEncoder}.
375 */
376 public static class UIResource extends DefaultTableCellRenderer
377 implements javax.swing.plaf.UIResource
378 {
379 }
380
381 }