package org.ripple.power.ui.view; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.Timer; import org.ripple.power.config.LSystem; import org.ripple.power.utils.GraphicsUtils; public class AnimationIcon implements Icon { private boolean fix; private final Icon delegateIcon; private final int width; private final int height; private final int[][] rotationOffsets = new int[][] { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { -1, 1 }, { -1, 1 }, { -1, 1 }, { -1, 1 }, { -1, 0 }, { -1, 0 }, { -1, 0 }, { -1, 0 }, { 0, 0 }, }; private final static int maxStepCount = 16; private double theta = 0; private double delta = 2 * Math.PI / maxStepCount; private int stepCount = 0; private final Timer timer; public AnimationIcon(Icon icon, final JComponent component, final boolean repeat) { delegateIcon = icon; width = delegateIcon.getIconWidth(); height = delegateIcon.getIconHeight(); timer = new Timer(100, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { incrementRotation(component); } }); LSystem.invokeLater(new Runnable() { @Override public void run() { component.repaint(); } }); timer.setRepeats(repeat); timer.start(); } public void incrementRotation(final JComponent component) { theta += delta; stepCount++; if (stepCount >= maxStepCount) { theta = 0; stepCount = 0; } LSystem.invokeLater(new Runnable() { @Override public void run() { component.repaint(); } }); } public void decrementRotation(final JComponent component) { theta -= delta; if (stepCount == 0) { theta = 2 * Math.PI - delta; stepCount = maxStepCount - 1; } else { stepCount--; } LSystem.invokeLater(new Runnable() { @Override public void run() { component.repaint(); } }); } public void fixRotation() { this.fix = true; } @Override public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D g2d = (Graphics2D) g.create(); GraphicsUtils.setExcellentRenderingHints(g2d); int xCenteringOffset = 0; int yCenteringOffset = 0; int xRotationOffset = fix ? rotationOffsets[stepCount][0] : 0; int yRotationOffset = fix ? rotationOffsets[stepCount][1] : 0; double centerX = xRotationOffset + xCenteringOffset + x + (width / 2); double centerY = yRotationOffset + yCenteringOffset + y + (height / 2); AffineTransform tx = new AffineTransform(); tx.rotate(theta, centerX, centerY); g2d.setTransform(tx); delegateIcon.paintIcon(c, g2d, xRotationOffset + xCenteringOffset + x, yRotationOffset + yCenteringOffset + y); g2d.dispose(); } public void start() { timer.start(); } public void stop() { timer.stop(); } @Override public int getIconWidth() { return width; } @Override public int getIconHeight() { return height; } }