package fr.utc.leapband.view; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import javax.swing.Icon; public class RotatedIcon implements Icon { public enum Rotate { DOWN, UP, UPSIDE_DOWN, ABOUT_CENTER; } private Icon icon; private Rotate rotate; private double angle; /** * Convenience constructor to create a RotatedIcon that is rotated DOWN. * * @param icon the Icon to rotate */ public RotatedIcon(Icon icon) { this(icon, Rotate.UP); } /** * Create a RotatedIcon * * @param icon the Icon to rotate * @param rotate the direction of rotation */ public RotatedIcon(Icon icon, Rotate rotate) { this.icon = icon; this.rotate = rotate; } /** * Create a RotatedIcon. The icon will rotate about its center. This * constructor will automatically set the Rotate enum to ABOUT_CENTER. * For rectangular icons the icon will be clipped before the rotation * to make sure it doesn't paint over the rest of the component. * * @param icon the Icon to rotate * @param angle the angle of rotation */ public RotatedIcon(Icon icon, double angle) { this(icon, Rotate.ABOUT_CENTER); this.angle = angle; } /** * Gets the Icon to be rotated * * @return the Icon to be rotated */ public Icon getIcon() { return icon; } /** * Gets the Rotate enum which indicates the direction of rotation * * @return the Rotate enum */ public Rotate getRotate() { return rotate; } /** * Gets the angle of rotation. Only use for Rotate.ABOUT_CENTER. * * @return the angle of rotation */ public double getAngle() { return angle; } // // Implement the Icon Interface // /** * Gets the width of this icon. * * @return the width of the icon in pixels. */ @Override public int getIconWidth() { if (rotate == Rotate.ABOUT_CENTER) { double radians = Math.toRadians( angle ); double sin = Math.abs( Math.sin( radians ) ); double cos = Math.abs( Math.cos( radians ) ); int width = (int)Math.floor(icon.getIconWidth() * cos + icon.getIconHeight() * sin); return width; } else if (rotate == Rotate.UPSIDE_DOWN) return icon.getIconWidth(); else return icon.getIconHeight(); } /** * Gets the height of this icon. * * @return the height of the icon in pixels. */ @Override public int getIconHeight() { if (rotate == Rotate.ABOUT_CENTER) { double radians = Math.toRadians( angle ); double sin = Math.abs( Math.sin( radians ) ); double cos = Math.abs( Math.cos( radians ) ); int height = (int)Math.floor(icon.getIconHeight() * cos + icon.getIconWidth() * sin); return height; } else if (rotate == Rotate.UPSIDE_DOWN) return icon.getIconHeight(); else return icon.getIconWidth(); } /** * Paint the icons of this compound icon at the specified location * * @param c The component on which the icon is painted * @param g the graphics context * @param x the X coordinate of the icon's top-left corner * @param y the Y coordinate of the icon's top-left corner */ @Override public void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D g2 = (Graphics2D)g.create(); int cWidth = icon.getIconWidth() / 2; int cHeight = icon.getIconHeight() / 2; int xAdjustment = (icon.getIconWidth() % 2) == 0 ? 0 : -1; int yAdjustment = (icon.getIconHeight() % 2) == 0 ? 0 : -1; if (rotate == Rotate.DOWN) { g2.translate(x + cHeight, y + cWidth); g2.rotate( Math.toRadians( 90 ) ); icon.paintIcon(c, g2, -cWidth, yAdjustment - cHeight); } else if (rotate == Rotate.UP) { g2.translate(x + cHeight, y + cWidth); g2.rotate( Math.toRadians( -90 ) ); icon.paintIcon(c, g2, xAdjustment - cWidth, -cHeight); } else if (rotate == Rotate.UPSIDE_DOWN) { g2.translate(x + cWidth, y + cHeight); g2.rotate( Math.toRadians( 180 ) ); icon.paintIcon(c, g2, xAdjustment - cWidth, yAdjustment - cHeight); } else if (rotate == Rotate.ABOUT_CENTER) { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); AffineTransform original = g2.getTransform(); AffineTransform at = new AffineTransform(); at.concatenate(original); at.translate((getIconWidth() - icon.getIconWidth()) / 2, (getIconHeight() - icon.getIconHeight()) / 2); at.rotate(Math.toRadians(angle), x + cWidth, y + cHeight); g2.setTransform(at); icon.paintIcon(c, g2, x, y); g2.setTransform(original); } } }