jdk/src/share/classes/javax/swing/JProgressBar.java
changeset 2 90ce3da70b43
child 438 2ae294e4518c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/javax/swing/JProgressBar.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,1127 @@
+/*
+ * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.swing;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import java.text.Format;
+import java.text.NumberFormat;
+
+import java.io.Serializable;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.IOException;
+
+import javax.swing.event.*;
+import javax.accessibility.*;
+import javax.swing.plaf.ProgressBarUI;
+
+
+/**
+ * A component that visually displays the progress of some task.  As the task
+ * progresses towards completion, the progress bar displays the
+ * task's percentage of completion.
+ * This percentage is typically represented visually by a rectangle which
+ * starts out empty and gradually becomes filled in as the task progresses.
+ * In addition, the progress bar can display a textual representation of this
+ * percentage.
+ * <p>
+ * {@code JProgressBar} uses a {@code BoundedRangeModel} as its data model,
+ * with the {@code value} property representing the "current" state of the task,
+ * and the {@code minimum} and {@code maximum} properties representing the
+ * beginning and end points, respectively.
+ * <p>
+ * To indicate that a task of unknown length is executing,
+ * you can put a progress bar into indeterminate mode.
+ * While the bar is in indeterminate mode,
+ * it animates constantly to show that work is occurring.
+ * As soon as you can determine the task's length and amount of progress,
+ * you should update the progress bar's value
+ * and switch it back to determinate mode.
+ *
+ * <p>
+ *
+ * Here is an example of creating a progress bar,
+ * where <code>task</code> is an object (representing some piece of work)
+ * which returns information about the progress of the task:
+ *
+ *<pre>
+ *progressBar = new JProgressBar(0, task.getLengthOfTask());
+ *progressBar.setValue(0);
+ *progressBar.setStringPainted(true);
+ *</pre>
+ *
+ * Here is an example of querying the current state of the task, and using
+ * the returned value to update the progress bar:
+ *
+ *<pre>
+ *progressBar.setValue(task.getCurrent());
+ *</pre>
+ *
+ * Here is an example of putting a progress bar into
+ * indeterminate mode,
+ * and then switching back to determinate mode
+ * once the length of the task is known:
+ *
+ *<pre>
+ *progressBar = new JProgressBar();
+ *<em>...//when the task of (initially) unknown length begins:</em>
+ *progressBar.setIndeterminate(true);
+ *<em>...//do some work; get length of task...</em>
+ *progressBar.setMaximum(newLength);
+ *progressBar.setValue(newValue);
+ *progressBar.setIndeterminate(false);
+ *</pre>
+ *
+ * <p>
+ *
+ * For complete examples and further documentation see
+ * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>,
+ * a section in <em>The Java Tutorial.</em>
+ *
+ * <p>
+ * <strong>Warning:</strong> Swing is not thread safe. For more
+ * information see <a
+ * href="package-summary.html#threading">Swing's Threading
+ * Policy</a>.
+ * <p>
+ * <strong>Warning:</strong>
+ * Serialized objects of this class will not be compatible with
+ * future Swing releases. The current serialization support is
+ * appropriate for short term storage or RMI between applications running
+ * the same version of Swing.  As of 1.4, support for long term storage
+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
+ * has been added to the <code>java.beans</code> package.
+ * Please see {@link java.beans.XMLEncoder}.
+ *
+ * @see javax.swing.plaf.basic.BasicProgressBarUI
+ * @see javax.swing.BoundedRangeModel
+ * @see javax.swing.SwingWorker
+ *
+ * @beaninfo
+ *      attribute: isContainer false
+ *    description: A component that displays an integer value.
+ *
+ * @author Michael C. Albers
+ * @author Kathy Walrath
+ */
+public class JProgressBar extends JComponent implements SwingConstants, Accessible
+{
+    /**
+     * @see #getUIClassID
+     */
+    private static final String uiClassID = "ProgressBarUI";
+
+    /**
+     * Whether the progress bar is horizontal or vertical.
+     * The default is <code>HORIZONTAL</code>.
+     *
+     * @see #setOrientation
+     */
+    protected int orientation;
+
+    /**
+     * Whether to display a border around the progress bar.
+     * The default is <code>true</code>.
+     *
+     * @see #setBorderPainted
+     */
+    protected boolean paintBorder;
+
+    /**
+     * The object that holds the data for the progress bar.
+     *
+     * @see #setModel
+     */
+    protected BoundedRangeModel model;
+
+    /**
+     * An optional string that can be displayed on the progress bar.
+     * The default is <code>null</code>. Setting this to a non-<code>null</code>
+     * value does not imply that the string will be displayed.
+     * To display the string, {@code paintString} must be {@code true}.
+     *
+     * @see #setString
+     * @see #setStringPainted
+     */
+    protected String progressString;
+
+    /**
+     * Whether to display a string of text on the progress bar.
+     * The default is <code>false</code>.
+     * Setting this to <code>true</code> causes a textual
+     * display of the progress to be rendered on the progress bar. If
+     * the <code>progressString</code> is <code>null</code>,
+     * the percentage of completion is displayed on the progress bar.
+     * Otherwise, the <code>progressString</code> is
+     * rendered on the progress bar.
+     *
+     * @see #setStringPainted
+     * @see #setString
+     */
+    protected boolean paintString;
+
+    /**
+     * The default minimum for a progress bar is 0.
+     */
+    static final private int defaultMinimum = 0;
+    /**
+     * The default maximum for a progress bar is 100.
+     */
+    static final private int defaultMaximum = 100;
+    /**
+     * The default orientation for a progress bar is <code>HORIZONTAL</code>.
+     */
+    static final private int defaultOrientation = HORIZONTAL;
+
+    /**
+     * Only one <code>ChangeEvent</code> is needed per instance since the
+     * event's only interesting property is the immutable source, which
+     * is the progress bar.
+     * The event is lazily created the first time that an
+     * event notification is fired.
+     *
+     * @see #fireStateChanged
+     */
+    protected transient ChangeEvent changeEvent = null;
+
+    /**
+     * Listens for change events sent by the progress bar's model,
+     * redispatching them
+     * to change-event listeners registered upon
+     * this progress bar.
+     *
+     * @see #createChangeListener
+     */
+    protected ChangeListener changeListener = null;
+
+    /**
+     * Format used when displaying percent complete.
+     */
+    private transient Format format;
+
+    /**
+     * Whether the progress bar is indeterminate (<code>true</code>) or
+     * normal (<code>false</code>); the default is <code>false</code>.
+     *
+     * @see #setIndeterminate
+     * @since 1.4
+     */
+    private boolean indeterminate;
+
+
+   /**
+     * Creates a horizontal progress bar
+     * that displays a border but no progress string.
+     * The initial and minimum values are 0,
+     * and the maximum is 100.
+     *
+     * @see #setOrientation
+     * @see #setBorderPainted
+     * @see #setStringPainted
+     * @see #setString
+     * @see #setIndeterminate
+     */
+    public JProgressBar()
+    {
+        this(defaultOrientation);
+    }
+
+   /**
+     * Creates a progress bar with the specified orientation,
+     * which can be
+     * either {@code SwingConstants.VERTICAL} or
+     * {@code SwingConstants.HORIZONTAL}.
+     * By default, a border is painted but a progress string is not.
+     * The initial and minimum values are 0,
+     * and the maximum is 100.
+     *
+     * @param orient  the desired orientation of the progress bar
+     * @throws IllegalArgumentException if {@code orient} is an illegal value
+     *
+     * @see #setOrientation
+     * @see #setBorderPainted
+     * @see #setStringPainted
+     * @see #setString
+     * @see #setIndeterminate
+     */
+    public JProgressBar(int orient)
+    {
+        this(orient, defaultMinimum, defaultMaximum);
+    }
+
+
+    /**
+     * Creates a horizontal progress bar
+     * with the specified minimum and maximum.
+     * Sets the initial value of the progress bar to the specified minimum.
+     * By default, a border is painted but a progress string is not.
+     * <p>
+     * The <code>BoundedRangeModel</code> that holds the progress bar's data
+     * handles any issues that may arise from improperly setting the
+     * minimum, initial, and maximum values on the progress bar.
+     * See the {@code BoundedRangeModel} documentation for details.
+     *
+     * @param min  the minimum value of the progress bar
+     * @param max  the maximum value of the progress bar
+     *
+     * @see BoundedRangeModel
+     * @see #setOrientation
+     * @see #setBorderPainted
+     * @see #setStringPainted
+     * @see #setString
+     * @see #setIndeterminate
+     */
+    public JProgressBar(int min, int max)
+    {
+        this(defaultOrientation, min, max);
+    }
+
+
+    /**
+     * Creates a progress bar using the specified orientation,
+     * minimum, and maximum.
+     * By default, a border is painted but a progress string is not.
+     * Sets the initial value of the progress bar to the specified minimum.
+     * <p>
+     * The <code>BoundedRangeModel</code> that holds the progress bar's data
+     * handles any issues that may arise from improperly setting the
+     * minimum, initial, and maximum values on the progress bar.
+     * See the {@code BoundedRangeModel} documentation for details.
+     *
+     * @param orient  the desired orientation of the progress bar
+     * @param min  the minimum value of the progress bar
+     * @param max  the maximum value of the progress bar
+     * @throws IllegalArgumentException if {@code orient} is an illegal value
+     *
+     * @see BoundedRangeModel
+     * @see #setOrientation
+     * @see #setBorderPainted
+     * @see #setStringPainted
+     * @see #setString
+     * @see #setIndeterminate
+     */
+    public JProgressBar(int orient, int min, int max)
+    {
+        // Creating the model this way is a bit simplistic, but
+        //  I believe that it is the the most common usage of this
+        //  component - it's what people will expect.
+        setModel(new DefaultBoundedRangeModel(min, 0, min, max));
+        updateUI();
+
+        setOrientation(orient);      // documented with set/getOrientation()
+        setBorderPainted(true);      // documented with is/setBorderPainted()
+        setStringPainted(false);     // see setStringPainted
+        setString(null);             // see getString
+        setIndeterminate(false);     // see setIndeterminate
+    }
+
+
+    /**
+     * Creates a horizontal progress bar
+     * that uses the specified model
+     * to hold the progress bar's data.
+     * By default, a border is painted but a progress string is not.
+     *
+     * @param newModel  the data model for the progress bar
+     *
+     * @see #setOrientation
+     * @see #setBorderPainted
+     * @see #setStringPainted
+     * @see #setString
+     * @see #setIndeterminate
+     */
+    public JProgressBar(BoundedRangeModel newModel)
+    {
+        setModel(newModel);
+        updateUI();
+
+        setOrientation(defaultOrientation);  // see setOrientation()
+        setBorderPainted(true);              // see setBorderPainted()
+        setStringPainted(false);             // see setStringPainted
+        setString(null);                     // see getString
+        setIndeterminate(false);             // see setIndeterminate
+    }
+
+
+    /**
+     * Returns {@code SwingConstants.VERTICAL} or
+     * {@code SwingConstants.HORIZONTAL}, depending on the orientation
+     * of the progress bar. The default orientation is
+     * {@code SwingConstants.HORIZONTAL}.
+     *
+     * @return <code>HORIZONTAL</code> or <code>VERTICAL</code>
+     * @see #setOrientation
+     */
+    public int getOrientation() {
+        return orientation;
+    }
+
+
+   /**
+     * Sets the progress bar's orientation to <code>newOrientation</code>,
+     * which must be {@code SwingConstants.VERTICAL} or
+     * {@code SwingConstants.HORIZONTAL}. The default orientation
+     * is {@code SwingConstants.HORIZONTAL}.
+     *
+     * @param  newOrientation  <code>HORIZONTAL</code> or <code>VERTICAL</code>
+     * @exception      IllegalArgumentException    if <code>newOrientation</code>
+     *                                              is an illegal value
+     * @see #getOrientation
+     *
+     * @beaninfo
+     *    preferred: true
+     *        bound: true
+     *    attribute: visualUpdate true
+     *  description: Set the progress bar's orientation.
+     */
+    public void setOrientation(int newOrientation) {
+        if (orientation != newOrientation) {
+            switch (newOrientation) {
+            case VERTICAL:
+            case HORIZONTAL:
+                int oldOrientation = orientation;
+                orientation = newOrientation;
+                firePropertyChange("orientation", oldOrientation, newOrientation);
+                if (accessibleContext != null) {
+                    accessibleContext.firePropertyChange(
+                            AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
+                            ((oldOrientation == VERTICAL)
+                             ? AccessibleState.VERTICAL
+                             : AccessibleState.HORIZONTAL),
+                            ((orientation == VERTICAL)
+                             ? AccessibleState.VERTICAL
+                             : AccessibleState.HORIZONTAL));
+                }
+                break;
+            default:
+                throw new IllegalArgumentException(newOrientation +
+                                             " is not a legal orientation");
+            }
+            revalidate();
+        }
+    }
+
+
+    /**
+     * Returns the value of the <code>stringPainted</code> property.
+     *
+     * @return the value of the <code>stringPainted</code> property
+     * @see    #setStringPainted
+     * @see    #setString
+     */
+    public boolean isStringPainted() {
+        return paintString;
+    }
+
+
+    /**
+     * Sets the value of the <code>stringPainted</code> property,
+     * which determines whether the progress bar
+     * should render a progress string.
+     * The default is <code>false</code>, meaning
+     * no string is painted.
+     * Some look and feels might not support progress strings
+     * or might support them only when the progress bar is in determinate mode.
+     *
+     * @param   b       <code>true</code> if the progress bar should render a string
+     * @see     #isStringPainted
+     * @see     #setString
+     * @beaninfo
+     *        bound: true
+     *    attribute: visualUpdate true
+     *  description: Whether the progress bar should render a string.
+     */
+    public void setStringPainted(boolean b) {
+        //PENDING: specify that string not painted when in indeterminate mode?
+        //         or just leave that to the L&F?
+        boolean oldValue = paintString;
+        paintString = b;
+        firePropertyChange("stringPainted", oldValue, paintString);
+        if (paintString != oldValue) {
+            revalidate();
+            repaint();
+        }
+    }
+
+
+    /**
+     * Returns a {@code String} representation of the current progress.
+     * By default, this returns a simple percentage {@code String} based on
+     * the value returned from {@code getPercentComplete}.  An example
+     * would be the "42%".  You can change this by calling {@code setString}.
+     *
+     * @return the value of the progress string, or a simple percentage string
+     *         if the progress string is {@code null}
+     * @see    #setString
+     */
+    public String getString(){
+        if (progressString != null) {
+            return progressString;
+        } else {
+            if (format == null) {
+                format = NumberFormat.getPercentInstance();
+            }
+            return format.format(new Double(getPercentComplete()));
+        }
+    }
+
+    /**
+     * Sets the value of the progress string. By default,
+     * this string is <code>null</code>, implying the built-in behavior of
+     * using a simple percent string.
+     * If you have provided a custom progress string and want to revert to
+     * the built-in behavior, set the string back to <code>null</code>.
+     * <p>
+     * The progress string is painted only if
+     * the <code>isStringPainted</code> method returns <code>true</code>.
+     *
+     * @param  s       the value of the progress string
+     * @see    #getString
+     * @see    #setStringPainted
+     * @see    #isStringPainted
+     * @beaninfo
+     *        bound: true
+     *    attribute: visualUpdate true
+     *  description: Specifies the progress string to paint
+     */
+    public void setString(String s){
+        String oldValue = progressString;
+        progressString = s;
+        firePropertyChange("string", oldValue, progressString);
+        if (progressString == null || oldValue == null || !progressString.equals(oldValue)) {
+            repaint();
+        }
+    }
+
+    /**
+     * Returns the percent complete for the progress bar.
+     * Note that this number is between 0.0 and 1.0.
+     *
+     * @return the percent complete for this progress bar
+     */
+    public double getPercentComplete() {
+        long span = model.getMaximum() - model.getMinimum();
+        double currentValue = model.getValue();
+        double pc = (currentValue - model.getMinimum()) / span;
+        return pc;
+    }
+
+    /**
+     * Returns the <code>borderPainted</code> property.
+     *
+     * @return the value of the <code>borderPainted</code> property
+     * @see    #setBorderPainted
+     * @beaninfo
+     *  description: Does the progress bar paint its border
+     */
+    public boolean isBorderPainted() {
+        return paintBorder;
+    }
+
+    /**
+     * Sets the <code>borderPainted</code> property, which is
+     * <code>true</code> if the progress bar should paint its border.
+     * The default value for this property is <code>true</code>.
+     * Some look and feels might not implement painted borders;
+     * they will ignore this property.
+     *
+     * @param   b       <code>true</code> if the progress bar
+     *                  should paint its border;
+     *                  otherwise, <code>false</code>
+     * @see     #isBorderPainted
+     * @beaninfo
+     *        bound: true
+     *    attribute: visualUpdate true
+     *  description: Whether the progress bar should paint its border.
+     */
+    public void setBorderPainted(boolean b) {
+        boolean oldValue = paintBorder;
+        paintBorder = b;
+        firePropertyChange("borderPainted", oldValue, paintBorder);
+        if (paintBorder != oldValue) {
+            repaint();
+        }
+    }
+
+    /**
+     * Paints the progress bar's border if the <code>borderPainted</code>
+     * property is <code>true</code>.
+     *
+     * @param g  the <code>Graphics</code> context within which to paint the border
+     * @see #paint
+     * @see #setBorder
+     * @see #isBorderPainted
+     * @see #setBorderPainted
+     */
+    protected void paintBorder(Graphics g) {
+        if (isBorderPainted()) {
+            super.paintBorder(g);
+        }
+    }
+
+
+    /**
+     * Returns the look-and-feel object that renders this component.
+     *
+     * @return the <code>ProgressBarUI</code> object that renders this component
+     */
+    public ProgressBarUI getUI() {
+        return (ProgressBarUI)ui;
+    }
+
+    /**
+     * Sets the look-and-feel object that renders this component.
+     *
+     * @param ui  a <code>ProgressBarUI</code> object
+     * @see UIDefaults#getUI
+     * @beaninfo
+     *        bound: true
+     *       hidden: true
+     *    attribute: visualUpdate true
+     *  description: The UI object that implements the Component's LookAndFeel.
+     */
+    public void setUI(ProgressBarUI ui) {
+        super.setUI(ui);
+    }
+
+
+    /**
+     * Resets the UI property to a value from the current look and feel.
+     *
+     * @see JComponent#updateUI
+     */
+    public void updateUI() {
+        setUI((ProgressBarUI)UIManager.getUI(this));
+    }
+
+
+    /**
+     * Returns the name of the look-and-feel class that renders this component.
+     *
+     * @return the string "ProgressBarUI"
+     * @see JComponent#getUIClassID
+     * @see UIDefaults#getUI
+     * @beaninfo
+     *        expert: true
+     *   description: A string that specifies the name of the look-and-feel class.
+     */
+    public String getUIClassID() {
+        return uiClassID;
+    }
+
+
+    /* We pass each Change event to the listeners with the
+     * the progress bar as the event source.
+     * <p>
+     * <strong>Warning:</strong>
+     * Serialized objects of this class will not be compatible with
+     * future Swing releases. The current serialization support is
+     * appropriate for short term storage or RMI between applications running
+     * the same version of Swing.  As of 1.4, support for long term storage
+     * of all JavaBeans<sup><font size="-2">TM</font></sup>
+     * has been added to the <code>java.beans</code> package.
+     * Please see {@link java.beans.XMLEncoder}.
+     */
+    private class ModelListener implements ChangeListener, Serializable {
+        public void stateChanged(ChangeEvent e) {
+            fireStateChanged();
+        }
+    }
+
+    /**
+     * Subclasses that want to handle change events
+     * from the model differently
+     * can override this to return
+     * an instance of a custom <code>ChangeListener</code> implementation.
+     * The default {@code ChangeListener} simply calls the
+     * {@code fireStateChanged} method to forward {@code ChangeEvent}s
+     * to the {@code ChangeListener}s that have been added directly to the
+     * progress bar.
+     *
+     * @see #changeListener
+     * @see #fireStateChanged
+     * @see javax.swing.event.ChangeListener
+     * @see javax.swing.BoundedRangeModel
+     */
+    protected ChangeListener createChangeListener() {
+        return new ModelListener();
+    }
+
+    /**
+     * Adds the specified <code>ChangeListener</code> to the progress bar.
+     *
+     * @param l the <code>ChangeListener</code> to add
+     */
+    public void addChangeListener(ChangeListener l) {
+        listenerList.add(ChangeListener.class, l);
+    }
+
+    /**
+     * Removes a <code>ChangeListener</code> from the progress bar.
+     *
+     * @param l the <code>ChangeListener</code> to remove
+     */
+    public void removeChangeListener(ChangeListener l) {
+        listenerList.remove(ChangeListener.class, l);
+    }
+
+    /**
+     * Returns an array of all the <code>ChangeListener</code>s added
+     * to this progress bar with <code>addChangeListener</code>.
+     *
+     * @return all of the <code>ChangeListener</code>s added or an empty
+     *         array if no listeners have been added
+     * @since 1.4
+     */
+    public ChangeListener[] getChangeListeners() {
+        return (ChangeListener[])listenerList.getListeners(
+                ChangeListener.class);
+    }
+
+    /**
+     * Send a {@code ChangeEvent}, whose source is this {@code JProgressBar}, to
+     * all {@code ChangeListener}s that have registered interest in
+     * {@code ChangeEvent}s.
+     * This method is called each time a {@code ChangeEvent} is received from
+     * the model.
+     * <p>
+     *
+     * The event instance is created if necessary, and stored in
+     * {@code changeEvent}.
+     *
+     * @see #addChangeListener
+     * @see EventListenerList
+     */
+    protected void fireStateChanged() {
+        // Guaranteed to return a non-null array
+        Object[] listeners = listenerList.getListenerList();
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for (int i = listeners.length-2; i>=0; i-=2) {
+            if (listeners[i]==ChangeListener.class) {
+                // Lazily create the event:
+                if (changeEvent == null)
+                    changeEvent = new ChangeEvent(this);
+                ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
+            }
+        }
+    }
+
+    /**
+     * Returns the data model used by this progress bar.
+     *
+     * @return the <code>BoundedRangeModel</code> currently in use
+     * @see #setModel
+     * @see    BoundedRangeModel
+     */
+    public BoundedRangeModel getModel() {
+        return model;
+    }
+
+    /**
+     * Sets the data model used by the <code>JProgressBar</code>.
+     * Note that the {@code BoundedRangeModel}'s {@code extent} is not used,
+     * and is set to {@code 0}.
+     *
+     * @param  newModel the <code>BoundedRangeModel</code> to use
+     *
+     * @beaninfo
+     *    expert: true
+     * description: The data model used by the JProgressBar.
+     */
+    public void setModel(BoundedRangeModel newModel) {
+        // PENDING(???) setting the same model to multiple bars is broken; listeners
+        BoundedRangeModel oldModel = getModel();
+
+        if (newModel != oldModel) {
+            if (oldModel != null) {
+                oldModel.removeChangeListener(changeListener);
+                changeListener = null;
+            }
+
+            model = newModel;
+
+            if (newModel != null) {
+                changeListener = createChangeListener();
+                newModel.addChangeListener(changeListener);
+            }
+
+            if (accessibleContext != null) {
+                accessibleContext.firePropertyChange(
+                        AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
+                        (oldModel== null
+                         ? null : new Integer(oldModel.getValue())),
+                        (newModel== null
+                         ? null : new Integer(newModel.getValue())));
+            }
+
+            if (model != null) {
+                model.setExtent(0);
+            }
+            repaint();
+        }
+    }
+
+
+    /* All of the model methods are implemented by delegation. */
+
+    /**
+     * Returns the progress bar's current {@code value}
+     * from the <code>BoundedRangeModel</code>.
+     * The value is always between the
+     * minimum and maximum values, inclusive.
+     *
+     * @return  the current value of the progress bar
+     * @see     #setValue
+     * @see     BoundedRangeModel#getValue
+     */
+    public int getValue() { return getModel().getValue(); }
+
+    /**
+     * Returns the progress bar's {@code minimum} value
+     * from the <code>BoundedRangeModel</code>.
+     *
+     * @return  the progress bar's minimum value
+     * @see     #setMinimum
+     * @see     BoundedRangeModel#getMinimum
+     */
+    public int getMinimum() { return getModel().getMinimum(); }
+
+    /**
+     * Returns the progress bar's {@code maximum} value
+     * from the <code>BoundedRangeModel</code>.
+     *
+     * @return  the progress bar's maximum value
+     * @see     #setMaximum
+     * @see     BoundedRangeModel#getMaximum
+     */
+    public int getMaximum() { return getModel().getMaximum(); }
+
+    /**
+     * Sets the progress bar's current value to {@code n}.  This method
+     * forwards the new value to the model.
+     * <p>
+     * The data model (an instance of {@code BoundedRangeModel})
+     * handles any mathematical
+     * issues arising from assigning faulty values.  See the
+     * {@code BoundedRangeModel} documentation for details.
+     * <p>
+     * If the new value is different from the previous value,
+     * all change listeners are notified.
+     *
+     * @param   n       the new value
+     * @see     #getValue
+     * @see     #addChangeListener
+     * @see     BoundedRangeModel#setValue
+     * @beaninfo
+     *    preferred: true
+     *  description: The progress bar's current value.
+     */
+    public void setValue(int n) {
+        BoundedRangeModel brm = getModel();
+        int oldValue = brm.getValue();
+        brm.setValue(n);
+
+        if (accessibleContext != null) {
+            accessibleContext.firePropertyChange(
+                    AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
+                    new Integer(oldValue),
+                    new Integer(brm.getValue()));
+        }
+    }
+
+    /**
+     * Sets the progress bar's minimum value
+     * (stored in the progress bar's data model) to <code>n</code>.
+     * <p>
+     * The data model (a <code>BoundedRangeModel</code> instance)
+     * handles any mathematical
+     * issues arising from assigning faulty values.
+     * See the {@code BoundedRangeModel} documentation for details.
+     * <p>
+     * If the minimum value is different from the previous minimum,
+     * all change listeners are notified.
+     *
+     * @param  n       the new minimum
+     * @see    #getMinimum
+     * @see    #addChangeListener
+     * @see    BoundedRangeModel#setMinimum
+     * @beaninfo
+     *  preferred: true
+     * description: The progress bar's minimum value.
+     */
+    public void setMinimum(int n) { getModel().setMinimum(n); }
+
+    /**
+     * Sets the progress bar's maximum value
+     * (stored in the progress bar's data model) to <code>n</code>.
+     * <p>
+     * The underlying <code>BoundedRangeModel</code> handles any mathematical
+     * issues arising from assigning faulty values.
+     * See the {@code BoundedRangeModel} documentation for details.
+     * <p>
+     * If the maximum value is different from the previous maximum,
+     * all change listeners are notified.
+     *
+     * @param  n       the new maximum
+     * @see    #getMaximum
+     * @see    #addChangeListener
+     * @see    BoundedRangeModel#setMaximum
+     * @beaninfo
+     *    preferred: true
+     *  description: The progress bar's maximum value.
+     */
+    public void setMaximum(int n) { getModel().setMaximum(n); }
+
+    /**
+     * Sets the <code>indeterminate</code> property of the progress bar,
+     * which determines whether the progress bar is in determinate
+     * or indeterminate mode.
+     * An indeterminate progress bar continuously displays animation
+     * indicating that an operation of unknown length is occurring.
+     * By default, this property is <code>false</code>.
+     * Some look and feels might not support indeterminate progress bars;
+     * they will ignore this property.
+     *
+     * <p>
+     *
+     * See
+     * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>
+     * for examples of using indeterminate progress bars.
+     *
+     * @param newValue  <code>true</code> if the progress bar
+     *                  should change to indeterminate mode;
+     *                  <code>false</code> if it should revert to normal.
+     *
+     * @see #isIndeterminate
+     * @see javax.swing.plaf.basic.BasicProgressBarUI
+     *
+     * @since 1.4
+     *
+     * @beaninfo
+     *        bound: true
+     *    attribute: visualUpdate true
+     *  description: Set whether the progress bar is indeterminate (true)
+     *               or normal (false).
+     */
+    public void setIndeterminate(boolean newValue) {
+        boolean oldValue = indeterminate;
+        indeterminate = newValue;
+        firePropertyChange("indeterminate", oldValue, indeterminate);
+    }
+
+    /**
+     * Returns the value of the <code>indeterminate</code> property.
+     *
+     * @return the value of the <code>indeterminate</code> property
+     * @see    #setIndeterminate
+     *
+     * @since 1.4
+     *
+     * @beaninfo
+     *  description: Is the progress bar indeterminate (true)
+     *               or normal (false)?
+     */
+    public boolean isIndeterminate() {
+        return indeterminate;
+    }
+
+
+    /**
+     * See readObject() and writeObject() in JComponent for more
+     * information about serialization in Swing.
+     */
+    private void writeObject(ObjectOutputStream s) throws IOException {
+        s.defaultWriteObject();
+        if (getUIClassID().equals(uiClassID)) {
+            byte count = JComponent.getWriteObjCounter(this);
+            JComponent.setWriteObjCounter(this, --count);
+            if (count == 0 && ui != null) {
+                ui.installUI(this);
+            }
+        }
+    }
+
+
+    /**
+     * Returns a string representation of this <code>JProgressBar</code>.
+     * This method is intended to be used only for debugging purposes. The
+     * content and format of the returned string may vary between
+     * implementations. The returned string may be empty but may not
+     * be <code>null</code>.
+     *
+     * @return  a string representation of this <code>JProgressBar</code>
+     */
+    protected String paramString() {
+        String orientationString = (orientation == HORIZONTAL ?
+                                    "HORIZONTAL" : "VERTICAL");
+        String paintBorderString = (paintBorder ?
+                                    "true" : "false");
+        String progressStringString = (progressString != null ?
+                                       progressString : "");
+        String paintStringString = (paintString ?
+                                    "true" : "false");
+        String indeterminateString = (indeterminate ?
+                                    "true" : "false");
+
+        return super.paramString() +
+        ",orientation=" + orientationString +
+        ",paintBorder=" + paintBorderString +
+        ",paintString=" + paintStringString +
+        ",progressString=" + progressStringString +
+        ",indeterminateString=" + indeterminateString;
+    }
+
+/////////////////
+// Accessibility support
+////////////////
+
+    /**
+     * Gets the <code>AccessibleContext</code> associated with this
+     * <code>JProgressBar</code>. For progress bars, the
+     * <code>AccessibleContext</code> takes the form of an
+     * <code>AccessibleJProgressBar</code>.
+     * A new <code>AccessibleJProgressBar</code> instance is created if necessary.
+     *
+     * @return an <code>AccessibleJProgressBar</code> that serves as the
+     *         <code>AccessibleContext</code> of this <code>JProgressBar</code>
+     * @beaninfo
+     *       expert: true
+     *  description: The AccessibleContext associated with this ProgressBar.
+     */
+    public AccessibleContext getAccessibleContext() {
+        if (accessibleContext == null) {
+            accessibleContext = new AccessibleJProgressBar();
+        }
+        return accessibleContext;
+    }
+
+    /**
+     * This class implements accessibility support for the
+     * <code>JProgressBar</code> class.  It provides an implementation of the
+     * Java Accessibility API appropriate to progress bar user-interface
+     * elements.
+     * <p>
+     * <strong>Warning:</strong>
+     * Serialized objects of this class will not be compatible with
+     * future Swing releases. The current serialization support is
+     * appropriate for short term storage or RMI between applications running
+     * the same version of Swing.  As of 1.4, support for long term storage
+     * of all JavaBeans<sup><font size="-2">TM</font></sup>
+     * has been added to the <code>java.beans</code> package.
+     * Please see {@link java.beans.XMLEncoder}.
+     */
+    protected class AccessibleJProgressBar extends AccessibleJComponent
+        implements AccessibleValue {
+
+        /**
+         * Gets the state set of this object.
+         *
+         * @return an instance of AccessibleState containing the current state
+         * of the object
+         * @see AccessibleState
+         */
+        public AccessibleStateSet getAccessibleStateSet() {
+            AccessibleStateSet states = super.getAccessibleStateSet();
+            if (getModel().getValueIsAdjusting()) {
+                states.add(AccessibleState.BUSY);
+            }
+            if (getOrientation() == VERTICAL) {
+                states.add(AccessibleState.VERTICAL);
+            } else {
+                states.add(AccessibleState.HORIZONTAL);
+            }
+            return states;
+        }
+
+        /**
+         * Gets the role of this object.
+         *
+         * @return an instance of AccessibleRole describing the role of the
+         * object
+         */
+        public AccessibleRole getAccessibleRole() {
+            return AccessibleRole.PROGRESS_BAR;
+        }
+
+        /**
+         * Gets the <code>AccessibleValue</code> associated with this object.  In the
+         * implementation of the Java Accessibility API for this class,
+         * returns this object, which is responsible for implementing the
+         * <code>AccessibleValue</code> interface on behalf of itself.
+         *
+         * @return this object
+         */
+        public AccessibleValue getAccessibleValue() {
+            return this;
+        }
+
+        /**
+         * Gets the accessible value of this object.
+         *
+         * @return the current value of this object
+         */
+        public Number getCurrentAccessibleValue() {
+            return new Integer(getValue());
+        }
+
+        /**
+         * Sets the value of this object as a <code>Number</code>.
+         *
+         * @return <code>true</code> if the value was set
+         */
+        public boolean setCurrentAccessibleValue(Number n) {
+            // TIGER- 4422535
+            if (n == null) {
+                return false;
+            }
+            setValue(n.intValue());
+            return true;
+        }
+
+        /**
+         * Gets the minimum accessible value of this object.
+         *
+         * @return the minimum value of this object
+         */
+        public Number getMinimumAccessibleValue() {
+            return new Integer(getMinimum());
+        }
+
+        /**
+         * Gets the maximum accessible value of this object.
+         *
+         * @return the maximum value of this object
+         */
+        public Number getMaximumAccessibleValue() {
+            // TIGER - 4422362
+            return new Integer(model.getMaximum() - model.getExtent());
+        }
+
+    } // AccessibleJProgressBar
+}