001 /*
002 * $Id: RadialGradientPainter.java,v 1.3 2006/03/26 07:02:08 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.Paint;
025 import java.awt.geom.Point2D;
026 import org.apache.batik.ext.awt.RadialGradientPaint;
027 import org.jdesktop.swingx.util.Resize;
028
029 /**
030 * <p>A Gradient based painter used for painting "multi-stop" radial gradients. These are
031 * gradients that imploys more than 2 colors, where each color is defined along
032 * with a float value between 0 and 1 indicating at what point along the gradient
033 * the new color is used.</p>
034 *
035 * <p>As with BasicGradienPainter and mentioned in AbstractGradientPainter, the values
036 * given to the centerPoint, radius, and focusPoint of the RadialGradientPainter are crucial. They
037 * represent what distance from the origin the gradient should begin and end at,
038 * depending on the size of the component. That is, they must be specified as values between
039 * 0 and 1, where 0 means "all the way on the left/top" and 1 means "all the way on the
040 * right/bottom".</p>
041 *
042 * <p>In addition, the resize behavior of the radius is specified in the resizeRadius
043 * property. If HORIZONTAL, then the width of the component is used to calculate
044 * the new radius. If VERTICAL then the height of the component is used. If BOTH,
045 * then the Math.min(width, height) is used. If NONE, then no resize occurs for
046 * the radius.</p>
047 *
048 * <p><strong>NOTE: RadialGradientPainter relies on LinearGradientPaint, which is
049 * included in the optional jar MultipleGradientPaint.jar. Be sure to have this
050 * jar on your classpath if you use this class</strong></p>
051 *
052 * @author rbair
053 */
054 public class RadialGradientPainter extends AbstractGradientPainter {
055 private RadialGradientPaint paint;
056 private Resize resizeRadius = Resize.BOTH;
057
058 /** Creates a new instance of RadialGradientPainter */
059 public RadialGradientPainter() {
060 }
061
062 /**
063 * Creates a new instance of RadialGradientPainter
064 * with the given RadialGradientPaint
065 *
066 * @param paint the RadialGradientPaint to use
067 */
068 public RadialGradientPainter(RadialGradientPaint paint) {
069 this.paint = paint;
070 }
071
072 /**
073 * Set the gradient paint to use. This may be null. If null, nothing is painted
074 *
075 * @param paint the RadialGradientPaint to use
076 */
077 public void setGradientPaint(RadialGradientPaint paint) {
078 RadialGradientPaint old = getGradientPaint();
079 this.paint = paint;
080 firePropertyChange("gradientPaint", old, getGradientPaint());
081 }
082
083 /**
084 * @return the RadialGradientPaint used for painting. This may be null
085 */
086 public RadialGradientPaint getGradientPaint() {
087 return paint;
088 }
089
090 /**
091 * Specifies the resize behavior for the radius of the RadialGradientPaint.
092 * If HORIZONTAL, then the width of the component is used to calculate
093 * the new radius. If VERTICAL then the height of the component is used. If BOTH,
094 * then the Math.min(width, height) is used. If NONE, then no resize occurs for
095 * the radius.
096 *
097 * @param r the Resize behavior for the radius
098 */
099 public void setResizeRadius(Resize r) {
100 Resize old = getResizeRadius();
101 this.resizeRadius = r;
102 firePropertyChange("resizeRadius", old, getResizeRadius());
103 }
104
105 /**
106 * @return the resize behavior for the radius
107 */
108 public Resize getResizeRadius() {
109 return resizeRadius;
110 }
111
112 /**
113 * @inheritDoc
114 */
115 protected Paint calculateSizedPaint(int width, int height) {
116 RadialGradientPaint paint = getGradientPaint();
117 if (paint == null) {
118 return null;
119 }
120
121 Point2D centerPoint = paint.getCenterPoint();
122 Point2D focusPoint = paint.getFocusPoint();
123
124 double x1 = isResizeHorizontal() ? centerPoint.getX() * width : centerPoint.getX();
125 double y1 = isResizeVertical() ? centerPoint.getY() * height : centerPoint.getY();
126 double x2 = isResizeHorizontal() ? focusPoint.getX() * width : focusPoint.getX();
127 double y2 = isResizeVertical() ? focusPoint.getY() * height : focusPoint.getY();
128 centerPoint = new Point2D.Double(x1, y1);
129 focusPoint = new Point2D.Double(x2, y2);
130
131 float radius = paint.getRadius();
132 Resize r = getResizeRadius();
133 r = r == null ? Resize.BOTH : r;
134 switch (r) {
135 case HORIZONTAL:
136 radius = radius * width;
137 break;
138 case VERTICAL:
139 radius = radius * height;
140 break;
141 case BOTH:
142 radius = radius * Math.min(width, height);
143 break;
144 case NONE:
145 break;
146 default:
147 throw new AssertionError("Cannot happen");
148 }
149
150 return new RadialGradientPaint(
151 centerPoint,
152 radius,
153 focusPoint,
154 paint.getFractions(),
155 paint.getColors(),
156 paint.getCycleMethod(),
157 paint.getColorSpace(),
158 paint.getTransform());
159 }
160 }