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.Config;
9 import tim.prune.I18nManager;
12 * Class to show a scale bar on the main map of Prune
14 public class ScaleBar extends JPanel
17 private int _zoomLevel = -1;
19 private int _yTile = -1;
22 /** Offset from left side in pixels */
23 private static final int LEFT_OFFSET = 20;
24 /** Offset from top in pixels */
25 private static final int Y_OFFSET = 10;
26 /** Tick height in pixels */
27 private static final int TICK_HEIGHT = 5;
28 /** Margin between bar and end text in pixels */
29 private static final int MARGIN_WIDTH = 8;
31 /** metric scales for each zoom level */
32 private static final int[] _metricScales = {10000, 5000, 2000, 2000, 1000, 500, 200, 100,
33 50, 20, 10, 5, 2, 2, 1, -2, -5, -10, -20, -50, -100, -200};
34 /** pixel counts for each zoom level (metric) */
35 private static final int[] _metricPixels = {64, 64, 51, 102, 102, 102, 81, 81,
36 81, 65, 65, 65, 52, 105, 105, 105, 83, 83, 83, 67, 67, 67};
37 /** imperial scales for each zoom level (num miles) */
38 private static final int[] _mileScales = {10000, 10000, 5000, 2000, 2000, 1000, 500, 200,
39 100, 50, 20, 10, 5, 2, 1, -2, -2, -5, -10, -20, -50, -100};
40 /** pixel counts for each zoom level (miles) */
41 private static final int[] _milePixels = {79, 79, 79, 64, 127, 127, 127, 102,
42 102, 102, 81, 81, 81, 65, 65, 65, 130, 104, 104, 104, 104, 83, 83};
52 setPreferredSize(new Dimension(100, 20));
56 * Paint method to override display
57 * @param inG graphics object
59 public void paint(Graphics inG)
65 boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
66 int rightSide = LEFT_OFFSET + (useMetric?_metricPixels[_zoomLevel]:_milePixels[_zoomLevel]);
67 int scale = (useMetric?_metricScales[_zoomLevel]:_mileScales[_zoomLevel]);
69 // work out cos(latitude) from y tile and zoom, and apply to scale
70 final double n = Math.pow(2, _zoomLevel);
71 final double angle = Math.PI * (1 - 2.0*_yTile/n);
72 final double lat = Math.atan(Math.sinh(angle));
73 final double cosLat = Math.cos(lat);
74 rightSide = (int) (rightSide / cosLat);
75 // Adjust if scale is too large
76 while (rightSide > 300)
80 // Abort if scale is now less than 1 unit (shouldn't ever be)
81 if (scale < 1) {return;}
85 inG.setColor(Color.BLACK);
86 inG.drawLine(LEFT_OFFSET, Y_OFFSET, rightSide, Y_OFFSET);
87 inG.drawLine(LEFT_OFFSET, Y_OFFSET+1, rightSide, Y_OFFSET+1);
89 inG.drawLine(LEFT_OFFSET, Y_OFFSET, LEFT_OFFSET, Y_OFFSET-TICK_HEIGHT);
90 inG.drawLine(LEFT_OFFSET+1, Y_OFFSET, LEFT_OFFSET+1, Y_OFFSET-TICK_HEIGHT);
92 inG.drawLine(rightSide, Y_OFFSET, rightSide, Y_OFFSET-TICK_HEIGHT);
93 inG.drawLine(rightSide+1, Y_OFFSET, rightSide+1, Y_OFFSET-TICK_HEIGHT);
95 String text = (scale>0?(""+scale):("1/"+(-scale))) + " " + I18nManager.getText(useMetric?"units.kilometres.short":"units.miles.short");
96 inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET);
98 catch (ArrayIndexOutOfBoundsException ai) {}
103 * Update the scale level
104 * @param inZoom new zoom level
106 public void updateScale(int inZoom, int inYtile)