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