Updated Graph to use Timeline + minor UI changes + wording

This commit is contained in:
Martin Beyer
2020-06-16 14:13:17 +02:00
parent 5180f2061a
commit 55e9cabf51
6 changed files with 172 additions and 58 deletions

View File

@@ -1,13 +1,16 @@
package org.cryptomator.ui.vaultstatistics;
import javafx.beans.property.LongProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
@@ -16,54 +19,85 @@ import javax.inject.Inject;
@VaultStatisticsScoped
public class VaultStatisticsController implements FxController {
private static final int IO_SAMPLING_STEPS = 100;
private static final double IO_SAMPLING_INTERVAL = 0.5;
private final Stage window;
private final ReadOnlyObjectProperty<Vault> vault;
private final Vault vault;
@FXML
private LineChart<Double, Double> lineGraph;
private final LongProperty currentReadData;
private final LongProperty currentWriteData;
private final XYChart.Series<Double, Double> readData;
private final XYChart.Series<Double, Double> writeData;
private long timeAtStartOfTracking;
private LineChart<Number, Number> lineGraph;
private final Series<Number, Number> readData;
private final Series<Number, Number> writeData;
private Timeline ioAnimation;
@Inject
public VaultStatisticsController(@VaultStatisticsWindow Stage window, ObjectProperty<Vault> vault) {
public VaultStatisticsController(@VaultStatisticsWindow Stage window, @VaultStatisticsWindow Vault vault) {
this.window = window;
this.vault = vault;
readData = new XYChart.Series<>();
readData = new Series<>();
readData.setName("Read Data"); // For Legend
//TODO Add Name to strings.properties
writeData = new XYChart.Series<>();
writeData = new Series<>();
writeData.setName("Write Data");
//TODO Add Name to strings.properties
currentReadData = new SimpleLongProperty();
currentReadData.bind(getVault().getStats().bytesPerSecondReadProperty());
currentReadData.addListener((observable, oldValue, newValue) -> updateReadWriteData());
currentWriteData = new SimpleLongProperty();
currentWriteData.bind(getVault().getStats().bytesPerSecondWrittenProperty());
currentWriteData.addListener((observable, oldValue, newValue) -> updateReadWriteData());
ioAnimation = new Timeline(); //TODO Research better timer
ioAnimation.getKeyFrames().add(new KeyFrame(Duration.seconds(IO_SAMPLING_INTERVAL), new IoSamplingAnimationHandler(readData, writeData)));
ioAnimation.setCycleCount(Animation.INDEFINITE);
ioAnimation.play();
}
@FXML
public void initialize() {
window.setTitle(window.getTitle() + " - " + vault.get().getDisplayableName());
lineGraph.getData().addAll(writeData, readData);
lineGraph.getData().addAll(readData, writeData);
}
private class IoSamplingAnimationHandler implements EventHandler<ActionEvent> {
private static final double BYTES_TO_MEGABYTES_FACTOR = 1.0 / IO_SAMPLING_INTERVAL / 1024.0 / 1024.0;
private final Series<Number, Number> decryptedBytesRead;
private final Series<Number, Number> encryptedBytesWrite;
public IoSamplingAnimationHandler(Series<Number, Number> readData, Series<Number, Number> writeData) {
this.decryptedBytesRead = readData;
this.encryptedBytesWrite = writeData;
// initialize data once and change value of datapoints later:
for (int i = 0; i < IO_SAMPLING_STEPS; i++) {
decryptedBytesRead.getData().add(new Data<>(i, 0));
encryptedBytesWrite.getData().add(new Data<>(i, 0));
}
}
@Override
public void handle(ActionEvent event) {
// move all values one step:
for (int i = 0; i < IO_SAMPLING_STEPS - 1; i++) {
int j = i + 1;
Number tmp = decryptedBytesRead.getData().get(j).getYValue();
decryptedBytesRead.getData().get(i).setYValue(tmp);
tmp = encryptedBytesWrite.getData().get(j).getYValue();
encryptedBytesWrite.getData().get(i).setYValue(tmp);
}
// add latest value:
final long decBytes = vault.getStats().bytesPerSecondReadProperty().get();
final double decMb = decBytes * BYTES_TO_MEGABYTES_FACTOR;
final long encBytes = vault.getStats().bytesPerSecondWrittenProperty().get();
final double encMb = encBytes * BYTES_TO_MEGABYTES_FACTOR;
decryptedBytesRead.getData().get(IO_SAMPLING_STEPS - 1).setYValue(decMb);
encryptedBytesWrite.getData().get(IO_SAMPLING_STEPS - 1).setYValue(encMb);
}
}
public Vault getVault() {
return vault.get();
}
private void updateReadWriteData() {
//So the graphs start at x = 0
if (timeAtStartOfTracking == 0) {
timeAtStartOfTracking = System.currentTimeMillis();
}
readData.getData().add(new XYChart.Data<Double, Double>((System.currentTimeMillis() - timeAtStartOfTracking) / 1000.0, ((getVault().getStats().bytesPerSecondReadProperty().get()) / 1024.0)));
writeData.getData().add(new XYChart.Data<Double, Double>((System.currentTimeMillis() - timeAtStartOfTracking) / 1000.0, ((getVault().getStats().bytesPerSecondWrittenProperty().get()) / 1024.0)));
return vault;
}
/*
public ReadOnlyObjectProperty<Vault> vaultProperty() {
return vault;
}*/
}

View File

@@ -4,9 +4,12 @@ import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
@@ -14,7 +17,6 @@ import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.StageFactory;
import org.cryptomator.ui.mainwindow.MainWindow;
import javax.inject.Provider;
import java.util.Map;
@@ -33,12 +35,19 @@ abstract class VaultStatisticsModule {
@Provides
@VaultStatisticsWindow
@VaultStatisticsScoped
static Stage provideStage(StageFactory factory, @MainWindow Stage owner, ResourceBundle resourceBundle) {
static Stage provideStage(StageFactory factory, ResourceBundle resourceBundle, @VaultStatisticsWindow Vault vault) {
Stage stage = factory.create();
stage.setTitle(resourceBundle.getString("vaultstatistics.title"));
stage.setTitle(String.format(resourceBundle.getString("vaultstatistics.title"), vault.getDisplayableName()));
stage.setResizable(false);
stage.initModality(Modality.NONE);
stage.initOwner(owner);
vault.stateProperty().addListener(new ChangeListener<>() {
@Override
public void changed(ObservableValue<? extends VaultState> observable, VaultState oldValue, VaultState newValue) {
if (newValue != VaultState.UNLOCKED) {
stage.hide();
observable.removeListener(this);
}
}
});
return stage;
}

View File

@@ -869,3 +869,56 @@
-fx-background-color: PROGRESS_BAR_BG;
-fx-background-radius: 4px;
}
/*******************************************************************************
* *
* I/O Statistics *
* *
******************************************************************************/
.chart {
-fx-padding: 10px;
}
.chart-plot-background {
-fx-background-color: MAIN_BG;
-fx-padding: 20px;
}
/*
.default-color0.chart-line-symbol { -fx-background-color: #00FFFF; }
.default-color1.chart-line-symbol { -fx-background-color: #00FF00; }
*/
/* content */
.chart-content {
-fx-padding: 10px;
}
.chart-horizontal-grid-lines {
-fx-stroke: #FFFFFF;
}
.chart-vertical-zero-line,
.chart-horizontal-zero-line {
-fx-stroke: #FFFFFF;
}
.chart-series-line {
-fx-stroke-width: 2px;
}
.chart-alternative-row-fill {
-fx-fill: #E1E1E1;
-fx-stroke: transparent;
-fx-stroke-width: 0;
}
.default-color0.chart-series-line { -fx-stroke: #FF0000; }
.default-color1.chart-series-line { -fx-stroke: #00FF00 ; }
.chart-legend {
-fx-background-color: transparent;
-fx-padding: 20px;
}
.chart-legend-item-symbol{
-fx-background-radius: 10;
}
.chart-legend-item{
-fx-text-fill: #FFFFFF;
}

View File

@@ -870,25 +870,44 @@
}
/*******************************************************************************
* *
* Vault Statistics *
* I/O Statistics *
* *
******************************************************************************/
.chart-plot-background {
-fx-background-color: #F7F7F7;
.chart {
-fx-padding: 10px;
}
.chart-vertical-grid-lines {
-fx-stroke: #49B04A;
.chart-plot-background {
-fx-background-color: MAIN_BG;
-fx-padding: 20px;
}
/*
.default-color0.chart-line-symbol { -fx-background-color: #00FFFF; }
.default-color1.chart-line-symbol { -fx-background-color: #00FF00; }
*/
/* content */
.chart-content {
-fx-padding: 10px;
}
.chart-horizontal-grid-lines {
-fx-stroke: #49B04A;
-fx-stroke: #000000;
}
.chart-vertical-zero-line,
.chart-horizontal-zero-line {
-fx-stroke: #000000;
}
.chart-series-line {
-fx-stroke-width: 2px;
}
.chart-alternative-row-fill {
-fx-fill: #E1E1E1;
-fx-stroke: transparent;
-fx-stroke-width: 0;
}
.default-color0.chart-series-line { -fx-stroke: #2D4D2E; }
.default-color1.chart-series-line { -fx-stroke: #66CC68 ; }
.default-color0.chart-series-line { -fx-stroke: #FF0000; }
.default-color1.chart-series-line { -fx-stroke: #00FF00 ; }
.chart-legend {
-fx-background-color: transparent;
@@ -896,9 +915,9 @@
}
.chart-legend-item-symbol{
-fx-background-radius: 0;
-fx-background-radius: 10;
}
.chart-legend-item{
-fx-text-fill: #191970;
-fx-text-fill: #000000;
}

View File

@@ -25,14 +25,13 @@
</HBox>
<LineChart
styleClass="chart-plot-background, chart-vertical-grid-lines, chart-horizontal-grid-lines, chart-alternative-row-fill, default-color0.chart-series-line, default-color1.chart-series-line, default-color2.chart-series-line, chart-legend, chart-legend-item-symbol, chart-legend-item"
fx:id="lineGraph" createSymbols="true" legendVisible="true" prefHeight="372.0" prefWidth="423.0" visible="true" animated="false" horizontalGridLinesVisible="true" verticalGridLinesVisible="true"
title="%vaultstatistics.throughputTitle">
styleClass="chart-plot-background, chart-alternative-row-fill, default-color2.chart-series-line"
fx:id="lineGraph" createSymbols="true" legendVisible="true" prefHeight="372.0" prefWidth="423.0" visible="true" animated="false" title="%vaultstatistics.throughputTitle" verticalZeroLineVisible="true" verticalGridLinesVisible="false" horizontalGridLinesVisible="true">
<xAxis>
<NumberAxis autoRanging="true" lowerBound="0" side="BOTTOM" tickUnit="1" upperBound="10" label="%vaultstatistics.xAxisTimeLabel"/>
<NumberAxis autoRanging="false" lowerBound="0" side="BOTTOM" tickUnit="5" upperBound="100" label="%vaultstatistics.xAxisTimeLabel"/>
</xAxis>
<yAxis>
<NumberAxis autoRanging="true" lowerBound="0" side="LEFT" tickUnit="1024" upperBound="100" label="%vaultstatistics.yAxisTimeLabel"/>
<NumberAxis autoRanging="true" lowerBound="0" side="LEFT" tickUnit="1024" upperBound="100" label="%vaultstatistics.yAxisThroughputLabel" forceZeroInRange="true"/>
</yAxis>
<cursor>
<Cursor fx:constant="DEFAULT"/>

View File

@@ -161,9 +161,9 @@ preferences.donationKey.getDonationKey=Get a donation key
preferences.about=About
# Vault Statistics
vaultstatistics.title=Vault Statistics
vaultstatistics.title=Statistics for %s
vaultstatistics.xAxisTimeLabel=Seconds
vaultstatistics.yAxisTimeLabel=Throughput in KiB
vaultstatistics.yAxisThroughputLabel=Throughput in KiB/s
vaultstatistics.throughputTitle=Read and Writes
# Main Window