/*******************************************************************************
* Copyright (c) 2016 Weasis Team and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.ui.util;
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;
/**
* <ul>
* <li>DOWN - rotated 90 degrees
* <li>UP (default) - rotated -90 degrees
* <li>UPSIDE_DOWN - rotated 180 degrees
* <li>ABOUT_CENTER - a specfic angle about its center
* </ul>
*/
public class RotatedIcon implements Icon {
public enum Rotate {
DOWN, UP, UPSIDE_DOWN, ABOUT_CENTER;
}
private Icon icon;
private Rotate rotate;
private double angle;
public RotatedIcon(Icon icon) {
this(icon, Rotate.UP);
}
public RotatedIcon(Icon icon, Rotate rotate) {
this.icon = icon;
this.rotate = rotate;
}
public RotatedIcon(Icon icon, double angle) {
this(icon, Rotate.ABOUT_CENTER);
this.angle = angle;
}
public Icon getIcon() {
return icon;
}
public Rotate getRotate() {
return rotate;
}
public double getAngle() {
return angle;
}
@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));
return (int) Math.floor(icon.getIconWidth() * cos + icon.getIconHeight() * sin);
} else if (rotate == Rotate.UPSIDE_DOWN) {
return icon.getIconWidth();
} else {
return icon.getIconHeight();
}
}
@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));
return (int) Math.floor(icon.getIconHeight() * cos + icon.getIconWidth() * sin);
} else if (rotate == Rotate.UPSIDE_DOWN) {
return icon.getIconHeight();
} else {
return icon.getIconWidth();
}
}
@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.0, (getIconHeight() - icon.getIconHeight()) / 2.0);
at.rotate(Math.toRadians(angle), x + icon.getIconWidth() / 2.0, y + icon.getIconHeight() / 2.0);
g2.setTransform(at);
icon.paintIcon(c, g2, x, y);
g2.setTransform(original);
}
}
}