/**
   * Called when one of the arrival and departure spinners changes value
   *
   * @param spinner the spinner
   */
  protected void spinnerValueChanged(JSpinner spinner) {
    // Check if we are in a quiescent state
    if (quiescent) {
      return;
    }

    if (spinner == departureSpinner) {
      Date date =
          ParseUtils.combineDateTime(departurePicker.getDate(), (Date) departureSpinner.getValue());
      route.setStarttime(date);
      adjustStartTime();
    } else if (spinner == arrivalSpinner) {
      Date date =
          ParseUtils.combineDateTime(arrivalPicker.getDate(), (Date) arrivalSpinner.getValue());
      recalculateSpeeds(date);
    } else {
      return;
    }

    routeUpdated();
  }
  /**
   * Called when one of the arrival and departure pickers changes value
   *
   * @param evt the event
   */
  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    // Check if we are in a quiescent state
    if (quiescent) {
      return;
    }

    if (evt.getSource() == departurePicker) {
      Date date =
          ParseUtils.combineDateTime(departurePicker.getDate(), (Date) departureSpinner.getValue());
      route.setStarttime(date);
      adjustStartTime();
    } else if (evt.getSource() == arrivalPicker) {
      Date date =
          ParseUtils.combineDateTime(arrivalPicker.getDate(), (Date) arrivalSpinner.getValue());
      recalculateSpeeds(date);
    } else {
      return;
    }

    routeUpdated();
  }
 /**
  * Parses the text field as a double. Will skip any type suffix.
  *
  * @param str the string to parse as a double
  * @return the resulting value
  */
 private static double parseDouble(String str) throws FormatException {
   str = str.replaceAll(",", ".");
   String[] parts = StringUtils.split(str, " ");
   return ParseUtils.parseDouble(parts[0]);
 }