1275 lines · 45.0 KB · Java
RawDownload
/* * Copyright (c) 1997, 2006, 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.plaf.basic; import sun.swing.SwingUtilities2;import java.awt.*;import java.awt.geom.AffineTransform;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;import javax.swing.plaf.*;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent;import java.io.Serializable;import sun.swing.DefaultLookup; /** * A Basic L&F implementation of ProgressBarUI. * * @author Michael C. Albers * @author Kathy Walrath */public class BasicProgressBarUI extends ProgressBarUI {    private int cachedPercent;    private int cellLength, cellSpacing;    // The "selectionForeground" is the color of the text when it is painted    // over a filled area of the progress bar. The "selectionBackground"    // is for the text over the unfilled progress bar area.    private Color selectionForeground, selectionBackground;     private Animator animator;     protected JProgressBar progressBar;    protected ChangeListener changeListener;    private Handler handler;     /**     * The current state of the indeterminate animation's cycle.     * 0, the initial value, means paint the first frame.     * When the progress bar is indeterminate and showing,     * the default animation thread updates this variable     * by invoking incrementAnimationIndex()     * every repaintInterval milliseconds.     */    private int animationIndex = 0;     /**     * The number of frames per cycle. Under the default implementation,     * this depends on the cycleTime and repaintInterval.  It     * must be an even number for the default painting algorithm.  This     * value is set in the initIndeterminateValues method.     */    private int numFrames;   //0 1|numFrames-1 ... numFrames/2     /**     * Interval (in ms) between repaints of the indeterminate progress bar.     * The value of this method is set     * (every time the progress bar changes to indeterminate mode)     * using the     * "ProgressBar.repaintInterval" key in the defaults table.     */    private int repaintInterval;     /**     * The number of milliseconds until the animation cycle repeats.     * The value of this method is set     * (every time the progress bar changes to indeterminate mode)     * using the     * "ProgressBar.cycleTime" key in the defaults table.     */    private int cycleTime;  //must be repaintInterval*2*aPositiveInteger     //performance stuff    private static boolean ADJUSTTIMER = true; //makes a BIG difference;                                               //make this false for                                               //performance tests     /**     * Used to hold the location and size of the bouncing box (returned     * by getBox) to be painted.     *     * @since 1.5     */    protected Rectangle boxRect;     /**     * The rectangle to be updated the next time the     * animation thread calls repaint.  For bouncing-box     * animation this rect should include the union of     * the currently displayed box (which needs to be erased)     * and the box to be displayed next.     * This rectangle's values are set in     * the setAnimationIndex method.     */    private Rectangle nextPaintRect;     //cache    /** The component's painting area, not including the border. */    private Rectangle componentInnards;    //the current painting area    private Rectangle oldComponentInnards; //used to see if the size changed     /** For bouncing-box animation, the change in position per frame. */    private double delta = 0.0;     private int maxPosition = 0; //maximum X (horiz) or Y box location      public static ComponentUI createUI(JComponent x) {        return new BasicProgressBarUI();    }     public void installUI(JComponent c) {        progressBar = (JProgressBar)c;        installDefaults();        installListeners();        if (progressBar.isIndeterminate()) {            initIndeterminateValues();        }    }     public void uninstallUI(JComponent c) {        if (progressBar.isIndeterminate()) {            cleanUpIndeterminateValues();        }        uninstallDefaults();        uninstallListeners();        progressBar = null;    }     protected void installDefaults() {        LookAndFeel.installProperty(progressBar, "opaque", Boolean.TRUE);        LookAndFeel.installBorder(progressBar,"ProgressBar.border");        LookAndFeel.installColorsAndFont(progressBar,                                         "ProgressBar.background",                                         "ProgressBar.foreground",                                         "ProgressBar.font");        cellLength = UIManager.getInt("ProgressBar.cellLength");        if (cellLength == 0) cellLength = 1;        cellSpacing = UIManager.getInt("ProgressBar.cellSpacing");        selectionForeground = UIManager.getColor("ProgressBar.selectionForeground");        selectionBackground = UIManager.getColor("ProgressBar.selectionBackground");    }     protected void uninstallDefaults() {        LookAndFeel.uninstallBorder(progressBar);    }     protected void installListeners() {        //Listen for changes in the progress bar's data.        changeListener = getHandler();        progressBar.addChangeListener(changeListener);         //Listen for changes between determinate and indeterminate state.        progressBar.addPropertyChangeListener(getHandler());    }     private Handler getHandler() {        if (handler == null) {            handler = new Handler();        }        return handler;    }     /**     * Starts the animation thread, creating and initializing     * it if necessary. This method is invoked when an     * indeterminate progress bar should start animating.     * Reasons for this may include:     * <ul>     *    <li>The progress bar is determinate and becomes displayable     *    <li>The progress bar is displayable and becomes determinate     *    <li>The progress bar is displayable and determinate and this     *        UI is installed     * </ul>     * If you implement your own animation thread,     * you must override this method.     *     * @since 1.4     * @see #stopAnimationTimer     */    protected void startAnimationTimer() {        if (animator == null) {            animator = new Animator();        }         animator.start(getRepaintInterval());    }     /**     * Stops the animation thread.     * This method is invoked when the indeterminate     * animation should be stopped. Reasons for this may include:     * <ul>     *    <li>The progress bar changes to determinate     *    <li>The progress bar is no longer part of a displayable hierarchy     *    <li>This UI in uninstalled     * </ul>     * If you implement your own animation thread,     * you must override this method.     *     * @since 1.4     * @see #startAnimationTimer     */    protected void stopAnimationTimer() {        if (animator != null) {            animator.stop();        }    }     /**     * Removes all listeners installed by this object.     */    protected void uninstallListeners() {        progressBar.removeChangeListener(changeListener);        progressBar.removePropertyChangeListener(getHandler());        handler = null;    }      /**     * Returns the baseline.     *     * @throws NullPointerException {@inheritDoc}     * @throws IllegalArgumentException {@inheritDoc}     * @see javax.swing.JComponent#getBaseline(int, int)     * @since 1.6     */    public int getBaseline(JComponent c, int width, int height) {        super.getBaseline(c, width, height);        if (progressBar.isStringPainted() &&                progressBar.getOrientation() == JProgressBar.HORIZONTAL) {            FontMetrics metrics = progressBar.                    getFontMetrics(progressBar.getFont());            Insets insets = progressBar.getInsets();            int y = insets.top;            height = height - insets.top - insets.bottom;            return y + (height + metrics.getAscent() -                        metrics.getLeading() -                        metrics.getDescent()) / 2;        }        return -1;    }     /**     * Returns an enum indicating how the baseline of the component     * changes as the size changes.     *     * @throws NullPointerException {@inheritDoc}     * @see javax.swing.JComponent#getBaseline(int, int)     * @since 1.6     */    public Component.BaselineResizeBehavior getBaselineResizeBehavior(            JComponent c) {        super.getBaselineResizeBehavior(c);        if (progressBar.isStringPainted() &&                progressBar.getOrientation() == JProgressBar.HORIZONTAL) {            return Component.BaselineResizeBehavior.CENTER_OFFSET;        }        return Component.BaselineResizeBehavior.OTHER;    }     // Many of the Basic*UI components have the following methods.    // This component does not have these methods because *ProgressBarUI    //  is not a compound component and does not accept input.    //    // protected void installComponents()    // protected void uninstallComponents()    // protected void installKeyboardActions()    // protected void uninstallKeyboardActions()     protected Dimension getPreferredInnerHorizontal() {        Dimension horizDim = (Dimension)DefaultLookup.get(progressBar, this,            "ProgressBar.horizontalSize");        if (horizDim == null) {            horizDim = new Dimension(146, 12);        }        return horizDim;    }     protected Dimension getPreferredInnerVertical() {        Dimension vertDim = (Dimension)DefaultLookup.get(progressBar, this,            "ProgressBar.verticalSize");        if (vertDim == null) {            vertDim = new Dimension(12, 146);        }        return vertDim;    }     /**     * The "selectionForeground" is the color of the text when it is painted     * over a filled area of the progress bar.     */    protected Color getSelectionForeground() {        return selectionForeground;    }     /**     * The "selectionBackground" is the color of the text when it is painted     * over an unfilled area of the progress bar.     */    protected Color getSelectionBackground() {        return selectionBackground;    }     private int getCachedPercent() {        return cachedPercent;    }     private void setCachedPercent(int cachedPercent) {        this.cachedPercent = cachedPercent;    }     /**     * Returns the width (if HORIZONTAL) or height (if VERTICAL)     * of each of the indivdual cells/units to be rendered in the     * progress bar. However, for text rendering simplification and     * aesthetic considerations, this function will return 1 when     * the progress string is being rendered.     *     * @return the value representing the spacing between cells     * @see    #setCellLength     * @see    JProgressBar#isStringPainted     */    protected int getCellLength() {        if (progressBar.isStringPainted()) {            return 1;        } else {            return cellLength;        }    }     protected void setCellLength(int cellLen) {        this.cellLength = cellLen;    }     /**     * Returns the spacing between each of the cells/units in the     * progress bar. However, for text rendering simplification and     * aesthetic considerations, this function will return 0 when     * the progress string is being rendered.     *     * @return the value representing the spacing between cells     * @see    #setCellSpacing     * @see    JProgressBar#isStringPainted     */    protected int getCellSpacing() {        if (progressBar.isStringPainted()) {            return 0;        } else {            return cellSpacing;        }    }     protected void setCellSpacing(int cellSpace) {        this.cellSpacing = cellSpace;    }     /**     * This determines the amount of the progress bar that should be filled     * based on the percent done gathered from the model. This is a common     * operation so it was abstracted out. It assumes that your progress bar     * is linear. That is, if you are making a circular progress indicator,     * you will want to override this method.     */    protected int getAmountFull(Insets b, int width, int height) {        int amountFull = 0;        BoundedRangeModel model = progressBar.getModel();         if ( (model.getMaximum() - model.getMinimum()) != 0) {            if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {                amountFull = (int)Math.round(width *                                             progressBar.getPercentComplete());            } else {                amountFull = (int)Math.round(height *                                             progressBar.getPercentComplete());            }        }        return amountFull;    }     /**     * Delegates painting to one of two methods:     * paintDeterminate or paintIndeterminate.     */    public void paint(Graphics g, JComponent c) {        if (progressBar.isIndeterminate()) {            paintIndeterminate(g, c);        } else {            paintDeterminate(g, c);        }    }     /**     * Stores the position and size of     * the bouncing box that would be painted for the current animation index     * in <code>r</code> and returns <code>r</code>.     * Subclasses that add to the painting performed     * in this class's implementation of <code>paintIndeterminate</code> --     * to draw an outline around the bouncing box, for example --     * can use this method to get the location of the bouncing     * box that was just painted.     * By overriding this method,     * you have complete control over the size and position     * of the bouncing box,     * without having to reimplement <code>paintIndeterminate</code>.     *     * @param r  the Rectangle instance to be modified;     *           may be <code>null</code>     * @return   <code>null</code> if no box should be drawn;     *           otherwise, returns the passed-in rectangle     *           (if non-null)     *           or a new rectangle     *     * @see #setAnimationIndex     * @since 1.4     */    protected Rectangle getBox(Rectangle r) {        int currentFrame = getAnimationIndex();        int middleFrame = numFrames/2;         if (sizeChanged() || delta == 0.0 || maxPosition == 0.0) {            updateSizes();        }         r = getGenericBox(r);         if (r == null) {            return null;        }        if (middleFrame <= 0) {            return null;        }         //assert currentFrame >= 0 && currentFrame < numFrames        if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {            if (currentFrame < middleFrame) {                r.x = componentInnards.x                      + (int)Math.round(delta * (double)currentFrame);            } else {                r.x = maxPosition                      - (int)Math.round(delta *                                        (currentFrame - middleFrame));            }        } else { //VERTICAL indeterminate progress bar            if (currentFrame < middleFrame) {                r.y = componentInnards.y                      + (int)Math.round(delta * currentFrame);            } else {                r.y = maxPosition                      - (int)Math.round(delta *                                        (currentFrame - middleFrame));            }        }        return r;    }     /**     * Updates delta, max position.     * Assumes componentInnards is correct (e.g. call after sizeChanged()).     */    private void updateSizes() {        int length = 0;         if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {            length = getBoxLength(componentInnards.width,                                  componentInnards.height);            maxPosition = componentInnards.x + componentInnards.width                          - length;         } else { //VERTICAL progress bar            length = getBoxLength(componentInnards.height,                                  componentInnards.width);            maxPosition = componentInnards.y + componentInnards.height                          - length;        }         //If we're doing bouncing-box animation, update delta.

Lines 1–500 of 1275.