GNU Classpath (0.17) | ||
Frames | No Frames |
1: /* LineBorder.java -- 2: Copyright (C) 2003 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.border; 40: 41: import java.awt.Color; 42: import java.awt.Component; 43: import java.awt.Graphics; 44: import java.awt.Insets; 45: 46: 47: /** 48: * A border that consists of a line whose thickness and color can be 49: * specified. There also is a variant with rounded corners. 50: * 51: * @author Sascha Brawer (brawer@dandelis.ch) 52: */ 53: public class LineBorder 54: extends AbstractBorder 55: { 56: /** 57: * Determined using the <code>serialver</code> tool 58: * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. 59: */ 60: static final long serialVersionUID = -787563427772288970L; 61: 62: 63: /** 64: * A shared instance of a black, one pixel thick, plain LineBorder. 65: * The singleton object is lazily created by {@link 66: * #createBlackLineBorder()} upon its first invocation. 67: */ 68: private static LineBorder blackLineBorder; 69: 70: 71: /** 72: * A shared instance of a gray, one pixel thick, plain LineBorder. 73: * The singleton object is lazily created by {@link 74: * #createBlackGrayBorder()} upon its first invocation. 75: */ 76: private static LineBorder grayLineBorder; 77: 78: 79: /** 80: * The width of the line in pixels. 81: */ 82: protected int thickness; 83: 84: 85: /** 86: * The color of the line. 87: */ 88: protected Color lineColor; 89: 90: 91: /** 92: * Indicates whether the line is drawn with rounded corners 93: * (<code>true</code>) or not ((<code>false</code>). 94: */ 95: protected boolean roundedCorners; 96: 97: 98: /** 99: * Constructs a LineBorder given its color. The border will be one 100: * pixel thick and have plain corners. 101: * 102: * @param color the color for drawing the border. 103: * 104: * @see #LineBorder(java.awt.Color, int, boolean) 105: */ 106: public LineBorder(Color color) 107: { 108: this(color, /* thickness */ 1, /* roundedCorners */ false); 109: } 110: 111: 112: /** 113: * Constructs a LineBorder given its color and thickness. The 114: * border will have plain corners. 115: * 116: * @param color the color for drawing the border. 117: * @param thickness the width of the line in pixels. 118: * 119: * @see #LineBorder(java.awt.Color, int, boolean) 120: */ 121: public LineBorder(Color color, int thickness) 122: { 123: this (color, thickness, /* roundedCorners */ false); 124: } 125: 126: 127: /** 128: * Constructs a LineBorder given its color, thickness, and whether 129: * it has rounded corners. 130: * 131: * <p><img src="doc-files/LineBorder-1.png" width="500" height="200" 132: * alt="[An illustration of two LineBorders]" /> 133: * 134: * <p>Note that the enlarged view in the right-hand picture shows 135: * that the implementation draws one more pixel than specified, 136: * provided that <code>roundedCorders</code> is <code>true</code> 137: * and anti-aliasing is turned on while painting. While this might 138: * be considered a bug, the Sun reference implementation (at least 139: * JDK 1.3.1 on Apple MacOS X 10.1.5) can be observed to fill 140: * exactly the same pixels as shown above. The GNU Classpath 141: * LineBorder replicates the observed behavior of the Sun 142: * implementation. 143: * 144: * @param color the color for drawing the border. 145: * @param thickness the width of the line in pixels. 146: * @param roundedCorners <code>true</code> for rounded corners, 147: * <code>false</code> for plain corners. 148: * 149: * @since 1.3 150: */ 151: // For the bug mentioned in the JavaDoc, please see also the comment 152: // in the paintBorder method below. 153: // 154: public LineBorder(Color color, int thickness, boolean roundedCorners) 155: { 156: if ((color == null) || (thickness < 0)) 157: throw new IllegalArgumentException(); 158: 159: this.lineColor = color; 160: this.thickness = thickness; 161: this.roundedCorners = roundedCorners; 162: } 163: 164: 165: /** 166: * Returns a black, one pixel thick, plain LineBorder. The method 167: * may always return the same (singleton) LineBorder instance. 168: */ 169: public static Border createBlackLineBorder() 170: { 171: /* Swing is not designed to be thread-safe, so there is no 172: * need to synchronize the access to the global variable. 173: */ 174: if (blackLineBorder == null) 175: blackLineBorder = new LineBorder(Color.black); 176: 177: return blackLineBorder; 178: } 179: 180: 181: /** 182: * Returns a gray, one pixel thick, plain LineBorder. The method 183: * may always return the same (singleton) LineBorder instance. 184: */ 185: public static Border createGrayLineBorder() 186: { 187: /* Swing is not designed to be thread-safe, so there is no 188: * need to synchronize the access to the global variable. 189: */ 190: if (grayLineBorder == null) 191: grayLineBorder = new LineBorder(Color.gray); 192: 193: return grayLineBorder; 194: } 195: 196: 197: /** 198: * Paints the line border around a given Component. 199: * 200: * @param c the component whose border is to be painted. 201: * @param g the graphics for painting. 202: * @param x the horizontal position for painting the border. 203: * @param y the vertical position for painting the border. 204: * @param width the width of the available area for painting the border. 205: * @param height the height of the available area for painting the border. 206: */ 207: public void paintBorder(Component c, Graphics g, 208: int x, int y, int width, int height) 209: { 210: Color oldColor = g.getColor(); 211: 212: try 213: { 214: g.setColor(lineColor); 215: 216: /* If width and height were not adjusted, the border would 217: * appear one pixel too large in both directions. 218: */ 219: width -= 1; 220: height -= 1; 221: 222: /* Blurred, too large appearance 223: * ----------------------------- 224: * While Java 2D has introduced line strokes of arbitrary width, 225: * it seems desirable to keep this code independent of Java 2D. 226: * Therefore, multiple nested rectangles (or rounded rectangles) 227: * are drawn in order to simulate a line whose thickness is 228: * greater than one pixel. 229: * 230: * This hack causes a blurred appearance when anti-aliasing is 231: * on. Interestingly enough, though, the Sun JDK 1.3.1 (at least 232: * on MacOS X 10.1.5) shows exactly the same appearance under 233: * this condition. It thus seems likely that Sun does the same 234: * hack for simulating thick lines. For this reason, the 235: * blurred appearance seems acceptable -- especially since GNU 236: * Classpath tries to be compatible with the Sun reference 237: * implementation. 238: */ 239: for (int i = 0; i < thickness; i++) 240: { 241: if (roundedCorners) 242: g.drawRoundRect(x, y, width, height, thickness, thickness); 243: else 244: g.drawRect(x, y, width, height); 245: 246: x += 1; 247: y += 1; 248: width -= 2; 249: height -= 2; 250: } 251: } 252: finally 253: { 254: g.setColor(oldColor); 255: } 256: } 257: 258: 259: /** 260: * Measures the width of this border. 261: * 262: * @param c the component whose border is to be measured. 263: * 264: * @return an Insets object whose <code>left</code>, <code>right</code>, 265: * <code>top</code> and <code>bottom</code> fields indicate the 266: * width of the border at the respective edge, which is the 267: * thickness of the line. 268: * 269: * @see #getBorderInsets(java.awt.Component, java.awt.Insets) 270: */ 271: public Insets getBorderInsets(Component c) 272: { 273: return new Insets(thickness, thickness, thickness, thickness); 274: } 275: 276: 277: /** 278: * Measures the width of this border, storing the results into a 279: * pre-existing Insets object. 280: * 281: * @param insets an Insets object for holding the result values. 282: * After invoking this method, the <code>left</code>, 283: * <code>right</code>, <code>top</code> and 284: * <code>bottom</code> fields indicate the width of the 285: * border at the respective edge, which is the thickness 286: * of the line. 287: * 288: * @return the same object that was passed for <code>insets</code>. 289: * 290: * @see #getBorderInsets() 291: */ 292: public Insets getBorderInsets(Component c, Insets insets) 293: { 294: insets.left = insets.right = insets.top = insets.bottom = thickness; 295: return insets; 296: } 297: 298: 299: /** 300: * Returns the color of the line. 301: */ 302: public Color getLineColor() 303: { 304: return lineColor; 305: } 306: 307: 308: /** 309: * Returns the thickness of the line in pixels. 310: */ 311: public int getThickness() 312: { 313: return thickness; 314: } 315: 316: 317: /** 318: * Returns whether this LineBorder os drawm with rounded 319: * or with plain corners. 320: * 321: * @return <code>true</code> if the corners are rounded, 322: * <code>false</code> if the corners are plain. 323: */ 324: public boolean getRoundedCorners() 325: { 326: return roundedCorners; 327: } 328: 329: 330: /** 331: * Determines whether this border fills every pixel in its area 332: * when painting. 333: * 334: * @return <code>true</code> if the corners are plain and the line 335: * color is fully opaque; <code>false</code> if the corners 336: * are rounded or the line color is partially transparent. 337: */ 338: public boolean isBorderOpaque() 339: { 340: return (!roundedCorners) && (lineColor.getAlpha() == 255); 341: } 342: }
GNU Classpath (0.17) |