001 /*
002 * $Id: MatteBorderExt.java,v 1.4 2005/10/10 18:02:55 rbair 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.border;
023
024 import java.awt.Color;
025 import java.awt.Component;
026 import java.awt.Graphics;
027 import java.awt.Insets;
028
029 import javax.swing.Icon;
030 import javax.swing.border.MatteBorder;
031
032 /**
033 * Matte border that allows specialized icons for corners and sides.
034 *
035 * @author Ramesh Gupta
036 */
037
038 public class MatteBorderExt extends MatteBorder {
039 protected Icon[] tileIcons = null;
040 private Icon defaultIcon = null;
041
042 /**
043 * Draws a matte border using specialized icons for corners and sides. If
044 * tileIcons is null, or if the length of tileIcons array is less than 2, this
045 * defaults to the {@link javax.swing.border.MatteBorder superclass} behavior.
046 * Otherwise, tileIcons must specify icons in clockwise order, starting with
047 * the top-left icon at index zero, culminating with the left icon at index 7.
048 * If the length of the tileIcons array is greater than 1, but less than 8,
049 * then tileIcons[0] is used to paint the corners, and tileIcons[1] is used
050 * to paint the sides, with icons rotated as necessary. Other icons, if any,
051 * are ignored.
052 *
053 * @param top top inset
054 * @param left left inset
055 * @param bottom bottom inset
056 * @param right right inset
057 * @param tileIcons array of icons starting with top-left in index 0,
058 * continuing clockwise through the rest of the indices
059 */
060 public MatteBorderExt(int top, int left, int bottom, int right,
061 Icon[] tileIcons) {
062 super(top, left, bottom, right,
063 (tileIcons == null) || (tileIcons.length == 0) ? null :
064 tileIcons[0]);
065 this.tileIcons = tileIcons;
066 }
067
068 /**
069 * @see MatteBorder#MatteBorder(int, int, int, int, java.awt.Color)
070 */
071 public MatteBorderExt(int top, int left, int bottom, int right,
072 Color matteColor) {
073 super(top, left, bottom, right, matteColor);
074 }
075
076 /**
077 * @see MatteBorder#MatteBorder(java.awt.Insets, java.awt.Color)
078 */
079 public MatteBorderExt(Insets borderInsets, Color matteColor) {
080 super(borderInsets, matteColor);
081 }
082
083 /**
084 * @see MatteBorder#MatteBorder(int, int, int, int, javax.swing.Icon)
085 */
086 public MatteBorderExt(int top, int left, int bottom, int right,
087 Icon tileIcon) {
088 super(top, left, bottom, right, tileIcon);
089 }
090
091 /**
092 * @see MatteBorder#MatteBorder(java.awt.Insets, javax.swing.Icon)
093 */
094 public MatteBorderExt(Insets borderInsets, Icon tileIcon) {
095 super(borderInsets, tileIcon);
096 }
097
098 /**
099 * @see MatteBorder#MatteBorder(javax.swing.Icon)
100 */
101 public MatteBorderExt(Icon tileIcon) {
102 super(tileIcon);
103 }
104
105 /**
106 * Returns the icons used by this border
107 *
108 * @return the icons used by this border
109 */
110 public Icon[] getTileIcons() {
111 return tileIcons;
112 }
113
114 /**
115 * {@inheritDoc}
116 */
117 public void paintBorder(Component c, Graphics g, int x, int y,
118 int width, int height) {
119 if ( (tileIcons == null) || (tileIcons.length < 2)) {
120 super.paintBorder(c, g, x, y, width, height);
121 return;
122 }
123
124 Insets insets = getBorderInsets(c);
125 int clipWidth, clipHeight;
126
127 clipWidth = Math.min(width, insets.left); // clip to component width or insets
128 clipHeight = Math.min(height, insets.top); // clip to component height or insets
129
130 if ( (clipWidth <= 0) || (clipHeight <= 0)) {
131 return; // nothing to paint
132 }
133
134 // We now know that we have at least two icons!
135
136 Color oldColor = g.getColor(); // restore before exiting
137 g.translate(x, y); // restore before exiting
138
139 for (int i = 0; i < tileIcons.length; i++) {
140 // Make sure we have an icon to paint with
141 if (tileIcons[i] == null) {
142 tileIcons[i] = getDefaultIcon();
143 }
144 }
145
146 paintTopLeft(c, g, 0, 0, insets.left, insets.top);
147 paintTop(c, g, insets.left, 0, width - insets.left - insets.right, insets.top);
148 paintTopRight(c, g, width - insets.right, 0, insets.right, insets.top);
149 paintRight(c, g, width - insets.right, insets.top, insets.right, height - insets.top - insets.bottom);
150 paintBottomRight(c, g, width - insets.right, height - insets.bottom, insets.right, insets.bottom);
151 paintBottom(c, g, insets.left, height - insets.bottom, width - insets.left - insets.right, insets.bottom);
152 paintBottomLeft(c, g, 0, height - insets.bottom, insets.left, insets.bottom);
153 paintLeft(c, g, 0, insets.top, insets.left, height - insets.top - insets.bottom);
154
155 g.translate( -x, -y); // restore
156 g.setColor(oldColor); // restore
157
158 }
159
160 protected void paint(Icon icon, Component c, Graphics g, int x, int y,
161 int width, int height) {
162 Graphics cg = g.create();
163 cg.setClip(x, y, width, height);
164 int tileW = icon.getIconWidth();
165 int tileH = icon.getIconHeight();
166 int xpos, ypos, startx, starty;
167 for (ypos = 0; height - ypos > 0; ypos += tileH) {
168 for (xpos = 0; width - xpos > 0; xpos += tileW) {
169 icon.paintIcon(c, cg, x+xpos, y+ypos);
170 }
171 }
172 cg.dispose();
173 }
174
175 /**
176 * Only called by paintBorder()
177 */
178 protected void paintTopLeft(Component c, Graphics g, int x, int y, int width, int height) {
179 Graphics cg = g.create();
180 cg.setClip(x, y, width, height);
181 tileIcons[0].paintIcon(c, cg, x, y);
182 cg.dispose();
183 }
184
185 /**
186 * Only called by paintBorder()
187 */
188 protected void paintTop(Component c, Graphics g, int x, int y, int width, int height) {
189 paint(tileIcons[1], c, g, x, y, width, height);
190 }
191
192 /**
193 * Only called by paintBorder()
194 */
195 protected void paintTopRight(Component c, Graphics g, int x, int y, int width, int height) {
196 if (tileIcons.length == 8) {
197 paint(tileIcons[2], c, g, x, y, width, height);
198 }
199 else {
200 Icon icon = tileIcons[0];
201 /** @todo Rotate -90 and paint icon */
202 }
203 }
204
205 /**
206 * Only called by paintBorder()
207 */
208 protected void paintRight(Component c, Graphics g, int x, int y, int width, int height) {
209 if (tileIcons.length == 8) {
210 paint(tileIcons[3], c, g, x, y, width, height);
211 }
212 else {
213 Icon icon = tileIcons[1];
214 /** @todo Rotate -90 and paint icon */
215 }
216 }
217
218 /**
219 * Only called by paintBorder()
220 */
221 protected void paintBottomRight(Component c, Graphics g, int x, int y, int width, int height) {
222 if (tileIcons.length == 8) {
223 paint(tileIcons[4], c, g, x, y, width, height);
224 }
225 else {
226 Icon icon = tileIcons[0];
227 /** @todo Rotate -180 and paint icon */
228 }
229 }
230
231 /**
232 * Only called by paintBorder()
233 */
234 protected void paintBottom(Component c, Graphics g, int x, int y, int width, int height) {
235 if (tileIcons.length == 8) {
236 paint(tileIcons[5], c, g, x, y, width, height);
237 }
238 else {
239 Icon icon = tileIcons[1];
240 /** @todo Rotate -180 and paint icon */
241 }
242 }
243
244 /**
245 * Only called by paintBorder()
246 */
247 protected void paintBottomLeft(Component c, Graphics g, int x, int y, int width, int height) {
248 if (tileIcons.length == 8) {
249 paint(tileIcons[6], c, g, x, y, width, height);
250 }
251 else {
252 Icon icon = tileIcons[0];
253 /** @todo Rotate -270 and paint icon */
254 }
255 }
256
257 /**
258 * Only called by paintBorder()
259 */
260 protected void paintLeft(Component c, Graphics g, int x, int y, int width, int height) {
261 if (tileIcons.length == 8) {
262 paint(tileIcons[7], c, g, x, y, width, height);
263 }
264 else {
265 Icon icon = tileIcons[1];
266 /** @todo Rotate -270 and paint icon */
267 }
268 }
269
270 /**
271 * Only called by paintBorder()
272 */
273 protected Icon getDefaultIcon() {
274 if (defaultIcon == null) {
275 defaultIcon = new Icon() {
276 private int width = 3;
277 private int height = 3;
278
279 public int getIconWidth() {
280 return width;
281 }
282
283 public int getIconHeight() {
284 return height;
285 }
286
287 public void paintIcon(Component c, Graphics g, int x, int y) {
288 g.setColor(c.getBackground().darker().darker());
289 //g.translate(x, y);
290 g.fillRect(x, y, width, height);
291 }
292 };
293 }
294 return defaultIcon;
295 }
296 }