]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/function/FullRangeDetails.java
338bf0bebbe1e1aef4d0130cf9b5d904b9c1a5c5
[GpsPrune.git] / tim / prune / function / FullRangeDetails.java
1 package tim.prune.function;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.FlowLayout;
6 import java.awt.GridLayout;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.text.NumberFormat;
10
11 import javax.swing.BorderFactory;
12 import javax.swing.JButton;
13 import javax.swing.JDialog;
14 import javax.swing.JLabel;
15 import javax.swing.JPanel;
16
17 import tim.prune.App;
18 import tim.prune.GenericFunction;
19 import tim.prune.I18nManager;
20 import tim.prune.config.Config;
21 import tim.prune.data.Altitude;
22 import tim.prune.data.Distance;
23 import tim.prune.data.Selection;
24 import tim.prune.gui.DisplayUtils;
25 import tim.prune.gui.profile.SpeedData;
26
27 /**
28  * Class to show the full range details in a separate popup
29  */
30 public class FullRangeDetails extends GenericFunction
31 {
32         /** Dialog */
33         private JDialog _dialog = null;
34         /** Label for number of segments */
35         private JLabel _numSegsLabel = null;
36         /** Label for pace */
37         private JLabel _paceLabel = null;
38         /** Label for gradient */
39         private JLabel _gradientLabel = null;
40         /** Moving distance, speed */
41         private JLabel _movingDistanceLabel = null, _aveMovingSpeedLabel = null;
42         private JLabel _maxSpeedLabel = null;
43         /** Number formatter for one decimal place */
44         private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance();
45         /** Flexible number formatter for different decimal places */
46         private NumberFormat _distanceFormatter = NumberFormat.getInstance();
47
48         /**
49          * Constructor
50          * @param inApp App object
51          */
52         public FullRangeDetails(App inApp)
53         {
54                 super(inApp);
55                 FORMAT_ONE_DP.setMaximumFractionDigits(1);
56                 FORMAT_ONE_DP.setMinimumFractionDigits(1);
57         }
58
59         /** Get the name key */
60         public String getNameKey() {
61                 return "function.fullrangedetails";
62         }
63
64         /**
65          * Begin the function
66          */
67         public void begin()
68         {
69                 if (_dialog == null)
70                 {
71                         _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
72                         _dialog.setLocationRelativeTo(_parentFrame);
73                         _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
74                         _dialog.getContentPane().add(makeDialogComponents());
75                         _dialog.pack();
76                 }
77                 updateDetails();
78                 _dialog.setVisible(true);
79         }
80
81         /**
82          * Create dialog components
83          * @return Panel containing all gui elements in dialog
84          */
85         private Component makeDialogComponents()
86         {
87                 JPanel dialogPanel = new JPanel();
88                 dialogPanel.setLayout(new BorderLayout(5, 5));
89                 // Label at top
90                 JLabel topLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro"));
91                 topLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
92                 dialogPanel.add(topLabel, BorderLayout.NORTH);
93
94                 // Details panel in middle
95                 JPanel midPanel = new JPanel();
96                 midPanel.setLayout(new GridLayout(0, 2, 6, 2));
97                 midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
98                 // Number of segments
99                 JLabel segLabel = new JLabel(I18nManager.getText("details.range.numsegments") + ": ");
100                 segLabel.setHorizontalAlignment(JLabel.RIGHT);
101                 midPanel.add(segLabel);
102                 _numSegsLabel = new JLabel("100");
103                 midPanel.add(_numSegsLabel);
104                 // Pace
105                 JLabel paceLabel = new JLabel(I18nManager.getText("details.range.pace") + ": ");
106                 paceLabel.setHorizontalAlignment(JLabel.RIGHT);
107                 midPanel.add(paceLabel);
108                 _paceLabel = new JLabel("8 min/km");
109                 midPanel.add(_paceLabel);
110                 // Gradient
111                 JLabel gradientLabel = new JLabel(I18nManager.getText("details.range.gradient") + ": ");
112                 gradientLabel.setHorizontalAlignment(JLabel.RIGHT);
113                 midPanel.add(gradientLabel);
114                 _gradientLabel = new JLabel("10 %");
115                 midPanel.add(_gradientLabel);
116                 // Moving distance
117                 JLabel movingDistLabel = new JLabel(I18nManager.getText("fieldname.movingdistance") + ": ");
118                 movingDistLabel.setHorizontalAlignment(JLabel.RIGHT);
119                 midPanel.add(movingDistLabel);
120                 _movingDistanceLabel = new JLabel("5 km");
121                 midPanel.add(_movingDistanceLabel);
122                 // Moving speed
123                 JLabel movingSpeedLabel = new JLabel(I18nManager.getText("details.range.avemovingspeed") + ": ");
124                 movingSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
125                 midPanel.add(movingSpeedLabel);
126                 _aveMovingSpeedLabel = new JLabel("5 km/h");
127                 midPanel.add(_aveMovingSpeedLabel);
128                 // Maximum speed
129                 JLabel maxSpeedLabel = new JLabel(I18nManager.getText("details.range.maxspeed") + ": ");
130                 maxSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
131                 midPanel.add(maxSpeedLabel);
132                 _maxSpeedLabel = new JLabel("10 km/h");
133                 midPanel.add(_maxSpeedLabel);
134
135                 dialogPanel.add(midPanel, BorderLayout.CENTER);
136                 // button panel at bottom
137                 JPanel buttonPanel = new JPanel();
138                 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
139                 JButton closeButton = new JButton(I18nManager.getText("button.close"));
140                 closeButton.addActionListener(new ActionListener() {
141                         public void actionPerformed(ActionEvent e)
142                         {
143                                 _dialog.dispose();
144                         }
145                 });
146                 buttonPanel.add(closeButton);
147                 dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
148                 return dialogPanel;
149         }
150
151
152         /**
153          * Update the labels with the current details
154          */
155         private void updateDetails()
156         {
157                 Selection selection = _app.getTrackInfo().getSelection();
158                 // Number of segments
159                 _numSegsLabel.setText("" + selection.getNumSegments());
160                 // Pace value
161                 if (selection.getNumSeconds() > 0)
162                 {
163                         boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
164                         Distance.Units distUnits = useMetric?Distance.Units.KILOMETRES:Distance.Units.MILES;
165                         String distUnitsStr = I18nManager.getText(useMetric?"units.kilometres.short":"units.miles.short");
166                         _paceLabel.setText(DisplayUtils.buildDurationString(
167                                         (long) (selection.getNumSeconds()/selection.getDistance(distUnits)))
168                                 + " / " + distUnitsStr);
169                 }
170                 else {
171                         _paceLabel.setText("");
172                 }
173                 // Gradient
174                 Altitude firstAlt = _app.getTrackInfo().getTrack().getPoint(selection.getStart()).getAltitude();
175                 Altitude lastAlt = _app.getTrackInfo().getTrack().getPoint(selection.getEnd()).getAltitude();
176                 double metreDist = selection.getDistance(Distance.Units.METRES);
177                 if (firstAlt.isValid() && lastAlt.isValid() && metreDist > 0.0)
178                 {
179                         // got an altitude and range
180                         int altDiffInMetres = lastAlt.getValue(Altitude.Format.METRES) - firstAlt.getValue(Altitude.Format.METRES);
181                         double gradient = altDiffInMetres * 100.0 / metreDist;
182                         _gradientLabel.setText(FORMAT_ONE_DP.format(gradient) + " %");
183                 }
184                 else {
185                         // no altitude given
186                         _gradientLabel.setText("");
187                 }
188
189                 // Show moving distance and average even when number of segments is 1
190                 final boolean isMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
191                 final Distance.Units distUnits = isMetric?Distance.Units.KILOMETRES:Distance.Units.MILES;
192                 final String distUnitsStr = I18nManager.getText(isMetric?"units.kilometres.short":"units.miles.short");
193                 final String speedUnitsStr = I18nManager.getText(isMetric?"units.kmh":"units.mph");
194                 // Moving distance
195                 _movingDistanceLabel.setText(roundedNumber(selection.getMovingDistance(distUnits)) + " " + distUnitsStr);
196                 // Moving average speed
197                 long numSecs = selection.getMovingSeconds();
198                 if (numSecs > 0) {
199                         _aveMovingSpeedLabel.setText(roundedNumber(selection.getMovingDistance(distUnits)/numSecs*3600.0)
200                                 + " " + speedUnitsStr);
201                 }
202                 else {
203                         _aveMovingSpeedLabel.setText("");
204                 }
205
206                 // Maximum speed
207                 SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack());
208                 speeds.init();
209                 double maxSpeed = 0.0;
210                 for (int i=selection.getStart(); i<=selection.getEnd(); i++) {
211                         if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) {
212                                 maxSpeed = speeds.getData(i);
213                         }
214                 }
215                 if (maxSpeed > 0.0) {
216                         _maxSpeedLabel.setText(roundedNumber(maxSpeed) + " " + speedUnitsStr);
217                 }
218                 else {
219                         _maxSpeedLabel.setText("");
220                 }
221         }
222
223         /**
224          * Format a number to a sensible precision
225          * @param inDist distance
226          * @return formatted String
227          */
228         private String roundedNumber(double inDist)
229         {
230                 // Set precision of formatter
231                 int numDigits = 0;
232                 if (inDist < 1.0)
233                         numDigits = 3;
234                 else if (inDist < 10.0)
235                         numDigits = 2;
236                 else if (inDist < 100.0)
237                         numDigits = 1;
238                 // set formatter
239                 _distanceFormatter.setMaximumFractionDigits(numDigits);
240                 _distanceFormatter.setMinimumFractionDigits(numDigits);
241                 return _distanceFormatter.format(inDist);
242         }
243 }