1 package tim.prune.gui.map;
4 import java.awt.Dimension;
5 import java.awt.Graphics;
6 import javax.swing.JPanel;
8 import tim.prune.I18nManager;
9 import tim.prune.config.ColourScheme;
10 import tim.prune.config.Config;
13 * Class to show a scale bar on the main map of Prune
15 public class ScaleBar extends JPanel
18 private int _zoomLevel = -1;
20 private double _yPos = 0.0;
23 /** Offset from left side in pixels */
24 private static final int LEFT_OFFSET = 20;
25 /** Offset from top in pixels */
26 private static final int Y_OFFSET = 10;
27 /** Tick height in pixels */
28 private static final int TICK_HEIGHT = 5;
29 /** Margin between bar and end text in pixels */
30 private static final int MARGIN_WIDTH = 8;
32 /** scales for each zoom level */
33 private static final int[] _scales = {10000, 5000, 2000, 2000, 1000, 500, 200, 100,
34 50, 20, 10, 5, 2, 2, 1,
35 -2, -5, -10, -20, -50, -100, -200};
36 /** pixel counts for each zoom level (metric) */
37 private static final double[] _metricPixels = {64, 64, 51, 102, 102, 102, 81, 81,
38 81, 65, 65, 65, 52, 105, 105,
39 105, 83, 83, 83, 67, 67, 67};
49 setPreferredSize(new Dimension(100, 20));
53 * Paint method to override display
54 * @param inG graphics object
56 public void paint(Graphics inG)
62 boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
63 double drightSide = LEFT_OFFSET + _metricPixels[_zoomLevel] * (useMetric?1:1.609);
64 int scale = _scales[_zoomLevel];
66 // work out cos(latitude) from y position, and apply to scale
67 final double angle = Math.PI * (1 - 2*_yPos);
68 final double lat = Math.atan(Math.sinh(angle));
69 final double cosLat = Math.cos(lat);
70 int rightSide = (int) (drightSide / cosLat);
71 // Adjust if scale is too large
72 while (rightSide > 300)
76 // Abort if scale is now less than 1 unit (shouldn't ever be)
77 if (scale < 1) {return;}
79 // Abort if scale is negative (around poles)
80 if (rightSide < 1) {return;}
82 // Determine colours to use
83 Color barColour = Config.getColourScheme().getColour(ColourScheme.IDX_TEXT);
84 Color blankColour = new Color(255-barColour.getRed(), 255-barColour.getGreen(), 255-barColour.getBlue());
85 // Should this blank colour be set to saturation zero?
86 // Draw blank bars behind
87 inG.setColor(blankColour);
88 inG.drawLine(LEFT_OFFSET, Y_OFFSET-1, rightSide+2, Y_OFFSET-1);
89 inG.drawLine(LEFT_OFFSET, Y_OFFSET+2, rightSide+2, Y_OFFSET+2);
90 inG.drawLine(LEFT_OFFSET-1, Y_OFFSET+2, LEFT_OFFSET-1, Y_OFFSET-TICK_HEIGHT);
91 inG.drawLine(LEFT_OFFSET+2, Y_OFFSET+2, LEFT_OFFSET+2, Y_OFFSET-TICK_HEIGHT);
92 inG.drawLine(rightSide-1, Y_OFFSET+2, rightSide-1, Y_OFFSET-TICK_HEIGHT);
93 inG.drawLine(rightSide+2, Y_OFFSET+2, rightSide+2, Y_OFFSET-TICK_HEIGHT);
95 inG.setColor(barColour);
96 inG.drawLine(LEFT_OFFSET, Y_OFFSET, rightSide, Y_OFFSET);
97 inG.drawLine(LEFT_OFFSET, Y_OFFSET+1, rightSide, Y_OFFSET+1);
99 inG.drawLine(LEFT_OFFSET, Y_OFFSET, LEFT_OFFSET, Y_OFFSET-TICK_HEIGHT);
100 inG.drawLine(LEFT_OFFSET+1, Y_OFFSET, LEFT_OFFSET+1, Y_OFFSET-TICK_HEIGHT);
102 inG.drawLine(rightSide, Y_OFFSET+1, rightSide, Y_OFFSET-TICK_HEIGHT);
103 inG.drawLine(rightSide+1, Y_OFFSET+1, rightSide+1, Y_OFFSET-TICK_HEIGHT);
105 String text = getScaleText(scale, useMetric);
106 inG.setColor(blankColour);
107 inG.drawString(text, rightSide+MARGIN_WIDTH-1, Y_OFFSET);
108 inG.drawString(text, rightSide+MARGIN_WIDTH+1, Y_OFFSET);
109 inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET-1);
110 inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET+1);
111 inG.setColor(barColour);
112 inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET);
114 catch (ArrayIndexOutOfBoundsException ai) {}
119 * Get the scale text for the given scale
120 * @param inScale scale number
121 * @param inUseMetric true to use km/m, false for miles/ft
122 * @return scale text as string
124 private static String getScaleText(int inScale, boolean inUseMetric)
127 // Positive scale means km or miles
128 return "" + inScale + " " +
129 I18nManager.getText(inUseMetric?"units.kilometres.short":"units.miles.short");
132 // negative scale means m
133 return "" + (-1000 / inScale) + " " + I18nManager.getText("units.metres.short");
135 // fallen through to feet
136 return "" + (-5280 / inScale) + " " + I18nManager.getText("units.feet.short");
140 * Update the scale level
141 * @param inZoom new zoom level
142 * @param inYPos y position, where 0 is north pole, 1 is south pole
144 public void updateScale(int inZoom, double inYPos)