001 /* 002 * $Id: MatteBorderExt.java 3256 2009-02-10 20:09:41Z 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 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 164 try { 165 cg.setClip(x, y, width, height); 166 int tileW = icon.getIconWidth(); 167 int tileH = icon.getIconHeight(); 168 int xpos, ypos, startx, starty; 169 for (ypos = 0; height - ypos > 0; ypos += tileH) { 170 for (xpos = 0; width - xpos > 0; xpos += tileW) { 171 icon.paintIcon(c, cg, x + xpos, y + ypos); 172 } 173 } 174 } finally { 175 cg.dispose(); 176 } 177 } 178 179 /** 180 * Only called by paintBorder() 181 */ 182 protected void paintTopLeft(Component c, Graphics g, int x, int y, int width, int height) { 183 Graphics cg = g.create(); 184 185 try { 186 cg.setClip(x, y, width, height); 187 tileIcons[0].paintIcon(c, cg, x, y); 188 } finally { 189 cg.dispose(); 190 } 191 } 192 193 /** 194 * Only called by paintBorder() 195 */ 196 protected void paintTop(Component c, Graphics g, int x, int y, int width, int height) { 197 paint(tileIcons[1], c, g, x, y, width, height); 198 } 199 200 /** 201 * Only called by paintBorder() 202 */ 203 protected void paintTopRight(Component c, Graphics g, int x, int y, int width, int height) { 204 if (tileIcons.length == 8) { 205 paint(tileIcons[2], c, g, x, y, width, height); 206 } 207 else { 208 Icon icon = tileIcons[0]; 209 /** @todo Rotate -90 and paint icon */ 210 } 211 } 212 213 /** 214 * Only called by paintBorder() 215 */ 216 protected void paintRight(Component c, Graphics g, int x, int y, int width, int height) { 217 if (tileIcons.length == 8) { 218 paint(tileIcons[3], c, g, x, y, width, height); 219 } 220 else { 221 Icon icon = tileIcons[1]; 222 /** @todo Rotate -90 and paint icon */ 223 } 224 } 225 226 /** 227 * Only called by paintBorder() 228 */ 229 protected void paintBottomRight(Component c, Graphics g, int x, int y, int width, int height) { 230 if (tileIcons.length == 8) { 231 paint(tileIcons[4], c, g, x, y, width, height); 232 } 233 else { 234 Icon icon = tileIcons[0]; 235 /** @todo Rotate -180 and paint icon */ 236 } 237 } 238 239 /** 240 * Only called by paintBorder() 241 */ 242 protected void paintBottom(Component c, Graphics g, int x, int y, int width, int height) { 243 if (tileIcons.length == 8) { 244 paint(tileIcons[5], c, g, x, y, width, height); 245 } 246 else { 247 Icon icon = tileIcons[1]; 248 /** @todo Rotate -180 and paint icon */ 249 } 250 } 251 252 /** 253 * Only called by paintBorder() 254 */ 255 protected void paintBottomLeft(Component c, Graphics g, int x, int y, int width, int height) { 256 if (tileIcons.length == 8) { 257 paint(tileIcons[6], c, g, x, y, width, height); 258 } 259 else { 260 Icon icon = tileIcons[0]; 261 /** @todo Rotate -270 and paint icon */ 262 } 263 } 264 265 /** 266 * Only called by paintBorder() 267 */ 268 protected void paintLeft(Component c, Graphics g, int x, int y, int width, int height) { 269 if (tileIcons.length == 8) { 270 paint(tileIcons[7], c, g, x, y, width, height); 271 } 272 else { 273 Icon icon = tileIcons[1]; 274 /** @todo Rotate -270 and paint icon */ 275 } 276 } 277 278 /** 279 * Only called by paintBorder() 280 */ 281 protected Icon getDefaultIcon() { 282 if (defaultIcon == null) { 283 defaultIcon = new Icon() { 284 private int width = 3; 285 private int height = 3; 286 287 public int getIconWidth() { 288 return width; 289 } 290 291 public int getIconHeight() { 292 return height; 293 } 294 295 public void paintIcon(Component c, Graphics g, int x, int y) { 296 g.setColor(c.getBackground().darker().darker()); 297 //g.translate(x, y); 298 g.fillRect(x, y, width, height); 299 } 300 }; 301 } 302 return defaultIcon; 303 } 304 }