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 }