Frames | No Frames |
1: /* EtchedBorder.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 looks like an engraving etched into the background 49: * surface, or (in its raised variant) coming out of the surface 50: * plane. Using different constructors, it is possible to either 51: * explicitly specify the border colors, or to let the colors derive 52: * from the background color of the enclosed Component. 53: * 54: * <p><img src="doc-files/EtchedBorder-1.png" width="500" height="200" 55: * alt="[An illustration of the two EtchedBorder variants]" /> 56: * 57: * @author Sascha Brawer (brawer@dandelis.ch) 58: */ 59: public class EtchedBorder extends AbstractBorder 60: { 61: /** 62: * Determined using the <code>serialver</code> tool 63: * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. 64: */ 65: static final long serialVersionUID = 4001244046866360638L; 66: 67: 68: /** 69: * Indicates that the border appears as coming out of the 70: * background. 71: */ 72: public static final int RAISED = 0; 73: 74: 75: /** 76: * Indicates that the border appears as engraved into the 77: * background. 78: */ 79: public static final int LOWERED = 1; 80: 81: 82: /** 83: * The type of this EtchedBorder, which is either {@link #RAISED} 84: * or {@link #LOWERED}. 85: */ 86: protected int etchType; 87: 88: 89: /** 90: * The highlight color, or <code>null</code> to indicate that the 91: * color shall be derived from the background of the enclosed 92: * component. 93: */ 94: protected Color highlight; 95: 96: 97: /** 98: * The shadow color, or <code>null</code> to indicate that the 99: * color shall be derived from the background of the enclosed 100: * component. 101: */ 102: protected Color shadow; 103: 104: 105: /** 106: * Constructs a lowered EtchedBorder. The colors will be derived 107: * from the background color of the enclosed Component when the 108: * border gets painted. 109: */ 110: public EtchedBorder() 111: { 112: this(LOWERED); 113: } 114: 115: 116: /** 117: * Constructs an EtchedBorder with the specified appearance. The 118: * colors will be derived from the background color of the enclosed 119: * Component when the border gets painted. 120: * 121: * <p><img src="doc-files/EtchedBorder-1.png" width="500" height="200" 122: * alt="[An illustration of the two EtchedBorder variants]" /> 123: * 124: * @param etchType the desired appearance of the border. The value 125: * must be either {@link #RAISED} or {@link #LOWERED}. 126: * 127: * @throws IllegalArgumentException if <code>etchType</code> has 128: * an unsupported value. 129: */ 130: public EtchedBorder(int etchType) 131: { 132: if ((etchType != RAISED) && (etchType != LOWERED)) 133: throw new IllegalArgumentException(); 134: 135: this.etchType = etchType; 136: 137: /* The highlight and shadow fields already have a null value 138: * when the constructor gets called, so there is no need to 139: * assign a value here. 140: */ 141: } 142: 143: 144: /** 145: * Constructs a lowered EtchedBorder, explicitly selecting the 146: * colors that will be used for highlight and shadow. 147: * 148: * @param highlight the color that will be used for painting 149: * the highlight part of the border. 150: * 151: * @param shadow the color that will be used for painting 152: * the shadow part of the border. 153: * 154: * @see #EtchedBorder(int, Color, Color) 155: */ 156: public EtchedBorder(Color highlight, Color shadow) 157: { 158: this(LOWERED, highlight, shadow); 159: } 160: 161: 162: /** 163: * Constructs an EtchedBorder with the specified appearance, 164: * explicitly selecting the colors that will be used for 165: * highlight and shadow. 166: * 167: * <p><img src="doc-files/EtchedBorder-2.png" width="500" height="200" 168: * alt="[An illustration that shows which pixels get painted 169: * in what color]" /> 170: * 171: * @param etchType the desired appearance of the border. The value 172: * must be either {@link #RAISED} or {@link #LOWERED}. 173: * 174: * @param highlight the color that will be used for painting 175: * the highlight part of the border. 176: * 177: * @param shadow the color that will be used for painting 178: * the shadow part of the border. 179: * 180: * @throws IllegalArgumentException if <code>etchType</code> has 181: * an unsupported value. 182: */ 183: public EtchedBorder(int etchType, Color highlight, Color shadow) 184: { 185: this(etchType); // Checks the validity of the value. 186: this.highlight = highlight; 187: this.shadow = shadow; 188: } 189: 190: 191: /** 192: * Paints the border for a given component. 193: * 194: * @param c the component whose border is to be painted. 195: * @param g the graphics for painting. 196: * @param x the horizontal position for painting the border. 197: * @param y the vertical position for painting the border. 198: * @param width the width of the available area for painting the border. 199: * @param height the height of the available area for painting the border. 200: */ 201: public void paintBorder(Component c, Graphics g, int x, int y, int width, 202: int height) 203: { 204: switch (etchType) 205: { 206: case RAISED: 207: paintEtchedBorder(g, x, y, width, height, 208: getHighlightColor(c), getShadowColor(c)); 209: break; 210: 211: case LOWERED: 212: paintEtchedBorder(g, x, y, width, height, 213: getShadowColor(c), getHighlightColor(c)); 214: break; 215: } 216: } 217: 218: 219: /** 220: * Measures the width of this border. 221: * 222: * @param c the component whose border is to be measured. 223: * 224: * @return an Insets object whose <code>left</code>, <code>right</code>, 225: * <code>top</code> and <code>bottom</code> fields indicate the 226: * width of the border at the respective edge. 227: * 228: * @see #getBorderInsets(java.awt.Component, java.awt.Insets) 229: */ 230: public Insets getBorderInsets(Component c) 231: { 232: return new Insets(2, 2, 2, 2); 233: } 234: 235: 236: /** 237: * Measures the width of this border, storing the results into a 238: * pre-existing Insets object. 239: * 240: * @param insets an Insets object for holding the result values. 241: * After invoking this method, the <code>left</code>, 242: * <code>right</code>, <code>top</code> and 243: * <code>bottom</code> fields indicate the width of the 244: * border at the respective edge. 245: * 246: * @return the same object that was passed for <code>insets</code>. 247: * 248: * @see #getBorderInsets(Component) 249: */ 250: public Insets getBorderInsets(Component c, Insets insets) 251: { 252: insets.left = insets.right = insets.top = insets.bottom = 2; 253: return insets; 254: } 255: 256: 257: /** 258: * Determines whether this border fills every pixel in its area 259: * when painting. 260: * 261: * <p>If the border colors are derived from the background color of 262: * the enclosed component, the result is <code>true</code> because 263: * the derivation method always returns opaque colors. Otherwise, 264: * the result depends on the opacity of the individual colors. 265: * 266: * @return <code>true</code> if the border is fully opaque, or 267: * <code>false</code> if some pixels of the background 268: * can shine through the border. 269: */ 270: public boolean isBorderOpaque() 271: { 272: // If the colors are to be derived from the enclosed Component's 273: // background color, the border is guaranteed to be fully opaque 274: // because Color.brighten() and Color.darken() always return an 275: // opaque color. 276: return 277: ((highlight == null) || (highlight.getAlpha() == 255)) 278: && ((shadow == null) || (shadow.getAlpha() == 255)); 279: } 280: 281: /** 282: * Returns the appearance of this EtchedBorder, which is either 283: * {@link #RAISED} or {@link #LOWERED}. 284: * 285: * @return The type ({@link #RAISED} or {@link #LOWERED}). 286: */ 287: public int getEtchType() 288: { 289: return etchType; 290: } 291: 292: 293: /** 294: * Determines the color that will be used for highlighted parts when 295: * painting the border around a given component. If a highlight 296: * color has been specified upon constructing the border, that color 297: * is returned. Otherwise, the background color of the enclosed 298: * component is brightened. 299: * 300: * @param c the component enclosed by this border. 301: * 302: * @return The color. 303: * 304: * @see java.awt.Component#getBackground() 305: * @see java.awt.Color#brighter() 306: */ 307: public Color getHighlightColor(Component c) 308: { 309: if (highlight != null) 310: return highlight; 311: else 312: return c.getBackground().brighter(); 313: } 314: 315: /** 316: * Returns the color that will be used for highlighted parts when 317: * painting the border, or <code>null</code> if that color will be 318: * derived from the background of the enclosed Component. 319: * 320: * @return The highlight color (possibly <code>null</code>). 321: */ 322: public Color getHighlightColor() 323: { 324: return highlight; 325: } 326: 327: 328: /** 329: * Determines the color that will be used for shadowed parts when 330: * painting the border around a given component. If a shadow color 331: * has been specified upon constructing the border, that color is 332: * returned. Otherwise, the background color of the enclosed 333: * component is darkened. 334: * 335: * @param c the component enclosed by this border. 336: * 337: * @return The shadow color. 338: * 339: * @see java.awt.Component#getBackground() 340: * @see java.awt.Color#darker() 341: */ 342: public Color getShadowColor(Component c) 343: { 344: if (shadow != null) 345: return shadow; 346: else 347: return c.getBackground().darker(); 348: } 349: 350: 351: /** 352: * Returns the color that will be used for shadowed parts when 353: * painting the border, or <code>null</code> if that color will be 354: * derived from the background of the enclosed Component. 355: * 356: * @return The shadow color (possibly <code>null</code>). 357: */ 358: public Color getShadowColor() 359: { 360: return shadow; 361: } 362: 363: 364: /** 365: * Paints a two-pixel etching in two colors. 366: * 367: * <pre> 368: * +++++++++++. 369: * +.........+. + = color a 370: * +. +. . = color b 371: * +. +. 372: * +++++++++++. 373: * ............</pre> 374: * 375: * @param g the graphics for painting. 376: * @param x the horizontal position for painting the border. 377: * @param y the vertical position for painting the border. 378: * @param width the width of the available area for painting the border. 379: * @param height the height of the available area for painting the border. 380: * @param a one of the two colors. 381: * @param b the second of the two colors. 382: */ 383: private static void paintEtchedBorder(Graphics g, int x, int y, int width, 384: int height, Color a, Color b) 385: { 386: Color oldColor; 387: 388: oldColor = g.getColor(); 389: g.translate(x, y); 390: width = width - 1; 391: height = height - 1; 392: 393: try 394: { 395: // To understand this code, it might be helpful to look at the 396: // images that are included with the JavaDoc. They are located 397: // in the "doc-files" subdirectory. EtchedBorder-2.png might 398: // be especially informative. 399: g.setColor(a); 400: g.drawRect(0, 0, width - 1, height - 1); 401: 402: g.setColor(b); 403: g.drawLine(1, 1, width - 2, 1); // top edge 404: g.drawLine(1, 2, 1, height - 2); // left edge 405: g.drawLine(0, height, width, height); // bottom edge 406: g.drawLine(width, 0, width, height - 1); // right edge 407: } 408: finally 409: { 410: g.translate(-x, -y); 411: g.setColor(oldColor); 412: } 413: } 414: }