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    }