+++ /dev/null
-package tim.prune.function.estimate;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.Font;
-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.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.SwingUtilities;
-
-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.DecimalNumberField;
-import tim.prune.gui.DisplayUtils;
-import tim.prune.gui.GuiGridLayout;
-import tim.prune.tips.TipManager;
-
-/**
- * Class to calculate and show the results of estimating (hike) time for the current range
- */
-public class EstimateTime extends GenericFunction
-{
- /** Dialog */
- private JDialog _dialog = null;
- /** Labels for distances */
- private JLabel _distanceLabel = null;
- /** Labels for durations */
- private JLabel _estimatedDurationLabel = null, _actualDurationLabel = null;
- /** Labels for climbs */
- private JLabel _gentleClimbLabel = null, _steepClimbLabel = null;
- /** Labels for descents */
- private JLabel _gentleDescentLabel = null, _steepDescentLabel = null;
- /** Labels and text fields for parameters */
- private JLabel _flatSpeedLabel = null;
- private DecimalNumberField _flatSpeedField = null;
- private JLabel _climbParamLabel = null;
- private DecimalNumberField _gentleClimbField = null, _steepClimbField = null;
- private JLabel _descentParamLabel = null;
- private DecimalNumberField _gentleDescentField = null, _steepDescentField = null;
- /** Range stats */
- private RangeStats _stats = null;
-
-
- /**
- * Constructor
- * @param inApp App object
- */
- public EstimateTime(App inApp)
- {
- super(inApp);
- }
-
- /** Get the name key */
- public String getNameKey() {
- return "function.estimatetime";
- }
-
- /**
- * Begin the function
- */
- public void begin()
- {
- // Get the stats on the selection before launching the dialog
- Selection selection = _app.getTrackInfo().getSelection();
- _stats = new RangeStats(_app.getTrackInfo().getTrack(), selection.getStart(), selection.getEnd());
-
- if (_stats.getMovingDistance() < 0.01)
- {
- _app.showErrorMessage(getNameKey(), "dialog.estimatetime.error.nodistance");
- return;
- }
- if (_dialog == null)
- {
- // First time in, check whether params are at default, show tip message if unaltered
- showTip();
- _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));
-
- // main panel with a box layout
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- // Label at top
- JLabel introLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro") + ":");
- introLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
- introLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
- mainPanel.add(introLabel);
- mainPanel.add(Box.createVerticalStrut(4));
-
- // Details panel in a grid
- JPanel detailsPanel = new JPanel();
- detailsPanel.setLayout(new GridLayout(0, 4, 6, 2));
- detailsPanel.setBorder(BorderFactory.createTitledBorder(
- I18nManager.getText("dialog.estimatetime.details")));
-
- // Distance
- JLabel distLabel = new JLabel(I18nManager.getText("fieldname.distance") + ": ");
- distLabel.setHorizontalAlignment(JLabel.RIGHT);
- detailsPanel.add(distLabel);
- _distanceLabel = new JLabel("5 km");
- detailsPanel.add(_distanceLabel);
- detailsPanel.add(new JLabel("")); detailsPanel.add(new JLabel("")); // two blank cells
-
- detailsPanel.add(new JLabel(""));
- detailsPanel.add(new JLabel(I18nManager.getText("dialog.estimatetime.gentle")));
- detailsPanel.add(new JLabel(I18nManager.getText("dialog.estimatetime.steep")));
- detailsPanel.add(new JLabel("")); // blank cells
-
- // Climb
- JLabel climbLabel = new JLabel(I18nManager.getText("dialog.estimatetime.climb") + ": ");
- climbLabel.setHorizontalAlignment(JLabel.RIGHT);
- detailsPanel.add(climbLabel);
- _gentleClimbLabel = new JLabel("1500 m");
- detailsPanel.add(_gentleClimbLabel);
- _steepClimbLabel = new JLabel("1500 m");
- detailsPanel.add(_steepClimbLabel);
- detailsPanel.add(new JLabel(""));
-
- // Descent
- JLabel descentLabel = new JLabel(I18nManager.getText("dialog.estimatetime.descent") + ": ");
- descentLabel.setHorizontalAlignment(JLabel.RIGHT);
- detailsPanel.add(descentLabel);
- _gentleDescentLabel = new JLabel("1500 m");
- detailsPanel.add(_gentleDescentLabel);
- _steepDescentLabel = new JLabel("1500 m");
- detailsPanel.add(_steepDescentLabel);
- detailsPanel.add(new JLabel(""));
-
- detailsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- mainPanel.add(detailsPanel);
- mainPanel.add(Box.createVerticalStrut(4));
-
- // Parameters panel in a flexible grid
- JPanel paramsPanel = new JPanel();
- GuiGridLayout paramsGrid = new GuiGridLayout(paramsPanel, new double[] {1.5, 0.2, 1.0, 0.2, 0.5},
- new boolean[] {true, false, false, false, false});
- paramsPanel.setBorder(BorderFactory.createTitledBorder(
- I18nManager.getText("dialog.estimatetime.parameters")));
- KeyAdapter paramChangeListener = new KeyAdapter() {
- public void keyTyped(KeyEvent inE) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- calculateEstimatedTime();
- }
- });
- }
- public void keyPressed(KeyEvent inE) {
- if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
- }
- };
-
- // Flat speed
- _flatSpeedLabel = new JLabel(I18nManager.getText("dialog.estimatetime.parameters.timefor") + ": "); // (filled in later)
- _flatSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
- paramsGrid.add(_flatSpeedLabel);
- _flatSpeedField = new DecimalNumberField();
- _flatSpeedField.addKeyListener(paramChangeListener);
- paramsGrid.add(_flatSpeedField);
- JLabel minsLabel = new JLabel(I18nManager.getText("units.minutes"));
- paramsGrid.add(minsLabel);
- paramsGrid.nextRow();
- // Headers for gentle and steep
- paramsGrid.add(new JLabel(""));
- paramsGrid.add(new JLabel(I18nManager.getText("dialog.estimatetime.gentle")));
- paramsGrid.add(new JLabel("")); // blank cell
- paramsGrid.add(new JLabel(I18nManager.getText("dialog.estimatetime.steep")));
- paramsGrid.nextRow();
- // Gentle climb
- _climbParamLabel = new JLabel(I18nManager.getText("dialog.estimatetime.parameters.timefor") + ": "); // (filled in later)
- _climbParamLabel.setHorizontalAlignment(JLabel.RIGHT);
- paramsGrid.add(_climbParamLabel);
- _gentleClimbField = new DecimalNumberField();
- _gentleClimbField.addKeyListener(paramChangeListener);
- paramsGrid.add(_gentleClimbField);
- paramsGrid.add(new JLabel(minsLabel.getText()));
- // Steep climb
- _steepClimbField = new DecimalNumberField();
- _steepClimbField.addKeyListener(paramChangeListener);
- paramsGrid.add(_steepClimbField);
- paramsGrid.add(new JLabel(minsLabel.getText()));
-
- // Gentle descent
- _descentParamLabel = new JLabel(I18nManager.getText("dialog.estimatetime.parameters.timefor") + ": "); // (filled in later)
- _descentParamLabel.setHorizontalAlignment(JLabel.RIGHT);
- paramsGrid.add(_descentParamLabel);
- _gentleDescentField = new DecimalNumberField(true); // negative numbers allowed
- _gentleDescentField.addKeyListener(paramChangeListener);
- paramsGrid.add(_gentleDescentField);
- paramsGrid.add(new JLabel(minsLabel.getText()));
- // Steep climb
- _steepDescentField = new DecimalNumberField(true); // negative numbers allowed
- _steepDescentField.addKeyListener(paramChangeListener);
- paramsGrid.add(_steepDescentField);
- paramsGrid.add(new JLabel(minsLabel.getText()));
-
- paramsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- mainPanel.add(paramsPanel);
- mainPanel.add(Box.createVerticalStrut(12));
-
- // Results panel
- JPanel resultsPanel = new JPanel();
- resultsPanel.setBorder(BorderFactory.createTitledBorder(
- I18nManager.getText("dialog.estimatetime.results")));
- resultsPanel.setLayout(new GridLayout(0, 2, 3, 3));
- // estimated time
- _estimatedDurationLabel = new JLabel(I18nManager.getText("dialog.estimatetime.results.estimatedtime") + ": "); // filled in later
- Font origFont = _estimatedDurationLabel.getFont();
- _estimatedDurationLabel.setFont(origFont.deriveFont(Font.BOLD, origFont.getSize2D() + 2.0f));
-
- resultsPanel.add(_estimatedDurationLabel);
- // actual time (if available)
- _actualDurationLabel = new JLabel(I18nManager.getText("dialog.estimatetime.results.actualtime") + ": "); // filled in later
- resultsPanel.add(_actualDurationLabel);
-
- resultsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- mainPanel.add(resultsPanel);
- mainPanel.add(Box.createVerticalStrut(4));
-
- dialogPanel.add(mainPanel, BorderLayout.NORTH);
- // 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)
- {
- finishDialog();
- }
- });
- closeButton.addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent inE) {
- if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
- }
- });
- buttonPanel.add(closeButton);
- dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
- return dialogPanel;
- }
-
-
- /**
- * Recalculate the values and update the labels
- */
- private void updateDetails()
- {
- // Warn if the current track hasn't got any height information
- if (!_stats.getMovingAltitudeRange().hasRange()) {
- _app.showErrorMessage(getNameKey(), "dialog.estimatetime.error.noaltitudes");
- }
-
- // Distance in current units
- final Unit distUnit = Config.getUnitSet().getDistanceUnit();
- final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey());
- final double movingDist = _stats.getMovingDistance();
- _distanceLabel.setText(DisplayUtils.roundedNumber(movingDist) + " " + distUnitsStr);
-
- // Climb and descent values
- final Unit altUnit = Config.getUnitSet().getAltitudeUnit();
- final String altUnitsStr = " " + I18nManager.getText(altUnit.getShortnameKey());
- _gentleClimbLabel.setText(_stats.getGentleAltitudeRange().getClimb(altUnit) + altUnitsStr);
- _steepClimbLabel.setText(_stats.getSteepAltitudeRange().getClimb(altUnit) + altUnitsStr);
- _gentleDescentLabel.setText(_stats.getGentleAltitudeRange().getDescent(altUnit) + altUnitsStr);
- _steepDescentLabel.setText(_stats.getSteepAltitudeRange().getDescent(altUnit) + altUnitsStr);
-
- // Try to get parameters from config
- EstimationParameters estParams = new EstimationParameters(Config.getConfigString(Config.KEY_ESTIMATION_PARAMS));
-
- String[] paramValues = estParams.getStrings();
- if (paramValues == null || paramValues.length != 5) {return;} // TODO: What to do in case of error?
- // Flat time is either for 5 km, 3 miles or 3 nm
- _flatSpeedLabel.setText(I18nManager.getText("dialog.estimatetime.parameters.timefor") +
- " " + EstimationParameters.getStandardDistance() + ": ");
- _flatSpeedField.setText(paramValues[0]);
-
- final String heightString = " " + EstimationParameters.getStandardClimb() + ": ";
- _climbParamLabel.setText(I18nManager.getText("dialog.estimatetime.climb") + heightString);
- _gentleClimbField.setText(paramValues[1]);
- _steepClimbField.setText(paramValues[2]);
- _descentParamLabel.setText(I18nManager.getText("dialog.estimatetime.descent") + heightString);
- _gentleDescentField.setText(paramValues[3]);
- _steepDescentField.setText(paramValues[4]);
-
- // Use the entered parameters to estimate the time
- calculateEstimatedTime();
-
- // Get the actual time if available, for comparison
- if (_stats.getMovingDurationInSeconds() > 0)
- {
- _actualDurationLabel.setText(I18nManager.getText("dialog.estimatetime.results.actualtime") + ": "
- + DisplayUtils.buildDurationString(_stats.getMovingDurationInSeconds()));
- }
- else {
- _actualDurationLabel.setText("");
- }
- }
-
-
- /**
- * Use the current parameter and the range stats to calculate the estimated time
- * and populate the answer in the dialog
- */
- private void calculateEstimatedTime()
- {
- // Populate an EstimationParameters object from the four strings
- EstimationParameters params = new EstimationParameters();
- params.populateWithStrings(_flatSpeedField.getText(), _gentleClimbField.getText(),
- _steepClimbField.getText(), _gentleDescentField.getText(), _steepDescentField.getText());
- if (!params.isValid()) {
- _estimatedDurationLabel.setText("- - -");
- }
- else
- {
- final long numSeconds = (long) (params.applyToStats(_stats) * 60.0);
- _estimatedDurationLabel.setText(I18nManager.getText("dialog.estimatetime.results.estimatedtime") + ": "
- + DisplayUtils.buildDurationString(numSeconds));
- }
- }
-
-
- /**
- * Finish with the dialog, by pressing the "Close" button
- */
- private void finishDialog()
- {
- // Make estimation parameters from entered strings, if valid save to config
- EstimationParameters params = new EstimationParameters();
- params.populateWithStrings(_flatSpeedField.getText(), _gentleClimbField.getText(),
- _steepClimbField.getText(), _gentleDescentField.getText(), _steepDescentField.getText());
- if (params.isValid()) {
- Config.setConfigString(Config.KEY_ESTIMATION_PARAMS, params.toConfigString());
- }
- _dialog.dispose();
- }
-
- /**
- * Show a tip to use the learn function, if appropriate
- */
- private void showTip()
- {
- EstimationParameters currParams = new EstimationParameters(
- Config.getConfigString(Config.KEY_ESTIMATION_PARAMS));
- if (currParams.sameAsDefaults()) {
- _app.showTip(TipManager.Tip_LearnTimeParams);
- }
- }
-}