001 /*
002 * $Id: CheckerboardPainter.java,v 1.6 2006/05/14 08:12:14 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.Color;
025 import java.awt.Graphics2D;
026 import java.awt.Paint;
027 import java.awt.Rectangle;
028 import java.awt.TexturePaint;
029 import java.awt.image.BufferedImage;
030 import javax.swing.JComponent;
031
032 /**
033 * <p>A Painter implementation that paints a checkerboard pattern. The light
034 * and dark colors (Paint instances) are configurable, as are the size of the
035 * squares (squareLength).</p>
036 *
037 * <p>To configure a checkerboard pattern that used a gradient for the dark
038 * tiles and Color.WHITE for the light tiles, you could:
039 * <pre><code>
040 * GradientPaint gp = new GradientPaint(
041 * new Point2D.Double(0, 0),
042 * Color.BLACK,
043 * new Point2D.Double(0, 32),
044 * Color.GRAY);
045 * CheckerboardPainter p = new CheckerboardPainter();
046 * p.setDarkPaint(gp);
047 * p.setLightPaint(Color.WHITE);
048 * p.setSquareLength(32);
049 * panel.seBackgroundPainter(p);
050 * </code></pre></p>
051 *
052 * <p>Note that in this example, the "32" in the GradientPaint matches the "32"
053 * set for the squareLength. This is necessary because GradientPaints don't
054 * readjust themselves for the size of the square. They are fixed and immutable
055 * at the time of creation.</p>
056 *
057 *
058 *
059 * @author rbair
060 */
061 public class CheckerboardPainter extends AbstractPainter {
062 private transient Paint checkerPaint;
063
064 private Paint darkPaint = new Color(204, 204, 204);
065 private Paint lightPaint = Color.WHITE;
066 private int squareLength = 8;
067
068 /**
069 * Create a new CheckerboardPainter. By default the light color is Color.WHITE,
070 * the dark color is a light gray, and the square length is 8.
071 */
072 public CheckerboardPainter() {
073 }
074
075 /**
076 * Create a new CheckerboardPainter with the specified light and dark paints.
077 * By default the square length is 8.
078 *
079 * @param darkPaint the paint used to draw the dark squares
080 * @param lightPaint the paint used to draw the light squares
081 */
082 public CheckerboardPainter(Paint darkPaint, Paint lightPaint) {
083 this(darkPaint, lightPaint, 8);
084 }
085
086 /**
087 * Create a new CheckerboardPainter with the specified light and dark paints
088 * and the specified square size.
089 *
090 * @param darkPaint the paint used to draw the dark squares
091 * @param lightPaint the paint used to draw the light squares
092 * @param length the length of the checker board squares
093 */
094 public CheckerboardPainter(Paint darkPaint, Paint lightPaint, int length) {
095 this.darkPaint = darkPaint;
096 this.lightPaint = lightPaint;
097 this.squareLength = length;
098 }
099
100
101 /**
102 * Specifies the length of the squares. By default, it is 8. A length of <=
103 * 0 will cause an IllegalArgumentException to be thrown.
104 *
105 * @param length the length of one side of a square tile. Must be > 0.
106 */
107 public void setSquareLength(int length) {
108 if (length <= 0) {
109 throw new IllegalArgumentException("Length must be > 0");
110 }
111
112 int old = getSquareLength();
113 this.squareLength = length;
114 checkerPaint = null;
115 firePropertyChange("squareLength", old, getSquareLength());
116 }
117
118 /**
119 * @return the squareLength. Will be > 0
120 */
121 public int getSquareLength() {
122 return squareLength;
123 }
124
125 /**
126 * Specifies the paint to use for dark tiles. This is a Paint and
127 * may be anything, including a TexturePaint for painting images. If null,
128 * the background color of the component is used.
129 *
130 * @param color the Paint to use for painting the "dark" tiles. May be null.
131 */
132 public void setDarkPaint(Paint color) {
133 Paint old = getDarkPaint();
134 this.darkPaint = color;
135 checkerPaint = null;
136 firePropertyChange("darkPaint", old, getDarkPaint());
137 }
138
139 /**
140 * @return the Paint used for painting the "dark" tiles. May be null
141 */
142 public Paint getDarkPaint() {
143 return darkPaint;
144 }
145
146 /**
147 * Specifies the paint to use for light tiles. This is a Paint and
148 * may be anything, including a TexturePaint for painting images. If null,
149 * the foreground color of the component is used.
150 *
151 * @param color the Paint to use for painting the "light" tiles. May be null.
152 */
153 public void setLightPaint(Paint color) {
154 Paint old = getLightPaint();
155 this.lightPaint = color;
156 checkerPaint = null;
157 firePropertyChange("lightPaint", old, getLightPaint());
158 }
159
160 /**
161 * @return the Paint used for painting the "light" tiles. May be null
162 */
163 public Paint getLightPaint() {
164 return lightPaint;
165 }
166
167 /**
168 * Helper method that creates and returns the Paint that incorporates the
169 * sizes and light and dark Paints in one TexturePaint. I may want to cache
170 * this value in the future for performance reasons
171 */
172 private Paint getCheckerPaint(JComponent c) {
173 if (checkerPaint == null) {
174 int sqlength = getSquareLength();
175 int length = sqlength * 2;
176 BufferedImage image = new BufferedImage(length, length, BufferedImage.TYPE_INT_ARGB);
177 Graphics2D gfx = image.createGraphics();
178 Paint p = getLightPaint();
179 if (p == null) {
180 p = c.getForeground();
181 }
182 gfx.setPaint(p);
183 gfx.fillRect(0, 0, length, length);
184 p = getDarkPaint();
185 if (p == null) {
186 p = c.getBackground();
187 }
188 gfx.setPaint(p);
189 gfx.fillRect(0, 0, sqlength - 1, sqlength - 1);
190 gfx.fillRect(sqlength, sqlength, sqlength - 1, sqlength - 1);
191 gfx.dispose();
192
193 checkerPaint = new TexturePaint(image, new Rectangle(0, 0, image.getWidth(), image.getHeight()));
194 }
195 return checkerPaint;
196 }
197
198 /**
199 * @inheritDoc
200 */
201 public void paintBackground(Graphics2D g, JComponent component) {
202 g.setPaint(getCheckerPaint(component));
203 g.fillRect(0, 0, component.getWidth(), component.getHeight());
204 }
205 }