Source for javax.swing.JProgressBar

   1: /* JProgressBar.java --
   2:    Copyright (C) 2002, 2004, 2005, 2006  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;
  40: 
  41: import java.awt.Graphics;
  42: import java.beans.PropertyChangeEvent;
  43: 
  44: import javax.accessibility.Accessible;
  45: import javax.accessibility.AccessibleContext;
  46: import javax.accessibility.AccessibleRole;
  47: import javax.accessibility.AccessibleState;
  48: import javax.accessibility.AccessibleStateSet;
  49: import javax.accessibility.AccessibleValue;
  50: import javax.swing.border.Border;
  51: import javax.swing.event.ChangeEvent;
  52: import javax.swing.event.ChangeListener;
  53: import javax.swing.plaf.ProgressBarUI;
  54: 
  55: /**
  56:  * The ProgressBar is a widget that displays in two modes. In 
  57:  * determinate mode, it displays fills a percentage of its bar
  58:  * based on its current value. In indeterminate mode, it creates
  59:  * box and bounces it between its bounds.
  60:  *
  61:  * <p>
  62:  * JProgressBars have the following properties:
  63:  * </p>
  64:  * 
  65:  * <table>
  66:  * <tr><th> Property         </th><th> Stored in   </th><th> Bound? </th></tr>
  67:  * <tr><td> borderPainted    </td><td> progressBar </td><td> yes    </td></tr>
  68:  * <tr><td> changeListeners  </td><td> progressBar </td><td> no     </td></tr>
  69:  * <tr><td> indeterminate    </td><td> progressBar </td><td> yes    </td></tr> 
  70:  * <tr><td> maximum          </td><td> model       </td><td> no     </td></tr>
  71:  * <tr><td> minimum          </td><td> model       </td><td> no     </td></tr>
  72:  * <tr><td> model            </td><td> progressBar </td><td> no     </td></tr> 
  73:  * <tr><td> orientation      </td><td> progressBar </td><td> yes    </td></tr>
  74:  * <tr><td> percentComplete  </td><td> progressBar </td><td> no     </td></tr>
  75:  * <tr><td> string           </td><td> progressBar </td><td> yes    </td></tr>
  76:  * <tr><td> stringPainted    </td><td> progressBar </td><td> yes    </td></tr>
  77:  * <tr><td> value            </td><td> model       </td><td> no     </td></tr>
  78:  * </table>
  79:  */
  80: public class JProgressBar extends JComponent implements SwingConstants,
  81:                                                         Accessible
  82: {
  83:   /**
  84:    * Provides the accessibility features for the <code>JProgressBar</code>
  85:    * component.
  86:    */
  87:   protected class AccessibleJProgressBar extends AccessibleJComponent
  88:     implements AccessibleValue
  89:   {
  90:     private static final long serialVersionUID = -2938130009392721813L;
  91:   
  92:     /**
  93:      * Creates a new <code>AccessibleJProgressBar</code> instance.
  94:      */
  95:     protected AccessibleJProgressBar()
  96:     {
  97:       // Nothing to do here.
  98:     } 
  99: 
 100:     /**
 101:      * Returns a set containing the current state of the {@link JProgressBar} 
 102:      * component.
 103:      *
 104:      * @return The accessible state set.
 105:      */
 106:     public AccessibleStateSet getAccessibleStateSet()
 107:     {
 108:       AccessibleStateSet result = super.getAccessibleStateSet();
 109:       if (orientation == JProgressBar.HORIZONTAL)
 110:         result.add(AccessibleState.HORIZONTAL);
 111:       else if (orientation == JProgressBar.VERTICAL)
 112:         result.add(AccessibleState.VERTICAL);
 113:       return result;
 114:     } 
 115: 
 116:     /**
 117:      * Returns the accessible role for the <code>JProgressBar</code> component.
 118:      *
 119:      * @return {@link AccessibleRole#PROGRESS_BAR}.
 120:      */
 121:     public AccessibleRole getAccessibleRole()
 122:     {
 123:       return AccessibleRole.PROGRESS_BAR;
 124:     } 
 125: 
 126:     /**
 127:      * Returns an object that provides access to the current, minimum and 
 128:      * maximum values.
 129:      *
 130:      * @return The accessible value.
 131:      */
 132:     public AccessibleValue getAccessibleValue()
 133:     {
 134:       return this;
 135:     } 
 136: 
 137:     /**
 138:      * Returns the current value of the {@link JProgressBar} component, as an
 139:      * {@link Integer}.
 140:      *
 141:      * @return The current value of the {@link JProgressBar} component.
 142:      */
 143:     public Number getCurrentAccessibleValue()
 144:     {
 145:       return new Integer(getValue());
 146:     }
 147: 
 148:     /**
 149:      * Sets the current value of the {@link JProgressBar} component and sends a
 150:      * {@link PropertyChangeEvent} (with the property name 
 151:      * {@link AccessibleContext#ACCESSIBLE_VALUE_PROPERTY}) to all registered
 152:      * listeners.  If the supplied value is <code>null</code>, this method 
 153:      * does nothing and returns <code>false</code>.
 154:      *
 155:      * @param value  the new progress bar value (<code>null</code> permitted).
 156:      *
 157:      * @return <code>true</code> if the slider value is updated, and 
 158:      *     <code>false</code> otherwise.
 159:      */
 160:     public boolean setCurrentAccessibleValue(Number value)
 161:     {
 162:       if (value == null)
 163:         return false;
 164:       Number oldValue = getCurrentAccessibleValue();
 165:       setValue(value.intValue());
 166:       firePropertyChange(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, oldValue, 
 167:                          new Integer(getValue()));
 168:       return true;
 169:     }
 170: 
 171:     /**
 172:      * Returns the minimum value of the {@link JProgressBar} component, as an
 173:      * {@link Integer}.
 174:      *
 175:      * @return The minimum value of the {@link JProgressBar} component.
 176:      */
 177:     public Number getMinimumAccessibleValue()
 178:     {
 179:       return new Integer(getMinimum());
 180:     }
 181: 
 182:     /**
 183:      * Returns the maximum value of the {@link JProgressBar} component, as an
 184:      * {@link Integer}.
 185:      *
 186:      * @return The maximum value of the {@link JProgressBar} component.
 187:      */
 188:     public Number getMaximumAccessibleValue()
 189:     {
 190:       return new Integer(getMaximum());
 191:     }
 192:   } 
 193: 
 194:   private static final long serialVersionUID = 1980046021813598781L;
 195:   
 196:   /** Whether the ProgressBar is determinate. */
 197:   private transient boolean indeterminate = false;
 198: 
 199:   /** The orientation of the ProgressBar. Always set by constructor. */
 200:   protected int orientation;
 201: 
 202:   /** Whether borders should be painted. */
 203:   protected boolean paintBorder = true;
 204: 
 205:   /** The model describing this ProgressBar. */
 206:   protected BoundedRangeModel model;
 207: 
 208:   /** The string that is displayed by the ProgressBar. */
 209:   protected String progressString;
 210: 
 211:   /** Whether the string should be painted. */
 212:   protected boolean paintString = false;
 213: 
 214:   /** The static changeEvent passed to all ChangeListeners. */
 215:   protected transient ChangeEvent changeEvent;
 216: 
 217:   /** The ChangeListener that listens to the model. */
 218:   protected ChangeListener changeListener;
 219: 
 220:   /**
 221:    * Creates a new horizontally oriented JProgressBar object 
 222:    * with a minimum of 0 and a maximum of 100.
 223:    */
 224:   public JProgressBar()
 225:   {
 226:     this(HORIZONTAL, 0, 100);
 227:   }
 228: 
 229:   /**
 230:    * Creates a new JProgressBar object with a minimum of 0,
 231:    * a maximum of 100, and the given orientation.
 232:    *
 233:    * @param orientation The orientation of the JProgressBar.
 234:    * 
 235:    * @throws IllegalArgumentException if <code>orientation</code> is not either
 236:    *         {@link #HORIZONTAL} or {@link #VERTICAL}.
 237:    */
 238:   public JProgressBar(int orientation)
 239:   {
 240:     this(orientation, 0, 100);
 241:   }
 242: 
 243:   /**
 244:    * Creates a new horizontally oriented JProgressBar object
 245:    * with the given minimum and maximum.
 246:    *
 247:    * @param minimum The minimum of the JProgressBar.
 248:    * @param maximum The maximum of the JProgressBar.
 249:    */
 250:   public JProgressBar(int minimum, int maximum)
 251:   {
 252:     this(HORIZONTAL, minimum, maximum);
 253:   }
 254: 
 255:   /**
 256:    * Creates a new JProgressBar object with the given minimum,
 257:    * maximum, and orientation.
 258:    *
 259:    * @param minimum The minimum of the JProgressBar.
 260:    * @param maximum The maximum of the JProgressBar.
 261:    * @param orientation The orientation of the JProgressBar.
 262:    * 
 263:    * @throws IllegalArgumentException if <code>orientation</code> is not either
 264:    *         {@link #HORIZONTAL} or {@link #VERTICAL}.
 265:    */
 266:   public JProgressBar(int orientation, int minimum, int maximum)
 267:   {
 268:     model = new DefaultBoundedRangeModel(minimum, 0, minimum, maximum);
 269:     if (orientation != HORIZONTAL && orientation != VERTICAL)
 270:       throw new IllegalArgumentException(orientation
 271:                                          + " is not a legal orientation");    
 272:     this.orientation = orientation;
 273:     changeListener = createChangeListener();
 274:     model.addChangeListener(changeListener);
 275:     updateUI();
 276:   }
 277: 
 278:   /**
 279:    * Creates a new horizontally oriented JProgressBar object 
 280:    * with the given model.
 281:    *
 282:    * @param model The model to be used with the JProgressBar.
 283:    */
 284:   public JProgressBar(BoundedRangeModel model)
 285:   {
 286:     this.model = model;
 287:     changeListener = createChangeListener();
 288:     if (model != null)
 289:       model.addChangeListener(changeListener);
 290:     updateUI();    
 291:   }
 292: 
 293:   /**
 294:    * This method returns the current value of the JProgressBar.
 295:    *
 296:    * @return The current value of the JProgressBar.
 297:    */
 298:   public int getValue()
 299:   {
 300:     return model.getValue();
 301:   }
 302: 
 303:   /**
 304:    * This method sets the value of the JProgressBar.
 305:    *
 306:    * @param value The value of the JProgressBar.
 307:    */
 308:   public void setValue(int value)
 309:   {
 310:     model.setValue(value);
 311:   }
 312: 
 313:   /**
 314:    * This method paints the border of the JProgressBar
 315:    *
 316:    * @param graphics The graphics object to paint with.
 317:    */
 318:   protected void paintBorder(Graphics graphics)
 319:   {
 320:     Border border = getBorder();
 321:     if (paintBorder && border != null)
 322:       border.paintBorder(this, graphics, 0, 0,
 323:                          getWidth(),
 324:                          getHeight());
 325:   }
 326: 
 327:   /**
 328:    * This method returns the orientation of the JProgressBar.
 329:    *
 330:    * @return The orientation of the JProgressBar.
 331:    */
 332:   public int getOrientation()
 333:   {
 334:     return orientation;
 335:   }
 336: 
 337:   /**
 338:    * This method changes the orientation property. The orientation of the 
 339:    * JProgressBar can be either horizontal or vertical.
 340:    *
 341:    * @param orientation The orientation of the JProgressBar.
 342:    * @throws IllegalArgumentException if <code>orientation</code> is not
 343:    *         either {@link #HORIZONTAL} or {@link #VERTICAL}.
 344:    */
 345:   public void setOrientation(int orientation)
 346:   {
 347:     if (orientation != VERTICAL && orientation != HORIZONTAL)
 348:       throw new IllegalArgumentException(orientation
 349:                                          + " is not a legal orientation");    
 350:     if (this.orientation != orientation)
 351:       {
 352:     int oldOrientation = this.orientation;
 353:     this.orientation = orientation;
 354:     firePropertyChange("orientation", oldOrientation,
 355:                        this.orientation);
 356:       }
 357:   }
 358: 
 359:   /**
 360:    * This method returns whether the progressString will be painted.
 361:    *
 362:    * @return Whether the string is painted.
 363:    */
 364:   public boolean isStringPainted()
 365:   {
 366:     return paintString;
 367:   }
 368: 
 369:   /**
 370:    * This method changes the stringPainted property.
 371:    *
 372:    * @param painted Whether the string is painted.
 373:    */
 374:   public void setStringPainted(boolean painted)
 375:   {
 376:     if (paintString != painted)
 377:       {
 378:     boolean oldPainted = paintString;
 379:     paintString = painted;
 380:     firePropertyChange("stringPainted", oldPainted,
 381:                        paintString);
 382:       }
 383:   }
 384: 
 385:   /**
 386:    * This method returns the string that is painted if the 
 387:    * stringPainted property is set to true. If there is no
 388:    * string set, it will return a string containing the 
 389:    * JProgressBar's value as a percent.
 390:    *
 391:    * @return The string that is painted.
 392:    */
 393:   public String getString()
 394:   {
 395:     if (progressString != null)
 396:       return progressString;
 397:     else
 398:       return (int) (getPercentComplete() * 100) + "%";
 399:   }
 400: 
 401:   /**
 402:    * This method changes the string property. The string
 403:    * given will be the one painted. If you want to 
 404:    * revert to the default string given, set the
 405:    * string to null.
 406:    *
 407:    * @param string The string to be painted.
 408:    */
 409:   public void setString(String string)
 410:   {
 411:     if (((string == null || progressString == null) &&
 412:         string != progressString) || (string != null &&
 413:     ! string.equals(progressString)))
 414:       {
 415:     String oldString = progressString;
 416:     progressString = string;
 417:     firePropertyChange("string", oldString, progressString);
 418:       }
 419:   }
 420: 
 421:   /**
 422:    * This method returns the percent of the bar
 423:    * that is "complete". (This is the amount value / (max - min)).
 424:    *
 425:    * @return DOCUMENT ME!
 426:    */
 427:   public double getPercentComplete()
 428:   {
 429:     if (getMaximum() == getMinimum())
 430:       return 1.0;
 431:     else
 432:       return (double) (model.getValue() - model.getMinimum()) / (model
 433:                                                                  .getMaximum()
 434:              - model.getMinimum());
 435:   }
 436: 
 437:   /**
 438:    * This method returns whether the border is painted.
 439:    *
 440:    * @return Whether the border is painted.
 441:    */
 442:   public boolean isBorderPainted()
 443:   {
 444:     return paintBorder;
 445:   }
 446: 
 447:   /**
 448:    * This method changes the borderPainted property.
 449:    *
 450:    * @param painted Whether the border is painted.
 451:    */
 452:   public void setBorderPainted(boolean painted)
 453:   {
 454:     if (painted != paintBorder)
 455:       {
 456:     boolean oldPainted = paintBorder;
 457:     paintBorder = painted;
 458:     firePropertyChange("borderPainted", oldPainted,
 459:                        paintBorder);
 460:       }
 461:   }
 462: 
 463:   /**
 464:    * This method returns the JProgressBar's UI delegate.
 465:    *
 466:    * @return This JProgressBar's UI delegate.
 467:    */
 468:   public ProgressBarUI getUI()
 469:   {
 470:     return (ProgressBarUI) ui;
 471:   }
 472: 
 473:   /**
 474:    * This method changes the UI property for this JProgressBar.
 475:    *
 476:    * @param ui The new UI delegate.
 477:    */
 478:   public void setUI(ProgressBarUI ui)
 479:   {
 480:     super.setUI(ui);
 481:   }
 482: 
 483:   /**
 484:    * This method reverts the UI delegate for this JProgressBar
 485:    * to the default for this Look and Feel.
 486:    */
 487:   public void updateUI()
 488:   {
 489:     setUI((ProgressBarUI) UIManager.getUI(this));
 490:   }
 491: 
 492:   /**
 493:    * This method returns the identifier to allow the UIManager
 494:    * to pick the correct class to act as the UI for
 495:    * this JProgressBar.
 496:    *
 497:    * @return The UIClassID: "ProgressBarUI".
 498:    */
 499:   public String getUIClassID()
 500:   {
 501:     return "ProgressBarUI";
 502:   }
 503: 
 504:   /**
 505:    * This method returns a ChangeListener that gets registered
 506:    * model. By default, the ChangeListener, propagates the 
 507:    * ChangeEvents to the ChangeListeners of the JProgressBar.
 508:    *
 509:    * @return A new ChangeListener.
 510:    */
 511:   protected ChangeListener createChangeListener()
 512:   {
 513:     return new ChangeListener()
 514:       {
 515:     public void stateChanged(ChangeEvent ce)
 516:     {
 517:       fireStateChanged();
 518:     }
 519:       };
 520:   }
 521: 
 522:   /**
 523:    * This method adds a ChangeListener to this JProgressBar.
 524:    *
 525:    * @param listener The ChangeListener to add to this JProgressBar.
 526:    */
 527:   public void addChangeListener(ChangeListener listener)
 528:   {
 529:     listenerList.add(ChangeListener.class, listener);
 530:   }
 531: 
 532:   /**
 533:    * This method removes a ChangeListener from this JProgressBar.
 534:    *
 535:    * @param listener The ChangeListener to remove from this JProgressBar.
 536:    */
 537:   public void removeChangeListener(ChangeListener listener)
 538:   {
 539:     listenerList.remove(ChangeListener.class, listener);
 540:   }
 541:   
 542:   /**
 543:    * This method returns an array of all ChangeListeners listening to this
 544:    * progress bar.
 545:    *
 546:    * @return An array of ChangeListeners listening to this progress bar.
 547:    */
 548:   public ChangeListener[] getChangeListeners()
 549:   {
 550:     return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
 551:   }  
 552: 
 553:   /**
 554:    * This method is called when the JProgressBar receives a ChangeEvent
 555:    * from its model. This simply propagates the event (changing the source
 556:    * to the JProgressBar) to the JProgressBar's listeners.
 557:    */
 558:   protected void fireStateChanged()
 559:   {
 560:     Object[] changeListeners = listenerList.getListenerList();
 561:     if (changeEvent == null)
 562:       changeEvent = new ChangeEvent(this);
 563:     for (int i = changeListeners.length - 2; i >= 0; i -= 2)
 564:       {
 565:     if (changeListeners[i] == ChangeListener.class)
 566:       ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
 567:       }
 568:   }
 569: 
 570:   /**
 571:    * This method returns the model used with this JProgressBar.
 572:    *
 573:    * @return The model used with this JProgressBar.
 574:    */
 575:   public BoundedRangeModel getModel()
 576:   {
 577:     return model;
 578:   }
 579: 
 580:   /**
 581:    * This method changes the model property for this JProgressBar.
 582:    *
 583:    * @param model The model to use with this JProgressBar.
 584:    */
 585:   public void setModel(BoundedRangeModel model)
 586:   {
 587:     if (model != this.model)
 588:       {
 589:         this.model.removeChangeListener(changeListener);
 590:     this.model = model;
 591:     this.model.addChangeListener(changeListener);
 592:     fireStateChanged();
 593:       }
 594:   }
 595: 
 596:   /**
 597:    * This method returns the minimum value of this JProgressBar.
 598:    *
 599:    * @return The minimum value of this JProgressBar.
 600:    */
 601:   public int getMinimum()
 602:   {
 603:     return model.getMinimum();
 604:   }
 605: 
 606:   /**
 607:    * This method sets the minimum value of this JProgressBar.
 608:    *
 609:    * @param minimum The minimum value of this JProgressBar.
 610:    */
 611:   public void setMinimum(int minimum)
 612:   {
 613:     model.setMinimum(minimum);
 614:   }
 615: 
 616:   /**
 617:    * This method returns the maximum value of this JProgressBar.
 618:    *
 619:    * @return The maximum value of this JProgressBar.
 620:    */
 621:   public int getMaximum()
 622:   {
 623:     return model.getMaximum();
 624:   }
 625: 
 626:   /**
 627:    * This method sets the maximum value of this JProgressBar.
 628:    *
 629:    * @param maximum The maximum value of this JProgressBar.
 630:    */
 631:   public void setMaximum(int maximum)
 632:   {
 633:     model.setMaximum(maximum);
 634:   }
 635: 
 636:   /**
 637:    * Returns an implementation-dependent string describing the attributes of
 638:    * this <code>JProgressBar</code>.
 639:    *
 640:    * @return A string describing the attributes of this 
 641:    *     <code>JProgressBar</code> (never <code>null</code>).
 642:    */
 643:   protected String paramString()
 644:   {
 645:     String superParamStr = super.paramString();
 646:     StringBuffer sb = new StringBuffer();
 647:     sb.append(",orientation=");
 648:     if (orientation == HORIZONTAL)
 649:       sb.append("HORIZONTAL");
 650:     else
 651:       sb.append("VERTICAL");
 652:     sb.append(",paintBorder=").append(isBorderPainted());
 653:     sb.append(",paintString=").append(isStringPainted());
 654:     sb.append(",progressString=");
 655:     if (progressString != null)
 656:       sb.append(progressString);
 657:     sb.append(",indeterminateString=").append(isIndeterminate());
 658:     return superParamStr + sb.toString();
 659:   }
 660: 
 661:   /**
 662:    * This method changes the indeterminate property. If the
 663:    * JProgressBar is determinate, it paints a percentage
 664:    * of the bar described by its value. If it is indeterminate,
 665:    * it simply bounces a box between the ends of the bar; the 
 666:    * value of the JProgressBar is ignored.
 667:    *
 668:    * @param newValue Whether the JProgressBar is indeterminate.
 669:    */
 670:   public void setIndeterminate(boolean newValue)
 671:   {
 672:     if (indeterminate != newValue)
 673:       {
 674:     boolean olddeter = indeterminate;
 675:     indeterminate = newValue;
 676:     firePropertyChange("indeterminate", olddeter,
 677:                        indeterminate);
 678:       }
 679:   }
 680: 
 681:   /**
 682:    * This method returns whether the JProgressBar is indeterminate.
 683:    *
 684:    * @return Whether this JProgressBar is indeterminate.
 685:    */
 686:   public boolean isIndeterminate()
 687:   {
 688:     return indeterminate;
 689:   }
 690: 
 691:   /**
 692:    * Returns the object that provides accessibility features for this
 693:    * <code>JProgressBar</code> component.
 694:    *
 695:    * @return The accessible context (an instance of 
 696:    *     {@link AccessibleJProgressBar}).
 697:    */
 698:   public AccessibleContext getAccessibleContext()
 699:   {
 700:     if (accessibleContext == null)
 701:       accessibleContext = new AccessibleJProgressBar();
 702:     
 703:     return accessibleContext;
 704:   } 
 705: }