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 }