]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/map/ScaleBar.java
1daa19ebd926dc05c852290fb2e653760532c00d
[GpsPrune.git] / tim / prune / gui / map / ScaleBar.java
1 package tim.prune.gui.map;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.Graphics;
6 import javax.swing.JPanel;
7
8 import tim.prune.I18nManager;
9 import tim.prune.config.ColourScheme;
10 import tim.prune.config.Config;
11
12 /**
13  * Class to show a scale bar on the main map of Prune
14  */
15 public class ScaleBar extends JPanel
16 {
17         /** zoom level */
18         private int _zoomLevel = -1;
19         /** y tile number */
20         private int _yTile = -1;
21
22         // Dimensions
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;
31
32         /** metric scales for each zoom level */
33         private static final int[] _metricScales = {10000, 5000, 2000, 2000, 1000, 500, 200, 100,
34                 50, 20, 10, 5, 2, 2, 1, -2, -5, -10, -20, -50, -100, -200};
35         /** pixel counts for each zoom level (metric) */
36         private static final int[] _metricPixels = {64, 64, 51, 102, 102, 102, 81, 81,
37                 81, 65, 65, 65, 52, 105, 105, 105, 83, 83, 83, 67, 67, 67};
38         /** imperial scales for each zoom level (num miles) */
39         private static final int[] _mileScales = {10000, 10000, 5000, 2000, 2000, 1000, 500, 200,
40                 100, 50, 20, 10, 5, 2, 1, -2, -2, -5, -10, -20, -50, -100};
41         /** pixel counts for each zoom level (miles) */
42         private static final int[] _milePixels = {79, 79, 79, 64, 127, 127, 127, 102,
43                 102, 102, 81, 81, 81, 65, 65, 65, 130, 104, 104, 104, 104, 83, 83};
44
45
46         /**
47          * Constructor
48          */
49         public ScaleBar()
50         {
51                 super();
52                 setOpaque(false);
53                 setPreferredSize(new Dimension(100, 20));
54         }
55
56         /**
57          * Paint method to override display
58          * @param inG graphics object
59          */
60         public void paint(Graphics inG)
61         {
62                 super.paint(inG);
63                 if (_zoomLevel > -1)
64                 {
65                         try {
66                                 boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
67                                 int rightSide = LEFT_OFFSET + (useMetric?_metricPixels[_zoomLevel]:_milePixels[_zoomLevel]);
68                                 int scale = (useMetric?_metricScales[_zoomLevel]:_mileScales[_zoomLevel]);
69
70                                 // work out cos(latitude) from y tile and zoom, and apply to scale
71                                 final double n = Math.pow(2, _zoomLevel);
72                                 final double angle = Math.PI * (1 - 2.0*_yTile/n);
73                                 final double lat = Math.atan(Math.sinh(angle));
74                                 final double cosLat = Math.cos(lat);
75                                 rightSide = (int) (rightSide / cosLat);
76                                 // Adjust if scale is too large
77                                 while (rightSide > 300)
78                                 {
79                                         rightSide /= 2;
80                                         scale /= 2;
81                                         // Abort if scale is now less than 1 unit (shouldn't ever be)
82                                         if (scale < 1) {return;}
83                                 }
84
85                                 // Determine colours to use
86                                 Color barColour = Config.getColourScheme().getColour(ColourScheme.IDX_TEXT);
87                                 Color blankColour = new Color(255-barColour.getRed(), 255-barColour.getGreen(), 255-barColour.getBlue());
88                                 // Should this blank colour be set to saturation zero?
89                                 // Draw blank bars behind
90                                 inG.setColor(blankColour);
91                                 inG.drawLine(LEFT_OFFSET, Y_OFFSET-1, rightSide+2, Y_OFFSET-1);
92                                 inG.drawLine(LEFT_OFFSET, Y_OFFSET+2, rightSide+2, Y_OFFSET+2);
93                                 inG.drawLine(LEFT_OFFSET-1, Y_OFFSET+2, LEFT_OFFSET-1, Y_OFFSET-TICK_HEIGHT);
94                                 inG.drawLine(LEFT_OFFSET+2, Y_OFFSET+2, LEFT_OFFSET+2, Y_OFFSET-TICK_HEIGHT);
95                                 inG.drawLine(rightSide-1, Y_OFFSET+2, rightSide-1, Y_OFFSET-TICK_HEIGHT);
96                                 inG.drawLine(rightSide+2, Y_OFFSET+2, rightSide+2, Y_OFFSET-TICK_HEIGHT);
97                                 // horizontal
98                                 inG.setColor(barColour);
99                                 inG.drawLine(LEFT_OFFSET, Y_OFFSET, rightSide, Y_OFFSET);
100                                 inG.drawLine(LEFT_OFFSET, Y_OFFSET+1, rightSide, Y_OFFSET+1);
101                                 // 0 tick
102                                 inG.drawLine(LEFT_OFFSET, Y_OFFSET, LEFT_OFFSET, Y_OFFSET-TICK_HEIGHT);
103                                 inG.drawLine(LEFT_OFFSET+1, Y_OFFSET, LEFT_OFFSET+1, Y_OFFSET-TICK_HEIGHT);
104                                 // end tick
105                                 inG.drawLine(rightSide, Y_OFFSET+1, rightSide, Y_OFFSET-TICK_HEIGHT);
106                                 inG.drawLine(rightSide+1, Y_OFFSET+1, rightSide+1, Y_OFFSET-TICK_HEIGHT);
107                                 // text
108                                 String text = (scale>0?(""+scale):("1/"+(-scale))) + " "
109                                         + I18nManager.getText(useMetric?"units.kilometres.short":"units.miles.short");
110                                 inG.setColor(blankColour);
111                                 inG.drawString(text, rightSide+MARGIN_WIDTH-1, Y_OFFSET);
112                                 inG.drawString(text, rightSide+MARGIN_WIDTH+1, Y_OFFSET);
113                                 inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET-1);
114                                 inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET+1);
115                                 inG.setColor(barColour);
116                                 inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET);
117                         }
118                         catch (ArrayIndexOutOfBoundsException ai) {}
119                 }
120         }
121
122         /**
123          * Update the scale level
124          * @param inZoom new zoom level
125          */
126         public void updateScale(int inZoom, int inYtile)
127         {
128                 _zoomLevel = inZoom;
129                 _yTile = inYtile;
130         }
131 }