1 package tim.prune.function;
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.awt.event.KeyAdapter;
10 import java.awt.event.KeyEvent;
12 import javax.swing.BorderFactory;
13 import javax.swing.JButton;
14 import javax.swing.JDialog;
15 import javax.swing.JLabel;
16 import javax.swing.JPanel;
19 import tim.prune.GenericFunction;
20 import tim.prune.I18nManager;
21 import tim.prune.config.Config;
22 import tim.prune.data.RangeStats;
23 import tim.prune.data.Selection;
24 import tim.prune.data.Unit;
25 import tim.prune.gui.DisplayUtils;
26 import tim.prune.gui.profile.SpeedData;
29 * Class to show the full range details in a separate popup
31 public class FullRangeDetails extends GenericFunction
34 private JDialog _dialog = null;
35 /** Label for number of points */
36 private JLabel _numPointsLabel = null;
37 /** Label for number of segments */
38 private JLabel _numSegsLabel = null;
39 /** Label for the maximum speed */
40 private JLabel _maxSpeedLabel = null;
42 /** Label for heading of "total" column */
43 private JLabel _colTotalLabel = null;
44 /** Label for heading of "segments" column */
45 private JLabel _colSegmentsLabel = null;
46 /** Labels for distances */
47 private JLabel _totalDistanceLabel = null, _movingDistanceLabel = null;
48 /** Labels for durations */
49 private JLabel _totalDurationLabel = null, _movingDurationLabel = null;
50 /** Labels for climbs */
51 private JLabel _totalClimbLabel = null, _movingClimbLabel = null;
52 /** Labels for descents */
53 private JLabel _totalDescentLabel = null, _movingDescentLabel = null;
54 /** Labels for pace */
55 private JLabel _totalPaceLabel = null, _movingPaceLabel = null;
56 /** Labels for gradient */
57 private JLabel _totalGradientLabel = null, _movingGradientLabel = null;
58 /** Labels for speed */
59 private JLabel _totalSpeedLabel, _movingSpeedLabel = null;
60 /** Labels for vertical speed */
61 private JLabel _totalVertSpeedLabel, _movingVertSpeedLabel = null;
66 * @param inApp App object
68 public FullRangeDetails(App inApp)
73 /** Get the name key */
74 public String getNameKey() {
75 return "function.fullrangedetails";
85 _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
86 _dialog.setLocationRelativeTo(_parentFrame);
87 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
88 _dialog.getContentPane().add(makeDialogComponents());
92 _dialog.setVisible(true);
96 * Create dialog components
97 * @return Panel containing all gui elements in dialog
99 private Component makeDialogComponents()
101 JPanel dialogPanel = new JPanel();
102 dialogPanel.setLayout(new BorderLayout(5, 5));
104 JLabel topLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro") + ":");
105 topLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
106 dialogPanel.add(topLabel, BorderLayout.NORTH);
108 // Details panel in middle
109 JPanel midPanel = new JPanel();
110 midPanel.setLayout(new GridLayout(0, 3, 6, 2));
111 midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
113 JLabel pointsLabel = new JLabel(I18nManager.getText("details.track.points") + ": ");
114 pointsLabel.setHorizontalAlignment(JLabel.RIGHT);
115 midPanel.add(pointsLabel);
116 _numPointsLabel = new JLabel("100");
117 midPanel.add(_numPointsLabel);
118 midPanel.add(new JLabel(" "));
119 // Number of segments
120 JLabel segLabel = new JLabel(I18nManager.getText("details.range.numsegments") + ": ");
121 segLabel.setHorizontalAlignment(JLabel.RIGHT);
122 midPanel.add(segLabel);
123 _numSegsLabel = new JLabel("100");
124 midPanel.add(_numSegsLabel);
125 midPanel.add(new JLabel(" "));
127 JLabel maxSpeedLabel = new JLabel(I18nManager.getText("details.range.maxspeed") + ": ");
128 maxSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
129 midPanel.add(maxSpeedLabel);
130 _maxSpeedLabel = new JLabel("10 km/h");
131 midPanel.add(_maxSpeedLabel);
132 midPanel.add(new JLabel(" "));
135 for (int i=0; i<3; i++) midPanel.add(new JLabel(" "));
137 // Row for column headings
138 midPanel.add(new JLabel(" "));
139 _colTotalLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.coltotal"));
140 midPanel.add(_colTotalLabel);
141 _colSegmentsLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.colsegments"));
142 midPanel.add(_colSegmentsLabel);
145 JLabel distLabel = new JLabel(I18nManager.getText("fieldname.distance") + ": ");
146 distLabel.setHorizontalAlignment(JLabel.RIGHT);
147 midPanel.add(distLabel);
148 _totalDistanceLabel = new JLabel("5 km");
149 midPanel.add(_totalDistanceLabel);
150 _movingDistanceLabel = new JLabel("5 km");
151 midPanel.add(_movingDistanceLabel);
154 JLabel durationLabel = new JLabel(I18nManager.getText("fieldname.duration") + ": ");
155 durationLabel.setHorizontalAlignment(JLabel.RIGHT);
156 midPanel.add(durationLabel);
157 _totalDurationLabel = new JLabel("15 min");
158 midPanel.add(_totalDurationLabel);
159 _movingDurationLabel = new JLabel("15 min");
160 midPanel.add(_movingDurationLabel);
163 JLabel speedLabel = new JLabel(I18nManager.getText("details.range.avespeed") + ": ");
164 speedLabel.setHorizontalAlignment(JLabel.RIGHT);
165 midPanel.add(speedLabel);
166 _totalSpeedLabel = new JLabel("5.5 km/h");
167 midPanel.add(_totalSpeedLabel);
168 _movingSpeedLabel = new JLabel("5.5 km/h");
169 midPanel.add(_movingSpeedLabel);
172 JLabel paceLabel = new JLabel(I18nManager.getText("details.range.pace") + ": ");
173 paceLabel.setHorizontalAlignment(JLabel.RIGHT);
174 midPanel.add(paceLabel);
175 _totalPaceLabel = new JLabel("8 min/km");
176 midPanel.add(_totalPaceLabel);
177 _movingPaceLabel = new JLabel("8 min/km");
178 midPanel.add(_movingPaceLabel);
181 JLabel climbLabel = new JLabel(I18nManager.getText("details.range.climb") + ": ");
182 climbLabel.setHorizontalAlignment(JLabel.RIGHT);
183 midPanel.add(climbLabel);
184 _totalClimbLabel = new JLabel("1000 m");
185 midPanel.add(_totalClimbLabel);
186 _movingClimbLabel = new JLabel("1000 m");
187 midPanel.add(_movingClimbLabel);
189 JLabel descentLabel = new JLabel(I18nManager.getText("details.range.descent") + ": ");
190 descentLabel.setHorizontalAlignment(JLabel.RIGHT);
191 midPanel.add(descentLabel);
192 _totalDescentLabel = new JLabel("1000 m");
193 midPanel.add(_totalDescentLabel);
194 _movingDescentLabel = new JLabel("1000 m");
195 midPanel.add(_movingDescentLabel);
198 JLabel gradientLabel = new JLabel(I18nManager.getText("details.range.gradient") + ": ");
199 gradientLabel.setHorizontalAlignment(JLabel.RIGHT);
200 midPanel.add(gradientLabel);
201 _totalGradientLabel = new JLabel("10 %");
202 midPanel.add(_totalGradientLabel);
203 _movingGradientLabel = new JLabel("10 %");
204 midPanel.add(_movingGradientLabel);
207 JLabel vSpeedLabel = new JLabel(I18nManager.getText("fieldname.verticalspeed") + ": ");
208 vSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
209 midPanel.add(vSpeedLabel);
210 _totalVertSpeedLabel = new JLabel("1 m/s");
211 midPanel.add(_totalVertSpeedLabel);
212 _movingVertSpeedLabel = new JLabel("1 m/s");
213 midPanel.add(_movingVertSpeedLabel);
215 dialogPanel.add(midPanel, BorderLayout.CENTER);
216 // button panel at bottom
217 JPanel buttonPanel = new JPanel();
218 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
219 JButton closeButton = new JButton(I18nManager.getText("button.close"));
220 closeButton.addActionListener(new ActionListener() {
221 public void actionPerformed(ActionEvent e)
226 closeButton.addKeyListener(new KeyAdapter() {
227 public void keyPressed(KeyEvent inE) {
228 if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
229 super.keyPressed(inE);
232 buttonPanel.add(closeButton);
233 dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
239 * Update the labels with the current details
241 private void updateDetails()
243 Selection selection = _app.getTrackInfo().getSelection();
244 // Do the calculations with a separate class
245 RangeStats stats = new RangeStats(_app.getTrackInfo().getTrack(), selection.getStart(), selection.getEnd());
248 _numPointsLabel.setText("" + stats.getNumPoints());
249 // Number of segments
250 _numSegsLabel.setText("" + stats.getNumSegments());
251 final boolean isMultiSegments = (stats.getNumSegments() > 1);
252 // Set visibility of third column accordingly
253 _movingDistanceLabel.setVisible(isMultiSegments);
254 _movingDurationLabel.setVisible(isMultiSegments || stats.getTimestampsOutOfSequence());
255 // FIXME: What to show if timestamps are out of sequence? Warning message?
256 _movingClimbLabel.setVisible(isMultiSegments);
257 _movingDescentLabel.setVisible(isMultiSegments);
258 _movingSpeedLabel.setVisible(isMultiSegments);
259 _movingPaceLabel.setVisible(isMultiSegments);
260 _movingGradientLabel.setVisible(isMultiSegments);
261 _movingVertSpeedLabel.setVisible(isMultiSegments);
263 // Total and moving distance in current units
264 final Unit distUnit = Config.getUnitSet().getDistanceUnit();
265 final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey());
266 _totalDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getTotalDistance()) + " " + distUnitsStr);
267 _movingDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getMovingDistance()) + " " + distUnitsStr);
270 _totalDurationLabel.setText(DisplayUtils.buildDurationString(stats.getTotalDurationInSeconds()));
271 _movingDurationLabel.setText(DisplayUtils.buildDurationString(stats.getMovingDurationInSeconds()));
274 final Unit altUnit = Config.getUnitSet().getAltitudeUnit();
275 final String altUnitsStr = " " + I18nManager.getText(altUnit.getShortnameKey());
276 if (stats.getTotalAltitudeRange().hasRange()) {
277 _totalClimbLabel.setText(stats.getTotalAltitudeRange().getClimb(altUnit) + altUnitsStr);
278 _totalDescentLabel.setText(stats.getTotalAltitudeRange().getDescent(altUnit) + altUnitsStr);
281 _totalClimbLabel.setText("");
282 _totalDescentLabel.setText("");
284 if (stats.getMovingAltitudeRange().hasRange()) {
285 _movingClimbLabel.setText(stats.getMovingAltitudeRange().getClimb(altUnit) + altUnitsStr);
286 _movingDescentLabel.setText(stats.getMovingAltitudeRange().getDescent(altUnit) + altUnitsStr);
289 _movingClimbLabel.setText("");
290 _movingDescentLabel.setText("");
293 // Overall pace and speed
294 final String speedUnitsStr = I18nManager.getText(Config.getUnitSet().getSpeedUnit().getShortnameKey());
295 long numSecs = stats.getTotalDurationInSeconds();
296 double dist = stats.getTotalDistance();
297 if (numSecs > 0 && dist > 0)
299 _totalSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr);
300 _totalPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist))
301 + " / " + distUnitsStr);
304 _totalSpeedLabel.setText("");
305 _totalPaceLabel.setText("");
307 // and same for within the segments
308 numSecs = stats.getMovingDurationInSeconds();
309 dist = stats.getMovingDistance();
310 if (numSecs > 0 && dist > 0)
312 _movingSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr);
313 _movingPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist))
314 + " / " + distUnitsStr);
317 _movingSpeedLabel.setText("");
318 _movingPaceLabel.setText("");
322 if (stats.getTotalAltitudeRange().hasRange()) {
323 _totalGradientLabel.setText(DisplayUtils.formatOneDp(stats.getTotalGradient()) + " %");
326 _totalGradientLabel.setText("");
328 if (stats.getMovingAltitudeRange().hasRange()) {
329 _movingGradientLabel.setText(DisplayUtils.formatOneDp(stats.getMovingGradient()) + " %");
332 _movingGradientLabel.setText("");
336 SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack());
337 speeds.init(Config.getUnitSet());
338 double maxSpeed = 0.0;
339 for (int i=selection.getStart(); i<=selection.getEnd(); i++)
341 if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) {
342 maxSpeed = speeds.getData(i);
345 if (maxSpeed > 0.0) {
346 _maxSpeedLabel.setText(DisplayUtils.roundedNumber(maxSpeed) + " " + speedUnitsStr);
349 _maxSpeedLabel.setText("");
353 final String vertSpeedUnitsStr = I18nManager.getText(Config.getUnitSet().getVerticalSpeedUnit().getShortnameKey());
354 if (stats.getMovingAltitudeRange().hasRange() && stats.getTotalDurationInSeconds() > 0)
356 // got an altitude and time - do totals
357 _totalVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getTotalVerticalSpeed()) + " " + vertSpeedUnitsStr);
358 _movingVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getMovingVerticalSpeed()) + " " + vertSpeedUnitsStr);
362 // no vertical speed available
363 _totalVertSpeedLabel.setText("");
364 _movingVertSpeedLabel.setText("");