Source for javax.swing.plaf.basic.BasicProgressBarUI

   1: /* BasicProgressBarUI.java --
   2:    Copyright (C) 2004, 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.basic;
  40: 
  41: import java.awt.Color;
  42: import java.awt.Dimension;
  43: import java.awt.Font;
  44: import java.awt.FontMetrics;
  45: import java.awt.Graphics;
  46: import java.awt.Insets;
  47: import java.awt.Point;
  48: import java.awt.Rectangle;
  49: import java.awt.event.ActionEvent;
  50: import java.awt.event.ActionListener;
  51: import java.awt.font.FontRenderContext;
  52: import java.awt.geom.AffineTransform;
  53: import java.awt.geom.Rectangle2D;
  54: import java.beans.PropertyChangeEvent;
  55: import java.beans.PropertyChangeListener;
  56: 
  57: import javax.swing.JComponent;
  58: import javax.swing.JProgressBar;
  59: import javax.swing.SwingConstants;
  60: import javax.swing.SwingUtilities;
  61: import javax.swing.Timer;
  62: import javax.swing.UIDefaults;
  63: import javax.swing.UIManager;
  64: import javax.swing.event.ChangeEvent;
  65: import javax.swing.event.ChangeListener;
  66: import javax.swing.plaf.ComponentUI;
  67: import javax.swing.plaf.ProgressBarUI;
  68: 
  69: /**
  70:  * The Basic Look and Feel UI delegate for the 
  71:  * JProgressBar.
  72:  */
  73: public class BasicProgressBarUI extends ProgressBarUI
  74: {
  75:   /**
  76:    * A helper class that listens for ChangeEvents 
  77:    * from the progressBar's model.
  78:    *
  79:    * @specnote Apparently this class was intended to be protected,
  80:    *           but was made public by a compiler bug and is now
  81:    *           public for compatibility.
  82:    */
  83:   public class ChangeHandler implements ChangeListener
  84:   {
  85:     /**
  86:      * Called every time the state of the model changes.
  87:      *
  88:      * @param e The ChangeEvent given by the model.
  89:      */
  90:     public void stateChanged(ChangeEvent e)
  91:     {
  92:       // Nothing to do but repaint.
  93:       progressBar.repaint();
  94:     }
  95:   }
  96: 
  97:   /**
  98:    * This helper class is used to listen for 
  99:    * PropertyChangeEvents from the progressBar.
 100:    */
 101:   private class PropertyChangeHandler implements PropertyChangeListener
 102:   {
 103:     /**
 104:      * Called every time the properties of the 
 105:      * progressBar change.
 106:      *
 107:      * @param e The PropertyChangeEvent given by the progressBar.
 108:      */
 109:     public void propertyChange(PropertyChangeEvent e)
 110:     {
 111:       // Only need to listen for indeterminate changes.
 112:       // All other things are done on a repaint.
 113:       if (e.getPropertyName().equals("inderterminate"))
 114:     if (((Boolean) e.getNewValue()).booleanValue())
 115:       startAnimationTimer();
 116:     else
 117:       stopAnimationTimer();
 118:       else
 119:         progressBar.repaint();
 120:     }
 121:   }
 122: 
 123:   /**
 124:    * This helper class is used to listen for 
 125:    * the animationTimer's intervals. On every interval,
 126:    * the bouncing box should move.
 127:    */
 128:   private class Animator implements ActionListener
 129:   {
 130:     /**
 131:      * Called every time the animationTimer reaches
 132:      * its interval.
 133:      *
 134:      * @param e The ActionEvent given by the timer.
 135:      */
 136:     public void actionPerformed(ActionEvent e)
 137:     {
 138:       // Incrementing the animation index will cause
 139:       // a repaint.
 140:       incrementAnimationIndex();
 141:     }
 142:   }
 143: 
 144:   /** The timer used to move the bouncing box. */
 145:   private transient Timer animationTimer;
 146: 
 147:   // The total number of frames must be an even number.
 148:   // The total number of frames is calculated from
 149:   // the cycleTime and repaintInterval given by
 150:   // the basic Look and Feel defaults.
 151:   //
 152:   // +-----------------------------------------------+
 153:   // | frame0 | frame1 | frame2 | frame 3 | frame 4  |
 154:   // |        | frame7 | frame6 | frame 5 |          |
 155:   // +-----------------------------------------------+
 156:   
 157:   /** The current animation index. */
 158:   private transient int animationIndex;
 159: 
 160:   /** The total number of frames.*/
 161:   private transient int numFrames;
 162: 
 163:   /** The helper that moves the bouncing box. */
 164:   private transient Animator animation;
 165: 
 166:   /** The helper that listens for property change events. */
 167:   private transient PropertyChangeHandler propertyListener;
 168: 
 169:   /** The Listener for the model. */
 170:   protected ChangeListener changeListener;
 171: 
 172:   /** The progressBar for this UI. */
 173:   protected JProgressBar progressBar;
 174: 
 175:   /** The length of the cell. The cell is the painted part. */
 176:   private transient int cellLength;
 177: 
 178:   /** The gap between cells. */
 179:   private transient int cellSpacing;
 180: 
 181:   /** The color of the text when the bar is not over it.*/
 182:   private transient Color selectionBackground;
 183: 
 184:   /** The color of the text when the bar is over it. */
 185:   private transient Color selectionForeground;
 186: 
 187:   /**
 188:    * Creates a new BasicProgressBarUI object.
 189:    */
 190:   public BasicProgressBarUI()
 191:   {
 192:     super();
 193:   }
 194: 
 195:   /**
 196:    * Creates a new BasicProgressBarUI for the component.
 197:    *
 198:    * @param x The JComponent to create the UI for.
 199:    *
 200:    * @return A new BasicProgressBarUI.
 201:    */
 202:   public static ComponentUI createUI(JComponent x)
 203:   {
 204:     return new BasicProgressBarUI();
 205:   }
 206: 
 207:   /**
 208:    * This method returns the length of the bar (from the minimum)
 209:    * in pixels (or units that the Graphics object draws in) based
 210:    * on the progressBar's getPercentComplete() value.
 211:    *
 212:    * @param b The insets of the progressBar.
 213:    * @param width The width of the progressBar.
 214:    * @param height The height of the progressBar.
 215:    *
 216:    * @return The length of the bar that should be painted in pixels.
 217:    */
 218:   protected int getAmountFull(Insets b, int width, int height)
 219:   {
 220:     double percentDone = progressBar.getPercentComplete();
 221:     if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
 222:       return (int) (percentDone * (width - b.left - b.right));
 223:     else
 224:       return (int) (percentDone * (height - b.top - b.bottom));
 225:   }
 226: 
 227:   /**
 228:    * The current animation index.
 229:    *
 230:    * @return The current animation index.
 231:    */
 232:   protected int getAnimationIndex()
 233:   {
 234:     return animationIndex;
 235:   }
 236: 
 237:   /**
 238:    * This method returns the size and position of the bouncing box
 239:    * for the current animation index. It stores the values in the 
 240:    * given rectangle and returns it. It returns null if no box should
 241:    * be drawn.
 242:    *
 243:    * @param r The bouncing box rectangle.
 244:    *
 245:    * @return The bouncing box rectangle.
 246:    */
 247:   protected Rectangle getBox(Rectangle r)
 248:   {
 249:     if (!progressBar.isIndeterminate())
 250:       return null;
 251:     //numFrames has to be an even number as defined by spec.
 252:     int iterations = numFrames / 2 + 1;
 253: 
 254:     double boxDependent;
 255:     double boxIndependent;
 256: 
 257:     if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
 258:       {
 259:     Dimension dims = getPreferredInnerHorizontal();
 260:     boxDependent = (double) dims.width / iterations;
 261:     boxIndependent = dims.height;
 262:       }
 263:     else
 264:       {
 265:     Dimension dims = getPreferredInnerVertical();
 266:     boxDependent = (double) dims.height / iterations;
 267:     boxIndependent = dims.width;
 268:       }
 269: 
 270:     Rectangle vr = new Rectangle();
 271:     SwingUtilities.calculateInnerArea(progressBar, vr);
 272: 
 273:     int index = getAnimationIndex();
 274:     if (animationIndex > (numFrames + 1) / 2)
 275:       index = numFrames - getAnimationIndex();
 276: 
 277:     if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
 278:       {
 279:     r.x = vr.x + (int) (index * boxDependent);
 280:     r.y = vr.y;
 281:     r.width = (int) boxDependent;
 282:     r.height = (int) boxIndependent;
 283:       }
 284:     else
 285:       {
 286:     index++;
 287:     r.x = vr.x;
 288:     r.y = vr.height - (int) (index * boxDependent) + vr.y;
 289:     r.width = (int) boxIndependent;
 290:     r.height = (int) boxDependent;
 291:       }
 292: 
 293:     return r;
 294:   }
 295: 
 296:   /**
 297:    * This method returns the length of the cells.
 298:    *
 299:    * @return The cell length.
 300:    */
 301:   protected int getCellLength()
 302:   {
 303:     return cellLength;
 304:   }
 305: 
 306:   /**
 307:    * This method returns the spacing between cells.
 308:    *
 309:    * @return The cell gap.
 310:    */
 311:   protected int getCellSpacing()
 312:   {
 313:     return cellSpacing;
 314:   }
 315: 
 316:   /**
 317:    * This method returns the maximum size of the JComponent.
 318:    * If it returns null, it is up to the LayoutManager
 319:    * to give it a size.
 320:    *
 321:    * @param c The component to find a maximum size for.
 322:    *
 323:    * @return The maximum size.
 324:    */
 325:   public Dimension getMaximumSize(JComponent c)
 326:   {
 327:     return getPreferredSize(c);
 328:   }
 329: 
 330:   /**
 331:    * This method returns the minimum size of the JComponent.
 332:    * If it returns null, it is up to the LayoutManager to
 333:    * give it a size.
 334:    *
 335:    * @param c The component to find a minimum size for.
 336:    *
 337:    * @return The minimum size.
 338:    */
 339:   public Dimension getMinimumSize(JComponent c)
 340:   {
 341:     return getPreferredSize(c);
 342:   }
 343: 
 344:   /**
 345:    * This method returns the preferred size of the inner
 346:    * rectangle (the bounds without the insets) if the
 347:    * progressBar is horizontal.
 348:    *
 349:    * @return The preferred size of the progressBar minus 
 350:    *         insets if it's horizontal.
 351:    */
 352:   protected Dimension getPreferredInnerHorizontal()
 353:   {
 354:     Rectangle vr = new Rectangle();
 355: 
 356:     SwingUtilities.calculateInnerArea(progressBar, vr);
 357: 
 358:     return new Dimension(vr.width, vr.height);
 359:   }
 360: 
 361:   /**
 362:    * This method returns the preferred size of the inner
 363:    * rectangle (the bounds without insets) if the 
 364:    * progressBar is vertical.
 365:    *
 366:    * @return The preferred size of the progressBar minus
 367:    *         insets if it's vertical.
 368:    */
 369:   protected Dimension getPreferredInnerVertical()
 370:   {
 371:     Rectangle vr = new Rectangle();
 372: 
 373:     SwingUtilities.calculateInnerArea(progressBar, vr);
 374: 
 375:     return new Dimension(vr.width, vr.height);
 376:   }
 377: 
 378:   /**
 379:    * This method returns the preferred size of the 
 380:    * given JComponent. If it returns null, then it
 381:    * is up to the LayoutManager to give it a size.
 382:    *
 383:    * @param c The component to find the preferred size for.
 384:    *
 385:    * @return The preferred size of the component.
 386:    */
 387:   public Dimension getPreferredSize(JComponent c)
 388:   {
 389:     // The only thing we need to worry about is
 390:     // the text size.
 391:     Insets insets = c.getInsets();
 392: 
 393:     // make a fontrenderer context so that we can make assumptions about
 394:     // the string bounds
 395:     FontRenderContext ctx = new FontRenderContext(new AffineTransform(),
 396:                                                   false, false);
 397:     Rectangle2D bounds = c.getFont().getStringBounds(progressBar.getString(),
 398:                                                      ctx);
 399:     int textW = (int) bounds.getWidth();
 400:     int textH = (int) bounds.getHeight();
 401: 
 402:     if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
 403:       {
 404:     if (textH < 20)
 405:       textH = 20;
 406:     if (textW < 200)
 407:       textW = 200;
 408:       }
 409:     else
 410:       {
 411:     if (textH < 200)
 412:       textH = 200;
 413:     if (textW < 20)
 414:       textW = 20;
 415:       }
 416:     textW += insets.left + insets.right;
 417:     textH += insets.top + insets.bottom;
 418:     return new Dimension(textW, textH);
 419:   }
 420: 
 421:   /**
 422:    * This method returns the Color that the text is shown in when the bar is
 423:    * not over the text.
 424:    *
 425:    * @return The color of the text when the bar is not over it.
 426:    */
 427:   protected Color getSelectionBackground()
 428:   {
 429:     return selectionBackground;
 430:   }
 431: 
 432:   /**
 433:    * This method returns the Color that the text is shown in  when the bar is
 434:    * over the text.
 435:    *
 436:    * @return The color of the text when the bar is over it.
 437:    */
 438:   protected Color getSelectionForeground()
 439:   {
 440:     return selectionForeground;
 441:   }
 442: 
 443:   /**
 444:    * This method returns the point (the top left of the bounding box)
 445:    * where the text should be painted. 
 446:    *
 447:    * @param g The Graphics object to measure FontMetrics with.
 448:    * @param progressString The string to paint.
 449:    * @param x The x coordinate of the overall bounds box.
 450:    * @param y The y coordinate of the overall bounds box.
 451:    * @param width The width of the overall bounds box.
 452:    * @param height The height of the overall bounds box.
 453:    *
 454:    * @return The top left of the bounding box where text should be painted.
 455:    */
 456:   protected Point getStringPlacement(Graphics g, String progressString, int x,
 457:                                      int y, int width, int height)
 458:   {
 459:     Rectangle tr = new Rectangle();
 460:     Rectangle vr = new Rectangle(x, y, width, height);
 461:     Rectangle ir = new Rectangle();
 462: 
 463:     Font f = g.getFont();
 464:     FontMetrics fm = g.getFontMetrics(f);
 465: 
 466:     SwingUtilities.layoutCompoundLabel(progressBar, fm, progressString, null,
 467:                                        SwingConstants.CENTER,
 468:                                        SwingConstants.CENTER,
 469:                                        SwingConstants.CENTER,
 470:                                        SwingConstants.CENTER, vr, ir, tr, 0);
 471:     return new Point(tr.x, tr.y);
 472:   }
 473: 
 474:   /**
 475:    * This method increments the animation index.
 476:    */
 477:   protected void incrementAnimationIndex()
 478:   {
 479:     animationIndex++;
 480:     //numFrames is like string length, it should be named numFrames or something
 481:     if (animationIndex >= numFrames)
 482:       animationIndex = 0;
 483:     progressBar.repaint();
 484:   }
 485: 
 486:   /**
 487:    * This method paints the progressBar. It delegates its responsibilities
 488:    * to paintDeterminate and paintIndeterminate.
 489:    *
 490:    * @param g The Graphics object to paint with.
 491:    * @param c The JComponent to paint.
 492:    */
 493:   public void paint(Graphics g, JComponent c)
 494:   {
 495:     if (! progressBar.isIndeterminate())
 496:       paintDeterminate(g, c);
 497:     else
 498:       paintIndeterminate(g, c);
 499:   }
 500: 
 501:   /**
 502:    * This method is called if the painting to be done is 
 503:    * for a determinate progressBar.
 504:    *
 505:    * @param g The Graphics object to paint with.
 506:    * @param c The JComponent to paint.
 507:    */
 508:   protected void paintDeterminate(Graphics g, JComponent c)
 509:   {
 510:     Color saved = g.getColor();
 511:     int space = getCellSpacing();
 512:     int len = getCellLength();
 513:     int max = progressBar.getMaximum();
 514:     int min = progressBar.getMinimum();
 515:     int value = progressBar.getValue();
 516: 
 517:     Rectangle vr = new Rectangle();
 518:     SwingUtilities.calculateInnerArea(c, vr);
 519: 
 520:     Rectangle or = c.getBounds();
 521: 
 522:     Insets insets = c.getInsets();
 523: 
 524:     int amountFull = getAmountFull(insets, or.width, or.height);
 525: 
 526:     g.setColor(c.getBackground());
 527:     g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);
 528: 
 529:     if (max != min && len != 0 && value > min)
 530:       {
 531:     int iterations = value / (space + len);
 532: 
 533:     if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
 534:       {
 535:         double spaceInUnits = space * (double) vr.width / (max - min);
 536:         double lenInUnits = len * (double) vr.width / (max - min);
 537:         double currX = vr.x;
 538: 
 539:         g.setColor(c.getForeground());
 540:         g.fill3DRect(vr.x, vr.y, amountFull, vr.height, true);
 541: 
 542:         g.setColor(c.getBackground());
 543:         if (spaceInUnits != 0)
 544:           {
 545:         for (int i = 0; i < iterations; i++)
 546:           {
 547:             currX += lenInUnits;
 548:             g.fill3DRect((int) currX, vr.y, (int) spaceInUnits,
 549:                          vr.height, true);
 550:             currX += spaceInUnits;
 551:           }
 552:           }
 553:       }
 554:     else
 555:       {
 556:         double currY = vr.y;
 557:         double spaceInUnits = space * (double) vr.height / (max - min);
 558:         double lenInUnits = len * (double) vr.height / (max - min);
 559: 
 560:         g.setColor(c.getForeground());
 561:         g.fill3DRect(vr.x, vr.y + vr.height - amountFull, vr.width,
 562:                      amountFull, true);
 563: 
 564:         g.setColor(c.getBackground());
 565: 
 566:         if (spaceInUnits != 0)
 567:           {
 568:         for (int i = 0; i < iterations; i++)
 569:           {
 570:             currY -= lenInUnits + spaceInUnits;
 571:             g.fill3DRect(vr.x, (int) currY, vr.width,
 572:                          (int) spaceInUnits, true);
 573:           }
 574:           }
 575:       }
 576:       }
 577: 
 578:     if (progressBar.isStringPainted() && !progressBar.getString().equals(""))
 579:       paintString(g, 0, 0, or.width, or.height, amountFull, insets);
 580:     g.setColor(saved);
 581:   }
 582: 
 583:   /**
 584:    * This method is called if the painting to be done is for
 585:    * an indeterminate progressBar.
 586:    *
 587:    * @param g The Graphics object to paint with.
 588:    * @param c The JComponent to paint.
 589:    */
 590:   protected void paintIndeterminate(Graphics g, JComponent c)
 591:   {
 592:     //need to paint the box at it's current position. no text is painted since
 593:     //all we're doing is bouncing back and forth
 594:     Color saved = g.getColor();
 595:     Insets insets = c.getInsets();
 596: 
 597:     Rectangle or = c.getBounds();
 598:     Rectangle vr = new Rectangle();
 599:     SwingUtilities.calculateInnerArea(c, vr);
 600: 
 601:     g.setColor(c.getBackground());
 602:     g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);
 603: 
 604:     Rectangle box = new Rectangle();
 605:     getBox(box);
 606: 
 607:     g.setColor(c.getForeground());
 608:     g.fill3DRect(box.x, box.y, box.width, box.height, true);
 609: 
 610:     if (progressBar.isStringPainted() && !progressBar.getString().equals(""))
 611:       paintString(g, 0, 0, or.width, or.height,
 612:                   getAmountFull(insets, or.width, or.height), insets);
 613: 
 614:     g.setColor(saved);
 615:   }
 616: 
 617:   /**
 618:    * This method paints the string for the progressBar.
 619:    *
 620:    * @param g The Graphics object to paint with.
 621:    * @param x The x coordinate of the progressBar.
 622:    * @param y The y coordinate of the progressBar.
 623:    * @param width The width of the progressBar.
 624:    * @param height The height of the progressBar.
 625:    * @param amountFull The amount of the progressBar that has its bar filled.
 626:    * @param b The insets of the progressBar.
 627:    */
 628:   protected void paintString(Graphics g, int x, int y, int width, int height,
 629:                              int amountFull, Insets b)
 630:   {
 631:     // We want to place in the exact center of the bar.
 632:     Point placement = getStringPlacement(g, progressBar.getString(),
 633:                                          x + b.left, y + b.top,
 634:                                          width - b.left - b.right,
 635:                                          height - b.top - b.bottom);
 636:     Color saved = g.getColor();
 637: 
 638:     // FIXME: The Color of the text should use selectionForeground and selectionBackground
 639:     // but that can't be done right now, so we'll use white in the mean time.
 640:     g.setColor(Color.WHITE);
 641: 
 642:     FontMetrics fm = g.getFontMetrics(progressBar.getFont());
 643: 
 644:     g.drawString(progressBar.getString(), placement.x,
 645:                  placement.y + fm.getAscent());
 646: 
 647:     g.setColor(saved);
 648:   }
 649: 
 650:   /**
 651:    * This method sets the current animation index. If the index
 652:    * is greater than the number of frames, it resets to 0.
 653:    *
 654:    * @param newValue The new animation index.
 655:    */
 656:   protected void setAnimationIndex(int newValue)
 657:   {
 658:     animationIndex = (newValue <= numFrames) ? newValue : 0;
 659:     progressBar.repaint();
 660:   }
 661: 
 662:   /**
 663:    * This method sets the cell length.
 664:    *
 665:    * @param cellLen The cell length.
 666:    */
 667:   protected void setCellLength(int cellLen)
 668:   {
 669:     cellLength = cellLen;
 670:   }
 671: 
 672:   /**
 673:    * This method sets the cell spacing.
 674:    *
 675:    * @param cellSpace The cell spacing.
 676:    */
 677:   protected void setCellSpacing(int cellSpace)
 678:   {
 679:     cellSpacing = cellSpace;
 680:   }
 681: 
 682:   /**
 683:    * This method starts the animation timer. It is called
 684:    * when the propertyChangeListener detects that the progressBar
 685:    * has changed to indeterminate mode.
 686:    *
 687:    * @since 1.4
 688:    */
 689:   protected void startAnimationTimer()
 690:   {
 691:     if (animationTimer != null)
 692:       animationTimer.start();
 693:   }
 694: 
 695:   /**
 696:    * This method stops the animation timer. It is called when
 697:    * the propertyChangeListener detects that the progressBar
 698:    * has changed to determinate mode.
 699:    *
 700:    * @since 1.4
 701:    */
 702:   protected void stopAnimationTimer()
 703:   {
 704:     if (animationTimer != null)
 705:       animationTimer.stop();
 706:     setAnimationIndex(0);
 707:   }
 708: 
 709:   /**
 710:    * This method changes the settings for the progressBar to
 711:    * the defaults provided by the current Look and Feel.
 712:    */
 713:   protected void installDefaults()
 714:   {
 715:     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
 716: 
 717:     progressBar.setFont(defaults.getFont("ProgressBar.font"));
 718:     progressBar.setForeground(defaults.getColor("ProgressBar.foreground"));
 719:     progressBar.setBackground(defaults.getColor("ProgressBar.background"));
 720:     progressBar.setBorder(defaults.getBorder("ProgressBar.border"));
 721:     progressBar.setOpaque(true);
 722: 
 723:     selectionForeground = defaults.getColor("ProgressBar.selectionForeground");
 724:     selectionBackground = defaults.getColor("ProgressBar.selectionBackground");
 725:     cellLength = defaults.getInt("ProgressBar.cellLength");
 726:     cellSpacing = defaults.getInt("ProgressBar.cellSpacing");
 727: 
 728:     int repaintInterval = defaults.getInt("ProgressBar.repaintInterval");
 729:     int cycleTime = defaults.getInt("ProgressBar.cycleTime");
 730: 
 731:     if (cycleTime % repaintInterval != 0
 732:         && (cycleTime / repaintInterval) % 2 != 0)
 733:       {
 734:     int div = (cycleTime / repaintInterval) + 2;
 735:     div /= 2;
 736:     div *= 2;
 737:     cycleTime = div * repaintInterval;
 738:       }
 739:     setAnimationIndex(0);
 740:     numFrames = cycleTime / repaintInterval;
 741:     animationTimer.setDelay(repaintInterval);
 742:   }
 743: 
 744:   /**
 745:    * The method uninstalls any defaults that were
 746:    * set by the current Look and Feel.
 747:    */
 748:   protected void uninstallDefaults()
 749:   {
 750:     progressBar.setFont(null);
 751:     progressBar.setForeground(null);
 752:     progressBar.setBackground(null);
 753: 
 754:     selectionForeground = null;
 755:     selectionBackground = null;
 756:   }
 757: 
 758:   /**
 759:    * This method registers listeners to all the 
 760:    * components that this UI delegate needs to listen to.
 761:    */
 762:   protected void installListeners()
 763:   {
 764:     changeListener = new ChangeHandler();
 765:     propertyListener = new PropertyChangeHandler();
 766:     animation = new Animator();
 767: 
 768:     progressBar.addChangeListener(changeListener);
 769:     progressBar.addPropertyChangeListener(propertyListener);
 770:     animationTimer.addActionListener(animation);
 771:   }
 772: 
 773:   /**
 774:    * This method unregisters listeners to all the 
 775:    * components that were listened to.
 776:    */
 777:   protected void uninstallListeners()
 778:   {
 779:     progressBar.removeChangeListener(changeListener);
 780:     progressBar.removePropertyChangeListener(propertyListener);
 781:     animationTimer.removeActionListener(animation);
 782: 
 783:     changeListener = null;
 784:     propertyListener = null;
 785:     animation = null;
 786:   }
 787: 
 788:   /**
 789:    * This method installs the UI for the given JComponent.
 790:    * This includes setting up defaults and listeners as
 791:    * well as initializing any values or objects that
 792:    * the UI may need.
 793:    *
 794:    * @param c The JComponent that is having this UI installed.
 795:    */
 796:   public void installUI(JComponent c)
 797:   {
 798:     super.installUI(c);
 799:     if (c instanceof JProgressBar)
 800:       {
 801:     progressBar = (JProgressBar) c;
 802: 
 803:     animationTimer = new Timer(200, null);
 804:     animationTimer.setRepeats(true);
 805: 
 806:     installDefaults();
 807:     installListeners();
 808:       }
 809:   }
 810: 
 811:   /**
 812:    * This method removes the UI for the given JComponent.
 813:    * This includes removing any listeners or defaults
 814:    * that the installUI may have set up.
 815:    *
 816:    * @param c The JComponent that is having this UI uninstalled.
 817:    */
 818:   public void uninstallUI(JComponent c)
 819:   {
 820:     super.uninstallUI(c);
 821:     uninstallListeners();
 822:     uninstallDefaults();
 823: 
 824:     animationTimer = null;
 825:     progressBar = null;
 826:   }
 827: }