1 package net.sf.openrocket.gui.components.compass;
4 import java.awt.Dimension;
5 import java.awt.Graphics;
6 import java.awt.Graphics2D;
7 import java.awt.RenderingHints;
9 import javax.swing.event.ChangeEvent;
10 import javax.swing.event.ChangeListener;
12 import net.sf.openrocket.gui.Resettable;
13 import net.sf.openrocket.gui.adaptors.DoubleModel;
16 * A component that draws a pointer onto a compass rose.
18 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
20 public class CompassPointer extends CompassRose implements Resettable {
22 private static final Color PRIMARY_POINTER_COLOR = new Color(1.0f, 0.2f, 0.2f);
23 private static final Color SECONDARY_POINTER_COLOR = new Color(0.2f, 0.2f, 0.2f, 0.2f);
25 private final DoubleModel model;
26 private final ChangeListener listener;
28 protected int width = -1;
29 protected int mid = -1;
31 private DoubleModel secondaryModel;
33 private float pointerLength = 0.95f;
34 private float pointerWidth = 0.1f;
35 private float pointerArrowWidth = 0.2f;
36 private boolean pointerArrow = true;
40 public CompassPointer(DoubleModel model) {
43 listener = new ChangeListener() {
45 public void stateChanged(ChangeEvent e) {
46 CompassPointer.this.repaint();
49 model.addChangeListener(listener);
54 public void paintComponent(Graphics g) {
55 super.paintComponent(g);
57 Graphics2D g2 = (Graphics2D) g;
60 Dimension dimension = this.getSize();
62 width = Math.min(dimension.width, dimension.height);
64 width = (int) (getScaler() * width);
67 g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
68 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
71 if (secondaryModel != null) {
72 drawArrow(secondaryModel.getValue(), SECONDARY_POINTER_COLOR, g2);
74 drawArrow(model.getValue(), PRIMARY_POINTER_COLOR, g2);
80 private void drawArrow(double angle, Color color, Graphics2D g2) {
82 int pLength = (int) (width * pointerLength / 2);
83 int pWidth = (int) (width * pointerWidth / 2);
84 int pArrowWidth = (int) (width * pointerArrowWidth / 2);
92 double sin = Math.sin(angle);
93 double cos = Math.cos(angle);
103 y[n] = -pLength + 2 * pArrowWidth;
106 y[n] = -pLength + 2 * pArrowWidth;
115 y[n] = pLength - pWidth;
124 y[n] = -pLength + 2 * pArrowWidth;
127 y[n] = -pLength + 2 * pArrowWidth;
132 for (int i = 0; i < n; i++) {
134 x2 = cos * x[i] - sin * y[i];
135 y2 = sin * x[i] + cos * y[i];
137 x[i] = (int) (x2 + mid);
138 y[i] = (int) (y2 + mid);
141 g2.fillPolygon(x, y, n);
143 g2.setColor(color.darker());
144 g2.drawPolygon(x, y, n);
149 public boolean isPointerArrow() {
154 public void setPointerArrow(boolean useArrow) {
155 this.pointerArrow = useArrow;
160 public float getPointerLength() {
161 return pointerLength;
165 public void setPointerLength(float pointerLength) {
166 this.pointerLength = pointerLength;
171 public float getPointerWidth() {
176 public void setPointerWidth(float pointerWidth) {
177 this.pointerWidth = pointerWidth;
182 public float getPointerArrowWidth() {
183 return pointerArrowWidth;
187 public void setPointerArrowWidth(float pointerArrowWidth) {
188 this.pointerArrowWidth = pointerArrowWidth;
194 public DoubleModel getSecondaryModel() {
195 return secondaryModel;
199 public void setSecondaryModel(DoubleModel secondaryModel) {
200 if (this.secondaryModel != null) {
201 this.secondaryModel.removeChangeListener(listener);
203 this.secondaryModel = secondaryModel;
204 if (this.secondaryModel != null) {
205 this.secondaryModel.addChangeListener(listener);
211 public void resetModel() {
212 model.removeChangeListener(listener);
213 setSecondaryModel(null);