kauron/estraba
Archived
1
0
Fork 0

Added load button and max HR dialog

This commit is contained in:
Carlos Galindo 2016-05-24 14:37:47 +02:00
parent 05d052fb00
commit 414c3c3ee9
Signed by: kauron
GPG key ID: 83E68706DEE119A3
4 changed files with 96 additions and 42 deletions

View file

@ -37,7 +37,10 @@ import es.kauron.estraba.model.DataBundle;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.AreaChart; import javafx.scene.chart.AreaChart;
import javafx.scene.chart.LineChart; import javafx.scene.chart.LineChart;
import javafx.scene.chart.PieChart; import javafx.scene.chart.PieChart;
@ -46,8 +49,10 @@ import javafx.scene.control.Tab;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import jgpx.model.analysis.Chunk; import jgpx.model.analysis.Chunk;
import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@ -62,7 +67,7 @@ public class DashboardController implements Initializable, MapComponentInitializ
private AnchorPane root; private AnchorPane root;
@FXML @FXML
private Tab tabDashboard, tabMap, tabGraph, tabSettings; private Tab tabDashboard, tabMap, tabGraph;
@FXML @FXML
private ImageView imgHR, imgSpeed, imgCadence, imgDate, imgDistance, imgElevation; private ImageView imgHR, imgSpeed, imgCadence, imgDate, imgDistance, imgElevation;
@ -92,6 +97,7 @@ public class DashboardController implements Initializable, MapComponentInitializ
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
mapView.setVisible(false);
// populate map icons // populate map icons
((ImageView)elevationButton.getGraphic()).setImage(new Image(App.class.getResourceAsStream("img/elevation.png"))); ((ImageView)elevationButton.getGraphic()).setImage(new Image(App.class.getResourceAsStream("img/elevation.png")));
((ImageView)speedButton.getGraphic()).setImage(new Image(App.class.getResourceAsStream("img/speed.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"))); 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 @FXML
private void onMapButton(ActionEvent event){ private void onMapButton(ActionEvent event){
switch (((JFXButton)event.getSource()).getId()) { switch (((JFXButton)event.getSource()).getId()) {
@ -196,16 +215,12 @@ public class DashboardController implements Initializable, MapComponentInitializ
coord[W] = Math.min(lon, coord[W]); coord[W] = Math.min(lon, coord[W]);
pathArray.push(new LatLong(lat, lon)); 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() map.addMarker(new Marker(new MarkerOptions()
.position(new LatLong( .position(new LatLong(
chunks.get(0).getFirstPoint().getLatitude(), chunks.get(0).getFirstPoint().getLatitude(),
chunks.get(0).getFirstPoint().getLongitude())) chunks.get(0).getFirstPoint().getLongitude()))
.title("label.begin"))); .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() map.addMarker(new Marker(new MarkerOptions()
.position(new LatLong( .position(new LatLong(
chunks.get(chunks.size() - 1).getLastPoint().getLatitude(), chunks.get(chunks.size() - 1).getLastPoint().getLatitude(),

View file

@ -38,12 +38,17 @@ import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.Parent; import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.*;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.input.Dragboard; import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode; import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Text;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import javafx.stage.Stage; import javafx.stage.Stage;
@ -78,6 +83,7 @@ public class SplashController implements Initializable{
private JFXSnackbar snackbar; private JFXSnackbar snackbar;
private File file; private File file;
private int maxHR;
@FXML @FXML
private void loadGPXFile(ActionEvent event) throws Exception { private void loadGPXFile(ActionEvent event) throws Exception {
@ -93,15 +99,16 @@ public class SplashController implements Initializable{
} }
public void loadGPXFile(File file) { public void loadGPXFile(File file) {
maxHR = showHRDialog();
if (maxHR < 0) errorLoading();
buttonLoad.setVisible(false); buttonLoad.setVisible(false);
labelWelcome.setVisible(false); labelWelcome.setVisible(false);
spinner.setVisible(true); spinner.setVisible(true);
snackbar.registerSnackbarContainer(root);
snackbar.show("Loading file", 5000); snackbar.show("Loading file", 5000);
Thread th = new Thread(new Task<DataBundle>() { Thread th = new Thread(new Task<DataBundle>() {
@Override @Override
protected DataBundle call() throws Exception { protected DataBundle call() throws Exception {
return DataBundle.loadFrom(file); return DataBundle.loadFrom(file, maxHR);
} }
@Override @Override
@ -169,6 +176,7 @@ public class SplashController implements Initializable{
e.setDropCompleted(success); e.setDropCompleted(success);
e.consume(); e.consume();
})); }));
snackbar.registerSnackbarContainer(root);
} }
private void errorLoading() { private void errorLoading() {
@ -177,5 +185,36 @@ public class SplashController implements Initializable{
spinner.setVisible(false); spinner.setVisible(false);
snackbar.show("Error loading file", 3000); 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;
}
} }

View file

@ -55,7 +55,7 @@ public class DataBundle {
public ObservableList<PieChart.Data> pieData; public ObservableList<PieChart.Data> pieData;
public ObservableList<Chunk> chunks; public ObservableList<Chunk> chunks;
private DataBundle(TrackData track) { private DataBundle(TrackData track, int maxHR) {
HRAvg = track.getAverageHeartrate() + App.GENERAL_BUNDLE.getString("unit.bpm"); HRAvg = track.getAverageHeartrate() + App.GENERAL_BUNDLE.getString("unit.bpm");
HRMax = track.getMaxHeartrate() + 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())); cadenceSeries.getData().add(new XYChart.Data<>(currentDistance, chunk.getAvgCadence()));
String zone; String zone;
if (chunk.getAvgHeartRate() > 170) zone = App.GENERAL_BUNDLE.getString("zone.anaerobic"); if (chunk.getAvgHeartRate() > maxHR * .9) zone = App.GENERAL_BUNDLE.getString("zone.anaerobic");
else if (chunk.getAvgHeartRate() > 150) zone = App.GENERAL_BUNDLE.getString("zone.threshold"); else if (chunk.getAvgHeartRate() > maxHR * .8) zone = App.GENERAL_BUNDLE.getString("zone.threshold");
else if (chunk.getAvgHeartRate() > 130) zone = App.GENERAL_BUNDLE.getString("zone.tempo"); else if (chunk.getAvgHeartRate() > maxHR * .7) zone = App.GENERAL_BUNDLE.getString("zone.tempo");
else if (chunk.getAvgHeartRate() > 110) zone = App.GENERAL_BUNDLE.getString("zone.endurance"); else if (chunk.getAvgHeartRate() > maxHR * .6) zone = App.GENERAL_BUNDLE.getString("zone.endurance");
else zone = App.GENERAL_BUNDLE.getString("zone.recovery"); else zone = App.GENERAL_BUNDLE.getString("zone.recovery");
boolean pieFound = false; boolean pieFound = false;
@ -117,13 +117,14 @@ public class DataBundle {
if (d.getName().equals(zone)) { if (d.getName().equals(zone)) {
pieFound = true; pieFound = true;
d.setPieValue(d.getPieValue() + 1); d.setPieValue(d.getPieValue() + 1);
break;
} }
} }
if (!pieFound) pieData.add( new PieChart.Data(zone, 1) ); 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; JAXBElement<Object> jaxbElement;
JAXBContext jaxbContext = JAXBContext.newInstance(GpxType.class, TrackPointExtensionT.class); JAXBContext jaxbContext = JAXBContext.newInstance(GpxType.class, TrackPointExtensionT.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
@ -131,6 +132,6 @@ public class DataBundle {
GpxType gpx = (GpxType) jaxbElement.getValue(); GpxType gpx = (GpxType) jaxbElement.getValue();
if (gpx == null) throw new Exception(); 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);
} }
} }

View file

@ -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 com.lynden.gmapsfx.GoogleMapView?>
<?import javafx.geometry.*?> <?import java.lang.String?>
<?import javafx.scene.chart.*?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?> <?import javafx.scene.chart.AreaChart?>
<?import javafx.scene.image.*?> <?import javafx.scene.chart.LineChart?>
<?import javafx.scene.layout.*?> <?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.text.*?> <?import javafx.scene.chart.PieChart?>
<?import java.lang.*?> <?import javafx.scene.control.Label?>
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="root" xmlns="http://javafx.com/javafx/8.0.76-ea" <?import javafx.scene.control.Tab?>
fx:controller="es.kauron.estraba.controller.DashboardController"> <?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"> <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"> <Tab fx:id="tabDashboard" styleClass=".estraba.dashboard" text="%tab.dashboard">
<VBox prefHeight="200.0" prefWidth="100.0"> <VBox prefHeight="200.0" prefWidth="100.0">
@ -201,7 +210,7 @@
</VBox> </VBox>
</HBox> </HBox>
</VBox> </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> </PieChart>
<VBox layoutX="15.0" layoutY="15.0" minHeight="360.0" minWidth="300.0" prefHeight="300.0"> <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"> <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> </HBox>
</VBox> </VBox>
</HBox> </HBox>
<Label fx:id="labelMotivationLower" alignment="CENTER" focusTraversable="false" maxWidth="1.7976931348623157E308" text="%label.motivation"> <HBox alignment="CENTER" spacing="10.0">
<font> <children>
<Font name="Roboto" size="56.0" /> <JFXButton minWidth="70.0" onAction="#loadFile" style="-fx-background-color: #fc4c02;" text="Load another file" textAlignment="CENTER" textFill="WHITE" />
</font> </children>
<VBox.margin> </HBox>
<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>
</VBox> </VBox>
</Tab> </Tab>
<Tab fx:id="tabMap" text="%tab.map"> <Tab fx:id="tabMap" text="%tab.map">
@ -456,8 +458,5 @@
</LineChart> </LineChart>
</VBox> </VBox>
</Tab> </Tab>
<Tab fx:id="tabSettings" text="%tab.settings">
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</Tab>
</JFXTabPane> </JFXTabPane>
</AnchorPane> </AnchorPane>