/**
* Xtreme Media Player a cross-platform media player.
* Copyright (C) 2005-2011 Besmir Beqiri
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package xtrememp.ui.label;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JLabel;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.trident.Timeline.RepeatBehavior;
import org.pushingpixels.trident.swing.SwingRepaintTimeline;
/**
* A simple circular animation, useful for denoting an action is taking
* place that may take an unknown length of time to complete.
*
* @author Besmir Beqiri
*/
public class BusyLabel extends JLabel {
private SwingRepaintTimeline repaintTimeline;
private int angle;
private boolean busy;
public BusyLabel(Dimension size) {
super();
this.setMinimumSize(size);
this.setPreferredSize(size);
this.setMaximumSize(size);
this.repaintTimeline = new SwingRepaintTimeline(this);
this.repaintTimeline.addPropertyToInterpolate("angle", 0, 360);
this.repaintTimeline.setDuration(36000);
this.repaintTimeline.setAutoRepaintMode(false);
}
/**
* Gets the current angle used in the animation. Used by the timeline to
* interpolate angle property.
*
* @return the angle.
*/
public int getAngle() {
return angle;
}
/**
* Sets the current angle used in the animation. Used by the timeline to
* interpolate angle property.
*
* @param angle The angle to set.
*/
public void setAngle(int angle) {
this.angle = angle;
this.repaintTimeline.forceRepaintOnNextPulse();
}
/**
* Gets whether this <code>BusyLabel</code> is busy. If busy, then
* the <code>BusyLabel</code> instance will indicate that it is busy,
* generally by animating some state.
*
* @return <code>true</code> if this instance is busy.
*/
public boolean isBusy() {
return busy;
}
/**
* Sets whether this <code>BusyLabel</code> instance should consider
* itself busy. A busy component indicate that it is busy via animation.
*
* @param busy Whether this <code>BusyLabel</code> instance should
* consider itself busy.
*/
public void setBusy(boolean busy) {
this.busy = busy;
if (busy) {
repaintTimeline.playLoop(RepeatBehavior.LOOP);
} else {
repaintTimeline.abort();
this.repaint();
}
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
int width = getWidth();
int height = getHeight();
int points = 8;
Color fgColor = getForeground();
if (SubstanceLookAndFeel.isCurrentLookAndFeel()) {
ComponentState labelState = isEnabled() ? ComponentState.ENABLED : ComponentState.DISABLED_UNSELECTED;
fgColor = SubstanceLookAndFeel.getCurrentSkin().getColorScheme(this, labelState).getForegroundColor();
}
for (int i = 0; i < points; i++) {
if (busy) {
int alpha = 255 * ((i + angle) % points) / points;
g2d.setColor(new Color(fgColor.getRed(), fgColor.getGreen(), fgColor.getBlue(), alpha));
} else {
g2d.setColor(fgColor);
}
double a = 2 * Math.PI / points, x = Math.sin(i * a), y = Math.cos(i * a);
g2d.drawLine(width / 2 + (int) (5 * x), height / 2 + (int) (5 * y),
width / 2 + (int) (width / 2.0D * x), height / 2 + (int) (height / 2.0D * y));
}
g2d.dispose();
}
}