FileDocCategorySizeDatePackage
InfiniteProgressPanel.javaAPI DocExample13545Mon Jan 09 11:02:00 GMT 2006None

InfiniteProgressPanel

public class InfiniteProgressPanel extends JComponent implements MouseListener
An infinite progress panel displays a rotating figure and a message to notice the user of a long, duration unknown task. The shape and the text are drawn upon a white veil which alpha level (or shield value) lets the underlying component shine through. This panel is meant to be used asa glass pane in the window performing the long operation.

On the contrary to regular glass panes, you don't need to set it visible or not by yourself. Once you've started the animation all the mouse events are intercepted by this panel, preventing them from being forwared to the underlying components.

The panel can be controlled by the start(), stop() and interrupt() methods.

Example:

InfiniteProgressPanel pane = new InfiniteProgressPanel();
frame.setGlassPane(pane);
pane.start()


Several properties can be configured at creation time. The message and its font can be changed at runtime. Changing the font can be done using setFont() and setForeground().
author
Romain Guy
version
1.0

Fields Summary
protected Area[]
ticker
Contains the bars composing the circular shape.
protected Thread
animation
The animation thread is responsible for fade in/out and rotation.
protected boolean
started
Notifies whether the animation is running or not.
protected int
alphaLevel
Alpha level of the veil, used for fade in/out.
protected int
rampDelay
Duration of the veil's fade in/out.
protected float
shield
Alpha level of the veil.
protected String
text
Message displayed below the circular shape.
protected int
barsCount
Amount of bars composing the circular shape.
protected float
fps
Amount of frames per seconde. Lowers this to save CPU.
protected RenderingHints
hints
Rendering hints to set anti aliasing.
Constructors Summary
public InfiniteProgressPanel()
Creates a new progress panel with default values:
  • No message
  • 14 bars
  • Veil's alpha level is 70%
  • 15 frames per second
  • Fade in/out last 300 ms


                                      
     
    
        this("");
    
public InfiniteProgressPanel(String text)
Creates a new progress panel with default values:
  • 14 bars
  • Veil's alpha level is 70%
  • 15 frames per second
  • Fade in/out last 300 ms

param
text The message to be displayed. Can be null or empty.

        this(text, 14);
    
public InfiniteProgressPanel(String text, int barsCount)
Creates a new progress panel with default values:
  • Veil's alpha level is 70%
  • 15 frames per second
  • Fade in/out last 300 ms

param
text The message to be displayed. Can be null or empty.
param
barsCount The amount of bars composing the circular shape

        this(text, barsCount, 0.70f);
    
public InfiniteProgressPanel(String text, int barsCount, float shield)
Creates a new progress panel with default values:
  • 15 frames per second
  • Fade in/out last 300 ms

param
text The message to be displayed. Can be null or empty.
param
barsCount The amount of bars composing the circular shape.
param
shield The alpha level between 0.0 and 1.0 of the colored shield (or veil).

        this(text, barsCount, shield, 15.0f);
    
public InfiniteProgressPanel(String text, int barsCount, float shield, float fps)
Creates a new progress panel with default values:
  • Fade in/out last 300 ms

param
text The message to be displayed. Can be null or empty.
param
barsCount The amount of bars composing the circular shape.
param
shield The alpha level between 0.0 and 1.0 of the colored shield (or veil).
param
fps The number of frames per second. Lower this value to decrease CPU usage.

        this(text, barsCount, shield, fps, 300);
    
public InfiniteProgressPanel(String text, int barsCount, float shield, float fps, int rampDelay)
Creates a new progress panel.

param
text The message to be displayed. Can be null or empty.
param
barsCount The amount of bars composing the circular shape.
param
shield The alpha level between 0.0 and 1.0 of the colored shield (or veil).
param
fps The number of frames per second. Lower this value to decrease CPU usage.
param
rampDelay The duration, in milli seconds, of the fade in and the fade out of the veil.

        this.text 	   = text;
        this.rampDelay = rampDelay >= 0 ? rampDelay : 0;
        this.shield    = shield >= 0.0f ? shield : 0.0f;
        this.fps       = fps > 0.0f ? fps : 15.0f;
        this.barsCount = barsCount > 0 ? barsCount : 14;

        this.hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        this.hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        this.hints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
    
Methods Summary
private java.awt.geom.AreabuildPrimitive()
Builds a bar.

        Rectangle2D.Double body = new Rectangle2D.Double(6, 0, 30, 12);
        Ellipse2D.Double   head = new Ellipse2D.Double(0, 0, 12, 12);
        Ellipse2D.Double   tail = new Ellipse2D.Double(30, 0, 12, 12);

        Area tick = new Area(body);
        tick.add(new Area(head));
        tick.add(new Area(tail));

        return tick;
    
private java.awt.geom.Area[]buildTicker()
Builds the circular shape and returns the result as an array of Area. Each Area is one of the bars composing the shape.

        Area[] ticker = new Area[barsCount];
        Point2D.Double center = new Point2D.Double((double) getWidth() / 2, (double) getHeight() / 2);
        double fixedAngle = 2.0 * Math.PI / ((double) barsCount);

        for (double i = 0.0; i < (double) barsCount; i++)
        {
            Area primitive = buildPrimitive();

            AffineTransform toCenter = AffineTransform.getTranslateInstance(center.getX(), center.getY());
            AffineTransform toBorder = AffineTransform.getTranslateInstance(45.0, -6.0);
            AffineTransform toCircle = AffineTransform.getRotateInstance(-i * fixedAngle, center.getX(), center.getY());

            AffineTransform toWheel = new AffineTransform();
            toWheel.concatenate(toCenter);
            toWheel.concatenate(toBorder);

            primitive.transform(toWheel);
            primitive.transform(toCircle);
            
            ticker[(int) i] = primitive;
        }

        return ticker;
    
public java.lang.StringgetText()
Returns the current displayed message.

        return text;
    
public voidinterrupt()
Interrupts the animation, whatever its state is. You can use it when you need to stop the animation without running the fade out phase. This methods sets the panel invisible at the end.

        if (animation != null) {
            animation.interrupt();
            animation = null;

            removeMouseListener(this);
            setVisible(false);
        }
    
public voidmouseClicked(java.awt.event.MouseEvent e)

    
public voidmouseEntered(java.awt.event.MouseEvent e)

    
public voidmouseExited(java.awt.event.MouseEvent e)

    
public voidmousePressed(java.awt.event.MouseEvent e)

    
public voidmouseReleased(java.awt.event.MouseEvent e)

    
public voidpaintComponent(java.awt.Graphics g)

        if (started)
        {
            int width  = getWidth();
            int height = getHeight();

            double maxY = 0.0; 

            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHints(hints);
            
            g2.setColor(new Color(255, 255, 255, (int) (alphaLevel * shield)));
            g2.fillRect(0, 0, getWidth(), getHeight());

            for (int i = 0; i < ticker.length; i++)
            {
                int channel = 224 - 128 / (i + 1);
                g2.setColor(new Color(channel, channel, channel, alphaLevel));
                g2.fill(ticker[i]);

                Rectangle2D bounds = ticker[i].getBounds2D();
                if (bounds.getMaxY() > maxY)
                    maxY = bounds.getMaxY();
            }

            if (text != null && text.length() > 0)
            {
	            FontRenderContext context = g2.getFontRenderContext();
	            TextLayout layout = new TextLayout(text, getFont(), context);
	            Rectangle2D bounds = layout.getBounds();
	            g2.setColor(getForeground());
	            layout.draw(g2, (float) (width - bounds.getWidth()) / 2,
	                    		(float) (maxY + layout.getLeading() + 2 * layout.getAscent()));
            }
        }
    
public voidsetText(java.lang.String text)
Changes the displayed message at runtime.

param
text The message to be displayed. Can be null or empty.

        this.text = text;
        repaint();
    
public voidstart()
Starts the waiting animation by fading the veil in, then rotating the shapes. This method handles the visibility of the glass pane.

        addMouseListener(this);
        setVisible(true);
        ticker = buildTicker();
        animation = new Thread(new Animator(true));
        animation.start();
    
public voidstop()
Stops the waiting animation by stopping the rotation of the circular shape and then by fading out the veil. This methods sets the panel invisible at the end.

        if (animation != null) {
	        animation.interrupt();
	        animation = null;
	        animation = new Thread(new Animator(false));
	        animation.start();
        }