JProgressBar.java 26.1 KB
Newer Older
Tom Tromey committed
1
/* JProgressBar.java --
2
   Copyright (C) 2002, 2004, 2005, 2006  Free Software Foundation, Inc.
Tom Tromey committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing;

41 42
import gnu.java.lang.CPStringBuilder;

Tom Tromey committed
43
import java.awt.Graphics;
44
import java.beans.PropertyChangeEvent;
Tom Tromey committed
45 46 47 48

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
49
import javax.accessibility.AccessibleState;
Tom Tromey committed
50 51 52 53 54 55 56 57
import javax.accessibility.AccessibleStateSet;
import javax.accessibility.AccessibleValue;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ProgressBarUI;

/**
58 59 60 61 62
 * A component that displays a visual indicator of the progress of a task. The
 * component has two modes: determinate and indeterminate.  In determinate mode,
 * the <code>JProgressBar</code> fills a percentage of its bar based on its 
 * current value. In indeterminate mode, it creates box and bounces it between 
 * its bounds.
Tom Tromey committed
63
 * <p>
64
 * This component has the following properties:
Tom Tromey committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
 * </p>
 * <table>
 * <tr><th> Property         </th><th> Stored in   </th><th> Bound? </th></tr>
 * <tr><td> borderPainted    </td><td> progressBar </td><td> yes    </td></tr>
 * <tr><td> changeListeners  </td><td> progressBar </td><td> no     </td></tr>
 * <tr><td> indeterminate    </td><td> progressBar </td><td> yes    </td></tr> 
 * <tr><td> maximum          </td><td> model       </td><td> no     </td></tr>
 * <tr><td> minimum          </td><td> model       </td><td> no     </td></tr>
 * <tr><td> model            </td><td> progressBar </td><td> no     </td></tr> 
 * <tr><td> orientation      </td><td> progressBar </td><td> yes    </td></tr>
 * <tr><td> percentComplete  </td><td> progressBar </td><td> no     </td></tr>
 * <tr><td> string           </td><td> progressBar </td><td> yes    </td></tr>
 * <tr><td> stringPainted    </td><td> progressBar </td><td> yes    </td></tr>
 * <tr><td> value            </td><td> model       </td><td> no     </td></tr>
 * </table>
 */
public class JProgressBar extends JComponent implements SwingConstants,
                                                        Accessible
{
  /**
85 86
   * Provides the accessibility features for the <code>JProgressBar</code>
   * component.
Tom Tromey committed
87 88 89 90 91 92 93
   */
  protected class AccessibleJProgressBar extends AccessibleJComponent
    implements AccessibleValue
  {
    private static final long serialVersionUID = -2938130009392721813L;
  
    /**
94
     * Creates a new <code>AccessibleJProgressBar</code> instance.
Tom Tromey committed
95 96 97
     */
    protected AccessibleJProgressBar()
    {
98
      // Nothing to do here.
Tom Tromey committed
99 100 101
    } 

    /**
102 103
     * Returns a set containing the current state of the {@link JProgressBar} 
     * component.
Tom Tromey committed
104
     *
105
     * @return The accessible state set.
Tom Tromey committed
106 107 108
     */
    public AccessibleStateSet getAccessibleStateSet()
    {
109 110 111 112 113 114
      AccessibleStateSet result = super.getAccessibleStateSet();
      if (orientation == JProgressBar.HORIZONTAL)
        result.add(AccessibleState.HORIZONTAL);
      else if (orientation == JProgressBar.VERTICAL)
        result.add(AccessibleState.VERTICAL);
      return result;
Tom Tromey committed
115 116 117
    } 

    /**
118
     * Returns the accessible role for the <code>JProgressBar</code> component.
Tom Tromey committed
119
     *
120
     * @return {@link AccessibleRole#PROGRESS_BAR}.
Tom Tromey committed
121 122 123 124 125 126 127
     */
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.PROGRESS_BAR;
    } 

    /**
128 129
     * Returns an object that provides access to the current, minimum and 
     * maximum values.
Tom Tromey committed
130
     *
131
     * @return The accessible value.
Tom Tromey committed
132 133 134
     */
    public AccessibleValue getAccessibleValue()
    {
135
      return this;
Tom Tromey committed
136 137 138
    } 

    /**
139 140
     * Returns the current value of the {@link JProgressBar} component, as an
     * {@link Integer}.
Tom Tromey committed
141
     *
142
     * @return The current value of the {@link JProgressBar} component.
Tom Tromey committed
143 144 145
     */
    public Number getCurrentAccessibleValue()
    {
146 147
      return new Integer(getValue());
    }
Tom Tromey committed
148 149

    /**
150 151 152 153 154
     * Sets the current value of the {@link JProgressBar} component and sends a
     * {@link PropertyChangeEvent} (with the property name 
     * {@link AccessibleContext#ACCESSIBLE_VALUE_PROPERTY}) to all registered
     * listeners.  If the supplied value is <code>null</code>, this method 
     * does nothing and returns <code>false</code>.
Tom Tromey committed
155
     *
156
     * @param value  the new progress bar value (<code>null</code> permitted).
Tom Tromey committed
157
     *
158 159
     * @return <code>true</code> if the slider value is updated, and 
     *     <code>false</code> otherwise.
Tom Tromey committed
160
     */
161
    public boolean setCurrentAccessibleValue(Number value)
Tom Tromey committed
162
    {
163 164 165 166 167 168 169 170
      if (value == null)
        return false;
      Number oldValue = getCurrentAccessibleValue();
      setValue(value.intValue());
      firePropertyChange(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, oldValue, 
                         new Integer(getValue()));
      return true;
    }
Tom Tromey committed
171 172

    /**
173 174
     * Returns the minimum value of the {@link JProgressBar} component, as an
     * {@link Integer}.
Tom Tromey committed
175
     *
176
     * @return The minimum value of the {@link JProgressBar} component.
Tom Tromey committed
177 178 179
     */
    public Number getMinimumAccessibleValue()
    {
180 181
      return new Integer(getMinimum());
    }
Tom Tromey committed
182 183

    /**
184 185
     * Returns the maximum value of the {@link JProgressBar} component, as an
     * {@link Integer}.
Tom Tromey committed
186
     *
187
     * @return The maximum value of the {@link JProgressBar} component.
Tom Tromey committed
188 189 190
     */
    public Number getMaximumAccessibleValue()
    {
191 192
      return new Integer(getMaximum());
    }
Tom Tromey committed
193 194 195 196
  } 

  private static final long serialVersionUID = 1980046021813598781L;
  
197 198 199 200
  /** 
   * A flag that determines the mode (<code>true</code> for indeterminate, 
   * <code>false</code> for determinate).
   */
Tom Tromey committed
201 202
  private transient boolean indeterminate = false;

203 204 205 206 207 208
  /** 
   * The orientation of the <code>JProgressBar</code> 
   * ({@link SwingConstants#HORIZONTAL} or {@link SwingConstants#VERTICAL}). 
   * Defaults to {@link SwingConstants#HORIZONTAL}.
   * @see #setOrientation(int)
   */
209
  protected int orientation;
Tom Tromey committed
210

211 212 213 214 215
  /** 
   * A flag the controls whether or not the component's border is painted.
   * The default is <code>true</code>. 
   * @see #setBorderPainted(boolean)
   */
Tom Tromey committed
216 217
  protected boolean paintBorder = true;

218 219 220 221
  /** 
   * The model defining the bounds and current value for the progress bar.
   * @see #setModel(BoundedRangeModel) 
   */
Tom Tromey committed
222 223
  protected BoundedRangeModel model;

224 225 226 227 228
  /** 
   * A custom string for display in the progress bar.  If this is 
   * <code>null</code>, a default string will be generated. 
   * @see #setString(String)
   */
Tom Tromey committed
229 230
  protected String progressString;

231 232 233 234 235
  /** 
   * A flag that controls whether a string is displayed within the progress 
   * bar. 
   * @see #setStringPainted(boolean)
   */
Tom Tromey committed
236 237
  protected boolean paintString = false;

238 239 240 241
  /** 
   * A single change event reused for all events.
   * @see #fireStateChanged() 
   */
Tom Tromey committed
242 243
  protected transient ChangeEvent changeEvent;

244 245
  /** 
   * The listener that is registered with the model. */
Tom Tromey committed
246 247 248
  protected ChangeListener changeListener;

  /**
249 250 251 252 253 254 255 256 257
   * Creates a new <code>JProgressBar</code> with default attributes.  The 
   * following defaults are used:
   * <p>
   * <ul>
   * <li><code>value</code>: 0;</li>
   * <li><code>minimum</code>: 0;</li>
   * <li><code>maximum</code>: 100;</li>
   * <li><code>orientation</code>: {@link SwingConstants#HORIZONTAL}.</li>
   * </ul>  
Tom Tromey committed
258 259 260 261 262 263 264
   */
  public JProgressBar()
  {
    this(HORIZONTAL, 0, 100);
  }

  /**
265 266 267 268 269 270 271 272
   * Creates a new <code>JProgressBar</code> with the specified 
   * <code>orientation</code>.  The following defaults are used:
   * <p>
   * <ul>
   * <li><code>value</code>: 0;</li>
   * <li><code>minimum</code>: 0;</li>
   * <li><code>maximum</code>: 100;</li>
   * </ul>  
Tom Tromey committed
273
   * 
274 275 276 277 278
   * @param orientation  the orientation ({@link #HORIZONTAL} or 
   *     {@link #VERTICAL}).
   * 
   * @throws IllegalArgumentException if <code>orientation</code> is not one of
   *     the specified values.
Tom Tromey committed
279 280 281 282 283 284 285
   */
  public JProgressBar(int orientation)
  {
    this(orientation, 0, 100);
  }

  /**
286 287 288 289 290 291 292 293 294 295
   * Creates a new <code>JProgressBar</code> with the specified value range.
   * The following defaults are used:
   * <p>
   * <ul>
   * <li><code>value</code>: <code>minimum</code>;</li>
   * <li><code>orientation</code>: {@link SwingConstants#HORIZONTAL}.</li>
   * </ul>  
   * 
   * @param minimum  the lower bound of the value range.
   * @param maximum  the upper bound of the value range.
Tom Tromey committed
296 297 298 299 300 301 302
   */
  public JProgressBar(int minimum, int maximum)
  {
    this(HORIZONTAL, minimum, maximum);
  }

  /**
303 304 305 306 307 308 309 310 311 312 313
   * Creates a new <code>JProgressBar</code> with the specified range and
   * orientation.  The following defaults are used:
   * <p>
   * <ul>
   * <li><code>value</code>: <code>minimum</code>;</li>
   * </ul>  
   * 
   * @param minimum  the lower bound of the value range.
   * @param maximum  the upper bound of the value range.
   * @param orientation  the orientation ({@link #HORIZONTAL} or 
   *     {@link #VERTICAL}).
Tom Tromey committed
314
   * 
315 316
   * @throws IllegalArgumentException if <code>orientation</code> is not one of
   *     the specified values.
Tom Tromey committed
317 318 319 320 321
   */
  public JProgressBar(int orientation, int minimum, int maximum)
  {
    model = new DefaultBoundedRangeModel(minimum, 0, minimum, maximum);
    if (orientation != HORIZONTAL && orientation != VERTICAL)
322 323 324
      throw new IllegalArgumentException(orientation
                                         + " is not a legal orientation");    
    this.orientation = orientation;
Tom Tromey committed
325 326 327 328 329 330
    changeListener = createChangeListener();
    model.addChangeListener(changeListener);
    updateUI();
  }

  /**
331 332 333 334 335 336 337 338
   * Creates a new <code>JProgressBar</code> with the specified model.  The
   * following defaults are used:
   * <p>
   * <ul>
   * <li><code>orientation</code>: {@link SwingConstants#HORIZONTAL}.</li>
   * </ul>  
   * 
   * @param model  the model (<code>null</code> not permitted).
Tom Tromey committed
339 340 341 342 343
   */
  public JProgressBar(BoundedRangeModel model)
  {
    this.model = model;
    changeListener = createChangeListener();
344 345
    if (model != null)
      model.addChangeListener(changeListener);
Tom Tromey committed
346 347 348 349
    updateUI();    
  }

  /**
350 351
   * Returns the current value for the <code>JProgressBar</code>.  This value 
   * is fetched from the model.
Tom Tromey committed
352
   *
353 354 355
   * @return The current value.
   * 
   * @see #setValue(int)
Tom Tromey committed
356 357 358 359 360 361 362
   */
  public int getValue()
  {
    return model.getValue();
  }

  /**
363 364 365 366 367 368 369 370 371 372
   * Sets the current value for the <code>JProgressBar</code>.  The value is
   * stored in the component's <code>model</code> (see {@link #getModel()}).  
   * If the new value is different to the old value, a {@link ChangeEvent} is 
   * sent to the model's registered listeners.  In turn, this triggers a call 
   * to {@link #fireStateChanged()} which will send a <code>ChangeEvent</code> 
   * to this component's registered listeners.
   * <p>
   * If <code>value</code> is outside the range <code>minimum</code> to 
   * <code>maximum</code>, it will be set to the nearest of those boundary 
   * values.
Tom Tromey committed
373
   *
374 375 376
   * @param value  the new value.
   * 
   * @see #getValue()
Tom Tromey committed
377 378 379 380 381 382 383
   */
  public void setValue(int value)
  {
    model.setValue(value);
  }

  /**
384 385
   * Paints the component's border, but only if {@link #isBorderPainted()}
   * returns <code>true</code>.
Tom Tromey committed
386
   *
387 388 389
   * @param graphics  the graphics object to paint with.
   * 
   * @see #setBorderPainted(boolean)
Tom Tromey committed
390 391 392 393 394
   */
  protected void paintBorder(Graphics graphics)
  {
    Border border = getBorder();
    if (paintBorder && border != null)
395
      border.paintBorder(this, graphics, 0, 0, getWidth(), getHeight());
Tom Tromey committed
396 397 398
  }

  /**
399 400 401 402
   * Returns the orientation of the <code>JProgressBar</code> component, which
   * is either {@link SwingConstants#HORIZONTAL} or 
   * {@link SwingConstants#VERTICAL}.  The default orientation is 
   * <code>HORIZONTAL</code>.
Tom Tromey committed
403
   *
404 405 406
   * @return The orientation.
   * 
   * @see #setOrientation(int)
Tom Tromey committed
407 408 409 410 411 412 413
   */
  public int getOrientation()
  {
    return orientation;
  }

  /**
414 415 416
   * Sets the orientation for this <code>JProgressBar</code> component and,
   * if the value changes, sends a {@link PropertyChangeEvent} (with the 
   * property name <code>"orientation"</code>) to all registered listeners.
Tom Tromey committed
417
   *
418 419 420
   * @param orientation  the orientation ({@link #HORIZONTAL} or 
   *     {@link #VERTICAL}).
   * 
421
   * @throws IllegalArgumentException if <code>orientation</code> is not
422 423 424
   *     one of the listed values.
   *     
   * @see #getOrientation()
Tom Tromey committed
425 426 427 428
   */
  public void setOrientation(int orientation)
  {
    if (orientation != VERTICAL && orientation != HORIZONTAL)
429 430
      throw new IllegalArgumentException(orientation
                                         + " is not a legal orientation");    
Tom Tromey committed
431 432
    if (this.orientation != orientation)
      {
433 434 435
        int oldOrientation = this.orientation;
        this.orientation = orientation;
        firePropertyChange("orientation", oldOrientation, this.orientation);
Tom Tromey committed
436 437 438 439
      }
  }

  /**
440 441 442
   * Returns the flag that controls whether or not the string returned by
   * {@link #getString()} is displayed by the <code>JProgressBar</code> 
   * component.
Tom Tromey committed
443
   *
444 445 446 447
   * @return <code>true</code> if the string should be displayed, and 
   *     <code>false</code> otherwise.
   * 
   * @see #setStringPainted(boolean)
Tom Tromey committed
448 449 450 451 452 453 454
   */
  public boolean isStringPainted()
  {
    return paintString;
  }

  /**
455 456 457 458 459
   * Sets the flag that controls whether or not the string returned by
   * {@link #getString()} is displayed by the <code>JProgressBar</code> 
   * component.  If the flag value changes, a {@link PropertyChangeEvent} (with 
   * the property name <code>"stringPainted"</code>) is sent to all registered 
   * listeners.
Tom Tromey committed
460
   *
461 462 463 464
   * @param painted  the new flag value.
   * 
   * @see #isStringPainted()
   * @see #setString(String)
Tom Tromey committed
465 466 467 468 469
   */
  public void setStringPainted(boolean painted)
  {
    if (paintString != painted)
      {
470 471 472
        boolean oldPainted = paintString;
        paintString = painted;
        firePropertyChange("stringPainted", oldPainted, paintString);
Tom Tromey committed
473 474 475 476
      }
  }

  /**
477 478 479 480
   * Returns the string that is painted on the <code>JProgressBar</code> if 
   * {@link #isStringPainted()} returns <code>true</code>.  If no string has 
   * been explicitly set, this method will return a string displaying the 
   * value of {@link #getPercentComplete()}.
Tom Tromey committed
481
   *
482 483 484 485
   * @return The string.
   * 
   * @see #setString(String)
   * @see #setStringPainted(boolean)
Tom Tromey committed
486 487 488 489 490 491 492 493 494 495
   */
  public String getString()
  {
    if (progressString != null)
      return progressString;
    else
      return (int) (getPercentComplete() * 100) + "%";
  }

  /**
496 497 498 499 500
   * Sets the string to display within the progress bar and, if the new value
   * is different to the old value, sends a {@link PropertyChangeEvent} (with 
   * the property name <code>"string"</code>) to all registered listeners. If 
   * the string is set to <code>null</code>, {@link #getString()} will return
   * a default string.
Tom Tromey committed
501
   *
502 503 504 505
   * @param string  the string (<code>null</code> permitted).
   * 
   * @see #getString()
   * @see #setStringPainted(boolean)
Tom Tromey committed
506 507 508 509 510 511 512
   */
  public void setString(String string)
  {
    if (((string == null || progressString == null) &&
        string != progressString) || (string != null &&
	! string.equals(progressString)))
      {
513 514 515
        String oldString = progressString;
        progressString = string;
        firePropertyChange("string", oldString, progressString);
Tom Tromey committed
516 517 518 519
      }
  }

  /**
520 521
   * Returns the current value expressed as a percentage.  This is calculated 
   * as <code>(value - min) / (max - min)</code>.
Tom Tromey committed
522
   *
523
   * @return The percentage (a value in the range 0.0 to 1.0).
Tom Tromey committed
524 525 526 527 528 529
   */
  public double getPercentComplete()
  {
    if (getMaximum() == getMinimum())
      return 1.0;
    else
530 531
      return (double) (model.getValue() - model.getMinimum()) 
          / (model.getMaximum() - model.getMinimum());
Tom Tromey committed
532 533 534
  }

  /**
535 536
   * Returns a flag that controls whether or not the component's border is
   * painted.  The default value is <code>true</code>.
Tom Tromey committed
537
   *
538 539 540 541
   * @return <code>true</code> if the component's border should be painted,
   *     and <code>false</code> otherwise.
   *     
   * @see #setBorderPainted(boolean)
Tom Tromey committed
542 543 544 545 546 547 548
   */
  public boolean isBorderPainted()
  {
    return paintBorder;
  }

  /**
549 550 551 552
   * Sets the flag that controls whether or not the component's border is
   * painted.  If the flag value is changed, this method sends a 
   * {@link PropertyChangeEvent} (with the property name "borderPainted") to 
   * all registered listeners.
Tom Tromey committed
553
   *
554 555 556 557
   * @param painted  the new flag value.
   * 
   * @see #isBorderPainted()
   * @see #paintBorder
Tom Tromey committed
558 559 560 561 562
   */
  public void setBorderPainted(boolean painted)
  {
    if (painted != paintBorder)
      {
563 564 565
        boolean oldPainted = paintBorder;
        paintBorder = painted;
        firePropertyChange("borderPainted", oldPainted, paintBorder);
Tom Tromey committed
566 567 568 569
      }
  }

  /**
570
   * Returns the UI delegate for this <code>JProgressBar</code>.
Tom Tromey committed
571
   *
572
   * @return The UI delegate.
Tom Tromey committed
573 574 575 576 577 578 579
   */
  public ProgressBarUI getUI()
  {
    return (ProgressBarUI) ui;
  }

  /**
580
   * Sets the UI delegate for this component.
Tom Tromey committed
581
   *
582
   * @param ui  the new UI delegate.
Tom Tromey committed
583 584 585 586 587 588 589
   */
  public void setUI(ProgressBarUI ui)
  {
    super.setUI(ui);
  }

  /**
590 591
   * Sets this <code>JProgressBar</code>'s UI delegate to the default 
   * (obtained from the {@link UIManager}) for the current look and feel.
Tom Tromey committed
592 593 594 595 596 597 598
   */
  public void updateUI()
  {
    setUI((ProgressBarUI) UIManager.getUI(this));
  }

  /**
599 600 601
   * Returns the suffix (<code>"ProgressBarUI"</code> in this case) used to 
   * determine the class name for a UI delegate that can provide the look and 
   * feel for a <code>JProgressBar</code>.
Tom Tromey committed
602
   *
603
   * @return <code>"ProgressBarUI"</code>.
Tom Tromey committed
604 605 606 607 608 609 610
   */
  public String getUIClassID()
  {
    return "ProgressBarUI";
  }

  /**
611 612 613 614 615 616
   * Creates a new {@link ChangeListener} that calls 
   * {@link #fireStateChanged()} whenever it receives a {@link ChangeEvent}
   * (typically from the component's <code>model</code>).  This listener is 
   * registered with the progress bar's model, so that changes made to the 
   * model directly will automatically result in the progress bar's listeners 
   * being notified also.
Tom Tromey committed
617
   *
618
   * @return A new listener.
Tom Tromey committed
619 620 621 622 623
   */
  protected ChangeListener createChangeListener()
  {
    return new ChangeListener()
      {
624 625 626 627
        public void stateChanged(ChangeEvent ce)
        {
          fireStateChanged();
	    }
Tom Tromey committed
628 629 630 631
      };
  }

  /**
632 633
   * Registers a listener with this component so that it will receive 
   * notification of component state changes.
Tom Tromey committed
634
   *
635 636 637
   * @param listener  the listener.
   * 
   * @see #removeChangeListener(ChangeListener)
Tom Tromey committed
638 639 640 641 642 643 644
   */
  public void addChangeListener(ChangeListener listener)
  {
    listenerList.add(ChangeListener.class, listener);
  }

  /**
645 646
   * Deregisters a listener so that it no longer receives notification of
   * component state changes.
Tom Tromey committed
647
   *
648 649 650
   * @param listener  the listener.
   * 
   * @see #addChangeListener(ChangeListener)
Tom Tromey committed
651 652 653 654 655 656 657
   */
  public void removeChangeListener(ChangeListener listener)
  {
    listenerList.remove(ChangeListener.class, listener);
  }
  
  /**
658 659
   * Returns an array of the listeners that are registered with this component.
   * The array may be empty, but is never <code>null</code>.
Tom Tromey committed
660
   *
661 662 663
   * @return An array of listeners.
   * 
   * @since 1.4
Tom Tromey committed
664 665 666 667 668 669 670
   */
  public ChangeListener[] getChangeListeners()
  {
    return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
  }  

  /**
671 672 673 674
   * Sends a {@link ChangeEvent} to all registered listeners to indicate that
   * the state of the <code>JProgressBar</code> has changed.  
   * 
   * @see #createChangeListener()
Tom Tromey committed
675 676 677 678 679 680 681 682
   */
  protected void fireStateChanged()
  {
    Object[] changeListeners = listenerList.getListenerList();
    if (changeEvent == null)
      changeEvent = new ChangeEvent(this);
    for (int i = changeListeners.length - 2; i >= 0; i -= 2)
      {
683 684
        if (changeListeners[i] == ChangeListener.class)
          ((ChangeListener) changeListeners[i + 1]).stateChanged(changeEvent);
Tom Tromey committed
685 686 687 688
      }
  }

  /**
689
   * Returns the model for the <code>JProgressBar</code>.
Tom Tromey committed
690
   *
691 692 693
   * @return The model (never <code>null</code>).
   * 
   * @see #setModel(BoundedRangeModel)
Tom Tromey committed
694 695 696 697 698 699 700
   */
  public BoundedRangeModel getModel()
  {
    return model;
  }

  /**
701 702
   * Sets the model for the <code>JProgressBar</code> and sends a 
   * {@link ChangeEvent} to all registered listeners.
Tom Tromey committed
703
   *
704 705 706
   * @param model  the model (<code>null</code> not permitted).
   * 
   * @see #getModel()
Tom Tromey committed
707 708 709 710 711 712
   */
  public void setModel(BoundedRangeModel model)
  {
    if (model != this.model)
      {
        this.model.removeChangeListener(changeListener);
713 714 715
        this.model = model;
        this.model.addChangeListener(changeListener);
        fireStateChanged();
Tom Tromey committed
716 717 718 719
      }
  }

  /**
720 721 722
   * Returns the minimum value for the <code>JProgressBar</code>. This defines 
   * the lower bound for the current value, and is stored in the component's 
   * <code>model</code>.
Tom Tromey committed
723
   *
724 725 726
   * @return The minimum value.
   * 
   * @see #setMinimum(int)
Tom Tromey committed
727 728 729 730 731 732 733
   */
  public int getMinimum()
  {
    return model.getMinimum();
  }

  /**
734 735 736 737 738 739 740 741 742 743
   * Sets the minimum value for the <code>JProgressBar</code>.  The value is
   * stored in the component's <code>model</code> (see {@link #getModel()}).  
   * If the new value is different to the old value, a {@link ChangeEvent} is 
   * sent to the model's registered listeners.  In turn, this triggers a call 
   * to {@link #fireStateChanged()} which will send a <code>ChangeEvent</code> 
   * to this component's registered listeners.
   * 
   * @param minimum  the minimum value.
   * 
   * @see #getMinimum()
Tom Tromey committed
744 745 746 747 748 749 750
   */
  public void setMinimum(int minimum)
  {
    model.setMinimum(minimum);
  }

  /**
751 752 753
   * Returns the maximum value for the <code>JProgressBar</code>.  This defines 
   * the upper bound for the current value, and is stored in the component's 
   * <code>model</code>.
Tom Tromey committed
754
   *
755 756 757
   * @return The maximum value.
   * 
   * @see #setMaximum(int)
Tom Tromey committed
758 759 760 761 762 763 764
   */
  public int getMaximum()
  {
    return model.getMaximum();
  }

  /**
765 766 767 768 769 770
   * Sets the maximum value for the <code>JProgressBar</code>.  The value is
   * stored in the component's <code>model</code> (see {@link #getModel()}).  
   * If the new value is different to the old value, a {@link ChangeEvent} is 
   * sent to the model's registered listeners.  In turn, this triggers a call 
   * to {@link #fireStateChanged()} which will send a <code>ChangeEvent</code> 
   * to this component's registered listeners.
Tom Tromey committed
771
   *
772 773 774
   * @param maximum  the maximum value.
   * 
   * @see #getMaximum()
Tom Tromey committed
775 776 777 778 779 780 781
   */
  public void setMaximum(int maximum)
  {
    model.setMaximum(maximum);
  }

  /**
782 783
   * Returns an implementation-dependent string describing the attributes of
   * this <code>JProgressBar</code>.
Tom Tromey committed
784
   *
785 786
   * @return A string describing the attributes of this 
   *     <code>JProgressBar</code> (never <code>null</code>).
Tom Tromey committed
787 788 789
   */
  protected String paramString()
  {
790
    String superParamStr = super.paramString();
791
    CPStringBuilder sb = new CPStringBuilder();
792 793 794 795 796 797 798 799 800 801 802 803
    sb.append(",orientation=");
    if (orientation == HORIZONTAL)
      sb.append("HORIZONTAL");
    else
      sb.append("VERTICAL");
    sb.append(",paintBorder=").append(isBorderPainted());
    sb.append(",paintString=").append(isStringPainted());
    sb.append(",progressString=");
    if (progressString != null)
      sb.append(progressString);
    sb.append(",indeterminateString=").append(isIndeterminate());
    return superParamStr + sb.toString();
Tom Tromey committed
804 805 806
  }

  /**
807 808 809 810 811 812 813 814 815 816
   * Sets the flag that controls the mode for this <code>JProgressBar</code>
   * (<code>true</code> for indeterminate mode, and <code>false</code> for
   * determinate mode).  If the flag value changes, this method sends a 
   * {@link PropertyChangeEvent} (with the property name 
   * <code>"indeterminate"</code>) to all registered listeners.
   * <p>
   * If the <code>JProgressBar</code> is determinate, it paints a percentage
   * of the bar described by its value. If it is indeterminate, it simply 
   * bounces a box between the ends of the bar; the value of the 
   * <code>JProgressBar</code> is ignored.
Tom Tromey committed
817
   *
818 819 820 821
   * @param flag  the new flag value.
   * 
   * @see #isIndeterminate()
   * @since 1.4
Tom Tromey committed
822
   */
823
  public void setIndeterminate(boolean flag)
Tom Tromey committed
824
  {
825
    if (indeterminate != flag)
Tom Tromey committed
826
      {
827 828
        indeterminate = flag;
        firePropertyChange("indeterminate", !flag, indeterminate);
Tom Tromey committed
829 830 831 832
      }
  }

  /**
833 834 835
   * Returns a flag that indicates the mode for this <code>JProgressBar</code>
   * (<code>true</code> for indeterminate mode, and <code>false</code> for 
   * determinate mode).  
Tom Tromey committed
836
   *
837 838 839 840
   * @return A flag indicating the mode for the <code>JProgressBar</code>.
   * 
   * @see #setIndeterminate(boolean)
   * @since 1.4
Tom Tromey committed
841 842 843 844 845 846 847
   */
  public boolean isIndeterminate()
  {
    return indeterminate;
  }

  /**
848 849
   * Returns the object that provides accessibility features for this
   * <code>JProgressBar</code> component.
Tom Tromey committed
850
   *
851 852
   * @return The accessible context (an instance of 
   *     {@link AccessibleJProgressBar}).
Tom Tromey committed
853 854 855 856 857 858 859 860 861
   */
  public AccessibleContext getAccessibleContext()
  {
    if (accessibleContext == null)
      accessibleContext = new AccessibleJProgressBar();
    
    return accessibleContext;
  } 
}