001 /* 002 * $Id: JRendererLabel.java 3235 2009-02-01 15:01:07Z rah003 $ 003 * 004 * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021 package org.jdesktop.swingx.renderer; 022 023 import java.awt.Color; 024 import java.awt.Component; 025 import java.awt.Graphics; 026 import java.awt.Graphics2D; 027 import java.awt.Rectangle; 028 029 import javax.swing.JLabel; 030 031 import org.jdesktop.swingx.painter.Painter; 032 033 /** 034 * A <code>JLabel</code> optimized for usage in renderers and 035 * with a minimal background painter support. <p> 036 * 037 * <i>Note</i>: the painter support will be switched to painter_work as 038 * soon it enters main. 039 * 040 * The reasoning for the performance-overrides is copied from core: <p> 041 * 042 * The standard <code>JLabel</code> component was not 043 * designed to be used this way and we want to avoid 044 * triggering a <code>revalidate</code> each time the 045 * cell is drawn. This would greatly decrease performance because the 046 * <code>revalidate</code> message would be 047 * passed up the hierarchy of the container to determine whether any other 048 * components would be affected. 049 * As the renderer is only parented for the lifetime of a painting operation 050 * we similarly want to avoid the overhead associated with walking the 051 * hierarchy for painting operations. 052 * So this class 053 * overrides the <code>validate</code>, <code>invalidate</code>, 054 * <code>revalidate</code>, <code>repaint</code>, and 055 * <code>firePropertyChange</code> methods to be 056 * no-ops and override the <code>isOpaque</code> method solely to improve 057 * performance. If you write your own renderer component, 058 * please keep this performance consideration in mind. 059 * <p> 060 * 061 * @author Jeanette Winzenburg 062 */ 063 public class JRendererLabel extends JLabel implements PainterAware { 064 065 protected Painter painter; 066 private boolean strict; 067 068 /** 069 * 070 */ 071 public JRendererLabel() { 072 super(); 073 setOpaque(true); 074 } 075 076 /** 077 * Overridden for performance reasons.<p> 078 * PENDING: Think about Painters and opaqueness? 079 * 080 */ 081 @Override 082 public boolean isOpaque() { 083 Color back = getBackground(); 084 Component p = getParent(); 085 if (p != null) { 086 p = p.getParent(); 087 } 088 // p should now be the JTable. 089 boolean colorMatch = (back != null) && (p != null) && 090 back.equals(p.getBackground()) && 091 p.isOpaque(); 092 return !colorMatch && super.isOpaque(); 093 } 094 095 /** 096 * {@inheritDoc} 097 */ 098 public void setPainter(Painter painter) { 099 Painter old = getPainter(); 100 this.painter = painter; 101 firePropertyChange("painter", old, getPainter()); 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 public Painter getPainter() { 108 return painter; 109 } 110 /** 111 * {@inheritDoc} <p> 112 * 113 * Overridden to inject Painter's painting. <p> 114 * TODO: cleanup logic - see JRendererCheckBox. 115 * 116 */ 117 @Override 118 protected void paintComponent(Graphics g) { 119 if (painter != null) { 120 // we have a custom (background) painter 121 // try to inject if possible 122 // there's no guarantee - some LFs have their own background 123 // handling elsewhere 124 if (isOpaque()) { 125 // replace the paintComponent completely 126 paintComponentWithPainter((Graphics2D) g); 127 } else { 128 // transparent apply the background painter before calling super 129 paintPainter(g); 130 super.paintComponent(g); 131 } 132 } else { 133 // nothing to worry about - delegate to super 134 super.paintComponent(g); 135 } 136 } 137 138 /** 139 * 140 * Hack around AbstractPainter.paint bug which disposes the Graphics. 141 * So here we give it a scratch to paint on. <p> 142 * TODO - remove again, the issue is fixed? 143 * 144 * @param g the graphics to paint on 145 */ 146 private void paintPainter(Graphics g) { 147 // fail fast: we assume that g must not be null 148 // which throws an NPE here instead deeper down the bowels 149 // this differs from corresponding core implementation! 150 Graphics2D scratch = (Graphics2D) g.create(); 151 try { 152 painter.paint(scratch, this, getWidth(), getHeight()); 153 } 154 finally { 155 scratch.dispose(); 156 } 157 } 158 159 // public void setStrictWidth(boolean strict) { 160 // this.strict = strict; 161 // } 162 // 163 // @Override 164 // public Dimension getMaximumSize() { 165 // if (strict) { 166 // return super.getMaximumSize(); 167 // } 168 // Dimension max = super.getMaximumSize(); 169 // max.width = Integer.MAX_VALUE - 1; 170 // return max; 171 // } 172 173 /** 174 * PRE: painter != null, isOpaque() 175 * @param g 176 */ 177 protected void paintComponentWithPainter(Graphics2D g) { 178 // 1. be sure to fill the background 179 // 2. paint the painter 180 // by-pass ui.update and hook into ui.paint directly 181 if (ui != null) { 182 // fail fast: we assume that g must not be null 183 // which throws an NPE here instead deeper down the bowels 184 // this differs from corresponding core implementation! 185 Graphics2D scratchGraphics = (Graphics2D) g.create(); 186 try { 187 scratchGraphics.setColor(getBackground()); 188 scratchGraphics.fillRect(0, 0, getWidth(), getHeight()); 189 paintPainter(g); 190 ui.paint(scratchGraphics, this); 191 } 192 finally { 193 scratchGraphics.dispose(); 194 } 195 } 196 } 197 198 199 /** 200 * {@inheritDoc} <p> 201 * 202 * Overridden to not automatically de/register itself from/to the ToolTipManager. 203 * As rendering component it is not considered to be active in any way, so the 204 * manager must not listen. 205 */ 206 @Override 207 public void setToolTipText(String text) { 208 putClientProperty(TOOL_TIP_TEXT_KEY, text); 209 } 210 211 /** 212 * Overridden for performance reasons. 213 * See the <a href="#override">Implementation Note</a> 214 * for more information. 215 * 216 * @since 1.5 217 */ 218 @Override 219 public void invalidate() {} 220 221 /** 222 * Overridden for performance reasons. 223 * See the <a href="#override">Implementation Note</a> 224 * for more information. 225 */ 226 @Override 227 public void validate() {} 228 229 /** 230 * Overridden for performance reasons. 231 * See the <a href="#override">Implementation Note</a> 232 * for more information. 233 */ 234 @Override 235 public void revalidate() {} 236 237 /** 238 * Overridden for performance reasons. 239 * See the <a href="#override">Implementation Note</a> 240 * for more information. 241 */ 242 @Override 243 public void repaint(long tm, int x, int y, int width, int height) {} 244 245 /** 246 * Overridden for performance reasons. 247 * See the <a href="#override">Implementation Note</a> 248 * for more information. 249 */ 250 @Override 251 public void repaint(Rectangle r) { } 252 253 /** 254 * Overridden for performance reasons. 255 * See the <a href="#override">Implementation Note</a> 256 * for more information. 257 * 258 * @since 1.5 259 */ 260 @Override 261 public void repaint() { 262 } 263 264 /** 265 * Overridden for performance reasons. 266 * See the <a href="#override">Implementation Note</a> 267 * for more information. 268 */ 269 @Override 270 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { 271 // Strings get interned... 272 if ("text".equals(propertyName)) { 273 super.firePropertyChange(propertyName, oldValue, newValue); 274 } 275 } 276 277 /** 278 * Overridden for performance reasons. 279 * See the <a href="#override">Implementation Note</a> 280 * for more information. 281 */ 282 @Override 283 public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { } 284 285 286 }