Source for javax.swing.plaf.metal.MetalBorders

   1: /* MetalBorders.java
   2:    Copyright (C) 2005 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.plaf.metal;
  40: 
  41: import java.awt.Color;
  42: import java.awt.Component;
  43: import java.awt.Graphics;
  44: import java.awt.Insets;
  45: 
  46: import javax.swing.AbstractButton;
  47: import javax.swing.ButtonModel;
  48: import javax.swing.JButton;
  49: import javax.swing.border.AbstractBorder;
  50: import javax.swing.border.Border;
  51: import javax.swing.plaf.BorderUIResource;
  52: import javax.swing.plaf.UIResource;
  53: import javax.swing.plaf.basic.BasicGraphicsUtils;
  54: import javax.swing.plaf.basic.BasicBorders;
  55: 
  56: /**
  57:  * This factory class creates borders for the different Swing components
  58:  * UI.
  59:  *
  60:  * @author Roman Kennke (roman@kennke.org)
  61:  */
  62: public class MetalBorders
  63: {
  64: 
  65:   /** The shared instance for getButtonBorder(). */
  66:   private static Border buttonBorder;
  67: 
  68:   /** The shared instance for getRolloverButtonBorder(). */
  69:   private static Border toolbarButtonBorder;
  70: 
  71:   /**
  72:    * A MarginBorder that gets shared by multiple components.
  73:    * Created on demand by the private helper function {@link
  74:    * #getMarginBorder()}.
  75:    */
  76:   private static BasicBorders.MarginBorder marginBorder;
  77: 
  78:   /**
  79:    * The border that is drawn around Swing buttons.
  80:    */
  81:   public static class MetalButtonBorder
  82:     extends AbstractBorder
  83:     implements UIResource
  84:   {
  85:     /** The borders insets. */
  86:     protected static Insets borderInsets = new Insets(3, 3, 3, 3);
  87: 
  88:     /**
  89:      * Creates a new instance of ButtonBorder.
  90:      */
  91:     public MetalButtonBorder()
  92:     {
  93:     }
  94: 
  95:     /**
  96:      * Paints the button border.
  97:      *
  98:      * @param c the component for which we paint the border
  99:      * @param g the Graphics context to use
 100:      * @param x the X coordinate of the upper left corner of c
 101:      * @param y the Y coordinate of the upper left corner of c
 102:      * @param w the width of c
 103:      * @param h the height of c
 104:      */
 105:     public void paintBorder(Component c, Graphics g, int x, int y, int w,
 106:                             int h)
 107:     {
 108:       ButtonModel bmodel = null;
 109:       
 110:       if (c instanceof AbstractButton)
 111:         bmodel = ((AbstractButton) c).getModel();
 112: 
 113:       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
 114:       Color shadow = MetalLookAndFeel.getControlShadow();
 115:       Color light = MetalLookAndFeel.getWhite();
 116:       Color middle = MetalLookAndFeel.getControl();
 117: 
 118:       // draw dark border
 119:       g.setColor(darkShadow);
 120:       g.drawRect(x, y, w - 2, h - 2);
 121: 
 122:       if (!bmodel.isPressed())
 123:         {
 124:           // draw light border
 125:           g.setColor(light);
 126:           g.drawRect(x + 1, y + 1, w - 2, h - 2);
 127: 
 128:           // draw crossing pixels of both borders
 129:           g.setColor(middle);
 130:           g.drawRect(x + 1, y + h - 2, 0, 0);
 131:           g.drawRect(x + w - 2, y + 1, 0, 0);
 132:         }
 133:       else
 134:         {
 135:           // draw light border
 136:           g.setColor(light);
 137:           g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
 138:           g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
 139: 
 140:           // draw shadow border
 141:           g.setColor(middle);
 142:           g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
 143:           g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
 144: 
 145:           // draw crossing pixels of both borders
 146:           g.setColor(shadow);
 147:           g.drawRect(x + 1, y + h - 2, 0, 0);
 148:           g.drawRect(x + w - 2, y + 1, 0, 0);
 149:         }
 150:     }
 151: 
 152:     /**
 153:      * Returns the insets of the ButtonBorder.
 154:      *
 155:      * @param c the component for which the border is used
 156:      *
 157:      * @return the insets of the ButtonBorder
 158:      */
 159:     public Insets getBorderInsets(Component c)
 160:     {
 161:       return getBorderInsets(c, null);
 162:     }
 163: 
 164:     /**
 165:      * Returns the insets of the ButtonBorder in the specified Insets object.
 166:      *
 167:      * @param c the component for which the border is used
 168:      * @param newInsets the insets object where to put the values
 169:      *
 170:      * @return the insets of the ButtonBorder
 171:      */
 172:     public Insets getBorderInsets(Component c, Insets newInsets)
 173:     {
 174:       if (newInsets == null)
 175:         newInsets = new Insets(0, 0, 0, 0);
 176: 
 177:       AbstractButton b = (AbstractButton) c;
 178:       newInsets.bottom = borderInsets.bottom;
 179:       newInsets.left = borderInsets.left;
 180:       newInsets.right = borderInsets.right;
 181:       newInsets.top = borderInsets.top;
 182:       return newInsets;
 183:     }
 184:   }
 185: 
 186:   /**
 187:    * A border for JScrollPanes.
 188:    */
 189:   public static class ScrollPaneBorder
 190:     extends AbstractBorder
 191:     implements UIResource
 192:   {
 193:     /** The border insets. */
 194:     private static Insets insets = new Insets(1, 1, 2, 2);
 195:     
 196:     /**
 197:      * Constructs a new ScrollPaneBorder.
 198:      */
 199:     public ScrollPaneBorder()
 200:     {
 201:     }
 202:     
 203:     /**
 204:      * Returns the insets of the border for the Component <code>c</code>.
 205:      *
 206:      * @param c the Component for which we return the border insets
 207:      */
 208:     public Insets getBorderInsets(Component c)
 209:     {
 210:       return insets;
 211:     }
 212: 
 213:     /**
 214:      * Paints the border.
 215:      *
 216:      * @param c the Component for which the border is painted
 217:      * @param g the Graphics context
 218:      * @param x the X coordinate of the upper left corner of the border
 219:      * @param y the Y coordinate of the upper left corner of the border
 220:      * @param w the width of the border
 221:      * @param h the height of the border
 222:      */
 223:     public void paintBorder(Component c, Graphics g, int x, int y,
 224:                             int w, int h)
 225:     {
 226:       Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
 227:       Color shadow = MetalLookAndFeel.getControlShadow();
 228:       Color light = MetalLookAndFeel.getWhite();
 229:       Color middle = MetalLookAndFeel.getControl();
 230: 
 231:       // paint top border line
 232:       g.setColor(darkShadow);
 233:       g.drawLine(x, y, x + w - 2, y);
 234: 
 235:       // paint left border line
 236:       g.drawLine(x, y, x, y + h - 2);
 237:  
 238:       // paint right inner border line
 239:       g.drawLine(x + w - 2, y, x + w - 2, y + h + 1);
 240: 
 241:       // paint bottom inner border line
 242:       g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2);
 243: 
 244:       // draw right outer border line
 245:       g.setColor(light);
 246:       g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
 247: 
 248:       // draw bottom outer border line
 249:       g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
 250: 
 251:       // paint the lighter points
 252:       g.setColor(middle);
 253:       g.drawLine(x + w - 1, y, x + w - 1, y);
 254:       g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2);
 255:       g.drawLine(x, y + h - 1, x, y + h - 1);
 256:       g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
 257: 
 258:     }
 259:     
 260:   }
 261:   
 262:   /**
 263:    * This border is used in Toolbar buttons as inner border.
 264:    */
 265:   static class RolloverMarginBorder extends AbstractBorder
 266:   {
 267:     /** The borders insets. */
 268:     protected static Insets borderInsets = new Insets(3, 3, 3, 3);
 269: 
 270:     /**
 271:      * Creates a new instance of RolloverBorder.
 272:      */
 273:     public RolloverMarginBorder()
 274:     {
 275:     }
 276:     
 277:     /**
 278:      * Returns the insets of the RolloverBorder.
 279:      *
 280:      * @param c the component for which the border is used
 281:      *
 282:      * @return the insets of the RolloverBorder
 283:      */
 284:     public Insets getBorderInsets(Component c)
 285:     {
 286:       return getBorderInsets(c, null);
 287:     }
 288: 
 289:     /**
 290:      * Returns the insets of the RolloverMarginBorder in the specified
 291:      * Insets object.
 292:      *
 293:      * @param c the component for which the border is used
 294:      * @param newInsets the insets object where to put the values
 295:      *
 296:      * @return the insets of the RolloverMarginBorder
 297:      */
 298:     public Insets getBorderInsets(Component c, Insets newInsets)
 299:     {
 300:       if (newInsets == null)
 301:         newInsets = new Insets(0, 0, 0, 0);
 302: 
 303:       AbstractButton b = (AbstractButton) c;
 304:       Insets margin = b.getMargin();
 305:       newInsets.bottom = borderInsets.bottom;
 306:       newInsets.left = borderInsets.left;
 307:       newInsets.right = borderInsets.right;
 308:       newInsets.top = borderInsets.top;
 309:       return newInsets;
 310:     }
 311:   }
 312: 
 313:   /**
 314:    * A border implementation for popup menus.
 315:    */
 316:   public static class PopupMenuBorder
 317:     extends AbstractBorder
 318:     implements UIResource
 319:   {
 320: 
 321:     /** The border's insets. */
 322:     protected static Insets borderInsets = new Insets(2, 2, 1, 1);
 323: 
 324:     /**
 325:      * Constructs a new PopupMenuBorder.
 326:      */
 327:     public PopupMenuBorder()
 328:     {
 329:     }
 330:     
 331:     /**
 332:      * Returns the insets of the border, creating a new Insets instance
 333:      * with each call.
 334:      *
 335:      * @param c the component for which we return the border insets
 336:      *          (not used here)
 337:      */
 338:     public Insets getBorderInsets(Component c)
 339:     {
 340:       return getBorderInsets(c, null);
 341:     }
 342:     
 343:     /**
 344:      * Returns the insets of the border, using the supplied Insets instance.
 345:      *
 346:      * @param c the component for which we return the border insets
 347:      *          (not used here)
 348:      * @param i the Insets instance to fill with the Insets values
 349:      */
 350:     public Insets getBorderInsets(Component c, Insets i)
 351:     {
 352:       Insets insets;
 353:       if (i == null)
 354:         insets = new Insets(borderInsets.top, borderInsets.left,
 355:                             borderInsets.bottom, borderInsets.right);
 356:       else
 357:         {
 358:           insets = i;
 359:           insets.top = borderInsets.top;
 360:           insets.left = borderInsets.left;
 361:           insets.bottom = borderInsets.bottom;
 362:           insets.right = borderInsets.right;
 363:         }
 364:       
 365:       return insets;
 366:     }
 367: 
 368:     /**
 369:      * Paints the border for component <code>c</code> using the
 370:      * Graphics context <code>g</code> with the dimension
 371:      * <code>x, y, w, h</code>.
 372:      *
 373:      * @param c the component for which we paint the border
 374:      * @param g the Graphics context to use
 375:      * @param x the X coordinate of the upper left corner of c
 376:      * @param y the Y coordinate of the upper left corner of c
 377:      * @param w the width of c
 378:      * @param h the height of c
 379:      */
 380:     public void paintBorder(Component c, Graphics g, int x, int y, int w,
 381:                             int h)
 382:     {
 383:       Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
 384:       Color light = MetalLookAndFeel.getPrimaryControlHighlight();
 385: 
 386:       // draw dark outer border
 387:       g.setColor(darkShadow);
 388:       g.drawRect(x, y, w - 1, h - 1);
 389:       
 390:       // draw highlighted inner border (only top and left)
 391:       g.setColor(light);
 392:       g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
 393:       g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
 394:     }
 395:     
 396:   }
 397: 
 398:   /**
 399:    * Returns a border for Swing buttons in the Metal Look &amp; Feel.
 400:    *
 401:    * @return a border for Swing buttons in the Metal Look &amp; Feel
 402:    */
 403:   public static Border getButtonBorder()
 404:   {
 405:     if (buttonBorder == null)
 406:       {
 407:         Border outer = new MetalButtonBorder();
 408:         Border inner = getMarginBorder();
 409:         buttonBorder = new BorderUIResource.CompoundBorderUIResource
 410:             (outer, inner);
 411:       }
 412:     return buttonBorder;
 413:   }
 414: 
 415:   /**
 416:    * Returns a border for Toolbar buttons in the Metal Look &amp; Feel.
 417:    *
 418:    * @return a border for Toolbar buttons in the Metal Look &amp; Feel
 419:    */
 420:   static Border getToolbarButtonBorder()
 421:   {
 422:     if (toolbarButtonBorder == null)
 423:       {
 424:         Border outer = new MetalButtonBorder();
 425:         Border inner = new RolloverMarginBorder();
 426:         toolbarButtonBorder = new BorderUIResource.CompoundBorderUIResource
 427:           (outer, inner);
 428:       }
 429:     return toolbarButtonBorder;
 430:   }
 431: 
 432:   /**
 433:    * Returns a shared instance of {@link BasicBorders.MarginBorder}.
 434:    *
 435:    * @return a shared instance of {@link BasicBorders.MarginBorder}
 436:    */
 437:   static Border getMarginBorder()
 438:   {
 439:     if (marginBorder == null)
 440:       marginBorder = new BasicBorders.MarginBorder();
 441:     return marginBorder;
 442:   }
 443: }