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