Source for javax.swing.plaf.metal.MetalScrollButton

   1: /* MetalScrollButton.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.Dimension;
  43: import java.awt.Graphics;
  44: import java.awt.Rectangle;
  45: 
  46: import javax.swing.SwingUtilities;
  47: import javax.swing.plaf.basic.BasicArrowButton;
  48: 
  49: /**
  50:  * A button used by the {@link MetalScrollBarUI}.  The button appearance
  51:  * varies according to the button direction, whether or not it is part of a 
  52:  * "free standing" scroll bar, and the current state of the button. 
  53:  */
  54: public class MetalScrollButton extends BasicArrowButton 
  55: {
  56:   
  57:   /** 
  58:    * The maximum size for buttons.
  59:    * @see #getMaximumSize()
  60:    */
  61:   private static Dimension maximumSize;     
  62:   
  63:   /** The width of the button. */
  64:   private int buttonWidth;
  65:   
  66:   /** 
  67:    * A flag that indicates whether the button is part of a free standing 
  68:    * scroll bar.  This affects how the border is drawn.
  69:    */
  70:   private boolean freeStanding;
  71:   
  72:   /**
  73:    * Creates a new button.
  74:    * 
  75:    * @param direction  the direction (this should be one of {@link #NORTH}, 
  76:    *                   {@link #SOUTH}, {@link #EAST} and {@link #WEST}, but 
  77:    *                   this is not enforced).
  78:    * @param width  the button width.
  79:    * @param freeStanding  a flag indicating whether the scroll button is free
  80:    *                      standing or not.
  81:    */
  82:   public MetalScrollButton(int direction, int width, boolean freeStanding)
  83:   {
  84:     super(direction);
  85:     buttonWidth = width;
  86:     this.freeStanding = freeStanding;
  87:     setFocusable(false);
  88:   }
  89:   
  90:   /**
  91:    * Returns the button width.
  92:    * 
  93:    * @return The button width.
  94:    */
  95:   public int getButtonWidth()
  96:   {
  97:     return buttonWidth;   
  98:   }
  99: 
 100:   /**
 101:    * Sets the free standing flag.  This controls how the button border is
 102:    * drawn.
 103:    * 
 104:    * @param freeStanding  the new value of the flag.
 105:    */
 106:   public void setFreeStanding(boolean freeStanding)
 107:   {
 108:     this.freeStanding = freeStanding;
 109:   }
 110:   
 111:   /**
 112:    * Paints the button.
 113:    * 
 114:    * @param g  the graphics device.
 115:    */
 116:   public void paint(Graphics g)
 117:   {
 118:     Rectangle bounds = SwingUtilities.getLocalBounds(this);
 119: 
 120:     // fill the background
 121:     if (getModel().isPressed())
 122:       g.setColor(MetalLookAndFeel.getControlShadow());
 123:     else
 124:       g.setColor(MetalLookAndFeel.getControl());
 125:     g.fillRect(0, 0, bounds.width, bounds.height);
 126:     
 127:     paintArrow(g, bounds.width, bounds.height);
 128:     
 129:     // paint a border manually - I tried using a real (custom) Border
 130:     // but couldn't get it to stay set for the button, something was 
 131:     // overwriting it...
 132:     if (freeStanding) 
 133:       {
 134:         if (direction == WEST)
 135:           paintWestBorderFreeStanding(g, bounds.width, bounds.height);        
 136:         else if (direction == EAST)
 137:           paintEastBorderFreeStanding(g, bounds.width, bounds.height);
 138:         else if (direction == SOUTH)
 139:           paintSouthBorderFreeStanding(g, bounds.width, bounds.height);
 140:         else // asume NORTH
 141:           paintNorthBorderFreeStanding(g, bounds.width, bounds.height);
 142:       }
 143:     else
 144:       {
 145:         if (direction == WEST)
 146:           paintWestBorder(g, bounds.width, bounds.height);        
 147:         else if (direction == EAST)
 148:           paintEastBorder(g, bounds.width, bounds.height);
 149:         else if (direction == SOUTH)
 150:           paintSouthBorder(g, bounds.width, bounds.height);
 151:         else // asume NORTH
 152:           paintNorthBorder(g, bounds.width, bounds.height);
 153:       }
 154:   }
 155:   
 156:   private void paintArrow(Graphics g, int w, int h)
 157:   {
 158:     if (isEnabled())
 159:       g.setColor(MetalLookAndFeel.getBlack());
 160:     else
 161:       g.setColor(MetalLookAndFeel.getControlDisabled());
 162:     
 163:     if (direction == SOUTH)
 164:       {
 165:         int x = w / 2;
 166:         int y = h / 2 + 2;
 167:         for (int i = 1; i < 5; i++)
 168:           g.drawLine(x - i, y - i, x + i - 1, y - i);
 169:       }
 170:     else if (direction == EAST)
 171:       {
 172:         int x = w / 2 + 2;
 173:         int y = h / 2;
 174:         for (int i = 1; i < 5; i++)
 175:           g.drawLine(x - i, y - i, x - i, y + i - 1);
 176:       }
 177:     else if (direction == WEST)
 178:       {
 179:         int x = w / 2 - 3;
 180:         int y = h / 2;
 181:         for (int i = 1; i < 5; i++)
 182:           g.drawLine(x + i, y - i, x + i, y + i - 1);        
 183:       }
 184:     else // assume NORTH
 185:       {
 186:         int x = w / 2;
 187:         int y = h / 2 - 3;
 188:         for (int i = 1; i < 5; i++)
 189:           g.drawLine(x - i, y + i, x + i - 1, y + i);
 190:       }
 191:   }
 192:   /**
 193:    * Paints the border for a button with a {@link #NORTH} direction that
 194:    * belongs to a free standing scroll bar.
 195:    * 
 196:    * @param g  the graphics device.
 197:    * @param w  the button width.
 198:    * @param h  the button height.
 199:    */
 200:   private void paintNorthBorderFreeStanding(Graphics g, int w, int h) 
 201:   {
 202:     if (isEnabled())
 203:       {
 204:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 205:         g.drawLine(0, 0, w - 2, 0);
 206:         g.drawLine(0, 0, 0, h - 1);
 207:         g.drawLine(2, h - 1, w - 2, h - 1);
 208:         g.drawLine(w - 2, 2, w - 2, h - 1);
 209:         
 210:         g.setColor(MetalLookAndFeel.getControlHighlight());
 211:         g.drawLine(1, 1, 1, h - 2);
 212:         g.drawLine(1, 1, w - 3, 1);
 213:         g.drawLine(w - 1, 1, w - 1, h - 1);
 214:       
 215:         g.setColor(MetalLookAndFeel.getControl());
 216:         g.drawLine(1, h - 1, 1, h - 1);
 217:         g.drawLine(w - 2, 1, w - 2, 1);
 218:       }
 219:     else
 220:       {
 221:         g.setColor(MetalLookAndFeel.getControlDisabled());
 222:         g.drawLine(0, 0, w - 1, 0);
 223:         g.drawLine(w - 1, 0, w - 1, h - 1);
 224:         g.drawLine(0, 0, 0, h - 1);
 225:       }
 226:   }
 227:   
 228:   /**
 229:    * Paints the border for a button with a {@link #SOUTH} direction that
 230:    * belongs to a free standing scroll bar.
 231:    * 
 232:    * @param g  the graphics device.
 233:    * @param w  the button width.
 234:    * @param h  the button height.
 235:    */
 236:   private void paintSouthBorderFreeStanding(Graphics g, int w, int h)
 237:   {
 238:     if (isEnabled())
 239:       {
 240:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 241:         g.drawLine(0, 0, w - 2, 0);
 242:         g.drawLine(0, 0, 0, h - 1);
 243:         g.drawLine(2, h - 1, w - 2, h - 1);
 244:         g.drawLine(w - 2, 2, w - 2, h - 1);
 245:         
 246:         g.setColor(MetalLookAndFeel.getControlHighlight());
 247:         g.drawLine(1, 1, 1, h - 1);
 248:         g.drawLine(1, 1, w - 1, 1);
 249:         g.drawLine(w - 1, 1, w - 1, h - 1);
 250:       
 251:         g.setColor(MetalLookAndFeel.getControl());
 252:         g.drawLine(1, h - 1, 1, h - 1);
 253:         g.drawLine(w - 1, 1, w - 1, 1);
 254:       }
 255:     else
 256:       {
 257:         g.setColor(MetalLookAndFeel.getControlDisabled());
 258:         g.drawLine(0, h - 1, w - 1, h - 1);
 259:         g.drawLine(w - 1, 0, w - 1, h - 1);
 260:         g.drawLine(0, 0, 0, h - 1);
 261:       }
 262:   }
 263:   
 264:   /**
 265:    * Paints the border for a button with an {@link #EAST} direction that
 266:    * belongs to a free standing scroll bar.
 267:    * 
 268:    * @param g  the graphics device.
 269:    * @param w  the button width.
 270:    * @param h  the button height.
 271:    */
 272:   private void paintEastBorderFreeStanding(Graphics g, int w, int h)
 273:   {
 274:     if (isEnabled())
 275:       {
 276:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 277:         g.drawLine(0, 0, w - 2, 0);
 278:         g.drawLine(w - 2, 0, w - 2, h - 2);
 279:         g.drawLine(0, h - 2, w - 2, h - 2);
 280:         
 281:         g.setColor(MetalLookAndFeel.getControlHighlight());
 282:         g.drawLine(0, 1, w - 1, 1);
 283:         g.drawLine(w - 1, 1, w - 1, h - 1);
 284:         g.drawLine(0, h - 1, w - 1, h - 1);
 285:       
 286:         g.setColor(MetalLookAndFeel.getControl());
 287:         g.drawLine(w - 2, 1, w - 2, 1);
 288:       }
 289:     else
 290:       {
 291:         g.setColor(MetalLookAndFeel.getControlDisabled());
 292:         g.drawLine(0, 0, w - 1, 0);
 293:         g.drawLine(w - 1, 0, w - 1, h - 1);
 294:         g.drawLine(0, h - 1, w - 1, h - 1);
 295:       }
 296:   }
 297:   
 298:   /**
 299:    * Paints the border for a button with a {@link #WEST} direction that
 300:    * belongs to a free standing scroll bar.
 301:    * 
 302:    * @param g  the graphics device.
 303:    * @param w  the button width.
 304:    * @param h  the button height.
 305:    */
 306:   private void paintWestBorderFreeStanding(Graphics g, int w, int h)
 307:   {
 308:     if (isEnabled())
 309:       {
 310:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 311:         g.drawLine(0, 0, w - 1, 0);
 312:         g.drawLine(0, 0, 0, h - 2);
 313:         g.drawLine(0, h - 2, w - 1, h - 2);
 314:         
 315:         g.setColor(MetalLookAndFeel.getControlHighlight());
 316:         g.drawLine(1, 1, w - 1, 1);
 317:         g.drawLine(1, 1, 1, h - 1);
 318:         g.drawLine(1, h - 1, w - 1, h - 1);
 319:       
 320:         g.setColor(MetalLookAndFeel.getControl());
 321:         g.drawLine(1, h - 2, 1, h - 2);
 322:       }
 323:     else
 324:       {
 325:         g.setColor(MetalLookAndFeel.getControlDisabled());
 326:         g.drawLine(0, 0, w - 1, 0);
 327:         g.drawLine(0, 0, 0, h - 1);
 328:         g.drawLine(0, h - 1, w - 1, h - 1);
 329:       }
 330:   }
 331:   
 332:   /**
 333:    * Paints the border for a button with a {@link #NORTH} direction that
 334:    * belongs to a scroll bar that is not free standing.
 335:    * 
 336:    * @param g  the graphics device.
 337:    * @param w  the button width.
 338:    * @param h  the button height.
 339:    */
 340:   private void paintNorthBorder(Graphics g, int w, int h) 
 341:   {
 342:     if (isEnabled())
 343:       {
 344:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 345:         g.drawLine(0, 0, 0, h - 1);
 346:          
 347:         g.setColor(MetalLookAndFeel.getControlHighlight());
 348:         g.drawLine(1, 0, 1, h - 1);
 349:         g.drawLine(1, 0, w - 1, 0);
 350:       }
 351:     else
 352:       {
 353:         g.setColor(MetalLookAndFeel.getControlDisabled());
 354:         g.drawLine(0, 0, 0, h - 1);
 355:       }
 356:   }
 357:   
 358:   /**
 359:    * Paints the border for a button with a {@link #SOUTH} direction that
 360:    * belongs to a scroll bar that is not free standing.
 361:    * 
 362:    * @param g  the graphics device.
 363:    * @param w  the button width.
 364:    * @param h  the button height.
 365:    */
 366:   private void paintSouthBorder(Graphics g, int w, int h)
 367:   {
 368:     if (isEnabled())
 369:       {
 370:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 371:         g.drawLine(0, 0, 0, h - 1);
 372:         g.drawLine(0, h - 1, w - 1, h - 1);
 373:          
 374:         g.setColor(MetalLookAndFeel.getControlHighlight());
 375:         g.drawLine(1, 0, 1, h - 1);
 376:         g.drawLine(1, 0, w - 1, 0);
 377:         
 378:         g.setColor(MetalLookAndFeel.getControl());
 379:         g.drawLine(1, h - 1, 1, h - 1);
 380:       }
 381:     else
 382:       {
 383:         g.setColor(MetalLookAndFeel.getControlDisabled());
 384:         g.drawLine(0, 0, 0, h - 1);
 385:       }
 386:   }
 387: 
 388:   /**
 389:    * Paints the border for a button with an {@link #EAST} direction that
 390:    * belongs to a scroll bar that is not free standing.
 391:    * 
 392:    * @param g  the graphics device.
 393:    * @param w  the button width.
 394:    * @param h  the button height.
 395:    */
 396:   private void paintEastBorder(Graphics g, int w, int h)
 397:   {
 398:     if (isEnabled())
 399:       {
 400:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 401:         g.drawLine(0, 0, w - 1, 0);
 402:         g.drawLine(w - 1, 2, w - 1, h - 1);
 403:         g.setColor(MetalLookAndFeel.getControlHighlight());
 404:         g.drawLine(0, 1, w - 2, 1);
 405:         g.drawLine(0, 1, 0, h - 1);
 406:       }
 407:     else
 408:       {
 409:         g.setColor(MetalLookAndFeel.getControlDisabled());
 410:         g.drawLine(0, 0, w - 1, 0);
 411:       }
 412:   }
 413:   
 414:   /**
 415:    * Paints the border for a button with a {@link #WEST} direction that
 416:    * belongs to a scroll bar that is not free standing.
 417:    * 
 418:    * @param g  the graphics device.
 419:    * @param w  the button width.
 420:    * @param h  the button height.
 421:    */
 422:   private void paintWestBorder(Graphics g, int w, int h)
 423:   {
 424:     Rectangle bounds = SwingUtilities.getLocalBounds(this);
 425:     if (isEnabled())
 426:       {
 427:         g.setColor(MetalLookAndFeel.getControlDarkShadow());
 428:         g.drawLine(0, 0, bounds.width - 1, 0);
 429:         g.setColor(MetalLookAndFeel.getControlHighlight());
 430:         g.drawLine(0, 1, bounds.width - 1, 1);
 431:         g.drawLine(0, 1, 0, bounds.height - 1);
 432:       }
 433:     else
 434:       {
 435:         g.setColor(MetalLookAndFeel.getControlDisabled());
 436:         g.drawLine(0, 0, bounds.width - 1, 0);
 437:       }
 438:   }
 439:     
 440:   /**
 441:    * Returns the preferred size for the button, which varies depending on 
 442:    * the direction of the button and whether or not it is free standing.
 443:    * 
 444:    * @return The preferred size.
 445:    */
 446:   public Dimension getPreferredSize()
 447:   {
 448:     int adj = 1;
 449:     if (!freeStanding)
 450:       adj = 2;
 451:     
 452:     if (direction == EAST)
 453:       return new Dimension(buttonWidth - adj, buttonWidth);    
 454:     else if (direction == WEST)
 455:       return new Dimension(buttonWidth - 2, buttonWidth);
 456:     else if (direction == SOUTH)
 457:       return new Dimension(buttonWidth, buttonWidth - adj);
 458:     else // assume NORTH
 459:       return new Dimension(buttonWidth, buttonWidth - 2);
 460:   }
 461:   
 462:   /**
 463:    * Returns the minimum size for the button.
 464:    * 
 465:    * @return The minimum size for the button.
 466:    */
 467:   public Dimension getMinimumSize()
 468:   {
 469:     return getPreferredSize();
 470:   }
 471:  
 472:   /**
 473:    * Returns the maximum size for the button.
 474:    * 
 475:    * @return <code>Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)</code>.
 476:    */
 477:   public Dimension getMaximumSize()
 478:   {
 479:     if (maximumSize == null)
 480:       maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
 481:     return maximumSize; 
 482:   }
 483:   
 484: }