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