package tim.prune.function; import java.awt.BorderLayout; import java.awt.Component; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import tim.prune.App; import tim.prune.GenericFunction; import tim.prune.I18nManager; import tim.prune.config.Config; 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 */ 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 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 * @param inApp App object */ public FullRangeDetails(App inApp) { super(inApp); } /** Get the name key */ public String getNameKey() { return "function.fullrangedetails"; } /** * Begin the function */ public void begin() { if (_dialog == null) { _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true); _dialog.setLocationRelativeTo(_parentFrame); _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); _dialog.getContentPane().add(makeDialogComponents()); _dialog.pack(); } updateDetails(); _dialog.setVisible(true); } /** * Create dialog components * @return Panel containing all gui elements in dialog */ private Component makeDialogComponents() { JPanel dialogPanel = new JPanel(); dialogPanel.setLayout(new BorderLayout(5, 5)); // Label at top 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, 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); _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); _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 JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); JButton closeButton = new JButton(I18nManager.getText("button.close")); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { _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; } /** * Update the labels with the current details */ 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("" + 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) { _totalSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr); _totalPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist)) + " / " + distUnitsStr); } else { _totalSpeedLabel.setText(""); _totalPaceLabel.setText(""); } // and same for within the segments numSecs = stats.getMovingDurationInSeconds(); dist = stats.getMovingDistance(); if (numSecs > 0 && dist > 0) { _movingSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr); _movingPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist)) + " / " + distUnitsStr); } else { _movingSpeedLabel.setText(""); _movingPaceLabel.setText(""); } // Gradient if (stats.getTotalAltitudeRange().hasRange()) { _totalGradientLabel.setText(DisplayUtils.formatOneDp(stats.getTotalGradient()) + " %"); } else { _totalGradientLabel.setText(""); } if (stats.getMovingAltitudeRange().hasRange()) { _movingGradientLabel.setText(DisplayUtils.formatOneDp(stats.getMovingGradient()) + " %"); } else { _movingGradientLabel.setText(""); } // 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(""); } } }