package net.sf.openrocket.gui.components.compass;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
/**
* A component that draws a compass rose. This class has no other functionality, but superclasses
* may add functionality to it.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class CompassRose extends JComponent {
private static final Translator trans = Application.getTranslator();
private static final Color MAIN_COLOR = new Color(0.4f, 0.4f, 1.0f);
private static final float MAIN_LENGTH = 0.95f;
private static final float MAIN_WIDTH = 0.15f;
private static final int CIRCLE_BORDER = 2;
private static final Color CIRCLE_HIGHLIGHT = new Color(1.0f, 1.0f, 1.0f, 0.7f);
private static final Color CIRCLE_SHADE = new Color(0.0f, 0.0f, 0.0f, 0.2f);
private static final Color MARKER_COLOR = Color.BLACK;
private double scaler;
private double markerRadius;
private Font markerFont;
/**
* Construct a compass rose with the default settings.
*/
public CompassRose() {
this(0.8, 1.1, Font.decode("Serif-PLAIN-16"));
}
/**
* Construct a compass rose with the specified settings.
*
* @param scaler The scaler of the rose. The bordering circle will we this portion of the component dimensions.
* @param markerRadius The radius for the marker positions (N/E/S/W), or NaN for no markers. A value greater than one
* will position the markers outside of the bordering circle.
* @param markerFont The font used for the markers.
*/
public CompassRose(double scaler, double markerRadius, Font markerFont) {
this.scaler = scaler;
this.markerRadius = markerRadius;
this.markerFont = markerFont;
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int[] x = new int[3];
int[] y = new int[3];
Dimension dimension = this.getSize();
int width = Math.min(dimension.width, dimension.height);
int mid = width / 2;
width = (int) (scaler * width);
int mainLength = (int) (width * MAIN_LENGTH / 2);
int mainWidth = (int) (width * MAIN_WIDTH / 2);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(MAIN_COLOR);
// North
x[0] = mid;
y[0] = mid;
x[1] = mid;
y[1] = mid - mainLength;
x[2] = mid - mainWidth;
y[2] = mid - mainWidth;
g2.fillPolygon(x, y, 3);
x[2] = mid + mainWidth;
g2.drawPolygon(x, y, 3);
// East
x[0] = mid;
y[0] = mid;
x[1] = mid + mainLength;
y[1] = mid;
x[2] = mid + mainWidth;
y[2] = mid - mainWidth;
g2.fillPolygon(x, y, 3);
y[2] = mid + mainWidth;
g2.drawPolygon(x, y, 3);
// South
x[0] = mid;
y[0] = mid;
x[1] = mid;
y[1] = mid + mainLength;
x[2] = mid + mainWidth;
y[2] = mid + mainWidth;
g2.fillPolygon(x, y, 3);
x[2] = mid - mainWidth;
g2.drawPolygon(x, y, 3);
// West
x[0] = mid;
y[0] = mid;
x[1] = mid - mainLength;
y[1] = mid;
x[2] = mid - mainWidth;
y[2] = mid + mainWidth;
g2.fillPolygon(x, y, 3);
y[2] = mid - mainWidth;
g2.drawPolygon(x, y, 3);
// Border circle
g2.setColor(CIRCLE_SHADE);
g2.drawArc(mid - width / 2 + CIRCLE_BORDER, mid - width / 2 + CIRCLE_BORDER,
width - 2 * CIRCLE_BORDER, width - 2 * CIRCLE_BORDER, 45, 180);
g2.setColor(CIRCLE_HIGHLIGHT);
g2.drawArc(mid - width / 2 + CIRCLE_BORDER, mid - width / 2 + CIRCLE_BORDER,
width - 2 * CIRCLE_BORDER, width - 2 * CIRCLE_BORDER, 180 + 45, 180);
// Draw direction markers
if (!Double.isNaN(markerRadius) && markerFont != null) {
int pos = (int) (width * markerRadius / 2);
g2.setColor(MARKER_COLOR);
drawMarker(g2, mid, mid - pos, trans.get("lbl.north"));
drawMarker(g2, mid + pos, mid, trans.get("lbl.east"));
drawMarker(g2, mid, mid + pos, trans.get("lbl.south"));
drawMarker(g2, mid - pos, mid, trans.get("lbl.west"));
}
}
private void drawMarker(Graphics2D g2, float x, float y, String str) {
GlyphVector gv = markerFont.createGlyphVector(g2.getFontRenderContext(), str);
Rectangle2D rect = gv.getVisualBounds();
x -= rect.getWidth() / 2;
y += rect.getHeight() / 2;
g2.drawGlyphVector(gv, x, y);
}
public double getScaler() {
return scaler;
}
public void setScaler(double scaler) {
this.scaler = scaler;
repaint();
}
public double getMarkerRadius() {
return markerRadius;
}
public void setMarkerRadius(double markerRadius) {
this.markerRadius = markerRadius;
repaint();
}
public Font getMarkerFont() {
return markerFont;
}
public void setMarkerFont(Font markerFont) {
this.markerFont = markerFont;
repaint();
}
@Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
int min = Math.min(dim.width, dim.height);
dim.setSize(min, min);
return dim;
}
}