Added load button and max HR dialog
This commit is contained in:
		
					parent
					
						
							
								05d052fb00
							
						
					
				
			
			
				commit
				
					
						414c3c3ee9
					
				
			
		
					 4 changed files with 96 additions and 42 deletions
				
			
		| 
						 | 
				
			
			@ -37,7 +37,10 @@ import es.kauron.estraba.model.DataBundle;
 | 
			
		|||
import javafx.collections.ObservableList;
 | 
			
		||||
import javafx.event.ActionEvent;
 | 
			
		||||
import javafx.fxml.FXML;
 | 
			
		||||
import javafx.fxml.FXMLLoader;
 | 
			
		||||
import javafx.fxml.Initializable;
 | 
			
		||||
import javafx.scene.Parent;
 | 
			
		||||
import javafx.scene.Scene;
 | 
			
		||||
import javafx.scene.chart.AreaChart;
 | 
			
		||||
import javafx.scene.chart.LineChart;
 | 
			
		||||
import javafx.scene.chart.PieChart;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,8 +49,10 @@ import javafx.scene.control.Tab;
 | 
			
		|||
import javafx.scene.image.Image;
 | 
			
		||||
import javafx.scene.image.ImageView;
 | 
			
		||||
import javafx.scene.layout.AnchorPane;
 | 
			
		||||
import javafx.stage.Stage;
 | 
			
		||||
import jgpx.model.analysis.Chunk;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.util.ResourceBundle;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +67,7 @@ public class DashboardController implements Initializable, MapComponentInitializ
 | 
			
		|||
    private AnchorPane root;
 | 
			
		||||
 | 
			
		||||
    @FXML
 | 
			
		||||
    private Tab tabDashboard, tabMap, tabGraph, tabSettings;
 | 
			
		||||
    private Tab tabDashboard, tabMap, tabGraph;
 | 
			
		||||
 | 
			
		||||
    @FXML
 | 
			
		||||
    private ImageView imgHR, imgSpeed, imgCadence, imgDate, imgDistance, imgElevation;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +97,7 @@ public class DashboardController implements Initializable, MapComponentInitializ
 | 
			
		|||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void initialize(URL location, ResourceBundle resources) {
 | 
			
		||||
        mapView.setVisible(false);
 | 
			
		||||
        // populate map icons
 | 
			
		||||
        ((ImageView)elevationButton.getGraphic()).setImage(new Image(App.class.getResourceAsStream("img/elevation.png")));
 | 
			
		||||
        ((ImageView)speedButton.getGraphic()).setImage(new Image(App.class.getResourceAsStream("img/speed.png")));
 | 
			
		||||
| 
						 | 
				
			
			@ -107,6 +113,19 @@ public class DashboardController implements Initializable, MapComponentInitializ
 | 
			
		|||
        imgElevation.setImage(new Image(App.class.getResourceAsStream("img/elevation.png")));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @FXML
 | 
			
		||||
    private void loadFile() {
 | 
			
		||||
        FXMLLoader loader = new FXMLLoader(
 | 
			
		||||
                App.class.getResource("fxml/Splash.fxml"), App.GENERAL_BUNDLE);
 | 
			
		||||
        Parent parent;
 | 
			
		||||
        try {
 | 
			
		||||
            parent = loader.load();
 | 
			
		||||
            ((Stage) root.getScene().getWindow()).setScene(new Scene(parent));
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @FXML
 | 
			
		||||
    private void onMapButton(ActionEvent event){
 | 
			
		||||
        switch (((JFXButton)event.getSource()).getId()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -196,16 +215,12 @@ public class DashboardController implements Initializable, MapComponentInitializ
 | 
			
		|||
            coord[W] = Math.min(lon, coord[W]);
 | 
			
		||||
            pathArray.push(new LatLong(lat, lon));
 | 
			
		||||
        });
 | 
			
		||||
        // Create and add the polyline using the array
 | 
			
		||||
        // This polyline displays instantly with no problem
 | 
			
		||||
        // TODO: add color with PolylineOptions.strokeColor("#ffff00") to match the color schemes of the app
 | 
			
		||||
        // When using that method, the line does not load properly, it needs an update to the zoom to show up.
 | 
			
		||||
        map.addMarker(new Marker(new MarkerOptions()
 | 
			
		||||
                .position(new LatLong(
 | 
			
		||||
                        chunks.get(0).getFirstPoint().getLatitude(),
 | 
			
		||||
                        chunks.get(0).getFirstPoint().getLongitude()))
 | 
			
		||||
                .title("label.begin")));
 | 
			
		||||
        map.addMapShape(new Polyline(new PolylineOptions().path(pathArray)));
 | 
			
		||||
        map.addMapShape(new Polyline(new PolylineOptions().path(pathArray).strokeColor("#fc4c02")));
 | 
			
		||||
        map.addMarker(new Marker(new MarkerOptions()
 | 
			
		||||
                .position(new LatLong(
 | 
			
		||||
                        chunks.get(chunks.size() - 1).getLastPoint().getLatitude(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,12 +38,17 @@ import javafx.fxml.FXMLLoader;
 | 
			
		|||
import javafx.fxml.Initializable;
 | 
			
		||||
import javafx.scene.Parent;
 | 
			
		||||
import javafx.scene.Scene;
 | 
			
		||||
import javafx.scene.control.Button;
 | 
			
		||||
import javafx.scene.control.Dialog;
 | 
			
		||||
import javafx.scene.control.Label;
 | 
			
		||||
import javafx.scene.control.*;
 | 
			
		||||
import javafx.scene.image.Image;
 | 
			
		||||
import javafx.scene.image.ImageView;
 | 
			
		||||
import javafx.scene.input.Dragboard;
 | 
			
		||||
import javafx.scene.input.TransferMode;
 | 
			
		||||
import javafx.scene.layout.AnchorPane;
 | 
			
		||||
import javafx.scene.layout.GridPane;
 | 
			
		||||
import javafx.scene.text.Text;
 | 
			
		||||
import javafx.stage.FileChooser;
 | 
			
		||||
import javafx.stage.Stage;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +83,7 @@ public class SplashController implements Initializable{
 | 
			
		|||
 | 
			
		||||
    private JFXSnackbar snackbar;
 | 
			
		||||
    private File file;
 | 
			
		||||
    private int maxHR;
 | 
			
		||||
 | 
			
		||||
    @FXML
 | 
			
		||||
    private void loadGPXFile(ActionEvent event) throws Exception {
 | 
			
		||||
| 
						 | 
				
			
			@ -93,15 +99,16 @@ public class SplashController implements Initializable{
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public void loadGPXFile(File file) {
 | 
			
		||||
        maxHR = showHRDialog();
 | 
			
		||||
        if (maxHR < 0) errorLoading();
 | 
			
		||||
        buttonLoad.setVisible(false);
 | 
			
		||||
        labelWelcome.setVisible(false);
 | 
			
		||||
        spinner.setVisible(true);
 | 
			
		||||
        snackbar.registerSnackbarContainer(root);
 | 
			
		||||
        snackbar.show("Loading file", 5000);
 | 
			
		||||
        Thread th = new Thread(new Task<DataBundle>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            protected DataBundle call() throws Exception {
 | 
			
		||||
                return DataBundle.loadFrom(file);
 | 
			
		||||
                return DataBundle.loadFrom(file, maxHR);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +176,7 @@ public class SplashController implements Initializable{
 | 
			
		|||
            e.setDropCompleted(success);
 | 
			
		||||
            e.consume();
 | 
			
		||||
        }));
 | 
			
		||||
        snackbar.registerSnackbarContainer(root);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void errorLoading() {
 | 
			
		||||
| 
						 | 
				
			
			@ -177,5 +185,36 @@ public class SplashController implements Initializable{
 | 
			
		|||
        spinner.setVisible(false);
 | 
			
		||||
        snackbar.show("Error loading file", 3000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private int showHRDialog() {
 | 
			
		||||
        Dialog<Integer> dialog = new Dialog<>();
 | 
			
		||||
        dialog.setTitle("Input your maximum heart rate or age");
 | 
			
		||||
        GridPane grid = new GridPane();
 | 
			
		||||
        grid.setHgap(5);
 | 
			
		||||
        grid.setVgap(2);
 | 
			
		||||
        grid.addColumn(0, new Text("Heart rate:"), new Text("Age:"));
 | 
			
		||||
        Spinner<Integer> spinnerAge = new Spinner<>(18, 99, 25, 1);
 | 
			
		||||
        Spinner<Integer> spinnerHR  = new Spinner<>(60, 202, 180, 5);
 | 
			
		||||
        spinnerAge.valueProperty().addListener((obs, oldV, newV) ->
 | 
			
		||||
            spinnerHR.setValueFactory(new SpinnerValueFactory
 | 
			
		||||
                    .IntegerSpinnerValueFactory(60, 202, 220 - newV, 5)));
 | 
			
		||||
        spinnerHR.valueProperty().addListener((obs, old, newV) ->
 | 
			
		||||
                spinnerAge.setValueFactory(new SpinnerValueFactory
 | 
			
		||||
                        .IntegerSpinnerValueFactory(18, 99, 220 - newV, 1)));
 | 
			
		||||
        grid.addColumn(1, spinnerHR, spinnerAge);
 | 
			
		||||
        Button buttonOk = new Button("Ok");
 | 
			
		||||
        buttonOk.setDefaultButton(true);
 | 
			
		||||
        buttonOk.setOnAction(event -> {
 | 
			
		||||
            dialog.setResult(spinnerHR.getValue());
 | 
			
		||||
            dialog.close();
 | 
			
		||||
        });
 | 
			
		||||
        grid.add(buttonOk, 1, 2);
 | 
			
		||||
        dialog.getDialogPane().setContent(grid);
 | 
			
		||||
        dialog.showAndWait();
 | 
			
		||||
        if (dialog.getResult() != null)
 | 
			
		||||
            return dialog.getResult();
 | 
			
		||||
        else
 | 
			
		||||
            return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ public class DataBundle {
 | 
			
		|||
    public ObservableList<PieChart.Data> pieData;
 | 
			
		||||
    public ObservableList<Chunk> chunks;
 | 
			
		||||
 | 
			
		||||
    private DataBundle(TrackData track) {
 | 
			
		||||
    private DataBundle(TrackData track, int maxHR) {
 | 
			
		||||
 | 
			
		||||
        HRAvg = track.getAverageHeartrate() + App.GENERAL_BUNDLE.getString("unit.bpm");
 | 
			
		||||
        HRMax = track.getMaxHeartrate() + App.GENERAL_BUNDLE.getString("unit.bpm");
 | 
			
		||||
| 
						 | 
				
			
			@ -106,10 +106,10 @@ public class DataBundle {
 | 
			
		|||
            cadenceSeries.getData().add(new XYChart.Data<>(currentDistance, chunk.getAvgCadence()));
 | 
			
		||||
 | 
			
		||||
            String zone;
 | 
			
		||||
            if (chunk.getAvgHeartRate() > 170) zone = App.GENERAL_BUNDLE.getString("zone.anaerobic");
 | 
			
		||||
            else if (chunk.getAvgHeartRate() > 150) zone = App.GENERAL_BUNDLE.getString("zone.threshold");
 | 
			
		||||
            else if (chunk.getAvgHeartRate() > 130) zone = App.GENERAL_BUNDLE.getString("zone.tempo");
 | 
			
		||||
            else if (chunk.getAvgHeartRate() > 110) zone = App.GENERAL_BUNDLE.getString("zone.endurance");
 | 
			
		||||
            if (chunk.getAvgHeartRate() > maxHR * .9) zone = App.GENERAL_BUNDLE.getString("zone.anaerobic");
 | 
			
		||||
            else if (chunk.getAvgHeartRate() > maxHR * .8) zone = App.GENERAL_BUNDLE.getString("zone.threshold");
 | 
			
		||||
            else if (chunk.getAvgHeartRate() > maxHR * .7) zone = App.GENERAL_BUNDLE.getString("zone.tempo");
 | 
			
		||||
            else if (chunk.getAvgHeartRate() > maxHR * .6) zone = App.GENERAL_BUNDLE.getString("zone.endurance");
 | 
			
		||||
            else zone = App.GENERAL_BUNDLE.getString("zone.recovery");
 | 
			
		||||
 | 
			
		||||
            boolean pieFound = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -117,13 +117,14 @@ public class DataBundle {
 | 
			
		|||
                if (d.getName().equals(zone)) {
 | 
			
		||||
                    pieFound = true;
 | 
			
		||||
                    d.setPieValue(d.getPieValue() + 1);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!pieFound) pieData.add( new PieChart.Data(zone, 1) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static DataBundle loadFrom(File file) throws Exception {
 | 
			
		||||
    public static DataBundle loadFrom(File file, int maxHR) throws Exception {
 | 
			
		||||
        JAXBElement<Object> jaxbElement;
 | 
			
		||||
        JAXBContext jaxbContext = JAXBContext.newInstance(GpxType.class, TrackPointExtensionT.class);
 | 
			
		||||
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
 | 
			
		||||
| 
						 | 
				
			
			@ -131,6 +132,6 @@ public class DataBundle {
 | 
			
		|||
        GpxType gpx = (GpxType) jaxbElement.getValue();
 | 
			
		||||
 | 
			
		||||
        if (gpx == null) throw new Exception();
 | 
			
		||||
        return new DataBundle(new TrackData(new Track(gpx.getTrk().get(0))));
 | 
			
		||||
        return new DataBundle(new TrackData(new Track(gpx.getTrk().get(0))), maxHR);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,17 +25,26 @@
 | 
			
		|||
  ~
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
<?import com.jfoenix.controls.*?>
 | 
			
		||||
<?import com.jfoenix.controls.JFXButton?>
 | 
			
		||||
<?import com.jfoenix.controls.JFXSpinner?>
 | 
			
		||||
<?import com.jfoenix.controls.JFXTabPane?>
 | 
			
		||||
<?import com.lynden.gmapsfx.GoogleMapView?>
 | 
			
		||||
<?import javafx.geometry.*?>
 | 
			
		||||
<?import javafx.scene.chart.*?>
 | 
			
		||||
<?import javafx.scene.control.*?>
 | 
			
		||||
<?import javafx.scene.image.*?>
 | 
			
		||||
<?import javafx.scene.layout.*?>
 | 
			
		||||
<?import javafx.scene.text.*?>
 | 
			
		||||
<?import java.lang.*?>
 | 
			
		||||
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="root" xmlns="http://javafx.com/javafx/8.0.76-ea"
 | 
			
		||||
            fx:controller="es.kauron.estraba.controller.DashboardController">
 | 
			
		||||
<?import java.lang.String?>
 | 
			
		||||
<?import javafx.geometry.Insets?>
 | 
			
		||||
<?import javafx.scene.chart.AreaChart?>
 | 
			
		||||
<?import javafx.scene.chart.LineChart?>
 | 
			
		||||
<?import javafx.scene.chart.NumberAxis?>
 | 
			
		||||
<?import javafx.scene.chart.PieChart?>
 | 
			
		||||
<?import javafx.scene.control.Label?>
 | 
			
		||||
<?import javafx.scene.control.Tab?>
 | 
			
		||||
<?import javafx.scene.image.ImageView?>
 | 
			
		||||
<?import javafx.scene.layout.AnchorPane?>
 | 
			
		||||
<?import javafx.scene.layout.HBox?>
 | 
			
		||||
<?import javafx.scene.layout.StackPane?>
 | 
			
		||||
<?import javafx.scene.layout.VBox?>
 | 
			
		||||
<?import javafx.scene.text.Font?>
 | 
			
		||||
 | 
			
		||||
<AnchorPane fx:id="root" xmlns="http://javafx.com/javafx/8.0.76-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="es.kauron.estraba.controller.DashboardController">
 | 
			
		||||
   <JFXTabPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="1000.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
 | 
			
		||||
      <Tab fx:id="tabDashboard" styleClass=".estraba.dashboard" text="%tab.dashboard">
 | 
			
		||||
         <VBox prefHeight="200.0" prefWidth="100.0">
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +210,7 @@
 | 
			
		|||
                     </VBox>
 | 
			
		||||
                  </HBox>
 | 
			
		||||
               </VBox>
 | 
			
		||||
               <PieChart fx:id="zoneChart" labelsVisible="false" legendVisible="true" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="360.0" startAngle="90" HBox.hgrow="ALWAYS">
 | 
			
		||||
               <PieChart fx:id="zoneChart" labelsVisible="false" legendVisible="true" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="360.0" startAngle="90">
 | 
			
		||||
               </PieChart>
 | 
			
		||||
               <VBox layoutX="15.0" layoutY="15.0" minHeight="360.0" minWidth="300.0" prefHeight="300.0">
 | 
			
		||||
                  <HBox alignment="CENTER" layoutX="10.0" layoutY="10.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="90.0" prefWidth="200.0" HBox.hgrow="ALWAYS" VBox.vgrow="ALWAYS">
 | 
			
		||||
| 
						 | 
				
			
			@ -346,18 +355,11 @@
 | 
			
		|||
                  </HBox>
 | 
			
		||||
               </VBox>
 | 
			
		||||
            </HBox>
 | 
			
		||||
            <Label fx:id="labelMotivationLower" alignment="CENTER" focusTraversable="false" maxWidth="1.7976931348623157E308" text="%label.motivation">
 | 
			
		||||
               <font>
 | 
			
		||||
                  <Font name="Roboto" size="56.0" />
 | 
			
		||||
               </font>
 | 
			
		||||
               <VBox.margin>
 | 
			
		||||
                  <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
 | 
			
		||||
               </VBox.margin>
 | 
			
		||||
               <styleClass>
 | 
			
		||||
                  <String fx:value=".estraba.dashboard.motivation" />
 | 
			
		||||
                  <String fx:value=".estraba.dashboard.motivation.lower" />
 | 
			
		||||
               </styleClass>
 | 
			
		||||
            </Label>
 | 
			
		||||
            <HBox alignment="CENTER" spacing="10.0">
 | 
			
		||||
               <children>
 | 
			
		||||
                  <JFXButton minWidth="70.0" onAction="#loadFile" style="-fx-background-color: #fc4c02;" text="Load another file" textAlignment="CENTER" textFill="WHITE" />
 | 
			
		||||
               </children>
 | 
			
		||||
            </HBox>
 | 
			
		||||
         </VBox>
 | 
			
		||||
      </Tab>
 | 
			
		||||
      <Tab fx:id="tabMap" text="%tab.map">
 | 
			
		||||
| 
						 | 
				
			
			@ -365,7 +367,7 @@
 | 
			
		|||
            <padding>
 | 
			
		||||
               <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
 | 
			
		||||
            </padding>
 | 
			
		||||
            <StackPane prefHeight="150.0" prefWidth="200.0" VBox.vgrow="ALWAYS" >
 | 
			
		||||
            <StackPane prefHeight="150.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
 | 
			
		||||
               <children>
 | 
			
		||||
                  <GoogleMapView fx:id="mapView" />
 | 
			
		||||
                  <JFXSpinner fx:id="mapSpinner" />
 | 
			
		||||
| 
						 | 
				
			
			@ -456,8 +458,5 @@
 | 
			
		|||
            </LineChart>
 | 
			
		||||
         </VBox>
 | 
			
		||||
      </Tab>
 | 
			
		||||
      <Tab fx:id="tabSettings" text="%tab.settings">
 | 
			
		||||
         <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
 | 
			
		||||
      </Tab>
 | 
			
		||||
   </JFXTabPane>
 | 
			
		||||
</AnchorPane>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Reference in a new issue