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; } }