mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-20 01:26:52 -04:00
make sure to release all strong referenced to the I/O chart when closing the window
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package org.cryptomator.ui.common;
|
||||
|
||||
import javafx.beans.binding.LongBinding;
|
||||
import javafx.beans.binding.StringBinding;
|
||||
import javafx.beans.value.ObservableObjectValue;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
|
||||
/**
|
||||
@@ -29,4 +31,23 @@ public final class WeakBindings {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new LongBinding that listens to changes from the given observable without being strongly referenced by it.
|
||||
*
|
||||
* @param observable The observable
|
||||
* @return a LongBinding weakly referenced from the given observable
|
||||
*/
|
||||
public static LongBinding bindLong(ObservableValue<Number> observable) {
|
||||
return new LongBinding() {
|
||||
{
|
||||
bind(observable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long computeValue() {
|
||||
return observable.getValue().longValue();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.cryptomator.ui.vaultstatistics;
|
||||
import javafx.animation.Animation;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.beans.binding.LongBinding;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
@@ -12,7 +13,9 @@ import javafx.scene.chart.XYChart.Series;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Duration;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultStats;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.WeakBindings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -22,31 +25,38 @@ 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 Vault vault;
|
||||
@FXML
|
||||
private LineChart<Number, Number> lineGraph;
|
||||
private final VaultStats stats;
|
||||
private final Series<Number, Number> readData;
|
||||
private final Series<Number, Number> writeData;
|
||||
private Timeline ioAnimation;
|
||||
private final Timeline ioAnimation;
|
||||
private final LongBinding bpsRead;
|
||||
private final LongBinding bpsWritten;
|
||||
|
||||
public LineChart<Number, Number> lineGraph;
|
||||
|
||||
@Inject
|
||||
public VaultStatisticsController(@VaultStatisticsWindow Stage window, @VaultStatisticsWindow Vault vault) {
|
||||
this.window = window;
|
||||
this.vault = vault;
|
||||
this.stats = vault.getStats();
|
||||
this.bpsRead = WeakBindings.bindLong(stats.bytesPerSecondReadProperty());
|
||||
this.bpsWritten = WeakBindings.bindLong(stats.bytesPerSecondWrittenProperty());
|
||||
|
||||
readData = new Series<>();
|
||||
this.readData = new Series<>();
|
||||
readData.setName("Read Data"); // For Legend
|
||||
//TODO Add Name to strings.properties
|
||||
writeData = new Series<>();
|
||||
this.writeData = new Series<>();
|
||||
writeData.setName("Write Data");
|
||||
//TODO Add Name to strings.properties
|
||||
|
||||
ioAnimation = new Timeline(); //TODO Research better timer
|
||||
this.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();
|
||||
|
||||
// make sure to stop animating,
|
||||
// otherwise a global timer (GC root) will keep a strong reference to animation
|
||||
window.setOnHiding(evt -> {
|
||||
ioAnimation.stop();
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -84,20 +94,30 @@ public class VaultStatisticsController implements FxController {
|
||||
}
|
||||
|
||||
// add latest value:
|
||||
final long decBytes = vault.getStats().bytesPerSecondReadProperty().get();
|
||||
final long decBytes = stats.bytesPerSecondReadProperty().get();
|
||||
final double decMb = decBytes * BYTES_TO_MEGABYTES_FACTOR;
|
||||
final long encBytes = vault.getStats().bytesPerSecondWrittenProperty().get();
|
||||
final long encBytes = stats.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;
|
||||
/* Getter/Setter */
|
||||
|
||||
public LongBinding bpsReadProperty() {
|
||||
return bpsRead;
|
||||
}
|
||||
|
||||
public long getBpsRead() {
|
||||
return bpsRead.get();
|
||||
}
|
||||
|
||||
public LongBinding bpsWrittenProperty() {
|
||||
return bpsWritten;
|
||||
}
|
||||
|
||||
public long getBpsWritten() {
|
||||
return bpsWritten.get();
|
||||
}
|
||||
/*
|
||||
public ReadOnlyObjectProperty<Vault> vaultProperty() {
|
||||
return vault;
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@@ -39,11 +40,15 @@ abstract class VaultStatisticsModule {
|
||||
Stage stage = factory.create();
|
||||
stage.setTitle(String.format(resourceBundle.getString("vaultstatistics.title"), vault.getDisplayableName()));
|
||||
stage.setResizable(false);
|
||||
var weakStage = new WeakReference<>(stage);
|
||||
vault.stateProperty().addListener(new ChangeListener<>() {
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends VaultState> observable, VaultState oldValue, VaultState newValue) {
|
||||
if (newValue != VaultState.UNLOCKED) {
|
||||
stage.hide();
|
||||
Stage stage = weakStage.get();
|
||||
if (stage != null) {
|
||||
stage.hide();
|
||||
}
|
||||
observable.removeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
<HBox alignment="CENTER_RIGHT" spacing="6">
|
||||
<Label styleClass="label-small,label-muted" text="%main.vaultDetail.bytesPerSecondRead"/>
|
||||
<ThrougputLabel styleClass="label-small,label-muted" alignment="CENTER_RIGHT" minWidth="60" idleFormat="%main.vaultDetail.throughput.idle" kibsFormat="%main.vaultDetail.throughput.kbps"
|
||||
mibsFormat="%main.vaultDetail.throughput.mbps" bytesPerSecond="${controller.vault.stats.bytesPerSecondRead}"/>
|
||||
mibsFormat="%main.vaultDetail.throughput.mbps" bytesPerSecond="${controller.bpsRead}"/>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER_RIGHT" spacing="6">
|
||||
<Label styleClass="label-small,label-muted" text="%main.vaultDetail.bytesPerSecondWritten"/>
|
||||
<ThrougputLabel styleClass="label-small,label-muted" alignment="CENTER_RIGHT" minWidth="60" idleFormat="%main.vaultDetail.throughput.idle" kibsFormat="%main.vaultDetail.throughput.kbps"
|
||||
mibsFormat="%main.vaultDetail.throughput.mbps" bytesPerSecond="${controller.vault.stats.bytesPerSecondWritten}"/>
|
||||
mibsFormat="%main.vaultDetail.throughput.mbps" bytesPerSecond="${controller.bpsWritten}"/>
|
||||
</HBox>
|
||||
|
||||
<LineChart
|
||||
|
||||
Reference in New Issue
Block a user