mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
1356 lines
47 KiB
Java
1356 lines
47 KiB
Java
![]() |
/*
|
||
|
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
|
||
|
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* @(#)BasicProgressBarUI.java 1.62 03/04/22
|
||
|
*
|
||
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||
|
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||
|
*/
|
||
|
|
||
|
package javax.swing.plaf.basic;
|
||
|
|
||
|
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;
|
||
|
|
||
|
//PENDING (kwalrath): Convert to logging, add assertions.
|
||
|
//PENDING (kwalrath): Make sure vertical is handled.
|
||
|
//PENDING (kwalrath): Should right-to-left indeterminate progress bar be
|
||
|
// handled differently?
|
||
|
//PENDING (kwalrath): Make sure method overriding is safe (esp. for ivars).
|
||
|
//PENDING (kwalrath): Support program-driven frame incrementation?
|
||
|
|
||
|
/**
|
||
|
* A Basic L&F implementation of ProgressBarUI.
|
||
|
*
|
||
|
* @version 1.62 04/22/03
|
||
|
* @author Michael C. Albers
|
||
|
* @author Kathy Walrath
|
||
|
*/
|
||
|
public class BasicProgressBarUI extends ProgressBarUI {
|
||
|
|
||
|
private static final Dimension PREFERRED_INNER_HORIZONTAL = new Dimension(146, 12);
|
||
|
private static final Dimension PREFERRED_INNER_VERTICAL = new Dimension(12, 146);
|
||
|
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 boolean isIndeterminate = false;
|
||
|
|
||
|
private Animator animator;
|
||
|
private PropertyChangeListener propertyListener;
|
||
|
|
||
|
protected JProgressBar progressBar;
|
||
|
protected ChangeListener changeListener;
|
||
|
|
||
|
/**
|
||
|
* 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
|
||
|
|
||
|
//debugging; PENDING (kwalrath): convert to logging API
|
||
|
private static boolean DEBUGALL = false; //severe performance impact
|
||
|
private static boolean DEBUGTIMER = false; //severe performance impact
|
||
|
private static boolean BASICDEBUG = false;
|
||
|
|
||
|
//performance data collection
|
||
|
private static boolean LOGSTATS = false;
|
||
|
private long startTime = 0;
|
||
|
private long lastLoopTime = 0;
|
||
|
private int numLoops = 0;
|
||
|
|
||
|
/**
|
||
|
* Used to hold the location and size of the bouncing box (returned
|
||
|
* by getBox) to be painted.
|
||
|
*/
|
||
|
private 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();
|
||
|
}
|
||
|
|
||
|
public void uninstallUI(JComponent c) {
|
||
|
uninstallDefaults();
|
||
|
uninstallListeners();
|
||
|
stopAnimationTimer();
|
||
|
progressBar = null;
|
||
|
}
|
||
|
|
||
|
protected void installDefaults() {
|
||
|
progressBar.setOpaque(true);
|
||
|
LookAndFeel.installBorder(progressBar,"ProgressBar.border");
|
||
|
LookAndFeel.installColorsAndFont(progressBar,
|
||
|
"ProgressBar.background",
|
||
|
"ProgressBar.foreground",
|
||
|
"ProgressBar.font");
|
||
|
cellLength = UIManager.getInt("ProgressBar.cellLength");
|
||
|
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 = new ChangeHandler();
|
||
|
progressBar.addChangeListener(changeListener);
|
||
|
|
||
|
//Listen for changes between determinate and indeterminate state.
|
||
|
propertyListener = new PropertyChangeHandler();
|
||
|
progressBar.addPropertyChangeListener(propertyListener);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Starts the animation thread, creating and initializing
|
||
|
* it if necessary. This method is invoked when
|
||
|
* the progress bar changes to indeterminate mode.
|
||
|
* If you implement your own animation thread,
|
||
|
* you must override this method.
|
||
|
*
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
protected void startAnimationTimer() {
|
||
|
if (animator == null) {
|
||
|
animator = new Animator();
|
||
|
}
|
||
|
|
||
|
animator.start(getRepaintInterval());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Stops the animation thread. This method is invoked when
|
||
|
* the progress bar changes from
|
||
|
* indeterminate to determinate mode
|
||
|
* and when this UI is uninstalled.
|
||
|
* If you implement your own animation thread,
|
||
|
* you must override this method.
|
||
|
*
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
protected void stopAnimationTimer() {
|
||
|
if (animator != null) {
|
||
|
animator.stop();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes all listeners installed by this object.
|
||
|
*/
|
||
|
protected void uninstallListeners() {
|
||
|
progressBar.removeChangeListener(changeListener);
|
||
|
progressBar.removePropertyChangeListener(propertyListener);
|
||
|
}
|
||
|
|
||
|
|
||
|
// 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() {
|
||
|
return PREFERRED_INNER_HORIZONTAL;
|
||
|
}
|
||
|
|
||
|
protected Dimension getPreferredInnerVertical() {
|
||
|
return PREFERRED_INNER_VERTICAL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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 (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 (DEBUGALL) {
|
||
|
System.out.println("----begin getBox----");
|
||
|
System.out.println(" getBox argument: " + r);
|
||
|
System.out.println(" currentFrame = " + currentFrame);
|
||
|
System.out.println(" middleFrame = " + middleFrame);
|
||
|
}
|
||
|
|
||
|
if (sizeChanged() || delta == 0.0 || maxPosition == 0.0) {
|
||
|
updateSizes();
|
||
|
}
|
||
|
|
||
|
r = getGenericBox(r);
|
||
|
|
||
|
if (r == null) {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" Exiting because r is null");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
if (middleFrame <= 0) {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" Exiting because middleFrame <= 0.");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
//assertion: currentFrame >= 0 && currentFrame < numFrames
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
if (currentFrame < middleFrame) {
|
||
|
if (componentInnards != null)
|
||
|
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) {
|
||
|
if (componentInnards != null)
|
||
|
r.y = componentInnards.y
|
||
|
+ (int)Math.round(delta * currentFrame);
|
||
|
} else {
|
||
|
r.y = maxPosition
|
||
|
- (int)Math.round(delta *
|
||
|
(currentFrame - middleFrame));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" getBox return value: " + r);
|
||
|
System.out.println("----end getBox----");
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates delta, max position.
|
||
|
* Assumes componentInnards is correct (e.g. call after sizeChanged()).
|
||
|
*/
|
||
|
private void updateSizes() {
|
||
|
if (componentInnards == null)
|
||
|
return;
|
||
|
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----begin 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.
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" Updating delta.");
|
||
|
}
|
||
|
|
||
|
delta = 2.0 * (double)maxPosition/(double)numFrames;
|
||
|
|
||
|
if (BASICDEBUG) {
|
||
|
System.out.println(" delta: " + delta);
|
||
|
System.out.println(" maxPosition: " + maxPosition);
|
||
|
}
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----end updateSizes----");
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Assumes that the component innards, max position, etc. are up-to-date.
|
||
|
*/
|
||
|
private Rectangle getGenericBox(Rectangle r) {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----begin getGenericBox----");
|
||
|
System.out.println(" argument: " + r);
|
||
|
}
|
||
|
|
||
|
if (r == null) {
|
||
|
r = new Rectangle();
|
||
|
}
|
||
|
|
||
|
if (componentInnards != null) {
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
r.width = getBoxLength(componentInnards.width,
|
||
|
componentInnards.height);
|
||
|
if (r.width < 0) {
|
||
|
r = null;
|
||
|
} else {
|
||
|
r.height = componentInnards.height;
|
||
|
r.y = componentInnards.y;
|
||
|
}
|
||
|
// end of HORIZONTAL
|
||
|
|
||
|
} else { //VERTICAL progress bar
|
||
|
r.height = getBoxLength(componentInnards.height,
|
||
|
componentInnards.width);
|
||
|
if (r.height < 0) {
|
||
|
r = null;
|
||
|
} else {
|
||
|
r.width = componentInnards.width;
|
||
|
r.x = componentInnards.x;
|
||
|
}
|
||
|
} // end of VERTICAL
|
||
|
}
|
||
|
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" getGenericBox returns: " + r);
|
||
|
System.out.println("----end getGenericBox----");
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the length
|
||
|
* of the "bouncing box" to be painted.
|
||
|
* This method is invoked by the
|
||
|
* default implementation of <code>paintIndeterminate</code>
|
||
|
* to get the width (if the progress bar is horizontal)
|
||
|
* or height (if vertical) of the box.
|
||
|
* For example:
|
||
|
* <blockquote>
|
||
|
* <pre>
|
||
|
*boxRect.width = getBoxLength(componentInnards.width,
|
||
|
* componentInnards.height);
|
||
|
* </pre>
|
||
|
* </blockquote>
|
||
|
*
|
||
|
* <p>
|
||
|
* By default, this method returns the available length
|
||
|
* divided by 6. Another possibility might
|
||
|
* be to make the bouncing box a square,
|
||
|
* which you could implement by overriding this method as follows:
|
||
|
* <blockquote>
|
||
|
* <pre>
|
||
|
*protected double getBoxLength(int availableLength,
|
||
|
* int otherDimension) {
|
||
|
* return Math.min(availableLength, otherDimension);
|
||
|
*}
|
||
|
* </blockquote>
|
||
|
* </pre>
|
||
|
*
|
||
|
* @param availableLength the amount of space available
|
||
|
* for the bouncing box to move in;
|
||
|
* for a horizontal progress bar,
|
||
|
* for example,
|
||
|
* this should be
|
||
|
* the inside width of the progress bar
|
||
|
* (the component width minus borders)
|
||
|
* @param otherDimension for a horizontal progress bar, this should be
|
||
|
* the inside height of the progress bar; this
|
||
|
* value might be used to constrain or determine
|
||
|
* the return value
|
||
|
*
|
||
|
* @return the size of the box dimension being determined;
|
||
|
* must be no larger than <code>availableLength</code>
|
||
|
*
|
||
|
* @see javax.swing.SwingUtilities#calculateInnerArea
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
private int getBoxLength(int availableLength, int otherDimension) {
|
||
|
return (int)Math.round(availableLength/6.0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* All purpose paint method that should do the right thing for all
|
||
|
* linear bouncing-box progress bars.
|
||
|
* Override this if you are making another kind of
|
||
|
* progress bar.
|
||
|
*
|
||
|
* @see #paintDeterminate
|
||
|
*
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
protected void paintIndeterminate(Graphics g, JComponent c) {
|
||
|
if (!(g instanceof Graphics2D)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Insets b = progressBar.getInsets(); // area for border
|
||
|
int barRectWidth = progressBar.getWidth() - (b.right + b.left);
|
||
|
int barRectHeight = progressBar.getHeight() - (b.top + b.bottom);
|
||
|
|
||
|
Graphics2D g2 = (Graphics2D)g;
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println();
|
||
|
System.out.println("basic: paintIndeterminate");
|
||
|
}
|
||
|
|
||
|
// Paint the bouncing box.
|
||
|
boxRect = getBox(boxRect);
|
||
|
if (boxRect != null) {
|
||
|
g2.setColor(progressBar.getForeground());
|
||
|
g2.fillRect(boxRect.x, boxRect.y,
|
||
|
boxRect.width, boxRect.height);
|
||
|
} else {
|
||
|
if (DEBUGALL)
|
||
|
//we're not initialized yet
|
||
|
System.out.println("boxRect == null; returning");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Deal with possible text painting
|
||
|
if (progressBar.isStringPainted()) {
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
paintString(g2, b.left, b.top,
|
||
|
barRectWidth, barRectHeight,
|
||
|
boxRect.x, boxRect.width, b);
|
||
|
}
|
||
|
else {
|
||
|
paintString(g2, b.left, b.top,
|
||
|
barRectWidth, barRectHeight,
|
||
|
boxRect.y, boxRect.height, b);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* All purpose paint method that should do the right thing for almost
|
||
|
* all linear, determinate progress bars. By setting a few values in
|
||
|
* the defaults
|
||
|
* table, things should work just fine to paint your progress bar.
|
||
|
* Naturally, override this if you are making a circular or
|
||
|
* semi-circular progress bar.
|
||
|
*
|
||
|
* @see #paintIndeterminate
|
||
|
*
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
protected void paintDeterminate(Graphics g, JComponent c) {
|
||
|
if (!(g instanceof Graphics2D)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Insets b = progressBar.getInsets(); // area for border
|
||
|
int barRectWidth = progressBar.getWidth() - (b.right + b.left);
|
||
|
int barRectHeight = progressBar.getHeight() - (b.top + b.bottom);
|
||
|
|
||
|
int cellLength = getCellLength();
|
||
|
int cellSpacing = getCellSpacing();
|
||
|
// amount of progress to draw
|
||
|
int amountFull = getAmountFull(b, barRectWidth, barRectHeight);
|
||
|
|
||
|
Graphics2D g2 = (Graphics2D)g;
|
||
|
g2.setColor(progressBar.getForeground());
|
||
|
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
// draw the cells
|
||
|
if (cellSpacing == 0 && amountFull > 0) {
|
||
|
// draw one big Rect because there is no space between cells
|
||
|
g2.setStroke(new BasicStroke((float)barRectHeight,
|
||
|
BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||
|
} else {
|
||
|
// draw each individual cell
|
||
|
g2.setStroke(new BasicStroke((float)barRectHeight,
|
||
|
BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL,
|
||
|
0.f, new float[] { cellLength, cellSpacing }, 0.f));
|
||
|
}
|
||
|
|
||
|
if (BasicGraphicsUtils.isLeftToRight(c)) {
|
||
|
g2.drawLine(b.left, (barRectHeight/2) + b.top,
|
||
|
amountFull + b.left, (barRectHeight/2) + b.top);
|
||
|
} else {
|
||
|
g2.drawLine((barRectWidth + b.left),
|
||
|
(barRectHeight/2) + b.top,
|
||
|
barRectWidth + b.left - amountFull,
|
||
|
(barRectHeight/2) + b.top);
|
||
|
}
|
||
|
|
||
|
} else { // VERTICAL
|
||
|
// draw the cells
|
||
|
if (cellSpacing == 0 && amountFull > 0) {
|
||
|
// draw one big Rect because there is no space between cells
|
||
|
g2.setStroke(new BasicStroke((float)barRectWidth,
|
||
|
BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||
|
} else {
|
||
|
// draw each individual cell
|
||
|
g2.setStroke(new BasicStroke((float)barRectWidth,
|
||
|
BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL,
|
||
|
0f, new float[] { cellLength, cellSpacing }, 0f));
|
||
|
}
|
||
|
|
||
|
g2.drawLine(barRectWidth/2 + b.left,
|
||
|
b.top + barRectHeight,
|
||
|
barRectWidth/2 + b.left,
|
||
|
b.top + barRectHeight - amountFull);
|
||
|
}
|
||
|
|
||
|
// Deal with possible text painting
|
||
|
if (progressBar.isStringPainted()) {
|
||
|
paintString(g, b.left, b.top,
|
||
|
barRectWidth, barRectHeight,
|
||
|
amountFull, b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
protected void paintString(Graphics g, int x, int y,
|
||
|
int width, int height,
|
||
|
int amountFull, Insets b) {
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
if (BasicGraphicsUtils.isLeftToRight(progressBar)) {
|
||
|
if (progressBar.isIndeterminate()) {
|
||
|
boxRect = getBox(boxRect);
|
||
|
if (boxRect != null)
|
||
|
paintString(g, x, y, width, height, boxRect.x, boxRect.width, b);
|
||
|
} else {
|
||
|
paintString(g, x, y, width, height, x, amountFull, b);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
paintString(g, x, y, width, height, x + width - amountFull,
|
||
|
amountFull, b);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (progressBar.isIndeterminate()) {
|
||
|
boxRect = getBox(boxRect);
|
||
|
if (boxRect != null)
|
||
|
paintString(g, x, y, width, height, boxRect.y, boxRect.height, b);
|
||
|
} else {
|
||
|
paintString(g, x, y, width, height, y + height - amountFull,
|
||
|
amountFull, b);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Paints the progress string.
|
||
|
*
|
||
|
* @param g Graphics used for drawing.
|
||
|
* @param x x location of bounding box
|
||
|
* @param y y location of bounding box
|
||
|
* @param width width of bounding box
|
||
|
* @param height height of bounding box
|
||
|
* @param fillStart start location, in x or y depending on orientation,
|
||
|
* of the filled portion of the progress bar.
|
||
|
* @param amountFull size of the fill region, either width or height
|
||
|
* depending upon orientation.
|
||
|
* @param b Insets of the progress bar.
|
||
|
*/
|
||
|
private void paintString(Graphics g, int x, int y, int width, int height,
|
||
|
int fillStart, int amountFull, Insets b) {
|
||
|
if (!(g instanceof Graphics2D)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Graphics2D g2 = (Graphics2D)g;
|
||
|
String progressString = progressBar.getString();
|
||
|
g2.setFont(progressBar.getFont());
|
||
|
Point renderLocation = getStringPlacement(g2, progressString,
|
||
|
x, y, width, height);
|
||
|
Rectangle oldClip = g2.getClipBounds();
|
||
|
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
g2.setColor(getSelectionBackground());
|
||
|
g2.drawString(progressString, renderLocation.x, renderLocation.y);
|
||
|
g2.setColor(getSelectionForeground());
|
||
|
g2.clipRect(fillStart, y, amountFull, height);
|
||
|
g.drawString(progressString, renderLocation.x, renderLocation.y);
|
||
|
} else { // VERTICAL
|
||
|
g2.setColor(getSelectionBackground());
|
||
|
AffineTransform rotate =
|
||
|
AffineTransform.getRotateInstance(Math.PI/2);
|
||
|
g2.setFont(progressBar.getFont().deriveFont(rotate));
|
||
|
renderLocation = getStringPlacement(g2, progressString,
|
||
|
x, y, width, height);
|
||
|
g2.drawString(progressString, renderLocation.x, renderLocation.y);
|
||
|
g2.setColor(getSelectionForeground());
|
||
|
g2.clipRect(x, fillStart, width, amountFull);
|
||
|
g2.drawString(progressString, renderLocation.x, renderLocation.y);
|
||
|
}
|
||
|
g2.setClip(oldClip);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Designate the place where the progress string will be painted.
|
||
|
* This implementation places it at the center of the progress
|
||
|
* bar (in both x and y). Override this if you want to right,
|
||
|
* left, top, or bottom align the progress string or if you need
|
||
|
* to nudge it around for any reason.
|
||
|
*/
|
||
|
protected Point getStringPlacement(Graphics g, String progressString,
|
||
|
int x,int y,int width,int height) {
|
||
|
FontMetrics fontSizer = progressBar.getFontMetrics(
|
||
|
progressBar.getFont());
|
||
|
int stringWidth = fontSizer.stringWidth(progressString);
|
||
|
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
return new Point(x + Math.round(width/2 - stringWidth/2),
|
||
|
y + ((height +
|
||
|
fontSizer.getAscent() -
|
||
|
fontSizer.getLeading() -
|
||
|
fontSizer.getDescent()) / 2));
|
||
|
} else { // VERTICAL
|
||
|
return new Point(x + ((width - fontSizer.getAscent() +
|
||
|
fontSizer.getLeading() + fontSizer.getDescent()) / 2),
|
||
|
y + Math.round(height/2 - stringWidth/2));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
public Dimension getPreferredSize(JComponent c) {
|
||
|
Dimension size;
|
||
|
Insets border = progressBar.getInsets();
|
||
|
FontMetrics fontSizer = progressBar.getFontMetrics(
|
||
|
progressBar.getFont());
|
||
|
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
size = new Dimension(getPreferredInnerHorizontal());
|
||
|
// Ensure that the progress string will fit
|
||
|
if (progressBar.isStringPainted()) {
|
||
|
// I'm doing this for completeness.
|
||
|
String progString = progressBar.getString();
|
||
|
int stringWidth = fontSizer.stringWidth(progString);
|
||
|
if (stringWidth > size.width) {
|
||
|
size.width = stringWidth;
|
||
|
}
|
||
|
// This uses both Height and Descent to be sure that
|
||
|
// there is more than enough room in the progress bar
|
||
|
// for everything.
|
||
|
// This does have a strange dependency on
|
||
|
// getStringPlacememnt() in a funny way.
|
||
|
int stringHeight = fontSizer.getHeight() +
|
||
|
fontSizer.getDescent();
|
||
|
if (stringHeight > size.height) {
|
||
|
size.height = stringHeight;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
size = new Dimension(getPreferredInnerVertical());
|
||
|
// Ensure that the progress string will fit.
|
||
|
if (progressBar.isStringPainted()) {
|
||
|
String progString = progressBar.getString();
|
||
|
int stringHeight = fontSizer.getHeight() +
|
||
|
fontSizer.getDescent();
|
||
|
if (stringHeight > size.width) {
|
||
|
size.width = stringHeight;
|
||
|
}
|
||
|
// This is also for completeness.
|
||
|
int stringWidth = fontSizer.stringWidth(progString);
|
||
|
if (stringWidth > size.height) {
|
||
|
size.height = stringWidth;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
size.width += border.left + border.right;
|
||
|
size.height += border.top + border.bottom;
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The Minimum size for this component is 10. The rationale here
|
||
|
* is that there should be at least one pixel per 10 percent.
|
||
|
*/
|
||
|
public Dimension getMinimumSize(JComponent c) {
|
||
|
Dimension pref = getPreferredSize(progressBar);
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
pref.width = 10;
|
||
|
} else {
|
||
|
pref.height = 10;
|
||
|
}
|
||
|
return pref;
|
||
|
}
|
||
|
|
||
|
public Dimension getMaximumSize(JComponent c) {
|
||
|
Dimension pref = getPreferredSize(progressBar);
|
||
|
if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
||
|
pref.width = Short.MAX_VALUE;
|
||
|
} else {
|
||
|
pref.height = Short.MAX_VALUE;
|
||
|
}
|
||
|
return pref;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the index of the current animation frame.
|
||
|
*
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
protected int getAnimationIndex() {
|
||
|
return animationIndex;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the index of the current animation frame
|
||
|
* to the specified value and requests that the
|
||
|
* progress bar be repainted.
|
||
|
* Subclasses that don't use the default painting code
|
||
|
* might need to override this method
|
||
|
* to change the way that the <code>repaint</code> method
|
||
|
* is invoked.
|
||
|
*
|
||
|
* @param newValue the new animation index; no checking
|
||
|
* is performed on its value
|
||
|
* @see #incrementAnimationIndex
|
||
|
*
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
protected void setAnimationIndex(int newValue) {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----begin setAnimationIndex----");
|
||
|
System.out.println(" argument = " + newValue);
|
||
|
}
|
||
|
|
||
|
if (animationIndex != newValue) {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" Changing animation index from "
|
||
|
+ animationIndex + " to "
|
||
|
+ newValue);
|
||
|
}
|
||
|
|
||
|
if (sizeChanged()) {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" size changed; resetting maxPosition, delta");
|
||
|
}
|
||
|
animationIndex = newValue;
|
||
|
maxPosition = 0; //needs to be recalculated
|
||
|
delta = 0.0; //needs to be recalculated
|
||
|
progressBar.repaint();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//Get the previous box drawn.
|
||
|
nextPaintRect = getBox(nextPaintRect);
|
||
|
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" previous paint rect = "
|
||
|
+ nextPaintRect);
|
||
|
System.out.println(" before setting, boxRect = "
|
||
|
+ boxRect);
|
||
|
}
|
||
|
|
||
|
//Update the frame number.
|
||
|
animationIndex = newValue;
|
||
|
|
||
|
//Get the next box to draw.
|
||
|
if (nextPaintRect != null) {
|
||
|
boxRect = getBox(boxRect);
|
||
|
if (boxRect != null) {
|
||
|
nextPaintRect.add(boxRect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" after setting, boxRect = "
|
||
|
+ boxRect);
|
||
|
System.out.println(" after setting, nextPaintRect = "
|
||
|
+ nextPaintRect);
|
||
|
}
|
||
|
} else { //animationIndex == newValue
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" No change in value");
|
||
|
System.out.println("----end setAnimationIndex----");
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (nextPaintRect != null) {
|
||
|
progressBar.repaint(nextPaintRect);
|
||
|
} else {
|
||
|
progressBar.repaint();
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println(" repaint without args");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----end setAnimationIndex----");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private boolean sizeChanged() {
|
||
|
if ((oldComponentInnards == null) || (componentInnards == null)) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
oldComponentInnards.setRect(componentInnards);
|
||
|
componentInnards = SwingUtilities.calculateInnerArea(progressBar,
|
||
|
componentInnards);
|
||
|
return !oldComponentInnards.equals(componentInnards);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the index of the current animation frame,
|
||
|
* to the next valid value,
|
||
|
* which results in the progress bar being repainted.
|
||
|
* The next valid value is, by default,
|
||
|
* the current animation index plus one.
|
||
|
* If the new value would be too large,
|
||
|
* this method sets the index to 0.
|
||
|
* Subclasses might need to override this method
|
||
|
* to ensure that the index does not go over
|
||
|
* the number of frames needed for the particular
|
||
|
* progress bar instance.
|
||
|
* This method is invoked by the default animation thread
|
||
|
* every <em>X</em> milliseconds,
|
||
|
* where <em>X</em> is specified by the "ProgressBar.repaintInterval"
|
||
|
* UI default.
|
||
|
*
|
||
|
* @see #setAnimationIndex
|
||
|
* @since 1.4
|
||
|
*/
|
||
|
protected void incrementAnimationIndex() {
|
||
|
int newValue = getAnimationIndex() + 1;
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println();
|
||
|
System.out.println("----begin incrementAnimationIndex----");
|
||
|
System.out.println(" newValue = " + newValue);
|
||
|
System.out.println(" numFrames = " + numFrames);
|
||
|
}
|
||
|
|
||
|
if (newValue < numFrames) {
|
||
|
setAnimationIndex(newValue);
|
||
|
} else {
|
||
|
setAnimationIndex(0);
|
||
|
if (LOGSTATS) {
|
||
|
numLoops++;
|
||
|
long time = System.currentTimeMillis();
|
||
|
System.out.println("Loop #" + numLoops + ": "
|
||
|
+ (time - lastLoopTime)
|
||
|
+ " (" + (time - startTime)
|
||
|
+ " total)");
|
||
|
lastLoopTime = time;
|
||
|
}
|
||
|
}
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----end incrementAnimationIndex----");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the desired number of milliseconds between repaints.
|
||
|
* This value is meaningful
|
||
|
* only if the progress bar is in indeterminate mode.
|
||
|
* The repaint interval determines how often the
|
||
|
* default animation thread's timer is fired.
|
||
|
* It's also used by the default indeterminate progress bar
|
||
|
* painting code when determining
|
||
|
* how far to move the bouncing box per frame.
|
||
|
* The repaint interval is specified by
|
||
|
* the "ProgressBar.repaintInterval" UI default.
|
||
|
*
|
||
|
* @return the repaint interval, in milliseconds
|
||
|
*/
|
||
|
private int getRepaintInterval() {
|
||
|
return repaintInterval;
|
||
|
}
|
||
|
|
||
|
private int initRepaintInterval() {
|
||
|
repaintInterval = UIManager.getInt("ProgressBar.repaintInterval");
|
||
|
if (BASICDEBUG) {
|
||
|
System.out.println(" value of ProgressBar.repaintInterval is "
|
||
|
+ repaintInterval);
|
||
|
}
|
||
|
return repaintInterval;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the number of milliseconds per animation cycle.
|
||
|
* This value is meaningful
|
||
|
* only if the progress bar is in indeterminate mode.
|
||
|
* The cycle time is used by the default indeterminate progress bar
|
||
|
* painting code when determining
|
||
|
* how far to move the bouncing box per frame.
|
||
|
* The cycle time is specified by
|
||
|
* the "ProgressBar.cycleTime" UI default
|
||
|
* and adjusted, if necessary,
|
||
|
* by the initIndeterminateDefaults method.
|
||
|
*
|
||
|
* @return the cycle time, in milliseconds
|
||
|
*/
|
||
|
private int getCycleTime() {
|
||
|
return cycleTime;
|
||
|
}
|
||
|
|
||
|
private int initCycleTime() {
|
||
|
cycleTime = UIManager.getInt("ProgressBar.cycleTime");
|
||
|
if (BASICDEBUG) {
|
||
|
System.out.println(" value of ProgressBar.cycleTime is "
|
||
|
+ cycleTime);
|
||
|
}
|
||
|
return cycleTime;
|
||
|
}
|
||
|
|
||
|
|
||
|
/** Initialize cycleTime, repaintInterval, numFrames, animationIndex. */
|
||
|
private void initIndeterminateDefaults() {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----begin initIndeterminateDefaults----");
|
||
|
}
|
||
|
initRepaintInterval(); //initialize repaint interval
|
||
|
initCycleTime(); //initialize cycle length
|
||
|
|
||
|
// Make sure repaintInterval is reasonable.
|
||
|
if (repaintInterval <= 0) {
|
||
|
repaintInterval = 100;
|
||
|
}
|
||
|
|
||
|
// Make sure cycleTime is reasonable.
|
||
|
if (repaintInterval > cycleTime) {
|
||
|
cycleTime = repaintInterval * 20;
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("cycleTime changed to " + cycleTime);
|
||
|
}
|
||
|
} else {
|
||
|
// Force cycleTime to be a even multiple of repaintInterval.
|
||
|
int factor = (int)Math.ceil(
|
||
|
((double)cycleTime)
|
||
|
/ ((double)repaintInterval*2));
|
||
|
if (DEBUGALL) {
|
||
|
int newCycleTime = repaintInterval*factor*2;
|
||
|
if (cycleTime != newCycleTime) {
|
||
|
System.out.println("cycleTime being changed to "
|
||
|
+ newCycleTime);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cycleTime = repaintInterval*factor*2;
|
||
|
}
|
||
|
|
||
|
if (BASICDEBUG) {
|
||
|
System.out.println(" cycle length: " + cycleTime);
|
||
|
System.out.println(" repaint interval: " + repaintInterval);
|
||
|
}
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----end initIndeterminateDefaults----");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Invoked by PropertyChangeHandler before startAnimationTimer().
|
||
|
*
|
||
|
* NOTE: This might not be invoked until after the first
|
||
|
* paintIndeterminate call.
|
||
|
*/
|
||
|
private void initIndeterminateValues() {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println();
|
||
|
System.out.println("----begin initIndeterminateValues----");
|
||
|
}
|
||
|
if (LOGSTATS) {
|
||
|
startTime = lastLoopTime = System.currentTimeMillis();
|
||
|
numLoops = 0;
|
||
|
}
|
||
|
|
||
|
if (BASICDEBUG) {
|
||
|
System.out.println("ADJUSTTIMER = " + ADJUSTTIMER);
|
||
|
}
|
||
|
|
||
|
initIndeterminateDefaults();
|
||
|
//assertion: cycleTime/repaintInterval is a whole multiple of 2.
|
||
|
numFrames = cycleTime/repaintInterval;
|
||
|
initAnimationIndex();
|
||
|
|
||
|
boxRect = new Rectangle();
|
||
|
nextPaintRect = new Rectangle();
|
||
|
componentInnards = new Rectangle();
|
||
|
oldComponentInnards = new Rectangle();
|
||
|
|
||
|
if (BASICDEBUG) {
|
||
|
System.out.println(" numFrames: " + numFrames);
|
||
|
}
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----end initIndeterminateValues----");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Invoked by PropertyChangeHandler after stopAnimationTimer(). */
|
||
|
private void cleanUpIndeterminateValues() {
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println();
|
||
|
System.out.println("----begin cleanUpIndeterminateValues----");
|
||
|
}
|
||
|
|
||
|
cycleTime = repaintInterval = 0;
|
||
|
numFrames = animationIndex = 0;
|
||
|
maxPosition = 0;
|
||
|
delta = 0.0;
|
||
|
|
||
|
boxRect = nextPaintRect = null;
|
||
|
componentInnards = oldComponentInnards = null;
|
||
|
|
||
|
if (LOGSTATS) {
|
||
|
startTime = lastLoopTime = numLoops = 0;
|
||
|
}
|
||
|
|
||
|
if (DEBUGALL) {
|
||
|
System.out.println("----end cleanUpIndeterminateValues----");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Called from initIndeterminateValues to initialize the animation index.
|
||
|
// This assumes that numFrames is set to a correct value.
|
||
|
private void initAnimationIndex() {
|
||
|
if ((progressBar.getOrientation() == JProgressBar.HORIZONTAL) &&
|
||
|
(BasicGraphicsUtils.isLeftToRight(progressBar))) {
|
||
|
// If this is a left-to-right progress bar,
|
||
|
// start at the first frame.
|
||
|
setAnimationIndex(0);
|
||
|
} else {
|
||
|
// If we go right-to-left or vertically, start at the right/bottom.
|
||
|
setAnimationIndex(numFrames/2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Animation Thread
|
||
|
//
|
||
|
/**
|
||
|
* Implements an animation thread that invokes repaint
|
||
|
* at a fixed rate. If ADJUSTTIMER is true, this thread
|
||
|
* will continuously adjust the repaint interval to
|
||
|
* try to make the actual time between repaints match
|
||
|
* the requested rate.
|
||
|
*/
|
||
|
private class Animator implements ActionListener {
|
||
|
private Timer timer;
|
||
|
private long previousDelay; //used to tune the repaint interval
|
||
|
private int interval; //the fixed repaint interval
|
||
|
private long lastCall; //the last time actionPerformed was called
|
||
|
private int MINIMUM_DELAY = 5;
|
||
|
|
||
|
/**
|
||
|
* Creates a timer if one doesn't already exist,
|
||
|
* then starts the timer thread.
|
||
|
*/
|
||
|
private void start(int interval) {
|
||
|
previousDelay = interval;
|
||
|
lastCall = 0;
|
||
|
|
||
|
if (timer == null) {
|
||
|
timer = new Timer(interval, this);
|
||
|
} else {
|
||
|
timer.setDelay(interval);
|
||
|
}
|
||
|
|
||
|
if (ADJUSTTIMER) {
|
||
|
timer.setRepeats(false);
|
||
|
timer.setCoalesce(false);
|
||
|
}
|
||
|
|
||
|
timer.start();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Stops the timer thread.
|
||
|
*/
|
||
|
private void stop() {
|
||
|
timer.stop();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reacts to the timer's action events.
|
||
|
*/
|
||
|
public void actionPerformed(ActionEvent e) {
|
||
|
if (ADJUSTTIMER) {
|
||
|
long time = System.currentTimeMillis();
|
||
|
|
||
|
if (lastCall > 0) { //adjust nextDelay
|
||
|
//XXX maybe should cache this after a while
|
||
|
//actual = time - lastCall
|
||
|
//difference = actual - interval
|
||
|
//nextDelay = previousDelay - difference
|
||
|
// = previousDelay - (time - lastCall - interval)
|
||
|
int nextDelay = (int)(previousDelay
|
||
|
- time + lastCall
|
||
|
+ getRepaintInterval());
|
||
|
if (nextDelay < MINIMUM_DELAY) {
|
||
|
nextDelay = MINIMUM_DELAY;
|
||
|
}
|
||
|
timer.setInitialDelay(nextDelay);
|
||
|
previousDelay = nextDelay;
|
||
|
if (DEBUGTIMER) {
|
||
|
System.out.println("---------------------");
|
||
|
System.out.println("actual delay = "
|
||
|
+ (time - lastCall));
|
||
|
System.out.println("next delay = " + nextDelay);
|
||
|
}
|
||
|
}
|
||
|
timer.start();
|
||
|
lastCall = time;
|
||
|
}
|
||
|
|
||
|
incrementAnimationIndex(); //paint next frame
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Property Change Events
|
||
|
//
|
||
|
/**
|
||
|
* [PENDING: add doc here]
|
||
|
* [PENDING: make this static?]
|
||
|
*/
|
||
|
private class PropertyChangeHandler implements PropertyChangeListener {
|
||
|
public void propertyChange(PropertyChangeEvent e) {
|
||
|
String prop = e.getPropertyName();
|
||
|
if ("indeterminate".equals(prop)) {
|
||
|
isIndeterminate = progressBar.isIndeterminate();
|
||
|
|
||
|
if (isIndeterminate) {
|
||
|
initIndeterminateValues();
|
||
|
|
||
|
//start the animation thread
|
||
|
startAnimationTimer();
|
||
|
} else {
|
||
|
//stop the animation thread
|
||
|
stopAnimationTimer();
|
||
|
|
||
|
//clean up
|
||
|
cleanUpIndeterminateValues();
|
||
|
}
|
||
|
|
||
|
progressBar.repaint();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Change Events
|
||
|
//
|
||
|
/**
|
||
|
* This inner class is marked "public" due to a compiler bug.
|
||
|
* This class should be treated as a "protected" inner class.
|
||
|
* Instantiate it only within subclasses of BasicProgressBarUI.
|
||
|
*/
|
||
|
public class ChangeHandler implements ChangeListener {
|
||
|
public void stateChanged(ChangeEvent e) {
|
||
|
BoundedRangeModel model = progressBar.getModel();
|
||
|
int newRange = model.getMaximum() - model.getMinimum();
|
||
|
int newPercent;
|
||
|
int oldPercent = getCachedPercent();
|
||
|
|
||
|
if (newRange > 0) {
|
||
|
newPercent = (int)((100 * (long)model.getValue()) / newRange);
|
||
|
} else {
|
||
|
newPercent = 0;
|
||
|
}
|
||
|
|
||
|
if (newPercent != oldPercent) {
|
||
|
setCachedPercent(newPercent);
|
||
|
progressBar.repaint();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|