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 gnu.java.lang.CPStringBuilder;
  42: 
  43: import java.awt.Graphics;
  44: import java.beans.PropertyChangeEvent;
  45: 
  46: import javax.accessibility.Accessible;
  47: import javax.accessibility.AccessibleContext;
  48: import javax.accessibility.AccessibleRole;
  49: import javax.accessibility.AccessibleState;
  50: import javax.accessibility.AccessibleStateSet;
  51: import javax.accessibility.AccessibleValue;
  52: import javax.swing.border.Border;
  53: import javax.swing.event.ChangeEvent;
  54: import javax.swing.event.ChangeListener;
  55: import javax.swing.plaf.ProgressBarUI;
  56: 
  57: /**
  58:  * A component that displays a visual indicator of the progress of a task. The
  59:  * component has two modes: determinate and indeterminate.  In determinate mode,
  60:  * the <code>JProgressBar</code> fills a percentage of its bar based on its
  61:  * current value. In indeterminate mode, it creates box and bounces it between
  62:  * its bounds.
  63:  * <p>
  64:  * This component has the following properties:
  65:  * </p>
  66:  * <table>
  67:  * <tr><th> Property         </th><th> Stored in   </th><th> Bound? </th></tr>
  68:  * <tr><td> borderPainted    </td><td> progressBar </td><td> yes    </td></tr>
  69:  * <tr><td> changeListeners  </td><td> progressBar </td><td> no     </td></tr>
  70:  * <tr><td> indeterminate    </td><td> progressBar </td><td> yes    </td></tr>
  71:  * <tr><td> maximum          </td><td> model       </td><td> no     </td></tr>
  72:  * <tr><td> minimum          </td><td> model       </td><td> no     </td></tr>
  73:  * <tr><td> model            </td><td> progressBar </td><td> no     </td></tr>
  74:  * <tr><td> orientation      </td><td> progressBar </td><td> yes    </td></tr>
  75:  * <tr><td> percentComplete  </td><td> progressBar </td><td> no     </td></tr>
  76:  * <tr><td> string           </td><td> progressBar </td><td> yes    </td></tr>
  77:  * <tr><td> stringPainted    </td><td> progressBar </td><td> yes    </td></tr>
  78:  * <tr><td> value            </td><td> model       </td><td> no     </td></tr>
  79:  * </table>
  80:  */
  81: public class JProgressBar extends JComponent implements SwingConstants,
  82:                                                         Accessible
  83: {
  84:   /**
  85:    * Provides the accessibility features for the <code>JProgressBar</code>
  86:    * component.
  87:    */
  88:   protected class AccessibleJProgressBar extends AccessibleJComponent
  89:     implements AccessibleValue
  90:   {
  91:     private static final long serialVersionUID = -2938130009392721813L;
  92: 
  93:     /**
  94:      * Creates a new <code>AccessibleJProgressBar</code> instance.
  95:      */
  96:     protected AccessibleJProgressBar()
  97:     {
  98:       // Nothing to do here.
  99:     }
 100: 
 101:     /**
 102:      * Returns a set containing the current state of the {@link JProgressBar}
 103:      * component.
 104:      *
 105:      * @return The accessible state set.
 106:      */
 107:     public AccessibleStateSet getAccessibleStateSet()
 108:     {
 109:       AccessibleStateSet result = super.getAccessibleStateSet();
 110:       if (orientation == JProgressBar.HORIZONTAL)
 111:         result.add(AccessibleState.HORIZONTAL);
 112:       else if (orientation == JProgressBar.VERTICAL)
 113:         result.add(AccessibleState.VERTICAL);
 114:       return result;
 115:     }
 116: 
 117:     /**
 118:      * Returns the accessible role for the <code>JProgressBar</code> component.
 119:      *
 120:      * @return {@link AccessibleRole#PROGRESS_BAR}.
 121:      */
 122:     public AccessibleRole getAccessibleRole()
 123:     {
 124:       return AccessibleRole.PROGRESS_BAR;
 125:     }
 126: 
 127:     /**
 128:      * Returns an object that provides access to the current, minimum and
 129:      * maximum values.
 130:      *
 131:      * @return The accessible value.
 132:      */
 133:     public AccessibleValue getAccessibleValue()
 134:     {
 135:       return this;
 136:     }
 137: 
 138:     /**
 139:      * Returns the current value of the {@link JProgressBar} component, as an
 140:      * {@link Integer}.
 141:      *
 142:      * @return The current value of the {@link JProgressBar} component.
 143:      */
 144:     public Number getCurrentAccessibleValue()
 145:     {
 146:       return new Integer(getValue());
 147:     }
 148: 
 149:     /**
 150:      * Sets the current value of the {@link JProgressBar} component and sends a
 151:      * {@link PropertyChangeEvent} (with the property name
 152:      * {@link AccessibleContext#ACCESSIBLE_VALUE_PROPERTY}) to all registered
 153:      * listeners.  If the supplied value is <code>null</code>, this method
 154:      * does nothing and returns <code>false</code>.
 155:      *
 156:      * @param value  the new progress bar value (<code>null</code> permitted).
 157:      *
 158:      * @return <code>true</code> if the slider value is updated, and
 159:      *     <code>false</code> otherwise.
 160:      */
 161:     public boolean setCurrentAccessibleValue(Number value)
 162:     {
 163:       if (value == null)
 164:         return false;
 165:       Number oldValue = getCurrentAccessibleValue();
 166:       setValue(value.intValue());
 167:       firePropertyChange(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, oldValue,
 168:                          new Integer(getValue()));
 169:       return true;
 170:     }
 171: 
 172:     /**
 173:      * Returns the minimum value of the {@link JProgressBar} component, as an
 174:      * {@link Integer}.
 175:      *
 176:      * @return The minimum value of the {@link JProgressBar} component.
 177:      */
 178:     public Number getMinimumAccessibleValue()
 179:     {
 180:       return new Integer(getMinimum());
 181:     }
 182: 
 183:     /**
 184:      * Returns the maximum value of the {@link JProgressBar} component, as an
 185:      * {@link Integer}.
 186:      *
 187:      * @return The maximum value of the {@link JProgressBar} component.
 188:      */
 189:     public Number getMaximumAccessibleValue()
 190:     {
 191:       return new Integer(getMaximum());
 192:     }
 193:   }
 194: 
 195:   private static final long serialVersionUID = 1980046021813598781L;
 196: 
 197:   /**
 198:    * A flag that determines the mode (<code>true</code> for indeterminate,
 199:    * <code>false</code> for determinate).
 200:    */
 201:   private transient boolean indeterminate = false;
 202: 
 203:   /**
 204:    * The orientation of the <code>JProgressBar</code>
 205:    * ({@link SwingConstants#HORIZONTAL} or {@link SwingConstants#VERTICAL}).
 206:    * Defaults to {@link SwingConstants#HORIZONTAL}.
 207:    * @see #setOrientation(int)
 208:    */
 209:   protected int orientation;
 210: 
 211:   /**
 212:    * A flag the controls whether or not the component's border is painted.
 213:    * The default is <code>true</code>.
 214:    * @see #setBorderPainted(boolean)
 215:    */
 216:   protected boolean paintBorder = true;
 217: 
 218:   /**
 219:    * The model defining the bounds and current value for the progress bar.
 220:    * @see #setModel(BoundedRangeModel)
 221:    */
 222:   protected BoundedRangeModel model;
 223: 
 224:   /**
 225:    * A custom string for display in the progress bar.  If this is
 226:    * <code>null</code>, a default string will be generated.
 227:    * @see #setString(String)
 228:    */
 229:   protected String progressString;
 230: 
 231:   /**
 232:    * A flag that controls whether a string is displayed within the progress
 233:    * bar.
 234:    * @see #setStringPainted(boolean)
 235:    */
 236:   protected boolean paintString = false;
 237: 
 238:   /**
 239:    * A single change event reused for all events.
 240:    * @see #fireStateChanged()
 241:    */
 242:   protected transient ChangeEvent changeEvent;
 243: 
 244:   /**
 245:    * The listener that is registered with the model. */
 246:   protected ChangeListener changeListener;
 247: 
 248:   /**
 249:    * Creates a new <code>JProgressBar</code> with default attributes.  The
 250:    * following defaults are used:
 251:    * <p>
 252:    * <ul>
 253:    * <li><code>value</code>: 0;</li>
 254:    * <li><code>minimum</code>: 0;</li>
 255:    * <li><code>maximum</code>: 100;</li>
 256:    * <li><code>orientation</code>: {@link SwingConstants#HORIZONTAL}.</li>
 257:    * </ul>
 258:    */
 259:   public JProgressBar()
 260:   {
 261:     this(HORIZONTAL, 0, 100);
 262:   }
 263: 
 264:   /**
 265:    * Creates a new <code>JProgressBar</code> with the specified
 266:    * <code>orientation</code>.  The following defaults are used:
 267:    * <p>
 268:    * <ul>
 269:    * <li><code>value</code>: 0;</li>
 270:    * <li><code>minimum</code>: 0;</li>
 271:    * <li><code>maximum</code>: 100;</li>
 272:    * </ul>
 273:    *
 274:    * @param orientation  the orientation ({@link #HORIZONTAL} or
 275:    *     {@link #VERTICAL}).
 276:    *
 277:    * @throws IllegalArgumentException if <code>orientation</code> is not one of
 278:    *     the specified values.
 279:    */
 280:   public JProgressBar(int orientation)
 281:   {
 282:     this(orientation, 0, 100);
 283:   }
 284: 
 285:   /**
 286:    * Creates a new <code>JProgressBar</code> with the specified value range.
 287:    * The following defaults are used:
 288:    * <p>
 289:    * <ul>
 290:    * <li><code>value</code>: <code>minimum</code>;</li>
 291:    * <li><code>orientation</code>: {@link SwingConstants#HORIZONTAL}.</li>
 292:    * </ul>
 293:    *
 294:    * @param minimum  the lower bound of the value range.
 295:    * @param maximum  the upper bound of the value range.
 296:    */
 297:   public JProgressBar(int minimum, int maximum)
 298:   {
 299:     this(HORIZONTAL, minimum, maximum);
 300:   }
 301: 
 302:   /**
 303:    * Creates a new <code>JProgressBar</code> with the specified range and
 304:    * orientation.  The following defaults are used:
 305:    * <p>
 306:    * <ul>
 307:    * <li><code>value</code>: <code>minimum</code>;</li>
 308:    * </ul>
 309:    *
 310:    * @param minimum  the lower bound of the value range.
 311:    * @param maximum  the upper bound of the value range.
 312:    * @param orientation  the orientation ({@link #HORIZONTAL} or
 313:    *     {@link #VERTICAL}).
 314:    *
 315:    * @throws IllegalArgumentException if <code>orientation</code> is not one of
 316:    *     the specified values.
 317:    */
 318:   public JProgressBar(int orientation, int minimum, int maximum)
 319:   {
 320:     model = new DefaultBoundedRangeModel(minimum, 0, minimum, maximum);
 321:     if (orientation != HORIZONTAL && orientation != VERTICAL)
 322:       throw new IllegalArgumentException(orientation
 323:                                          + " is not a legal orientation");
 324:     this.orientation = orientation;
 325:     changeListener = createChangeListener();
 326:     model.addChangeListener(changeListener);
 327:     updateUI();
 328:   }
 329: 
 330:   /**
 331:    * Creates a new <code>JProgressBar</code> with the specified model.  The
 332:    * following defaults are used:
 333:    * <p>
 334:    * <ul>
 335:    * <li><code>orientation</code>: {@link SwingConstants#HORIZONTAL}.</li>
 336:    * </ul>
 337:    *
 338:    * @param model  the model (<code>null</code> not permitted).
 339:    */
 340:   public JProgressBar(BoundedRangeModel model)
 341:   {
 342:     this.model = model;
 343:     changeListener = createChangeListener();
 344:     if (model != null)
 345:       model.addChangeListener(changeListener);
 346:     updateUI();
 347:   }
 348: 
 349:   /**
 350:    * Returns the current value for the <code>JProgressBar</code>.  This value
 351:    * is fetched from the model.
 352:    *
 353:    * @return The current value.
 354:    *
 355:    * @see #setValue(int)
 356:    */
 357:   public int getValue()
 358:   {
 359:     return model.getValue();
 360:   }
 361: 
 362:   /**
 363:    * Sets the current value for the <code>JProgressBar</code>.  The value is
 364:    * stored in the component's <code>model</code> (see {@link #getModel()}).
 365:    * If the new value is different to the old value, a {@link ChangeEvent} is
 366:    * sent to the model's registered listeners.  In turn, this triggers a call
 367:    * to {@link #fireStateChanged()} which will send a <code>ChangeEvent</code>
 368:    * to this component's registered listeners.
 369:    * <p>
 370:    * If <code>value</code> is outside the range <code>minimum</code> to
 371:    * <code>maximum</code>, it will be set to the nearest of those boundary
 372:    * values.
 373:    *
 374:    * @param value  the new value.
 375:    *
 376:    * @see #getValue()
 377:    */
 378:   public void setValue(int value)
 379:   {
 380:     model.setValue(value);
 381:   }
 382: 
 383:   /**
 384:    * Paints the component's border, but only if {@link #isBorderPainted()}
 385:    * returns <code>true</code>.
 386:    *
 387:    * @param graphics  the graphics object to paint with.
 388:    *
 389:    * @see #setBorderPainted(boolean)
 390:    */
 391:   protected void paintBorder(Graphics graphics)
 392:   {
 393:     Border border = getBorder();
 394:     if (paintBorder && border != null)
 395:       border.paintBorder(this, graphics, 0, 0, getWidth(), getHeight());
 396:   }
 397: 
 398:   /**
 399:    * Returns the orientation of the <code>JProgressBar</code> component, which
 400:    * is either {@link SwingConstants#HORIZONTAL} or
 401:    * {@link SwingConstants#VERTICAL}.  The default orientation is
 402:    * <code>HORIZONTAL</code>.
 403:    *
 404:    * @return The orientation.
 405:    *
 406:    * @see #setOrientation(int)
 407:    */
 408:   public int getOrientation()
 409:   {
 410:     return orientation;
 411:   }
 412: 
 413:   /**
 414:    * Sets the orientation for this <code>JProgressBar</code> component and,
 415:    * if the value changes, sends a {@link PropertyChangeEvent} (with the
 416:    * property name <code>"orientation"</code>) to all registered listeners.
 417:    *
 418:    * @param orientation  the orientation ({@link #HORIZONTAL} or
 419:    *     {@link #VERTICAL}).
 420:    *
 421:    * @throws IllegalArgumentException if <code>orientation</code> is not
 422:    *     one of the listed values.
 423:    *
 424:    * @see #getOrientation()
 425:    */
 426:   public void setOrientation(int orientation)
 427:   {
 428:     if (orientation != VERTICAL && orientation != HORIZONTAL)
 429:       throw new IllegalArgumentException(orientation
 430:                                          + " is not a legal orientation");
 431:     if (this.orientation != orientation)
 432:       {
 433:         int oldOrientation = this.orientation;
 434:         this.orientation = orientation;
 435:         firePropertyChange("orientation", oldOrientation, this.orientation);
 436:       }
 437:   }
 438: 
 439:   /**
 440:    * Returns the flag that controls whether or not the string returned by
 441:    * {@link #getString()} is displayed by the <code>JProgressBar</code>
 442:    * component.
 443:    *
 444:    * @return <code>true</code> if the string should be displayed, and
 445:    *     <code>false</code> otherwise.
 446:    *
 447:    * @see #setStringPainted(boolean)
 448:    */
 449:   public boolean isStringPainted()
 450:   {
 451:     return paintString;
 452:   }
 453: 
 454:   /**
 455:    * Sets the flag that controls whether or not the string returned by
 456:    * {@link #getString()} is displayed by the <code>JProgressBar</code>
 457:    * component.  If the flag value changes, a {@link PropertyChangeEvent} (with
 458:    * the property name <code>"stringPainted"</code>) is sent to all registered
 459:    * listeners.
 460:    *
 461:    * @param painted  the new flag value.
 462:    *
 463:    * @see #isStringPainted()
 464:    * @see #setString(String)
 465:    */
 466:   public void setStringPainted(boolean painted)
 467:   {
 468:     if (paintString != painted)
 469:       {
 470:         boolean oldPainted = paintString;
 471:         paintString = painted;
 472:         firePropertyChange("stringPainted", oldPainted, paintString);
 473:       }
 474:   }
 475: 
 476:   /**
 477:    * Returns the string that is painted on the <code>JProgressBar</code> if
 478:    * {@link #isStringPainted()} returns <code>true</code>.  If no string has
 479:    * been explicitly set, this method will return a string displaying the
 480:    * value of {@link #getPercentComplete()}.
 481:    *
 482:    * @return The string.
 483:    *
 484:    * @see #setString(String)
 485:    * @see #setStringPainted(boolean)
 486:    */
 487:   public String getString()
 488:   {
 489:     if (progressString != null)
 490:       return progressString;
 491:     else
 492:       return (int) (getPercentComplete() * 100) + "%";
 493:   }
 494: 
 495:   /**
 496:    * Sets the string to display within the progress bar and, if the new value
 497:    * is different to the old value, sends a {@link PropertyChangeEvent} (with
 498:    * the property name <code>"string"</code>) to all registered listeners. If
 499:    * the string is set to <code>null</code>, {@link #getString()} will return
 500:    * a default string.
 501:    *
 502:    * @param string  the string (<code>null</code> permitted).
 503:    *
 504:    * @see #getString()
 505:    * @see #setStringPainted(boolean)
 506:    */
 507:   public void setString(String string)
 508:   {
 509:     if (((string == null || progressString == null) &&
 510:         string != progressString) || (string != null &&
 511:         ! string.equals(progressString)))
 512:       {
 513:         String oldString = progressString;
 514:         progressString = string;
 515:         firePropertyChange("string", oldString, progressString);
 516:       }
 517:   }
 518: 
 519:   /**
 520:    * Returns the current value expressed as a percentage.  This is calculated
 521:    * as <code>(value - min) / (max - min)</code>.
 522:    *
 523:    * @return The percentage (a value in the range 0.0 to 1.0).
 524:    */
 525:   public double getPercentComplete()
 526:   {
 527:     if (getMaximum() == getMinimum())
 528:       return 1.0;
 529:     else
 530:       return (double) (model.getValue() - model.getMinimum())
 531:           / (model.getMaximum() - model.getMinimum());
 532:   }
 533: 
 534:   /**
 535:    * Returns a flag that controls whether or not the component's border is
 536:    * painted.  The default value is <code>true</code>.
 537:    *
 538:    * @return <code>true</code> if the component's border should be painted,
 539:    *     and <code>false</code> otherwise.
 540:    *
 541:    * @see #setBorderPainted(boolean)
 542:    */
 543:   public boolean isBorderPainted()
 544:   {
 545:     return paintBorder;
 546:   }
 547: 
 548:   /**
 549:    * Sets the flag that controls whether or not the component's border is
 550:    * painted.  If the flag value is changed, this method sends a
 551:    * {@link PropertyChangeEvent} (with the property name "borderPainted") to
 552:    * all registered listeners.
 553:    *
 554:    * @param painted  the new flag value.
 555:    *
 556:    * @see #isBorderPainted()
 557:    * @see #paintBorder
 558:    */
 559:   public void setBorderPainted(boolean painted)
 560:   {
 561:     if (painted != paintBorder)
 562:       {
 563:         boolean oldPainted = paintBorder;
 564:         paintBorder = painted;
 565:         firePropertyChange("borderPainted", oldPainted, paintBorder);
 566:       }
 567:   }
 568: 
 569:   /**
 570:    * Returns the UI delegate for this <code>JProgressBar</code>.
 571:    *
 572:    * @return The UI delegate.
 573:    */
 574:   public ProgressBarUI getUI()
 575:   {
 576:     return (ProgressBarUI) ui;
 577:   }
 578: 
 579:   /**
 580:    * Sets the UI delegate for this component.
 581:    *
 582:    * @param ui  the new UI delegate.
 583:    */
 584:   public void setUI(ProgressBarUI ui)
 585:   {
 586:     super.setUI(ui);
 587:   }
 588: 
 589:   /**
 590:    * Sets this <code>JProgressBar</code>'s UI delegate to the default
 591:    * (obtained from the {@link UIManager}) for the current look and feel.
 592:    */
 593:   public void updateUI()
 594:   {
 595:     setUI((ProgressBarUI) UIManager.getUI(this));
 596:   }
 597: 
 598:   /**
 599:    * Returns the suffix (<code>"ProgressBarUI"</code> in this case) used to
 600:    * determine the class name for a UI delegate that can provide the look and
 601:    * feel for a <code>JProgressBar</code>.
 602:    *
 603:    * @return <code>"ProgressBarUI"</code>.
 604:    */
 605:   public String getUIClassID()
 606:   {
 607:     return "ProgressBarUI";
 608:   }
 609: 
 610:   /**
 611:    * Creates a new {@link ChangeListener} that calls
 612:    * {@link #fireStateChanged()} whenever it receives a {@link ChangeEvent}
 613:    * (typically from the component's <code>model</code>).  This listener is
 614:    * registered with the progress bar's model, so that changes made to the
 615:    * model directly will automatically result in the progress bar's listeners
 616:    * being notified also.
 617:    *
 618:    * @return A new listener.
 619:    */
 620:   protected ChangeListener createChangeListener()
 621:   {
 622:     return new ChangeListener()
 623:       {
 624:         public void stateChanged(ChangeEvent ce)
 625:         {
 626:           fireStateChanged();
 627:             }
 628:       };
 629:   }
 630: 
 631:   /**
 632:    * Registers a listener with this component so that it will receive
 633:    * notification of component state changes.
 634:    *
 635:    * @param listener  the listener.
 636:    *
 637:    * @see #removeChangeListener(ChangeListener)
 638:    */
 639:   public void addChangeListener(ChangeListener listener)
 640:   {
 641:     listenerList.add(ChangeListener.class, listener);
 642:   }
 643: 
 644:   /**
 645:    * Deregisters a listener so that it no longer receives notification of
 646:    * component state changes.
 647:    *
 648:    * @param listener  the listener.
 649:    *
 650:    * @see #addChangeListener(ChangeListener)
 651:    */
 652:   public void removeChangeListener(ChangeListener listener)
 653:   {
 654:     listenerList.remove(ChangeListener.class, listener);
 655:   }
 656: 
 657:   /**
 658:    * Returns an array of the listeners that are registered with this component.
 659:    * The array may be empty, but is never <code>null</code>.
 660:    *
 661:    * @return An array of listeners.
 662:    *
 663:    * @since 1.4
 664:    */
 665:   public ChangeListener[] getChangeListeners()
 666:   {
 667:     return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
 668:   }
 669: 
 670:   /**
 671:    * Sends a {@link ChangeEvent} to all registered listeners to indicate that
 672:    * the state of the <code>JProgressBar</code> has changed.
 673:    *
 674:    * @see #createChangeListener()
 675:    */
 676:   protected void fireStateChanged()
 677:   {
 678:     Object[] changeListeners = listenerList.getListenerList();
 679:     if (changeEvent == null)
 680:       changeEvent = new ChangeEvent(this);
 681:     for (int i = changeListeners.length - 2; i >= 0; i -= 2)
 682:       {
 683:         if (changeListeners[i] == ChangeListener.class)
 684:           ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
 685:       }
 686:   }
 687: 
 688:   /**
 689:    * Returns the model for the <code>JProgressBar</code>.
 690:    *
 691:    * @return The model (never <code>null</code>).
 692:    *
 693:    * @see #setModel(BoundedRangeModel)
 694:    */
 695:   public BoundedRangeModel getModel()
 696:   {
 697:     return model;
 698:   }
 699: 
 700:   /**
 701:    * Sets the model for the <code>JProgressBar</code> and sends a
 702:    * {@link ChangeEvent} to all registered listeners.
 703:    *
 704:    * @param model  the model (<code>null</code> not permitted).
 705:    *
 706:    * @see #getModel()
 707:    */
 708:   public void setModel(BoundedRangeModel model)
 709:   {
 710:     if (model != this.model)
 711:       {
 712:         this.model.removeChangeListener(changeListener);
 713:         this.model = model;
 714:         this.model.addChangeListener(changeListener);
 715:         fireStateChanged();
 716:       }
 717:   }
 718: 
 719:   /**
 720:    * Returns the minimum value for the <code>JProgressBar</code>. This defines
 721:    * the lower bound for the current value, and is stored in the component's
 722:    * <code>model</code>.
 723:    *
 724:    * @return The minimum value.
 725:    *
 726:    * @see #setMinimum(int)
 727:    */
 728:   public int getMinimum()
 729:   {
 730:     return model.getMinimum();
 731:   }
 732: 
 733:   /**
 734:    * Sets the minimum value for the <code>JProgressBar</code>.  The value is
 735:    * stored in the component's <code>model</code> (see {@link #getModel()}).
 736:    * If the new value is different to the old value, a {@link ChangeEvent} is
 737:    * sent to the model's registered listeners.  In turn, this triggers a call
 738:    * to {@link #fireStateChanged()} which will send a <code>ChangeEvent</code>
 739:    * to this component's registered listeners.
 740:    *
 741:    * @param minimum  the minimum value.
 742:    *
 743:    * @see #getMinimum()
 744:    */
 745:   public void setMinimum(int minimum)
 746:   {
 747:     model.setMinimum(minimum);
 748:   }
 749: 
 750:   /**
 751:    * Returns the maximum value for the <code>JProgressBar</code>.  This defines
 752:    * the upper bound for the current value, and is stored in the component's
 753:    * <code>model</code>.
 754:    *
 755:    * @return The maximum value.
 756:    *
 757:    * @see #setMaximum(int)
 758:    */
 759:   public int getMaximum()
 760:   {
 761:     return model.getMaximum();
 762:   }
 763: 
 764:   /**
 765:    * Sets the maximum value for the <code>JProgressBar</code>.  The value is
 766:    * stored in the component's <code>model</code> (see {@link #getModel()}).
 767:    * If the new value is different to the old value, a {@link ChangeEvent} is
 768:    * sent to the model's registered listeners.  In turn, this triggers a call
 769:    * to {@link #fireStateChanged()} which will send a <code>ChangeEvent</code>
 770:    * to this component's registered listeners.
 771:    *
 772:    * @param maximum  the maximum value.
 773:    *
 774:    * @see #getMaximum()
 775:    */
 776:   public void setMaximum(int maximum)
 777:   {
 778:     model.setMaximum(maximum);
 779:   }
 780: 
 781:   /**
 782:    * Returns an implementation-dependent string describing the attributes of
 783:    * this <code>JProgressBar</code>.
 784:    *
 785:    * @return A string describing the attributes of this
 786:    *     <code>JProgressBar</code> (never <code>null</code>).
 787:    */
 788:   protected String paramString()
 789:   {
 790:     String superParamStr = super.paramString();
 791:     CPStringBuilder sb = new CPStringBuilder();
 792:     sb.append(",orientation=");
 793:     if (orientation == HORIZONTAL)
 794:       sb.append("HORIZONTAL");
 795:     else
 796:       sb.append("VERTICAL");
 797:     sb.append(",paintBorder=").append(isBorderPainted());
 798:     sb.append(",paintString=").append(isStringPainted());
 799:     sb.append(",progressString=");
 800:     if (progressString != null)
 801:       sb.append(progressString);
 802:     sb.append(",indeterminateString=").append(isIndeterminate());
 803:     return superParamStr + sb.toString();
 804:   }
 805: 
 806:   /**
 807:    * Sets the flag that controls the mode for this <code>JProgressBar</code>
 808:    * (<code>true</code> for indeterminate mode, and <code>false</code> for
 809:    * determinate mode).  If the flag value changes, this method sends a
 810:    * {@link PropertyChangeEvent} (with the property name
 811:    * <code>"indeterminate"</code>) to all registered listeners.
 812:    * <p>
 813:    * If the <code>JProgressBar</code> is determinate, it paints a percentage
 814:    * of the bar described by its value. If it is indeterminate, it simply
 815:    * bounces a box between the ends of the bar; the value of the
 816:    * <code>JProgressBar</code> is ignored.
 817:    *
 818:    * @param flag  the new flag value.
 819:    *
 820:    * @see #isIndeterminate()
 821:    * @since 1.4
 822:    */
 823:   public void setIndeterminate(boolean flag)
 824:   {
 825:     if (indeterminate != flag)
 826:       {
 827:         indeterminate = flag;
 828:         firePropertyChange("indeterminate", !flag, indeterminate);
 829:       }
 830:   }
 831: 
 832:   /**
 833:    * Returns a flag that indicates the mode for this <code>JProgressBar</code>
 834:    * (<code>true</code> for indeterminate mode, and <code>false</code> for
 835:    * determinate mode).
 836:    *
 837:    * @return A flag indicating the mode for the <code>JProgressBar</code>.
 838:    *
 839:    * @see #setIndeterminate(boolean)
 840:    * @since 1.4
 841:    */
 842:   public boolean isIndeterminate()
 843:   {
 844:     return indeterminate;
 845:   }
 846: 
 847:   /**
 848:    * Returns the object that provides accessibility features for this
 849:    * <code>JProgressBar</code> component.
 850:    *
 851:    * @return The accessible context (an instance of
 852:    *     {@link AccessibleJProgressBar}).
 853:    */
 854:   public AccessibleContext getAccessibleContext()
 855:   {
 856:     if (accessibleContext == null)
 857:       accessibleContext = new AccessibleJProgressBar();
 858: 
 859:     return accessibleContext;
 860:   }
 861: }