/*
 * Copyright (c) 1997, 2021, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing;

import java.awt.Graphics;
import java.beans.BeanProperty;
import java.beans.JavaBean;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serial;
import java.io.Serializable;
import java.text.Format;
import java.text.NumberFormat;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import javax.accessibility.AccessibleValue;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
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="https://docs.oracle.com/javase/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
 * 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
 *
 * @author Michael C. Albers
 * @author Kathy Walrath
 * @since 1.2
 */
@JavaBean(defaultProperty = "UI", description = "A component that displays an integer value.")
@SwingContainer(false)
@SuppressWarnings("serial") // Same-version serialization only
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.
     */
    private static final int defaultMinimum = 0;
    /**
     * The default maximum for a progress bar is 100.
     */
    private static final int defaultMaximum = 100;
    /**
     * The default orientation for a progress bar is <code>HORIZONTAL</code>.
     */
    private static final 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 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>
     * @throws      IllegalArgumentException    if <code>newOrientation</code>
     *                                              is an illegal value
     * @see #getOrientation
     */
    @BeanProperty(preferred = true, 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
     */
    @BeanProperty(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(Double.valueOf(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
     */
    @BeanProperty(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
     */
    @BeanProperty(bound = false)
    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
     */
    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
     */
    @BeanProperty(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
     */
    @BeanProperty(hidden = true, 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
     */
    @BeanProperty(bound = false, 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
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    @SuppressWarnings("serial") // Same-version serialization only
    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.
     *
     * @return the instance of a custom {@code ChangeListener} implementation.
     * @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
     */
    @BeanProperty(bound = false)
    public ChangeListener[] getChangeListeners() {
        return 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
     */
    @BeanProperty(bound = false, 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 : Integer.valueOf(oldModel.getValue())),
                        (newModel== null
                         ? null : Integer.valueOf(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
     */
    @BeanProperty(bound = false, 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,
                    Integer.valueOf(oldValue),
                    Integer.valueOf(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
     */
    @BeanProperty(bound = false, 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
     */
    @BeanProperty(bound = false, 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="https://docs.oracle.com/javase/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
     */
    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
     */
    @BeanProperty(bound = false, 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.
     */
    @Serial
    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>
     */
    @BeanProperty(bound = false, 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
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    @SuppressWarnings("serial") // Same-version serialization only
    protected class AccessibleJProgressBar extends AccessibleJComponent
        implements AccessibleValue {

        /**
         * Constructs an {@code AccessibleJProgressBar}.
         */
        protected AccessibleJProgressBar() {}

        /**
         * 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 Integer.valueOf(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 Integer.valueOf(getMinimum());
        }

        /**
         * Gets the maximum accessible value of this object.
         *
         * @return the maximum value of this object
         */
        public Number getMaximumAccessibleValue() {
            // TIGER - 4422362
            return Integer.valueOf(model.getMaximum() - model.getExtent());
        }

    } // AccessibleJProgressBar
}
