001/*
002 * $Id: JXRendererHyperlink.java 3235 2009-02-01 15:01:07Z rah003 $
003 *
004 * Copyright 2007 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 */
021package org.jdesktop.swingx.renderer;
022
023import java.awt.Graphics;
024import java.awt.Graphics2D;
025import java.awt.Rectangle;
026
027import org.jdesktop.swingx.JXHyperlink;
028import org.jdesktop.swingx.painter.Painter;
029
030/**
031 * A <code>JXHyperlink</code> optimized for usage in renderers and
032 * with a minimal background painter support. <p>
033 * 
034 * <i>Note</i>: the painter support will be switched to painter_work as 
035 * soon it enters main. 
036 * 
037 * @author Jeanette Winzenburg
038 */
039public class JXRendererHyperlink extends JXHyperlink implements PainterAware {
040    protected Painter painter;
041
042    /**
043     * {@inheritDoc}
044     */
045    public void setPainter(Painter painter) {
046        Painter old = getPainter();
047        this.painter = painter;
048        if (painter != null) {
049            // ui maps to !opaque
050            // Note: this is incomplete - need to keep track of the 
051            // "real" contentfilled property
052            setContentAreaFilled(false);
053        }
054        firePropertyChange("painter", old, getPainter());
055    }
056
057    /**
058     * {@inheritDoc}
059     */
060    public Painter getPainter() {
061        return painter;
062    }
063    
064    @Override
065    protected void paintComponent(Graphics g) {
066        if (painter != null) {
067            // we have a custom (background) painter
068            // try to inject if possible
069            // there's no guarantee - some LFs have their own background 
070            // handling  elsewhere
071            paintComponentWithPainter((Graphics2D) g);
072        } else {
073            // no painter - delegate to super
074            super.paintComponent(g);
075        }
076    }
077
078    /**
079     * 
080     * Hack around AbstractPainter.paint bug which disposes the Graphics.
081     * So here we give it a scratch to paint on. <p>
082     * TODO - remove again, the issue is fixed?
083     * 
084     * @param g the graphics to paint on
085     */
086    private void paintPainter(Graphics g) {
087        // fail fast: we assume that g must not be null
088        // which throws an NPE here instead deeper down the bowels
089        // this differs from corresponding core implementation!
090        Graphics2D scratch = (Graphics2D) g.create();
091        try {
092            painter.paint(scratch, this, getWidth(), getHeight());
093        }
094        finally {
095            scratch.dispose();
096        }
097    }
098
099    /**
100     * PRE: painter != null
101     * @param g
102     */
103    protected void paintComponentWithPainter(Graphics2D g) {
104        // 1. be sure to fill the background
105        // 2. paint the painter
106        // by-pass ui.update and hook into ui.paint directly
107        if (ui != null) {
108            // fail fast: we assume that g must not be null
109            // which throws an NPE here instead deeper down the bowels
110            // this differs from corresponding core implementation!
111            Graphics scratchGraphics = g.create();
112            try {
113                scratchGraphics.setColor(getBackground());
114                scratchGraphics.fillRect(0, 0, getWidth(), getHeight());
115                paintPainter(g);
116                ui.paint(scratchGraphics, this);
117            } finally {
118                scratchGraphics.dispose();
119            }
120        }
121
122    }
123
124    @Override
125    public void updateUI() {
126        super.updateUI();
127        setBorderPainted(true);
128        setOpaque(true);
129    }
130    /**
131     * {@inheritDoc} <p>
132     * 
133     * Overridden to not automatically de/register itself from/to the ToolTipManager.
134     * As rendering component it is not considered to be active in any way, so the
135     * manager must not listen. 
136     */
137    @Override
138    public void setToolTipText(String text) {
139        putClientProperty(TOOL_TIP_TEXT_KEY, text);
140    }
141    
142    /**
143     * Overridden for performance reasons.
144     * See the <a href="#override">Implementation Note</a> 
145     * for more information.
146     *
147     * @since 1.5
148     */
149    @Override
150    public void invalidate() {}
151
152    /**
153     * Overridden for performance reasons.
154     * See the <a href="#override">Implementation Note</a> 
155     * for more information.
156     */
157    @Override
158    public void validate() {}
159
160    /**
161     * Overridden for performance reasons.
162     * See the <a href="#override">Implementation Note</a> 
163     * for more information.
164     */
165    @Override
166    public void revalidate() {}
167
168    /**
169     * Overridden for performance reasons.
170     * See the <a href="#override">Implementation Note</a> 
171     * for more information.
172     */
173    @Override
174    public void repaint(long tm, int x, int y, int width, int height) {}
175
176    /**
177     * Overridden for performance reasons.
178     * See the <a href="#override">Implementation Note</a> 
179     * for more information.
180     */
181    @Override
182    public void repaint(Rectangle r) { }
183
184    /**
185     * Overridden for performance reasons.
186     * See the <a href="#override">Implementation Note</a> 
187     * for more information.
188     *
189     * @since 1.5
190     */
191    @Override
192    public void repaint() {
193    }
194
195    /**
196     * Overridden for performance reasons.
197     * See the <a href="#override">Implementation Note</a> 
198     * for more information.
199     */
200    @Override
201    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {  
202        // Strings get interned...
203        if ("text".equals(propertyName)) {
204            super.firePropertyChange(propertyName, oldValue, newValue);
205        }
206    }
207
208    /**
209     * Overridden for performance reasons.
210     * See the <a href="#override">Implementation Note</a> 
211     * for more information.
212     */
213    @Override
214    public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { }
215
216}