001/* 002 * $Id: PinstripePainter.java 4147 2012-02-01 17:13:24Z kschaefe $ 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 022package org.jdesktop.swingx.painter; 023 024import java.awt.BasicStroke; 025import java.awt.Graphics2D; 026import java.awt.Paint; 027import java.awt.Rectangle; 028import java.awt.Shape; 029import java.awt.geom.Area; 030import java.awt.geom.Line2D; 031 032import org.jdesktop.beans.JavaBean; 033 034/** 035 * <p>A fun Painter that paints pinstripes. You can specify the Paint to paint 036 * those pinstripes in (could even be a texture paint!), the angle at which 037 * to paint the pinstripes, and the spacing between stripes.</p> 038 * 039 * <p>The default PinstripePainter configuration will paint the pinstripes 040 * using the foreground color of the component (the default behavior if a 041 * Paint is not specified) at a 45 degree angle with 8 pixels between stripes</p> 042 * 043 * <p>Here is a custom code snippet that paints Color.GRAY pinstripes at a 135 044 * degree angle: 045 * <pre><code> 046 * PinstripePainter p = new PinstripePainter(); 047 * p.setAngle(135); 048 * p.setPaint(Color.GRAY); 049 * </code></pre> 050 * 051 * @author rbair 052 */ 053@JavaBean 054public class PinstripePainter extends AbstractPainter<Object> { 055 /** 056 * The angle in degrees to paint the pinstripes at. The default 057 * value is 45. The value will be between 0 and 360 inclusive. The 058 * setAngle method will ensure this. 059 */ 060 private double angle = 45; 061 /** 062 * The spacing between pinstripes 063 */ 064 private double spacing = 8; 065 066 /** 067 * The stroke width of the pinstripes 068 */ 069 private double stripeWidth = 1; 070 071 /** 072 * The Paint to use when drawing the pinstripes 073 */ 074 private Paint paint; 075 076 /** 077 * Create a new PinstripePainter. By default the angle with be 45 degrees, 078 * the spacing will be 8 pixels, and the color will be the Component foreground 079 * color. 080 */ 081 public PinstripePainter() { 082 } 083 084 /** 085 * Create a new PinstripePainter using an angle of 45, 8 pixel spacing, 086 * and the given Paint. 087 * 088 * @param paint the paint used when drawing the stripes 089 */ 090 public PinstripePainter(Paint paint) { 091 this(paint, 45); 092 } 093 094 /** 095 * Create a new PinstripePainter using the given angle, 8 pixel spacing, 096 * and the given Paint 097 * 098 * @param paint the paint used when drawing the stripes 099 * @param angle the angle, in degrees, in which to paint the pinstripes 100 */ 101 public PinstripePainter(Paint paint, double angle) { 102 this.paint = paint; 103 this.angle = angle; 104 } 105 106 /** 107 * Create a new PinstripePainter using the given angle, 8 pixel spacing, 108 * and the foreground color of the Component 109 * 110 * @param angle the angle, in degrees, in which to paint the pinstripes 111 */ 112 public PinstripePainter(double angle) { 113 this.angle = angle; 114 } 115 116 /** 117 * Create a new PinstripePainter with the specified paint, angle, stripe width, and stripe spacing. 118 * @param paint 119 * @param angle 120 * @param stripeWidth 121 * @param spacing 122 */ 123 public PinstripePainter(Paint paint, double angle, double stripeWidth, double spacing) { 124 this.paint = paint; 125 this.angle = angle; 126 this.stripeWidth = stripeWidth; 127 this.spacing = spacing; 128 } 129 130 /** 131 * Set the paint to use for drawing the pinstripes 132 * 133 * @param p the Paint to use. May be a Color. 134 */ 135 public void setPaint(Paint p) { 136 Paint old = getPaint(); 137 this.paint = p; 138 firePropertyChange("paint", old, getPaint()); 139 } 140 141 /** 142 * Get the current paint used for drawing the pinstripes 143 * @return the Paint to use to draw the pinstripes 144 */ 145 public Paint getPaint() { 146 return paint; 147 } 148 149 /** 150 * Sets the angle, in degrees, at which to paint the pinstripes. If the 151 * given angle is < 0 or > 360, it will be appropriately constrained. For 152 * example, if a value of 365 is given, it will result in 5 degrees. The 153 * conversion is not perfect, but "a man on a galloping horse won't be 154 * able to tell the difference". 155 * 156 * @param angle the Angle in degrees at which to paint the pinstripes 157 */ 158 public void setAngle(double angle) { 159 if (angle > 360) { 160 angle = angle % 360; 161 } 162 163 if (angle < 0) { 164 angle = 360 - ((angle * -1) % 360); 165 } 166 167 double old = getAngle(); 168 this.angle = angle; 169 firePropertyChange("angle", old, getAngle()); 170 } 171 172 /** 173 * Gets the current angle of the pinstripes 174 * @return the angle, in degrees, at which the pinstripes are painted 175 */ 176 public double getAngle() { 177 return angle; 178 } 179 180 /** 181 * Sets the spacing between pinstripes 182 * 183 * @param spacing spacing between pinstripes 184 */ 185 public void setSpacing(double spacing) { 186 double old = getSpacing(); 187 this.spacing = spacing; 188 firePropertyChange("spacing", old, getSpacing()); 189 } 190 191 /** 192 * Get the current spacing between the stripes 193 * @return the spacing between pinstripes 194 */ 195 public double getSpacing() { 196 return spacing; 197 } 198 199 /** 200 * {@inheritDoc} 201 */ 202 @Override 203 protected void doPaint(Graphics2D g, Object component, int width, int height) { 204 //draws pinstripes at the angle specified in this class 205 //and at the given distance apart 206 Shape oldClip = g.getClip(); 207 Area area = new Area(new Rectangle(0,0,width,height)); 208 if(oldClip != null) { 209 area = new Area(oldClip); 210 } 211 area.intersect(new Area(new Rectangle(0,0,width,height))); 212 g.setClip(area); 213 //g.setClip(oldClip.intersection(new Rectangle(0,0,width,height))); 214 Paint p = PainterUtils.getForegroundPaint(getPaint(), component); 215 g.setPaint(p); 216 217 g.setStroke(new BasicStroke((float)getStripeWidth())); 218 219 double hypLength = Math.sqrt((width * width) + 220 (height * height)); 221 222 double radians = Math.toRadians(getAngle()); 223 g.rotate(radians); 224 225 double spacing = getSpacing(); 226 spacing += getStripeWidth(); 227 int numLines = (int)(hypLength / spacing); 228 229 for (int i=0; i<numLines; i++) { 230 double x = i * spacing; 231 Line2D line = new Line2D.Double(x, -hypLength, x, hypLength); 232 g.draw(line); 233 } 234 g.setClip(oldClip); 235 } 236 237 /** 238 * Gets the current width of the pinstripes 239 * @return the current pinstripe width 240 */ 241 public double getStripeWidth() { 242 return stripeWidth; 243 } 244 245 /** 246 * Set the width of the pinstripes 247 * @param stripeWidth a new width for the pinstripes 248 */ 249 public void setStripeWidth(double stripeWidth) { 250 double oldSripeWidth = getStripeWidth(); 251 this.stripeWidth = stripeWidth; 252 firePropertyChange("stripeWidth",new Double(oldSripeWidth),new Double(stripeWidth)); 253 } 254 255}