001 /*
002 * $Id: PinstripePainter.java,v 1.5 2006/05/14 15:55:54 dmouse 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;
023
024 import java.awt.Graphics2D;
025 import java.awt.Paint;
026 import java.awt.geom.Line2D;
027 import java.awt.geom.Point2D;
028 import java.awt.geom.Rectangle2D;
029 import javax.swing.JComponent;
030
031 /**
032 * <p>A fun Painter that paints pinstripes. You can specify the Paint to paint
033 * those pinstripes in (could even be a texture paint!), the angle at which
034 * to paint the pinstripes, and the spacing between stripes.</p>
035 *
036 * <p>The default PinstripePainter configuration will paint the pinstripes
037 * using the foreground color of the component (the default behavior if a
038 * Paint is not specified) at a 45 degree angle with 8 pixels between stripes</p>
039 *
040 * <p>Here is a custom code snippet that paints Color.GRAY pinstripes at a 135
041 * degree angle:
042 * <pre><code>
043 * PinstripePainter p = new PinstripePainter();
044 * p.setAngle(135);
045 * p.setPaint(Color.GRAY);
046 * </code></pre>
047 *
048 * @author rbair
049 */
050 public class PinstripePainter extends AbstractPainter {
051 /**
052 * The angle in degrees to paint the pinstripes at. The default
053 * value is 45. The value will be between 0 and 360 inclusive. The
054 * setAngle method will ensure this.
055 */
056 private double angle = 45;
057 /**
058 * The spacing between pinstripes
059 */
060 private double spacing = 8;
061 /**
062 * The Paint to use when drawing the pinstripes
063 */
064 private Paint paint;
065
066 /**
067 * Create a new PinstripePainter. By default the angle with be 45 degrees,
068 * the spacing will be 8 pixels, and the color will be the Component foreground
069 * color.
070 */
071 public PinstripePainter() {
072 }
073
074 /**
075 * Create a new PinstripePainter using an angle of 45, 8 pixel spacing,
076 * and the given Paint.
077 *
078 * @param paint the paint used when drawing the stripes
079 */
080 public PinstripePainter(Paint paint) {
081 this(paint, 45);
082 }
083
084 /**
085 * Create a new PinstripePainter using the given angle, 8 pixel spacing,
086 * and the given Paint
087 *
088 * @param paint the paint used when drawing the stripes
089 * @param angle the angle, in degrees, in which to paint the pinstripes
090 */
091 public PinstripePainter(Paint paint, double angle) {
092 this.paint = paint;
093 this.angle = angle;
094 }
095
096 /**
097 * Create a new PinstripePainter using the given angle, 8 pixel spacing,
098 * and the foreground color of the Component
099 *
100 * @param angle the angle, in degrees, in which to paint the pinstripes
101 */
102 public PinstripePainter(double angle) {
103 this.angle = angle;
104 }
105
106 /**
107 * Set the paint to use for drawing the pinstripes
108 *
109 * @param p the Paint to use. May be a Color.
110 */
111 public void setPaint(Paint p) {
112 Paint old = getPaint();
113 this.paint = p;
114 firePropertyChange("paint", old, getPaint());
115 }
116
117 /**
118 * @return the Paint to use to draw the pinstripes
119 */
120 public Paint getPaint() {
121 return paint;
122 }
123
124 /**
125 * Sets the angle, in degrees, at which to paint the pinstripes. If the
126 * given angle is < 0 or > 360, it will be appropriately constrained. For
127 * example, if a value of 365 is given, it will result in 5 degrees. The
128 * conversion is not perfect, but "a man on a galloping horse won't be
129 * able to tell the difference".
130 *
131 * @param angle the Angle in degrees at which to paint the pinstripes
132 */
133 public void setAngle(double angle) {
134 if (angle > 360) {
135 angle = angle % 360;
136 }
137
138 if (angle < 0) {
139 angle = 360 - ((angle * -1) % 360);
140 }
141
142 double old = getAngle();
143 this.angle = angle;
144 firePropertyChange("angle", old, getAngle());
145 }
146
147 /**
148 * @return the angle, in degrees, at which the pinstripes are painted
149 */
150 public double getAngle() {
151 return angle;
152 }
153
154 /**
155 * Sets the spacing between pinstripes
156 *
157 * @param spacing spacing between pinstripes
158 */
159 public void setSpacing(double spacing) {
160 double old = getSpacing();
161 this.spacing = spacing;
162 firePropertyChange("spacing", old, getSpacing());
163 }
164
165 /**
166 * @return the spacing between pinstripes
167 */
168 public double getSpacing() {
169 return spacing;
170 }
171
172 /**
173 * @inheritDoc
174 */
175 public void paintBackground(Graphics2D g, JComponent component) {
176 //draws pinstripes at the angle specified in this class
177 //and at the given distance apart
178 Paint p = getPaint();
179 if (p == null) {
180 g.setColor(component.getForeground());
181 } else {
182 g.setPaint(p);
183 }
184
185 double hypLength = Math.sqrt((component.getWidth() * component.getWidth()) +
186 (component.getHeight() * component.getHeight()));
187
188 double radians = Math.toRadians(getAngle());
189 g.rotate(radians);
190
191 int numLines = (int)(hypLength / getSpacing());
192
193 for (int i=0; i<numLines; i++) {
194 double x = i * getSpacing();
195 Line2D line = new Line2D.Double(x, -hypLength, x, hypLength);
196 g.draw(line);
197 }
198 }
199 }