package net.sf.openrocket.gui.components.compass;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.sf.openrocket.gui.Resettable;
import net.sf.openrocket.gui.adaptors.DoubleModel;
/**
* A component that draws a pointer onto a compass rose.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class CompassPointer extends CompassRose implements Resettable {
private static final Color PRIMARY_POINTER_COLOR = new Color(1.0f, 0.2f, 0.2f);
private static final Color SECONDARY_POINTER_COLOR = new Color(0.2f, 0.2f, 0.2f, 0.2f);
private final DoubleModel model;
private final ChangeListener listener;
protected int width = -1;
protected int mid = -1;
private DoubleModel secondaryModel;
private float pointerLength = 0.95f;
private float pointerWidth = 0.1f;
private float pointerArrowWidth = 0.2f;
private boolean pointerArrow = true;
public CompassPointer(DoubleModel model) {
super();
this.model = model;
listener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
CompassPointer.this.repaint();
}
};
model.addChangeListener(listener);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Dimension dimension = this.getSize();
width = Math.min(dimension.width, dimension.height);
mid = width / 2;
width = (int) (getScaler() * width);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (secondaryModel != null) {
drawArrow(secondaryModel.getValue(), SECONDARY_POINTER_COLOR, g2);
}
drawArrow(model.getValue(), PRIMARY_POINTER_COLOR, g2);
}
private void drawArrow(double angle, Color color, Graphics2D g2) {
int pLength = (int) (width * pointerLength / 2);
int pWidth = (int) (width * pointerWidth / 2);
int pArrowWidth = (int) (width * pointerArrowWidth / 2);
int[] x = new int[8];
int[] y = new int[8];
g2.setColor(color);
double sin = Math.sin(angle);
double cos = Math.cos(angle);
int n = 0;
// Top part
x[n] = 0;
y[n] = -pLength;
n++;
if (pointerArrow) {
x[n] = -pArrowWidth;
y[n] = -pLength + 2 * pArrowWidth;
n++;
x[n] = -pWidth;
y[n] = -pLength + 2 * pArrowWidth;
n++;
}
// Bottom part
x[n] = -pWidth;
y[n] = pLength;
n++;
x[n] = 0;
y[n] = pLength - pWidth;
n++;
x[n] = pWidth;
y[n] = pLength;
n++;
// Top part
if (pointerArrow) {
x[n] = pWidth;
y[n] = -pLength + 2 * pArrowWidth;
n++;
x[n] = pArrowWidth;
y[n] = -pLength + 2 * pArrowWidth;
n++;
}
// Rotate and shift
for (int i = 0; i < n; i++) {
double x2, y2;
x2 = cos * x[i] - sin * y[i];
y2 = sin * x[i] + cos * y[i];
x[i] = (int) (x2 + mid);
y[i] = (int) (y2 + mid);
}
g2.fillPolygon(x, y, n);
g2.setColor(color.darker());
g2.drawPolygon(x, y, n);
}
public boolean isPointerArrow() {
return pointerArrow;
}
public void setPointerArrow(boolean useArrow) {
this.pointerArrow = useArrow;
repaint();
}
public float getPointerLength() {
return pointerLength;
}
public void setPointerLength(float pointerLength) {
this.pointerLength = pointerLength;
repaint();
}
public float getPointerWidth() {
return pointerWidth;
}
public void setPointerWidth(float pointerWidth) {
this.pointerWidth = pointerWidth;
repaint();
}
public float getPointerArrowWidth() {
return pointerArrowWidth;
}
public void setPointerArrowWidth(float pointerArrowWidth) {
this.pointerArrowWidth = pointerArrowWidth;
repaint();
}
public DoubleModel getSecondaryModel() {
return secondaryModel;
}
public void setSecondaryModel(DoubleModel secondaryModel) {
if (this.secondaryModel != null) {
this.secondaryModel.removeChangeListener(listener);
}
this.secondaryModel = secondaryModel;
if (this.secondaryModel != null) {
this.secondaryModel.addChangeListener(listener);
}
}
@Override
public void resetModel() {
model.removeChangeListener(listener);
setSecondaryModel(null);
}
}