Procházet zdrojové kódy

Updated Graph to use Timeline + minor UI changes + wording

Martin Beyer před 5 roky
rodič
revize
55e9cabf51

+ 68 - 34
main/ui/src/main/java/org/cryptomator/ui/vaultstatistics/VaultStatisticsController.java

@@ -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);
 	}
 
-	public Vault getVault() {
-		return vault.get();
-	}
+	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;
 
-	private void updateReadWriteData() {
-		//So the graphs start at x = 0
-		if (timeAtStartOfTracking == 0) {
-			timeAtStartOfTracking = System.currentTimeMillis();
+			// 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));
+			}
 		}
-		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)));
+
+		@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;
 	}
+	/*
+	public ReadOnlyObjectProperty<Vault> vaultProperty() {
+		return vault;
+	}*/
 }

+ 15 - 6
main/ui/src/main/java/org/cryptomator/ui/vaultstatistics/VaultStatisticsModule.java

@@ -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;
 	}
 

+ 53 - 0
main/ui/src/main/resources/css/dark_theme.css

@@ -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;
+}

+ 28 - 9
main/ui/src/main/resources/css/light_theme.css

@@ -870,25 +870,44 @@
 }
 /*******************************************************************************
  *                                                                             *
- * Vault Statistics                                                                *
+ * I/O Statistics                                                              *
  *                                                                             *
  ******************************************************************************/
+.chart {
+	-fx-padding: 10px;
+}
+
 .chart-plot-background {
-	-fx-background-color: #F7F7F7;
+	-fx-background-color: MAIN_BG;
+	-fx-padding: 20px;
 }
-.chart-vertical-grid-lines {
-	-fx-stroke: #49B04A;
+/*
+.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;
 }

+ 4 - 5
main/ui/src/main/resources/fxml/vault_statistics.fxml

@@ -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"/>

+ 2 - 2
main/ui/src/main/resources/i18n/strings.properties

@@ -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