1 /* 2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 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. 24 */ 25 26 package javax.swing.table; 27 28 import javax.swing.*; 29 import javax.swing.border.*; 30 31 import java.awt.Component; 32 import java.awt.Color; 33 import java.awt.Rectangle; 34 35 import java.io.Serializable; 36 import sun.swing.DefaultLookup; 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™ 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 private static final Border SAFE_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); 96 private static final Border DEFAULT_NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); 97 protected static Border noFocusBorder = DEFAULT_NO_FOCUS_BORDER; 98 99 // We need a place to store the color the JLabel should be returned 100 // to after its foreground and background colors have been set 101 // to the selection background color. 102 // These ivars will be made protected when their names are finalized. 103 private Color unselectedForeground; 104 private Color unselectedBackground; 105 106 /** 107 * Creates a default table cell renderer. 108 */ 109 public DefaultTableCellRenderer() { 110 super(); 111 setOpaque(true); 112 setBorder(getNoFocusBorder()); 113 setName("Table.cellRenderer"); 114 } 115 116 private Border getNoFocusBorder() { 117 Border border = DefaultLookup.getBorder(this, ui, "Table.cellNoFocusBorder"); 118 if (System.getSecurityManager() != null) { 119 if (border != null) return border; 120 return SAFE_NO_FOCUS_BORDER; 121 } else if (border != null) { 122 if (noFocusBorder == null || noFocusBorder == DEFAULT_NO_FOCUS_BORDER) { 123 return border; 124 } 125 } 126 return noFocusBorder; 127 } 128 129 /** 130 * Overrides <code>JComponent.setForeground</code> to assign 131 * the unselected-foreground color to the specified color. 132 * 133 * @param c set the foreground color to this value 134 */ 135 public void setForeground(Color c) { 136 super.setForeground(c); 137 unselectedForeground = c; 138 } 139 140 /** 141 * Overrides <code>JComponent.setBackground</code> to assign 142 * the unselected-background color to the specified color. 143 * 144 * @param c set the background color to this value 145 */ 146 public void setBackground(Color c) { 147 super.setBackground(c); 148 unselectedBackground = c; 149 } 150 151 /** 152 * Notification from the <code>UIManager</code> that the look and feel 153 * [L&F] has changed. 154 * Replaces the current UI object with the latest version from the 155 * <code>UIManager</code>. 156 * 157 * @see JComponent#updateUI 158 */ 159 public void updateUI() { 160 super.updateUI(); 161 setForeground(null); 162 setBackground(null); 163 } 164 165 // implements javax.swing.table.TableCellRenderer 166 /** 167 * 168 * Returns the default table cell renderer. 169 * <p> 170 * During a printing operation, this method will be called with 171 * <code>isSelected</code> and <code>hasFocus</code> values of 172 * <code>false</code> to prevent selection and focus from appearing 173 * in the printed output. To do other customization based on whether 174 * or not the table is being printed, check the return value from 175 * {@link javax.swing.JComponent#isPaintingForPrint()}. 176 * 177 * @param table the <code>JTable</code> 178 * @param value the value to assign to the cell at 179 * <code>[row, column]</code> 180 * @param isSelected true if cell is selected 181 * @param hasFocus true if cell has focus 182 * @param row the row of the cell to render 183 * @param column the column of the cell to render 184 * @return the default table cell renderer 185 * @see javax.swing.JComponent#isPaintingForPrint() 186 */ 187 public Component getTableCellRendererComponent(JTable table, Object value, 188 boolean isSelected, boolean hasFocus, int row, int column) { 189 if (table == null) { 190 return this; 191 } 192 193 Color fg = null; 194 Color bg = null; 195 196 JTable.DropLocation dropLocation = table.getDropLocation(); 197 if (dropLocation != null 198 && !dropLocation.isInsertRow() 199 && !dropLocation.isInsertColumn() 200 && dropLocation.getRow() == row 201 && dropLocation.getColumn() == column) { 202 203 fg = DefaultLookup.getColor(this, ui, "Table.dropCellForeground"); 204 bg = DefaultLookup.getColor(this, ui, "Table.dropCellBackground"); 205 206 isSelected = true; 207 } 208 209 if (isSelected) { 210 super.setForeground(fg == null ? table.getSelectionForeground() 211 : fg); 212 super.setBackground(bg == null ? table.getSelectionBackground() 213 : bg); 214 } else { 215 Color background = unselectedBackground != null 216 ? unselectedBackground 217 : table.getBackground(); 218 if (background == null || background instanceof javax.swing.plaf.UIResource) { 219 Color alternateColor = DefaultLookup.getColor(this, ui, "Table.alternateRowColor"); 220 if (alternateColor != null && row % 2 != 0) { 221 background = alternateColor; 222 } 223 } 224 super.setForeground(unselectedForeground != null 225 ? unselectedForeground 226 : table.getForeground()); 227 super.setBackground(background); 228 } 229 230 setFont(table.getFont()); 231 232 if (hasFocus) { 233 Border border = null; 234 if (isSelected) { 235 border = DefaultLookup.getBorder(this, ui, "Table.focusSelectedCellHighlightBorder"); 236 } 237 if (border == null) { 238 border = DefaultLookup.getBorder(this, ui, "Table.focusCellHighlightBorder"); 239 } 240 setBorder(border); 241 242 if (!isSelected && table.isCellEditable(row, column)) { 243 Color col; 244 col = DefaultLookup.getColor(this, ui, "Table.focusCellForeground"); 245 if (col != null) { 246 super.setForeground(col); 247 } 248 col = DefaultLookup.getColor(this, ui, "Table.focusCellBackground"); 249 if (col != null) { 250 super.setBackground(col); 251 } 252 } 253 } else { 254 setBorder(getNoFocusBorder()); 255 } 256 257 setValue(value); 258 259 return this; 260 } 261 262 /* 263 * The following methods are overridden as a performance measure to 264 * to prune code-paths are often called in the case of renders 265 * but which we know are unnecessary. Great care should be taken 266 * when writing your own renderer to weigh the benefits and 267 * drawbacks of overriding methods like these. 268 */ 269 270 /** 271 * Overridden for performance reasons. 272 * See the <a href="#override">Implementation Note</a> 273 * for more information. 274 */ 275 public boolean isOpaque() { 276 Color back = getBackground(); 277 Component p = getParent(); 278 if (p != null) { 279 p = p.getParent(); 280 } 281 282 // p should now be the JTable. 283 boolean colorMatch = (back != null) && (p != null) && 284 back.equals(p.getBackground()) && 285 p.isOpaque(); 286 return !colorMatch && super.isOpaque(); 287 } 288 289 /** 290 * Overridden for performance reasons. 291 * See the <a href="#override">Implementation Note</a> 292 * for more information. 293 * 294 * @since 1.5 295 */ 296 public void invalidate() {} 297 298 /** 299 * Overridden for performance reasons. 300 * See the <a href="#override">Implementation Note</a> 301 * for more information. 302 */ 303 public void validate() {} 304 305 /** 306 * Overridden for performance reasons. 307 * See the <a href="#override">Implementation Note</a> 308 * for more information. 309 */ 310 public void revalidate() {} 311 312 /** 313 * Overridden for performance reasons. 314 * See the <a href="#override">Implementation Note</a> 315 * for more information. 316 */ 317 public void repaint(long tm, int x, int y, int width, int height) {} 318 319 /** 320 * Overridden for performance reasons. 321 * See the <a href="#override">Implementation Note</a> 322 * for more information. 323 */ 324 public void repaint(Rectangle r) { } 325 326 /** 327 * Overridden for performance reasons. 328 * See the <a href="#override">Implementation Note</a> 329 * for more information. 330 * 331 * @since 1.5 332 */ 333 public void repaint() { 334 } 335 336 /** 337 * Overridden for performance reasons. 338 * See the <a href="#override">Implementation Note</a> 339 * for more information. 340 */ 341 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { 342 // Strings get interned... 343 if (propertyName=="text" 344 || propertyName == "labelFor" 345 || propertyName == "displayedMnemonic" 346 || ((propertyName == "font" || propertyName == "foreground") 347 && oldValue != newValue 348 && getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey) != null)) { 349 350 super.firePropertyChange(propertyName, oldValue, newValue); 351 } 352 } 353 354 /** 355 * Overridden for performance reasons. 356 * See the <a href="#override">Implementation Note</a> 357 * for more information. 358 */ 359 public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { } 360 361 362 /** 363 * Sets the <code>String</code> object for the cell being rendered to 364 * <code>value</code>. 365 * 366 * @param value the string value for this cell; if value is 367 * <code>null</code> it sets the text value to an empty string 368 * @see JLabel#setText 369 * 370 */ 371 protected void setValue(Object value) { 372 setText((value == null) ? "" : value.toString()); 373 } 374 375 376 /** 377 * A subclass of <code>DefaultTableCellRenderer</code> that 378 * implements <code>UIResource</code>. 379 * <code>DefaultTableCellRenderer</code> doesn't implement 380 * <code>UIResource</code> 381 * directly so that applications can safely override the 382 * <code>cellRenderer</code> property with 383 * <code>DefaultTableCellRenderer</code> subclasses. 384 * <p> 385 * <strong>Warning:</strong> 386 * Serialized objects of this class will not be compatible with 387 * future Swing releases. The current serialization support is 388 * appropriate for short term storage or RMI between applications running 389 * the same version of Swing. As of 1.4, support for long term storage 390 * of all JavaBeans™ 391 * has been added to the <code>java.beans</code> package. 392 * Please see {@link java.beans.XMLEncoder}. 393 */ 394 public static class UIResource extends DefaultTableCellRenderer 395 implements javax.swing.plaf.UIResource 396 { 397 } 398 399 }