src/share/classes/javax/swing/JProgressBar.java
author dav
Mon Apr 07 14:53:51 2008 +0400 (4 years ago)
changeset 250 664def01b886
parent 037a05a11f281
child 415b6d6877c1155
permissions -rw-r--r--
6613529: Avoid duplicate object creation within JDK packages
Summary: avoid using constructors when unique values are not necessary
Reviewed-by: volk, igor, peterz
        1 /*
        2  * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
        3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
        4  *
        5  * This code is free software; you can redistribute it and/or modify it
        6  * under the terms of the GNU General Public License version 2 only, as
        7  * published by the Free Software Foundation.  Sun designates this
        8  * particular file as subject to the "Classpath" exception as provided
        9  * by Sun in the LICENSE file that accompanied this code.
       10  *
       11  * This code is distributed in the hope that it will be useful, but WITHOUT
       12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       14  * version 2 for more details (a copy is included in the LICENSE file that
       15  * accompanied this code).
       16  *
       17  * You should have received a copy of the GNU General Public License version
       18  * 2 along with this work; if not, write to the Free Software Foundation,
       19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       20  *
       21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       22  * CA 95054 USA or visit www.sun.com if you need additional information or
       23  * have any questions.
       24  */
       25 
       26 package javax.swing;
       27 
       28 import java.awt.Color;
       29 import java.awt.Graphics;
       30 
       31 import java.text.Format;
       32 import java.text.NumberFormat;
       33 
       34 import java.io.Serializable;
       35 import java.io.ObjectOutputStream;
       36 import java.io.ObjectInputStream;
       37 import java.io.IOException;
       38 
       39 import javax.swing.event.*;
       40 import javax.accessibility.*;
       41 import javax.swing.plaf.ProgressBarUI;
       42 
       43 
       44 /**
       45  * A component that visually displays the progress of some task.  As the task
       46  * progresses towards completion, the progress bar displays the
       47  * task's percentage of completion.
       48  * This percentage is typically represented visually by a rectangle which
       49  * starts out empty and gradually becomes filled in as the task progresses.
       50  * In addition, the progress bar can display a textual representation of this
       51  * percentage.
       52  * <p>
       53  * {@code JProgressBar} uses a {@code BoundedRangeModel} as its data model,
       54  * with the {@code value} property representing the "current" state of the task,
       55  * and the {@code minimum} and {@code maximum} properties representing the
       56  * beginning and end points, respectively.
       57  * <p>
       58  * To indicate that a task of unknown length is executing,
       59  * you can put a progress bar into indeterminate mode.
       60  * While the bar is in indeterminate mode,
       61  * it animates constantly to show that work is occurring.
       62  * As soon as you can determine the task's length and amount of progress,
       63  * you should update the progress bar's value
       64  * and switch it back to determinate mode.
       65  *
       66  * <p>
       67  *
       68  * Here is an example of creating a progress bar,
       69  * where <code>task</code> is an object (representing some piece of work)
       70  * which returns information about the progress of the task:
       71  *
       72  *<pre>
       73  *progressBar = new JProgressBar(0, task.getLengthOfTask());
       74  *progressBar.setValue(0);
       75  *progressBar.setStringPainted(true);
       76  *</pre>
       77  *
       78  * Here is an example of querying the current state of the task, and using
       79  * the returned value to update the progress bar:
       80  *
       81  *<pre>
       82  *progressBar.setValue(task.getCurrent());
       83  *</pre>
       84  *
       85  * Here is an example of putting a progress bar into
       86  * indeterminate mode,
       87  * and then switching back to determinate mode
       88  * once the length of the task is known:
       89  *
       90  *<pre>
       91  *progressBar = new JProgressBar();
       92  *<em>...//when the task of (initially) unknown length begins:</em>
       93  *progressBar.setIndeterminate(true);
       94  *<em>...//do some work; get length of task...</em>
       95  *progressBar.setMaximum(newLength);
       96  *progressBar.setValue(newValue);
       97  *progressBar.setIndeterminate(false);
       98  *</pre>
       99  *
      100  * <p>
      101  *
      102  * For complete examples and further documentation see
      103  * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>,
      104  * a section in <em>The Java Tutorial.</em>
      105  *
      106  * <p>
      107  * <strong>Warning:</strong> Swing is not thread safe. For more
      108  * information see <a
      109  * href="package-summary.html#threading">Swing's Threading
      110  * Policy</a>.
      111  * <p>
      112  * <strong>Warning:</strong>
      113  * Serialized objects of this class will not be compatible with
      114  * future Swing releases. The current serialization support is
      115  * appropriate for short term storage or RMI between applications running
      116  * the same version of Swing.  As of 1.4, support for long term storage
      117  * of all JavaBeans<sup><font size="-2">TM</font></sup>
      118  * has been added to the <code>java.beans</code> package.
      119  * Please see {@link java.beans.XMLEncoder}.
      120  *
      121  * @see javax.swing.plaf.basic.BasicProgressBarUI
      122  * @see javax.swing.BoundedRangeModel
      123  * @see javax.swing.SwingWorker
      124  *
      125  * @beaninfo
      126  *      attribute: isContainer false
      127  *    description: A component that displays an integer value.
      128  *
      129  * @author Michael C. Albers
      130  * @author Kathy Walrath
      131  */
      132 public class JProgressBar extends JComponent implements SwingConstants, Accessible
      133 {
      134     /**
      135      * @see #getUIClassID
      136      */
      137     private static final String uiClassID = "ProgressBarUI";
      138 
      139     /**
      140      * Whether the progress bar is horizontal or vertical.
      141      * The default is <code>HORIZONTAL</code>.
      142      *
      143      * @see #setOrientation
      144      */
      145     protected int orientation;
      146 
      147     /**
      148      * Whether to display a border around the progress bar.
      149      * The default is <code>true</code>.
      150      *
      151      * @see #setBorderPainted
      152      */
      153     protected boolean paintBorder;
      154 
      155     /**
      156      * The object that holds the data for the progress bar.
      157      *
      158      * @see #setModel
      159      */
      160     protected BoundedRangeModel model;
      161 
      162     /**
      163      * An optional string that can be displayed on the progress bar.
      164      * The default is <code>null</code>. Setting this to a non-<code>null</code>
      165      * value does not imply that the string will be displayed.
      166      * To display the string, {@code paintString} must be {@code true}.
      167      *
      168      * @see #setString
      169      * @see #setStringPainted
      170      */
      171     protected String progressString;
      172 
      173     /**
      174      * Whether to display a string of text on the progress bar.
      175      * The default is <code>false</code>.
      176      * Setting this to <code>true</code> causes a textual
      177      * display of the progress to be rendered on the progress bar. If
      178      * the <code>progressString</code> is <code>null</code>,
      179      * the percentage of completion is displayed on the progress bar.
      180      * Otherwise, the <code>progressString</code> is
      181      * rendered on the progress bar.
      182      *
      183      * @see #setStringPainted
      184      * @see #setString
      185      */
      186     protected boolean paintString;
      187 
      188     /**
      189      * The default minimum for a progress bar is 0.
      190      */
      191     static final private int defaultMinimum = 0;
      192     /**
      193      * The default maximum for a progress bar is 100.
      194      */
      195     static final private int defaultMaximum = 100;
      196     /**
      197      * The default orientation for a progress bar is <code>HORIZONTAL</code>.
      198      */
      199     static final private int defaultOrientation = HORIZONTAL;
      200 
      201     /**
      202      * Only one <code>ChangeEvent</code> is needed per instance since the
      203      * event's only interesting property is the immutable source, which
      204      * is the progress bar.
      205      * The event is lazily created the first time that an
      206      * event notification is fired.
      207      *
      208      * @see #fireStateChanged
      209      */
      210     protected transient ChangeEvent changeEvent = null;
      211 
      212     /**
      213      * Listens for change events sent by the progress bar's model,
      214      * redispatching them
      215      * to change-event listeners registered upon
      216      * this progress bar.
      217      *
      218      * @see #createChangeListener
      219      */
      220     protected ChangeListener changeListener = null;
      221 
      222     /**
      223      * Format used when displaying percent complete.
      224      */
      225     private transient Format format;
      226 
      227     /**
      228      * Whether the progress bar is indeterminate (<code>true</code>) or
      229      * normal (<code>false</code>); the default is <code>false</code>.
      230      *
      231      * @see #setIndeterminate
      232      * @since 1.4
      233      */
      234     private boolean indeterminate;
      235 
      236 
      237    /**
      238      * Creates a horizontal progress bar
      239      * that displays a border but no progress string.
      240      * The initial and minimum values are 0,
      241      * and the maximum is 100.
      242      *
      243      * @see #setOrientation
      244      * @see #setBorderPainted
      245      * @see #setStringPainted
      246      * @see #setString
      247      * @see #setIndeterminate
      248      */
      249     public JProgressBar()
      250     {
      251         this(defaultOrientation);
      252     }
      253 
      254    /**
      255      * Creates a progress bar with the specified orientation,
      256      * which can be
      257      * either {@code SwingConstants.VERTICAL} or
      258      * {@code SwingConstants.HORIZONTAL}.
      259      * By default, a border is painted but a progress string is not.
      260      * The initial and minimum values are 0,
      261      * and the maximum is 100.
      262      *
      263      * @param orient  the desired orientation of the progress bar
      264      * @throws IllegalArgumentException if {@code orient} is an illegal value
      265      *
      266      * @see #setOrientation
      267      * @see #setBorderPainted
      268      * @see #setStringPainted
      269      * @see #setString
      270      * @see #setIndeterminate
      271      */
      272     public JProgressBar(int orient)
      273     {
      274         this(orient, defaultMinimum, defaultMaximum);
      275     }
      276 
      277 
      278     /**
      279      * Creates a horizontal progress bar
      280      * with the specified minimum and maximum.
      281      * Sets the initial value of the progress bar to the specified minimum.
      282      * By default, a border is painted but a progress string is not.
      283      * <p>
      284      * The <code>BoundedRangeModel</code> that holds the progress bar's data
      285      * handles any issues that may arise from improperly setting the
      286      * minimum, initial, and maximum values on the progress bar.
      287      * See the {@code BoundedRangeModel} documentation for details.
      288      *
      289      * @param min  the minimum value of the progress bar
      290      * @param max  the maximum value of the progress bar
      291      *
      292      * @see BoundedRangeModel
      293      * @see #setOrientation
      294      * @see #setBorderPainted
      295      * @see #setStringPainted
      296      * @see #setString
      297      * @see #setIndeterminate
      298      */
      299     public JProgressBar(int min, int max)
      300     {
      301         this(defaultOrientation, min, max);
      302     }
      303 
      304 
      305     /**
      306      * Creates a progress bar using the specified orientation,
      307      * minimum, and maximum.
      308      * By default, a border is painted but a progress string is not.
      309      * Sets the initial value of the progress bar to the specified minimum.
      310      * <p>
      311      * The <code>BoundedRangeModel</code> that holds the progress bar's data
      312      * handles any issues that may arise from improperly setting the
      313      * minimum, initial, and maximum values on the progress bar.
      314      * See the {@code BoundedRangeModel} documentation for details.
      315      *
      316      * @param orient  the desired orientation of the progress bar
      317      * @param min  the minimum value of the progress bar
      318      * @param max  the maximum value of the progress bar
      319      * @throws IllegalArgumentException if {@code orient} is an illegal value
      320      *
      321      * @see BoundedRangeModel
      322      * @see #setOrientation
      323      * @see #setBorderPainted
      324      * @see #setStringPainted
      325      * @see #setString
      326      * @see #setIndeterminate
      327      */
      328     public JProgressBar(int orient, int min, int max)
      329     {
      330         // Creating the model this way is a bit simplistic, but
      331         //  I believe that it is the the most common usage of this
      332         //  component - it's what people will expect.
      333         setModel(new DefaultBoundedRangeModel(min, 0, min, max));
      334         updateUI();
      335 
      336         setOrientation(orient);      // documented with set/getOrientation()
      337         setBorderPainted(true);      // documented with is/setBorderPainted()
      338         setStringPainted(false);     // see setStringPainted
      339         setString(null);             // see getString
      340         setIndeterminate(false);     // see setIndeterminate
      341     }
      342 
      343 
      344     /**
      345      * Creates a horizontal progress bar
      346      * that uses the specified model
      347      * to hold the progress bar's data.
      348      * By default, a border is painted but a progress string is not.
      349      *
      350      * @param newModel  the data model for the progress bar
      351      *
      352      * @see #setOrientation
      353      * @see #setBorderPainted
      354      * @see #setStringPainted
      355      * @see #setString
      356      * @see #setIndeterminate
      357      */
      358     public JProgressBar(BoundedRangeModel newModel)
      359     {
      360         setModel(newModel);
      361         updateUI();
      362 
      363         setOrientation(defaultOrientation);  // see setOrientation()
      364         setBorderPainted(true);              // see setBorderPainted()
      365         setStringPainted(false);             // see setStringPainted
      366         setString(null);                     // see getString
      367         setIndeterminate(false);             // see setIndeterminate
      368     }
      369 
      370 
      371     /**
      372      * Returns {@code SwingConstants.VERTICAL} or
      373      * {@code SwingConstants.HORIZONTAL}, depending on the orientation
      374      * of the progress bar. The default orientation is
      375      * {@code SwingConstants.HORIZONTAL}.
      376      *
      377      * @return <code>HORIZONTAL</code> or <code>VERTICAL</code>
      378      * @see #setOrientation
      379      */
      380     public int getOrientation() {
      381         return orientation;
      382     }
      383 
      384 
      385    /**
      386      * Sets the progress bar's orientation to <code>newOrientation</code>,
      387      * which must be {@code SwingConstants.VERTICAL} or
      388      * {@code SwingConstants.HORIZONTAL}. The default orientation
      389      * is {@code SwingConstants.HORIZONTAL}.
      390      *
      391      * @param  newOrientation  <code>HORIZONTAL</code> or <code>VERTICAL</code>
      392      * @exception      IllegalArgumentException    if <code>newOrientation</code>
      393      *                                              is an illegal value
      394      * @see #getOrientation
      395      *
      396      * @beaninfo
      397      *    preferred: true
      398      *        bound: true
      399      *    attribute: visualUpdate true
      400      *  description: Set the progress bar's orientation.
      401      */
      402     public void setOrientation(int newOrientation) {
      403         if (orientation != newOrientation) {
      404             switch (newOrientation) {
      405             case VERTICAL:
      406             case HORIZONTAL:
      407                 int oldOrientation = orientation;
      408                 orientation = newOrientation;
      409                 firePropertyChange("orientation", oldOrientation, newOrientation);
      410                 if (accessibleContext != null) {
      411                     accessibleContext.firePropertyChange(
      412                             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
      413                             ((oldOrientation == VERTICAL)
      414                              ? AccessibleState.VERTICAL
      415                              : AccessibleState.HORIZONTAL),
      416                             ((orientation == VERTICAL)
      417                              ? AccessibleState.VERTICAL
      418                              : AccessibleState.HORIZONTAL));
      419                 }
      420                 break;
      421             default:
      422                 throw new IllegalArgumentException(newOrientation +
      423                                              " is not a legal orientation");
      424             }
      425             revalidate();
      426         }
      427     }
      428 
      429 
      430     /**
      431      * Returns the value of the <code>stringPainted</code> property.
      432      *
      433      * @return the value of the <code>stringPainted</code> property
      434      * @see    #setStringPainted
      435      * @see    #setString
      436      */
      437     public boolean isStringPainted() {
      438         return paintString;
      439     }
      440 
      441 
      442     /**
      443      * Sets the value of the <code>stringPainted</code> property,
      444      * which determines whether the progress bar
      445      * should render a progress string.
      446      * The default is <code>false</code>, meaning
      447      * no string is painted.
      448      * Some look and feels might not support progress strings
      449      * or might support them only when the progress bar is in determinate mode.
      450      *
      451      * @param   b       <code>true</code> if the progress bar should render a string
      452      * @see     #isStringPainted
      453      * @see     #setString
      454      * @beaninfo
      455      *        bound: true
      456      *    attribute: visualUpdate true
      457      *  description: Whether the progress bar should render a string.
      458      */
      459     public void setStringPainted(boolean b) {
      460         //PENDING: specify that string not painted when in indeterminate mode?
      461         //         or just leave that to the L&F?
      462         boolean oldValue = paintString;
      463         paintString = b;
      464         firePropertyChange("stringPainted", oldValue, paintString);
      465         if (paintString != oldValue) {
      466             revalidate();
      467             repaint();
      468         }
      469     }
      470 
      471 
      472     /**
      473      * Returns a {@code String} representation of the current progress.
      474      * By default, this returns a simple percentage {@code String} based on
      475      * the value returned from {@code getPercentComplete}.  An example
      476      * would be the "42%".  You can change this by calling {@code setString}.
      477      *
      478      * @return the value of the progress string, or a simple percentage string
      479      *         if the progress string is {@code null}
      480      * @see    #setString
      481      */
      482     public String getString(){
      483         if (progressString != null) {
      484             return progressString;
      485         } else {
      486             if (format == null) {
      487                 format = NumberFormat.getPercentInstance();
      488             }
      489             return format.format(new Double(getPercentComplete()));
      490         }
      491     }
      492 
      493     /**
      494      * Sets the value of the progress string. By default,
      495      * this string is <code>null</code>, implying the built-in behavior of
      496      * using a simple percent string.
      497      * If you have provided a custom progress string and want to revert to
      498      * the built-in behavior, set the string back to <code>null</code>.
      499      * <p>
      500      * The progress string is painted only if
      501      * the <code>isStringPainted</code> method returns <code>true</code>.
      502      *
      503      * @param  s       the value of the progress string
      504      * @see    #getString
      505      * @see    #setStringPainted
      506      * @see    #isStringPainted
      507      * @beaninfo
      508      *        bound: true
      509      *    attribute: visualUpdate true
      510      *  description: Specifies the progress string to paint
      511      */
      512     public void setString(String s){
      513         String oldValue = progressString;
      514         progressString = s;
      515         firePropertyChange("string", oldValue, progressString);
      516         if (progressString == null || oldValue == null || !progressString.equals(oldValue)) {
      517             repaint();
      518         }
      519     }
      520 
      521     /**
      522      * Returns the percent complete for the progress bar.
      523      * Note that this number is between 0.0 and 1.0.
      524      *
      525      * @return the percent complete for this progress bar
      526      */
      527     public double getPercentComplete() {
      528         long span = model.getMaximum() - model.getMinimum();
      529         double currentValue = model.getValue();
      530         double pc = (currentValue - model.getMinimum()) / span;
      531         return pc;
      532     }
      533 
      534     /**
      535      * Returns the <code>borderPainted</code> property.
      536      *
      537      * @return the value of the <code>borderPainted</code> property
      538      * @see    #setBorderPainted
      539      * @beaninfo
      540      *  description: Does the progress bar paint its border
      541      */
      542     public boolean isBorderPainted() {
      543         return paintBorder;
      544     }
      545 
      546     /**
      547      * Sets the <code>borderPainted</code> property, which is
      548      * <code>true</code> if the progress bar should paint its border.
      549      * The default value for this property is <code>true</code>.
      550      * Some look and feels might not implement painted borders;
      551      * they will ignore this property.
      552      *
      553      * @param   b       <code>true</code> if the progress bar
      554      *                  should paint its border;
      555      *                  otherwise, <code>false</code>
      556      * @see     #isBorderPainted
      557      * @beaninfo
      558      *        bound: true
      559      *    attribute: visualUpdate true
      560      *  description: Whether the progress bar should paint its border.
      561      */
      562     public void setBorderPainted(boolean b) {
      563         boolean oldValue = paintBorder;
      564         paintBorder = b;
      565         firePropertyChange("borderPainted", oldValue, paintBorder);
      566         if (paintBorder != oldValue) {
      567             repaint();
      568         }
      569     }
      570 
      571     /**
      572      * Paints the progress bar's border if the <code>borderPainted</code>
      573      * property is <code>true</code>.
      574      *
      575      * @param g  the <code>Graphics</code> context within which to paint the border
      576      * @see #paint
      577      * @see #setBorder
      578      * @see #isBorderPainted
      579      * @see #setBorderPainted
      580      */
      581     protected void paintBorder(Graphics g) {
      582         if (isBorderPainted()) {
      583             super.paintBorder(g);
      584         }
      585     }
      586 
      587 
      588     /**
      589      * Returns the look-and-feel object that renders this component.
      590      *
      591      * @return the <code>ProgressBarUI</code> object that renders this component
      592      */
      593     public ProgressBarUI getUI() {
      594         return (ProgressBarUI)ui;
      595     }
      596 
      597     /**
      598      * Sets the look-and-feel object that renders this component.
      599      *
      600      * @param ui  a <code>ProgressBarUI</code> object
      601      * @see UIDefaults#getUI
      602      * @beaninfo
      603      *        bound: true
      604      *       hidden: true
      605      *    attribute: visualUpdate true
      606      *  description: The UI object that implements the Component's LookAndFeel.
      607      */
      608     public void setUI(ProgressBarUI ui) {
      609         super.setUI(ui);
      610     }
      611 
      612 
      613     /**
      614      * Resets the UI property to a value from the current look and feel.
      615      *
      616      * @see JComponent#updateUI
      617      */
      618     public void updateUI() {
      619         setUI((ProgressBarUI)UIManager.getUI(this));
      620     }
      621 
      622 
      623     /**
      624      * Returns the name of the look-and-feel class that renders this component.
      625      *
      626      * @return the string "ProgressBarUI"
      627      * @see JComponent#getUIClassID
      628      * @see UIDefaults#getUI
      629      * @beaninfo
      630      *        expert: true
      631      *   description: A string that specifies the name of the look-and-feel class.
      632      */
      633     public String getUIClassID() {
      634         return uiClassID;
      635     }
      636 
      637 
      638     /* We pass each Change event to the listeners with the
      639      * the progress bar as the event source.
      640      * <p>
      641      * <strong>Warning:</strong>
      642      * Serialized objects of this class will not be compatible with
      643      * future Swing releases. The current serialization support is
      644      * appropriate for short term storage or RMI between applications running
      645      * the same version of Swing.  As of 1.4, support for long term storage
      646      * of all JavaBeans<sup><font size="-2">TM</font></sup>
      647      * has been added to the <code>java.beans</code> package.
      648      * Please see {@link java.beans.XMLEncoder}.
      649      */
      650     private class ModelListener implements ChangeListener, Serializable {
      651         public void stateChanged(ChangeEvent e) {
      652             fireStateChanged();
      653         }
      654     }
      655 
      656     /**
      657      * Subclasses that want to handle change events
      658      * from the model differently
      659      * can override this to return
      660      * an instance of a custom <code>ChangeListener</code> implementation.
      661      * The default {@code ChangeListener} simply calls the
      662      * {@code fireStateChanged} method to forward {@code ChangeEvent}s
      663      * to the {@code ChangeListener}s that have been added directly to the
      664      * progress bar.
      665      *
      666      * @see #changeListener
      667      * @see #fireStateChanged
      668      * @see javax.swing.event.ChangeListener
      669      * @see javax.swing.BoundedRangeModel
      670      */
      671     protected ChangeListener createChangeListener() {
      672         return new ModelListener();
      673     }
      674 
      675     /**
      676      * Adds the specified <code>ChangeListener</code> to the progress bar.
      677      *
      678      * @param l the <code>ChangeListener</code> to add
      679      */
      680     public void addChangeListener(ChangeListener l) {
      681         listenerList.add(ChangeListener.class, l);
      682     }
      683 
      684     /**
      685      * Removes a <code>ChangeListener</code> from the progress bar.
      686      *
      687      * @param l the <code>ChangeListener</code> to remove
      688      */
      689     public void removeChangeListener(ChangeListener l) {
      690         listenerList.remove(ChangeListener.class, l);
      691     }
      692 
      693     /**
      694      * Returns an array of all the <code>ChangeListener</code>s added
      695      * to this progress bar with <code>addChangeListener</code>.
      696      *
      697      * @return all of the <code>ChangeListener</code>s added or an empty
      698      *         array if no listeners have been added
      699      * @since 1.4
      700      */
      701     public ChangeListener[] getChangeListeners() {
      702         return (ChangeListener[])listenerList.getListeners(
      703                 ChangeListener.class);
      704     }
      705 
      706     /**
      707      * Send a {@code ChangeEvent}, whose source is this {@code JProgressBar}, to
      708      * all {@code ChangeListener}s that have registered interest in
      709      * {@code ChangeEvent}s.
      710      * This method is called each time a {@code ChangeEvent} is received from
      711      * the model.
      712      * <p>
      713      *
      714      * The event instance is created if necessary, and stored in
      715      * {@code changeEvent}.
      716      *
      717      * @see #addChangeListener
      718      * @see EventListenerList
      719      */
      720     protected void fireStateChanged() {
      721         // Guaranteed to return a non-null array
      722         Object[] listeners = listenerList.getListenerList();
      723         // Process the listeners last to first, notifying
      724         // those that are interested in this event
      725         for (int i = listeners.length-2; i>=0; i-=2) {
      726             if (listeners[i]==ChangeListener.class) {
      727                 // Lazily create the event:
      728                 if (changeEvent == null)
      729                     changeEvent = new ChangeEvent(this);
      730                 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
      731             }
      732         }
      733     }
      734 
      735     /**
      736      * Returns the data model used by this progress bar.
      737      *
      738      * @return the <code>BoundedRangeModel</code> currently in use
      739      * @see #setModel
      740      * @see    BoundedRangeModel
      741      */
      742     public BoundedRangeModel getModel() {
      743         return model;
      744     }
      745 
      746     /**
      747      * Sets the data model used by the <code>JProgressBar</code>.
      748      * Note that the {@code BoundedRangeModel}'s {@code extent} is not used,
      749      * and is set to {@code 0}.
      750      *
      751      * @param  newModel the <code>BoundedRangeModel</code> to use
      752      *
      753      * @beaninfo
      754      *    expert: true
      755      * description: The data model used by the JProgressBar.
      756      */
      757     public void setModel(BoundedRangeModel newModel) {
      758         // PENDING(???) setting the same model to multiple bars is broken; listeners
      759         BoundedRangeModel oldModel = getModel();
      760 
      761         if (newModel != oldModel) {
      762             if (oldModel != null) {
      763                 oldModel.removeChangeListener(changeListener);
      764                 changeListener = null;
      765             }
      766 
      767             model = newModel;
      768 
      769             if (newModel != null) {
      770                 changeListener = createChangeListener();
      771                 newModel.addChangeListener(changeListener);
      772             }
      773 
      774             if (accessibleContext != null) {
      775                 accessibleContext.firePropertyChange(
      776                         AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
      777                         (oldModel== null
      778                          ? null : Integer.valueOf(oldModel.getValue())),
      779                         (newModel== null
      780                          ? null : Integer.valueOf(newModel.getValue())));
      781             }
      782 
      783             if (model != null) {
      784                 model.setExtent(0);
      785             }
      786             repaint();
      787         }
      788     }
      789 
      790 
      791     /* All of the model methods are implemented by delegation. */
      792 
      793     /**
      794      * Returns the progress bar's current {@code value}
      795      * from the <code>BoundedRangeModel</code>.
      796      * The value is always between the
      797      * minimum and maximum values, inclusive.
      798      *
      799      * @return  the current value of the progress bar
      800      * @see     #setValue
      801      * @see     BoundedRangeModel#getValue
      802      */
      803     public int getValue() { return getModel().getValue(); }
      804 
      805     /**
      806      * Returns the progress bar's {@code minimum} value
      807      * from the <code>BoundedRangeModel</code>.
      808      *
      809      * @return  the progress bar's minimum value
      810      * @see     #setMinimum
      811      * @see     BoundedRangeModel#getMinimum
      812      */
      813     public int getMinimum() { return getModel().getMinimum(); }
      814 
      815     /**
      816      * Returns the progress bar's {@code maximum} value
      817      * from the <code>BoundedRangeModel</code>.
      818      *
      819      * @return  the progress bar's maximum value
      820      * @see     #setMaximum
      821      * @see     BoundedRangeModel#getMaximum
      822      */
      823     public int getMaximum() { return getModel().getMaximum(); }
      824 
      825     /**
      826      * Sets the progress bar's current value to {@code n}.  This method
      827      * forwards the new value to the model.
      828      * <p>
      829      * The data model (an instance of {@code BoundedRangeModel})
      830      * handles any mathematical
      831      * issues arising from assigning faulty values.  See the
      832      * {@code BoundedRangeModel} documentation for details.
      833      * <p>
      834      * If the new value is different from the previous value,
      835      * all change listeners are notified.
      836      *
      837      * @param   n       the new value
      838      * @see     #getValue
      839      * @see     #addChangeListener
      840      * @see     BoundedRangeModel#setValue
      841      * @beaninfo
      842      *    preferred: true
      843      *  description: The progress bar's current value.
      844      */
      845     public void setValue(int n) {
      846         BoundedRangeModel brm = getModel();
      847         int oldValue = brm.getValue();
      848         brm.setValue(n);
      849 
      850         if (accessibleContext != null) {
      851             accessibleContext.firePropertyChange(
      852                     AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
      853                     Integer.valueOf(oldValue),
      854                     Integer.valueOf(brm.getValue()));
      855         }
      856     }
      857 
      858     /**
      859      * Sets the progress bar's minimum value
      860      * (stored in the progress bar's data model) to <code>n</code>.
      861      * <p>
      862      * The data model (a <code>BoundedRangeModel</code> instance)
      863      * handles any mathematical
      864      * issues arising from assigning faulty values.
      865      * See the {@code BoundedRangeModel} documentation for details.
      866      * <p>
      867      * If the minimum value is different from the previous minimum,
      868      * all change listeners are notified.
      869      *
      870      * @param  n       the new minimum
      871      * @see    #getMinimum
      872      * @see    #addChangeListener
      873      * @see    BoundedRangeModel#setMinimum
      874      * @beaninfo
      875      *  preferred: true
      876      * description: The progress bar's minimum value.
      877      */
      878     public void setMinimum(int n) { getModel().setMinimum(n); }
      879 
      880     /**
      881      * Sets the progress bar's maximum value
      882      * (stored in the progress bar's data model) to <code>n</code>.
      883      * <p>
      884      * The underlying <code>BoundedRangeModel</code> handles any mathematical
      885      * issues arising from assigning faulty values.
      886      * See the {@code BoundedRangeModel} documentation for details.
      887      * <p>
      888      * If the maximum value is different from the previous maximum,
      889      * all change listeners are notified.
      890      *
      891      * @param  n       the new maximum
      892      * @see    #getMaximum
      893      * @see    #addChangeListener
      894      * @see    BoundedRangeModel#setMaximum
      895      * @beaninfo
      896      *    preferred: true
      897      *  description: The progress bar's maximum value.
      898      */
      899     public void setMaximum(int n) { getModel().setMaximum(n); }
      900 
      901     /**
      902      * Sets the <code>indeterminate</code> property of the progress bar,
      903      * which determines whether the progress bar is in determinate
      904      * or indeterminate mode.
      905      * An indeterminate progress bar continuously displays animation
      906      * indicating that an operation of unknown length is occurring.
      907      * By default, this property is <code>false</code>.
      908      * Some look and feels might not support indeterminate progress bars;
      909      * they will ignore this property.
      910      *
      911      * <p>
      912      *
      913      * See
      914      * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>
      915      * for examples of using indeterminate progress bars.
      916      *
      917      * @param newValue  <code>true</code> if the progress bar
      918      *                  should change to indeterminate mode;
      919      *                  <code>false</code> if it should revert to normal.
      920      *
      921      * @see #isIndeterminate
      922      * @see javax.swing.plaf.basic.BasicProgressBarUI
      923      *
      924      * @since 1.4
      925      *
      926      * @beaninfo
      927      *        bound: true
      928      *    attribute: visualUpdate true
      929      *  description: Set whether the progress bar is indeterminate (true)
      930      *               or normal (false).
      931      */
      932     public void setIndeterminate(boolean newValue) {
      933         boolean oldValue = indeterminate;
      934         indeterminate = newValue;
      935         firePropertyChange("indeterminate", oldValue, indeterminate);
      936     }
      937 
      938     /**
      939      * Returns the value of the <code>indeterminate</code> property.
      940      *
      941      * @return the value of the <code>indeterminate</code> property
      942      * @see    #setIndeterminate
      943      *
      944      * @since 1.4
      945      *
      946      * @beaninfo
      947      *  description: Is the progress bar indeterminate (true)
      948      *               or normal (false)?
      949      */
      950     public boolean isIndeterminate() {
      951         return indeterminate;
      952     }
      953 
      954 
      955     /**
      956      * See readObject() and writeObject() in JComponent for more
      957      * information about serialization in Swing.
      958      */
      959     private void writeObject(ObjectOutputStream s) throws IOException {
      960         s.defaultWriteObject();
      961         if (getUIClassID().equals(uiClassID)) {
      962             byte count = JComponent.getWriteObjCounter(this);
      963             JComponent.setWriteObjCounter(this, --count);
      964             if (count == 0 && ui != null) {
      965                 ui.installUI(this);
      966             }
      967         }
      968     }
      969 
      970 
      971     /**
      972      * Returns a string representation of this <code>JProgressBar</code>.
      973      * This method is intended to be used only for debugging purposes. The
      974      * content and format of the returned string may vary between
      975      * implementations. The returned string may be empty but may not
      976      * be <code>null</code>.
      977      *
      978      * @return  a string representation of this <code>JProgressBar</code>
      979      */
      980     protected String paramString() {
      981         String orientationString = (orientation == HORIZONTAL ?
      982                                     "HORIZONTAL" : "VERTICAL");
      983         String paintBorderString = (paintBorder ?
      984                                     "true" : "false");
      985         String progressStringString = (progressString != null ?
      986                                        progressString : "");
      987         String paintStringString = (paintString ?
      988                                     "true" : "false");
      989         String indeterminateString = (indeterminate ?
      990                                     "true" : "false");
      991 
      992         return super.paramString() +
      993         ",orientation=" + orientationString +
      994         ",paintBorder=" + paintBorderString +
      995         ",paintString=" + paintStringString +
      996         ",progressString=" + progressStringString +
      997         ",indeterminateString=" + indeterminateString;
      998     }
      999 
     1000 /////////////////
     1001 // Accessibility support
     1002 ////////////////
     1003 
     1004     /**
     1005      * Gets the <code>AccessibleContext</code> associated with this
     1006      * <code>JProgressBar</code>. For progress bars, the
     1007      * <code>AccessibleContext</code> takes the form of an
     1008      * <code>AccessibleJProgressBar</code>.
     1009      * A new <code>AccessibleJProgressBar</code> instance is created if necessary.
     1010      *
     1011      * @return an <code>AccessibleJProgressBar</code> that serves as the
     1012      *         <code>AccessibleContext</code> of this <code>JProgressBar</code>
     1013      * @beaninfo
     1014      *       expert: true
     1015      *  description: The AccessibleContext associated with this ProgressBar.
     1016      */
     1017     public AccessibleContext getAccessibleContext() {
     1018         if (accessibleContext == null) {
     1019             accessibleContext = new AccessibleJProgressBar();
     1020         }
     1021         return accessibleContext;
     1022     }
     1023 
     1024     /**
     1025      * This class implements accessibility support for the
     1026      * <code>JProgressBar</code> class.  It provides an implementation of the
     1027      * Java Accessibility API appropriate to progress bar user-interface
     1028      * elements.
     1029      * <p>
     1030      * <strong>Warning:</strong>
     1031      * Serialized objects of this class will not be compatible with
     1032      * future Swing releases. The current serialization support is
     1033      * appropriate for short term storage or RMI between applications running
     1034      * the same version of Swing.  As of 1.4, support for long term storage
     1035      * of all JavaBeans<sup><font size="-2">TM</font></sup>
     1036      * has been added to the <code>java.beans</code> package.
     1037      * Please see {@link java.beans.XMLEncoder}.
     1038      */
     1039     protected class AccessibleJProgressBar extends AccessibleJComponent
     1040         implements AccessibleValue {
     1041 
     1042         /**
     1043          * Gets the state set of this object.
     1044          *
     1045          * @return an instance of AccessibleState containing the current state
     1046          * of the object
     1047          * @see AccessibleState
     1048          */
     1049         public AccessibleStateSet getAccessibleStateSet() {
     1050             AccessibleStateSet states = super.getAccessibleStateSet();
     1051             if (getModel().getValueIsAdjusting()) {
     1052                 states.add(AccessibleState.BUSY);
     1053             }
     1054             if (getOrientation() == VERTICAL) {
     1055                 states.add(AccessibleState.VERTICAL);
     1056             } else {
     1057                 states.add(AccessibleState.HORIZONTAL);
     1058             }
     1059             return states;
     1060         }
     1061 
     1062         /**
     1063          * Gets the role of this object.
     1064          *
     1065          * @return an instance of AccessibleRole describing the role of the
     1066          * object
     1067          */
     1068         public AccessibleRole getAccessibleRole() {
     1069             return AccessibleRole.PROGRESS_BAR;
     1070         }
     1071 
     1072         /**
     1073          * Gets the <code>AccessibleValue</code> associated with this object.  In the
     1074          * implementation of the Java Accessibility API for this class,
     1075          * returns this object, which is responsible for implementing the
     1076          * <code>AccessibleValue</code> interface on behalf of itself.
     1077          *
     1078          * @return this object
     1079          */
     1080         public AccessibleValue getAccessibleValue() {
     1081             return this;
     1082         }
     1083 
     1084         /**
     1085          * Gets the accessible value of this object.
     1086          *
     1087          * @return the current value of this object
     1088          */
     1089         public Number getCurrentAccessibleValue() {
     1090             return Integer.valueOf(getValue());
     1091         }
     1092 
     1093         /**
     1094          * Sets the value of this object as a <code>Number</code>.
     1095          *
     1096          * @return <code>true</code> if the value was set
     1097          */
     1098         public boolean setCurrentAccessibleValue(Number n) {
     1099             // TIGER- 4422535
     1100             if (n == null) {
     1101                 return false;
     1102             }
     1103             setValue(n.intValue());
     1104             return true;
     1105         }
     1106 
     1107         /**
     1108          * Gets the minimum accessible value of this object.
     1109          *
     1110          * @return the minimum value of this object
     1111          */
     1112         public Number getMinimumAccessibleValue() {
     1113             return Integer.valueOf(getMinimum());
     1114         }
     1115 
     1116         /**
     1117          * Gets the maximum accessible value of this object.
     1118          *
     1119          * @return the maximum value of this object
     1120          */
     1121         public Number getMaximumAccessibleValue() {
     1122             // TIGER - 4422362
     1123             return Integer.valueOf(model.getMaximum() - model.getExtent());
     1124         }
     1125 
     1126     } // AccessibleJProgressBar
     1127 }