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 }