X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=tim%2Fprune%2Ffunction%2FFullRangeDetails.java;h=07ef39e36a1151d06af5b4f2238857c278bc7d44;hb=326f489e36aa7f235bc19409a57bf4955cd50f24;hp=ed86ef90ec54e75e7da713bd87f6424e8f051d66;hpb=1ee49ae3c8ef3aa2e63eadd458531e5f8bd4f92c;p=GpsPrune.git diff --git a/tim/prune/function/FullRangeDetails.java b/tim/prune/function/FullRangeDetails.java index ed86ef9..07ef39e 100644 --- a/tim/prune/function/FullRangeDetails.java +++ b/tim/prune/function/FullRangeDetails.java @@ -6,7 +6,8 @@ import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.text.NumberFormat; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import javax.swing.BorderFactory; import javax.swing.JButton; @@ -18,10 +19,11 @@ import tim.prune.App; import tim.prune.GenericFunction; import tim.prune.I18nManager; import tim.prune.config.Config; -import tim.prune.data.Altitude; -import tim.prune.data.Distance; +import tim.prune.data.RangeStats; import tim.prune.data.Selection; +import tim.prune.data.Unit; import tim.prune.gui.DisplayUtils; +import tim.prune.gui.profile.SpeedData; /** * Class to show the full range details in a separate popup @@ -30,18 +32,34 @@ public class FullRangeDetails extends GenericFunction { /** Dialog */ private JDialog _dialog = null; + /** Label for number of points */ + private JLabel _numPointsLabel = null; /** Label for number of segments */ private JLabel _numSegsLabel = null; - /** Label for pace */ - private JLabel _paceLabel = null; - /** Label for gradient */ - private JLabel _gradientLabel = null; - /** Moving distance, speed */ - private JLabel _movingDistanceLabel = null, _aveMovingSpeedLabel = null; - /** Number formatter for one decimal place */ - private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance(); - /** Flexible number formatter for different decimal places */ - private NumberFormat _distanceFormatter = NumberFormat.getInstance(); + /** Label for the maximum speed */ + private JLabel _maxSpeedLabel = null; + + /** Label for heading of "total" column */ + private JLabel _colTotalLabel = null; + /** Label for heading of "segments" column */ + private JLabel _colSegmentsLabel = null; + /** Labels for distances */ + private JLabel _totalDistanceLabel = null, _movingDistanceLabel = null; + /** Labels for durations */ + private JLabel _totalDurationLabel = null, _movingDurationLabel = null; + /** Labels for climbs */ + private JLabel _totalClimbLabel = null, _movingClimbLabel = null; + /** Labels for descents */ + private JLabel _totalDescentLabel = null, _movingDescentLabel = null; + /** Labels for pace */ + private JLabel _totalPaceLabel = null, _movingPaceLabel = null; + /** Labels for gradient */ + private JLabel _totalGradientLabel = null, _movingGradientLabel = null; + /** Labels for speed */ + private JLabel _totalSpeedLabel, _movingSpeedLabel = null; + /** Labels for vertical speed */ + private JLabel _totalVertSpeedLabel, _movingVertSpeedLabel = null; + /** * Constructor @@ -50,8 +68,6 @@ public class FullRangeDetails extends GenericFunction public FullRangeDetails(App inApp) { super(inApp); - FORMAT_ONE_DP.setMaximumFractionDigits(1); - FORMAT_ONE_DP.setMinimumFractionDigits(1); } /** Get the name key */ @@ -85,44 +101,116 @@ public class FullRangeDetails extends GenericFunction JPanel dialogPanel = new JPanel(); dialogPanel.setLayout(new BorderLayout(5, 5)); // Label at top - JLabel topLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro")); + JLabel topLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro") + ":"); topLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); dialogPanel.add(topLabel, BorderLayout.NORTH); // Details panel in middle JPanel midPanel = new JPanel(); - midPanel.setLayout(new GridLayout(0, 2, 6, 2)); + midPanel.setLayout(new GridLayout(0, 3, 6, 2)); midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15)); + // Number of points + JLabel pointsLabel = new JLabel(I18nManager.getText("details.track.points") + ": "); + pointsLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(pointsLabel); + _numPointsLabel = new JLabel("100"); + midPanel.add(_numPointsLabel); + midPanel.add(new JLabel(" ")); // Number of segments JLabel segLabel = new JLabel(I18nManager.getText("details.range.numsegments") + ": "); segLabel.setHorizontalAlignment(JLabel.RIGHT); midPanel.add(segLabel); _numSegsLabel = new JLabel("100"); midPanel.add(_numSegsLabel); + midPanel.add(new JLabel(" ")); + // Maximum speed + JLabel maxSpeedLabel = new JLabel(I18nManager.getText("details.range.maxspeed") + ": "); + maxSpeedLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(maxSpeedLabel); + _maxSpeedLabel = new JLabel("10 km/h"); + midPanel.add(_maxSpeedLabel); + midPanel.add(new JLabel(" ")); + + // blank row + for (int i=0; i<3; i++) midPanel.add(new JLabel(" ")); + + // Row for column headings + midPanel.add(new JLabel(" ")); + _colTotalLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.coltotal")); + midPanel.add(_colTotalLabel); + _colSegmentsLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.colsegments")); + midPanel.add(_colSegmentsLabel); + + // Distance + JLabel distLabel = new JLabel(I18nManager.getText("fieldname.distance") + ": "); + distLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(distLabel); + _totalDistanceLabel = new JLabel("5 km"); + midPanel.add(_totalDistanceLabel); + _movingDistanceLabel = new JLabel("5 km"); + midPanel.add(_movingDistanceLabel); + + // Duration + JLabel durationLabel = new JLabel(I18nManager.getText("fieldname.duration") + ": "); + durationLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(durationLabel); + _totalDurationLabel = new JLabel("15 min"); + midPanel.add(_totalDurationLabel); + _movingDurationLabel = new JLabel("15 min"); + midPanel.add(_movingDurationLabel); + + // Speed + JLabel speedLabel = new JLabel(I18nManager.getText("details.range.avespeed") + ": "); + speedLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(speedLabel); + _totalSpeedLabel = new JLabel("5.5 km/h"); + midPanel.add(_totalSpeedLabel); + _movingSpeedLabel = new JLabel("5.5 km/h"); + midPanel.add(_movingSpeedLabel); + // Pace JLabel paceLabel = new JLabel(I18nManager.getText("details.range.pace") + ": "); paceLabel.setHorizontalAlignment(JLabel.RIGHT); midPanel.add(paceLabel); - _paceLabel = new JLabel("8 min/km"); - midPanel.add(_paceLabel); + _totalPaceLabel = new JLabel("8 min/km"); + midPanel.add(_totalPaceLabel); + _movingPaceLabel = new JLabel("8 min/km"); + midPanel.add(_movingPaceLabel); + + // Climb + JLabel climbLabel = new JLabel(I18nManager.getText("details.range.climb") + ": "); + climbLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(climbLabel); + _totalClimbLabel = new JLabel("1000 m"); + midPanel.add(_totalClimbLabel); + _movingClimbLabel = new JLabel("1000 m"); + midPanel.add(_movingClimbLabel); + // Descent + JLabel descentLabel = new JLabel(I18nManager.getText("details.range.descent") + ": "); + descentLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(descentLabel); + _totalDescentLabel = new JLabel("1000 m"); + midPanel.add(_totalDescentLabel); + _movingDescentLabel = new JLabel("1000 m"); + midPanel.add(_movingDescentLabel); + // Gradient JLabel gradientLabel = new JLabel(I18nManager.getText("details.range.gradient") + ": "); gradientLabel.setHorizontalAlignment(JLabel.RIGHT); midPanel.add(gradientLabel); - _gradientLabel = new JLabel("10 %"); - midPanel.add(_gradientLabel); - // Moving distance - JLabel movingDistLabel = new JLabel(I18nManager.getText("fieldname.movingdistance") + ": "); - movingDistLabel.setHorizontalAlignment(JLabel.RIGHT); - midPanel.add(movingDistLabel); - _movingDistanceLabel = new JLabel("5 km"); - midPanel.add(_movingDistanceLabel); - // Moving speed - JLabel movingSpeedLabel = new JLabel(I18nManager.getText("details.range.avemovingspeed") + ": "); - movingSpeedLabel.setHorizontalAlignment(JLabel.RIGHT); - midPanel.add(movingSpeedLabel); - _aveMovingSpeedLabel = new JLabel("5 km/h"); - midPanel.add(_aveMovingSpeedLabel); + _totalGradientLabel = new JLabel("10 %"); + midPanel.add(_totalGradientLabel); + _movingGradientLabel = new JLabel("10 %"); + midPanel.add(_movingGradientLabel); + + // Vertical speed + JLabel vSpeedLabel = new JLabel(I18nManager.getText("fieldname.verticalspeed") + ": "); + vSpeedLabel.setHorizontalAlignment(JLabel.RIGHT); + midPanel.add(vSpeedLabel); + _totalVertSpeedLabel = new JLabel("1 m/s"); + midPanel.add(_totalVertSpeedLabel); + _movingVertSpeedLabel = new JLabel("1 m/s"); + midPanel.add(_movingVertSpeedLabel); dialogPanel.add(midPanel, BorderLayout.CENTER); // button panel at bottom @@ -135,6 +223,12 @@ public class FullRangeDetails extends GenericFunction _dialog.dispose(); } }); + closeButton.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent inE) { + if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();} + super.keyPressed(inE); + } + }); buttonPanel.add(closeButton); dialogPanel.add(buttonPanel, BorderLayout.SOUTH); return dialogPanel; @@ -147,73 +241,127 @@ public class FullRangeDetails extends GenericFunction private void updateDetails() { Selection selection = _app.getTrackInfo().getSelection(); + // Do the calculations with a separate class + RangeStats stats = new RangeStats(_app.getTrackInfo().getTrack(), selection.getStart(), selection.getEnd()); + + // Number of points + _numPointsLabel.setText("" + stats.getNumPoints()); // Number of segments - _numSegsLabel.setText("" + selection.getNumSegments()); - // Pace value - if (selection.getNumSeconds() > 0) + _numSegsLabel.setText("" + stats.getNumSegments()); + final boolean isMultiSegments = (stats.getNumSegments() > 1); + // Set visibility of third column accordingly + _movingDistanceLabel.setVisible(isMultiSegments); + _movingDurationLabel.setVisible(isMultiSegments || stats.getTimestampsOutOfSequence()); + // FIXME: What to show if timestamps are out of sequence? Warning message? + _movingClimbLabel.setVisible(isMultiSegments); + _movingDescentLabel.setVisible(isMultiSegments); + _movingSpeedLabel.setVisible(isMultiSegments); + _movingPaceLabel.setVisible(isMultiSegments); + _movingGradientLabel.setVisible(isMultiSegments); + _movingVertSpeedLabel.setVisible(isMultiSegments); + + // Total and moving distance in current units + final Unit distUnit = Config.getUnitSet().getDistanceUnit(); + final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey()); + _totalDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getTotalDistance()) + " " + distUnitsStr); + _movingDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getMovingDistance()) + " " + distUnitsStr); + + // Duration + _totalDurationLabel.setText(DisplayUtils.buildDurationString(stats.getTotalDurationInSeconds())); + _movingDurationLabel.setText(DisplayUtils.buildDurationString(stats.getMovingDurationInSeconds())); + + // Climb and descent + final Unit altUnit = Config.getUnitSet().getAltitudeUnit(); + final String altUnitsStr = " " + I18nManager.getText(altUnit.getShortnameKey()); + if (stats.getTotalAltitudeRange().hasRange()) { + _totalClimbLabel.setText(stats.getTotalAltitudeRange().getClimb(altUnit) + altUnitsStr); + _totalDescentLabel.setText(stats.getTotalAltitudeRange().getDescent(altUnit) + altUnitsStr); + } + else { + _totalClimbLabel.setText(""); + _totalDescentLabel.setText(""); + } + if (stats.getMovingAltitudeRange().hasRange()) { + _movingClimbLabel.setText(stats.getMovingAltitudeRange().getClimb(altUnit) + altUnitsStr); + _movingDescentLabel.setText(stats.getMovingAltitudeRange().getDescent(altUnit) + altUnitsStr); + } + else { + _movingClimbLabel.setText(""); + _movingDescentLabel.setText(""); + } + + // Overall pace and speed + final String speedUnitsStr = I18nManager.getText(Config.getUnitSet().getSpeedUnit().getShortnameKey()); + long numSecs = stats.getTotalDurationInSeconds(); + double dist = stats.getTotalDistance(); + if (numSecs > 0 && dist > 0) { - boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS); - Distance.Units distUnits = useMetric?Distance.Units.KILOMETRES:Distance.Units.MILES; - String distUnitsStr = I18nManager.getText(useMetric?"units.kilometres.short":"units.miles.short"); - _paceLabel.setText(DisplayUtils.buildDurationString( - (long) (selection.getNumSeconds()/selection.getDistance(distUnits))) + _totalSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr); + _totalPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist)) + " / " + distUnitsStr); } else { - _paceLabel.setText(""); + _totalSpeedLabel.setText(""); + _totalPaceLabel.setText(""); } - // Gradient - Altitude firstAlt = _app.getTrackInfo().getTrack().getPoint(selection.getStart()).getAltitude(); - Altitude lastAlt = _app.getTrackInfo().getTrack().getPoint(selection.getEnd()).getAltitude(); - double metreDist = selection.getDistance(Distance.Units.METRES); - if (firstAlt.isValid() && lastAlt.isValid() && metreDist > 0.0) + // and same for within the segments + numSecs = stats.getMovingDurationInSeconds(); + dist = stats.getMovingDistance(); + if (numSecs > 0 && dist > 0) { - // got an altitude and range - int altDiffInMetres = lastAlt.getValue(Altitude.Format.METRES) - firstAlt.getValue(Altitude.Format.METRES); - double gradient = altDiffInMetres * 100.0 / metreDist; - _gradientLabel.setText(FORMAT_ONE_DP.format(gradient) + " %"); + _movingSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr); + _movingPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist)) + + " / " + distUnitsStr); } else { - // no altitude given - _gradientLabel.setText(""); - } - - // Show moving distance and average even when number of segments is 1 - final boolean isMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS); - final Distance.Units distUnits = isMetric?Distance.Units.KILOMETRES:Distance.Units.MILES; - final String distUnitsStr = I18nManager.getText(isMetric?"units.kilometres.short":"units.miles.short"); - final String speedUnitsStr = I18nManager.getText(isMetric?"units.kmh":"units.mph"); - // Moving distance - _movingDistanceLabel.setText(roundedNumber(selection.getMovingDistance(distUnits)) + " " + distUnitsStr); - // Moving average speed - long numSecs = selection.getMovingSeconds(); - if (numSecs > 0) { - _aveMovingSpeedLabel.setText(roundedNumber(selection.getMovingDistance(distUnits)/numSecs*3600.0) - + " " + speedUnitsStr); + _movingSpeedLabel.setText(""); + _movingPaceLabel.setText(""); + } + + // Gradient + if (stats.getTotalAltitudeRange().hasRange()) { + _totalGradientLabel.setText(DisplayUtils.formatOneDp(stats.getTotalGradient()) + " %"); } else { - _aveMovingSpeedLabel.setText(""); + _totalGradientLabel.setText(""); + } + if (stats.getMovingAltitudeRange().hasRange()) { + _movingGradientLabel.setText(DisplayUtils.formatOneDp(stats.getMovingGradient()) + " %"); + } + else { + _movingGradientLabel.setText(""); } - } - /** - * Format a number to a sensible precision - * @param inDist distance - * @return formatted String - */ - private String roundedNumber(double inDist) - { - // Set precision of formatter - int numDigits = 0; - if (inDist < 1.0) - numDigits = 3; - else if (inDist < 10.0) - numDigits = 2; - else if (inDist < 100.0) - numDigits = 1; - // set formatter - _distanceFormatter.setMaximumFractionDigits(numDigits); - _distanceFormatter.setMinimumFractionDigits(numDigits); - return _distanceFormatter.format(inDist); + // Maximum speed + SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack()); + speeds.init(Config.getUnitSet()); + double maxSpeed = 0.0; + for (int i=selection.getStart(); i<=selection.getEnd(); i++) + { + if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) { + maxSpeed = speeds.getData(i); + } + } + if (maxSpeed > 0.0) { + _maxSpeedLabel.setText(DisplayUtils.roundedNumber(maxSpeed) + " " + speedUnitsStr); + } + else { + _maxSpeedLabel.setText(""); + } + + // vertical speed + final String vertSpeedUnitsStr = I18nManager.getText(Config.getUnitSet().getVerticalSpeedUnit().getShortnameKey()); + if (stats.getMovingAltitudeRange().hasRange() && stats.getTotalDurationInSeconds() > 0) + { + // got an altitude and time - do totals + _totalVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getTotalVerticalSpeed()) + " " + vertSpeedUnitsStr); + _movingVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getMovingVerticalSpeed()) + " " + vertSpeedUnitsStr); + } + else + { + // no vertical speed available + _totalVertSpeedLabel.setText(""); + _movingVertSpeedLabel.setText(""); + } } }