001    /*
002     * $Id: BasicGradientPainter.java,v 1.1 2006/03/22 19:05:44 rbair Exp $
003     *
004     * Copyright 2004 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    
022    package org.jdesktop.swingx.painter.gradient;
023    
024    import java.awt.Color;
025    import java.awt.GradientPaint;
026    import java.awt.Paint;
027    import java.awt.PaintContext;
028    import java.awt.Rectangle;
029    import java.awt.RenderingHints;
030    import java.awt.color.ColorSpace;
031    import java.awt.geom.AffineTransform;
032    import java.awt.geom.Point2D;
033    import java.awt.geom.Rectangle2D;
034    import java.awt.image.ColorModel;
035    import javax.swing.UIManager;
036    
037    /**
038     * <p>A Gradient based Painter that uses GradientPaint to paint the gradient.
039     * Simply specify the GradientPaint to use.</p>
040     *
041     * <p>In order for resizing to work properly with GradientPaint
042     * it is necessary that the various control points used in
043     * these paints be specified in such a manner that they can be reliably resized.
044     * For example, BasicGradientPainter takes GradientPaints who's point1 and point2
045     * properties are specified between 0 and 1, representing at what percentage of
046     * the distance from the origin the gradient begins and ends. Thus, if I created
047     * a GradientPaint like this:
048     * <pre><code>
049     *  GradientPaint gp = new GradientPaint(
050     *      new Point2D.Double(.2d, 0),
051     *      Color.BLUE,
052     *      new Point2D.Double(.8d, 0),
053     *      Color.WHITE);
054     * </code></pre>
055     * 
056     * then when painted, the gradient will start with a BLUE at 20% of the width of
057     * the component, and finish with WHITE at 80% of the width of the component.</p>
058     *
059     * <p>Various built in gradients also exist as public static final properties.
060     * They are defined as GradientPaints rather than BasicGradientPainters because
061     * BasicGradientPainter is mutable and thus don't make very reliable public static
062     * final defaults. To use:
063     * <pre><code>
064     *  panel.setBackgroundPainter(new BasicGradientPainter(BasicGradientPainter.BLUE_EXPERIENCE));
065     * </code></pre></p>
066     *
067     * @author rbair
068     */
069    public class BasicGradientPainter extends AbstractGradientPainter {
070    //    public static final GradientPaint WHITE_TO_CONTROL_HORZONTAL = new GradientPaint(
071    //            new Point2D.Double(0, 0),
072    //            Color.WHITE,
073    //            new Point2D.Double(1, 0),
074    //            new UIColor("control"));
075    //    public static final GradientPaint WHITE_TO_CONTROL_VERTICAL = new GradientPaint(
076    //            new Point2D.Double(0, 0),
077    //            Color.WHITE,
078    //            new Point2D.Double(0, 1),
079    //            new UIColor("control"));
080        public static final GradientPaint BLUE_EXPERIENCE = new GradientPaint(
081                new Point2D.Double(0, 0),
082                new Color(168, 204, 241),
083                new Point2D.Double(0, 1),
084                new Color(44, 61, 146));
085        public static final GradientPaint MAC_OSX_SELECTED = new GradientPaint(
086                new Point2D.Double(0, 0),
087                new Color(81, 141, 236),
088                new Point2D.Double(0, 1),
089                new Color(36, 96, 192));
090        public static final GradientPaint MAC_OSX = new GradientPaint(
091                new Point2D.Double(0, 0),
092                new Color(167, 210, 250),
093                new Point2D.Double(0, 1),
094                new Color(99, 147, 206));
095        public static final GradientPaint AERITH = new GradientPaint(
096                new Point2D.Double(0, 0),
097                Color.WHITE,
098                new Point2D.Double(0, 1),
099                new Color(64, 110, 161));
100        public static final GradientPaint GRAY = new GradientPaint(
101                new Point2D.Double(0, 0),
102                new Color(226, 226, 226),
103                new Point2D.Double(0, 1),
104                new Color(250, 248, 248));
105        public static final GradientPaint RED_XP = new GradientPaint(
106                new Point2D.Double(0, 0),
107                new Color(236, 81, 81),
108                new Point2D.Double(0, 1),
109                new Color(192, 36, 36));
110        public static final GradientPaint NIGHT_GRAY = new GradientPaint(
111                new Point2D.Double(0, 0),
112                new Color(102, 111, 127),
113                new Point2D.Double(0, 1),
114                new Color(38, 45, 61));
115        public static final GradientPaint NIGHT_GRAY_LIGHT = new GradientPaint(
116                new Point2D.Double(0, 0),
117                new Color(129, 138, 155),
118                new Point2D.Double(0, 1),
119                new Color(58, 66, 82));
120        
121        
122        
123        private GradientPaint paint;
124        
125        /**
126         * Creates a new instance of BasicGradientPainter
127         */
128        public BasicGradientPainter() {
129        }
130        
131        /**
132         * Creates a new instance of BasicGradientPainter
133         */
134        public BasicGradientPainter(GradientPaint paint) {
135            this.paint = paint;
136        }
137        
138        /**
139         * Constructs a simple acyclic <code>BasicGradientPainter</code> object.
140         * 
141         * @param x1 x coordinate of the first specified
142         * <code>Point</code> in user space
143         * @param y1 y coordinate of the first specified
144         * <code>Point</code> in user space
145         * @param startColor <code>Color</code> at the first specified 
146         * <code>Point</code>
147         * @param x2 x coordinate of the second specified
148         * <code>Point</code> in user space
149         * @param y2 y coordinate of the second specified
150         * <code>Point</code> in user space
151         * @param endColor <code>Color</code> at the second specified 
152         * <code>Point</code>
153         * @throws NullPointerException if either one of colors is null
154         */
155        public BasicGradientPainter(float x1,
156                   float y1,
157                   Color startColor,
158                   float x2,
159                   float y2,
160                   Color endColor) {
161            this.paint = new GradientPaint(x1, y1, startColor, x2, y2, endColor);
162        }
163    
164        /**
165         * Constructs a simple acyclic <code>BasicGradientPainter</code> object.
166         * 
167         * @param startPoint the first specified <code>Point</code> in user space
168         * @param startColor <code>Color</code> at the first specified 
169         * <code>Point</code>
170         * @param endPoint the second specified <code>Point</code> in user space
171         * @param endColor <code>Color</code> at the second specified 
172         * <code>Point</code>
173         * @throws NullPointerException if either one of colors or points 
174         * is null
175         */
176        public BasicGradientPainter(Point2D startPoint,
177                   Color startColor,
178                   Point2D endPoint,
179                   Color endColor) {
180            
181            this.paint = new GradientPaint(startPoint, startColor, endPoint, endColor);
182        }
183    
184        /**
185         * Constructs either a cyclic or acyclic <code>BasicGradientPainter</code>
186         * object depending on the <code>boolean</code> parameter.
187         * 
188         * @param x1 x coordinate of the first specified
189         * <code>Point</code> in user space
190         * @param y1 y coordinate of the first specified
191         * <code>Point</code> in user space
192         * @param startColor <code>Color</code> at the first specified 
193         * <code>Point</code>
194         * @param x2 x coordinate of the second specified
195         * <code>Point</code> in user space
196         * @param y2 y coordinate of the second specified
197         * <code>Point</code> in user space
198         * @param endColor <code>Color</code> at the second specified 
199         * <code>Point</code>
200         * @param cyclic <code>true</code> if the gradient pattern should cycle
201         * repeatedly between the two colors; <code>false</code> otherwise
202         */
203        public BasicGradientPainter(float x1,
204                   float y1,
205                   Color startColor,
206                   float x2,
207                   float y2,
208                   Color endColor,
209                   boolean cyclic) {
210        paint = new GradientPaint(x1, y1, startColor, x2, y2, endColor, cyclic);
211        }
212    
213        /**
214         * Constructs either a cyclic or acyclic <code>BasicGradientPainter</code>
215         * object depending on the <code>boolean</code> parameter.
216         * 
217         * @param startPoint the first specified <code>Point</code> 
218         * in user space
219         * @param startColor <code>Color</code> at the first specified 
220         * <code>Point</code>
221         * @param endPoint the second specified <code>Point</code> 
222         * in user space
223         * @param endColor <code>Color</code> at the second specified 
224         * <code>Point</code>
225         * @param cyclic <code>true</code> if the gradient pattern should cycle
226         * repeatedly between the two colors; <code>false</code> otherwise
227         * @throws NullPointerException if either one of colors or points 
228         * is null
229         */
230        public BasicGradientPainter(Point2D startPoint,
231                   Color startColor,
232                   Point2D endPoint,
233                   Color endColor,
234                   boolean cyclic) {
235        paint = new GradientPaint(startPoint, startColor, endPoint, endColor, cyclic);
236        }
237        
238        /**
239         * Set the gradient paint to use. This may be null. If null, nothing is painted
240         *
241         * @param paint the GradientPaint to use
242         */
243        public void setGradientPaint(GradientPaint paint) {
244            GradientPaint old = getGradientPaint();
245            this.paint = paint;
246            firePropertyChange("gradientPaint", old, getGradientPaint());
247        }
248        
249        /**
250         * @return the GradientPaint used for painting. This may be null
251         */
252        public GradientPaint getGradientPaint() {
253            return paint;
254        }
255        
256        /**
257         * @inheritDoc
258         */
259        protected Paint calculateSizedPaint(int width, int height) {
260            GradientPaint paint = getGradientPaint();
261            if (paint == null) {
262                return null;
263            }
264            
265            Point2D startPoint = paint.getPoint1();
266            Point2D endPoint = paint.getPoint2();
267            
268            double x1 = isResizeHorizontal() ? startPoint.getX() * width : startPoint.getX();
269            double y1 = isResizeVertical() ? startPoint.getY() * height : startPoint.getY();
270            double x2 = isResizeHorizontal() ? endPoint.getX() * width : endPoint.getX();
271            double y2 = isResizeVertical() ? endPoint.getY() * height : endPoint.getY();
272            startPoint = new Point2D.Double(x1, y1);
273            endPoint = new Point2D.Double(x2, y2);
274            
275            return new GradientPaint(
276                    startPoint,
277                    paint.getColor1(),
278                    endPoint,
279                    paint.getColor2());
280        }
281    
282        //Experimental support for getting colors for gradients out of UIManager
283        //and hiding that fact from users, at least part of the time
284    //    private static final class UIColor extends Color {
285    //        private Color c = null;
286    //        private Object key;
287    //        
288    //        public UIColor(Object key) {
289    //            super(0xffffffff);
290    //            this.key = key;
291    //            maybeUpdate();
292    //        }
293    //        
294    //        private void maybeUpdate() {
295    //            Color newc = UIManager.getColor(key);
296    //            if (c != newc) {
297    //                c = newc;
298    //            }
299    //            if (c == null) {
300    //                c = Color.WHITE;
301    //            }
302    //        }
303    //        
304    //        public float[] getComponents(ColorSpace cspace, float[] compArray) {
305    //            maybeUpdate();
306    //            return c.getComponents(cspace, compArray);
307    //        }
308    //
309    //        public float[] getColorComponents(ColorSpace cspace, float[] compArray) {
310    //            maybeUpdate();
311    //            return c.getColorComponents(cspace, compArray);
312    //        }
313    //
314    //        public PaintContext createContext(ColorModel cm, Rectangle r, Rectangle2D r2d, AffineTransform xform, RenderingHints hints) {
315    //            maybeUpdate();
316    //            return c.createContext(cm, r, r2d, xform, hints);
317    //        }
318    //
319    //        public float[] getRGBComponents(float[] compArray) {
320    //            maybeUpdate();
321    //            return c.getRGBComponents(compArray);
322    //        }
323    //
324    //        public float[] getRGBColorComponents(float[] compArray) {
325    //            maybeUpdate();
326    //            return c.getRGBColorComponents(compArray);
327    //        }
328    //
329    //        public float[] getColorComponents(float[] compArray) {
330    //            maybeUpdate();
331    //            return c.getColorComponents(compArray);
332    //        }
333    //
334    //        public float[] getComponents(float[] compArray) {
335    //            maybeUpdate();
336    //            return c.getComponents(compArray);
337    //        }
338    //
339    //        public int getGreen() {
340    //            maybeUpdate();
341    //            return c.getGreen();
342    //        }
343    //
344    //        public int getBlue() {
345    //            maybeUpdate();
346    //            return c.getBlue();
347    //        }
348    //
349    //        public ColorSpace getColorSpace() {
350    //            maybeUpdate();
351    //            return c.getColorSpace();
352    //        }
353    //
354    //        public Color brighter() {
355    //            maybeUpdate();
356    //            return c.brighter();
357    //        }
358    //
359    //        public int getAlpha() {
360    //            maybeUpdate();
361    //            return c.getAlpha();
362    //        }
363    //
364    //        public int getRed() {
365    //            maybeUpdate();
366    //            return c.getRed();
367    //        }
368    //
369    //        public int getRGB() {
370    //            maybeUpdate();
371    //            return c.getRGB();
372    //        }
373    //
374    //        public int getTransparency() {
375    //            maybeUpdate();
376    //            return c.getTransparency();
377    //        }
378    //
379    //        public Color darker() {
380    //            maybeUpdate();
381    //            return c.darker();
382    //        }
383    //    }
384    }