mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-21 07:24:37 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
845189c638 |
@@ -0,0 +1,78 @@
|
|||||||
|
package org.cryptomator.ui.stats;
|
||||||
|
|
||||||
|
import javafx.beans.NamedArg;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.geometry.Point2D;
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.chart.AreaChart;
|
||||||
|
import javafx.scene.chart.Axis;
|
||||||
|
import javafx.scene.shape.ClosePath;
|
||||||
|
import javafx.scene.shape.CubicCurveTo;
|
||||||
|
import javafx.scene.shape.LineTo;
|
||||||
|
import javafx.scene.shape.MoveTo;
|
||||||
|
import javafx.scene.shape.Path;
|
||||||
|
import javafx.scene.shape.PathElement;
|
||||||
|
|
||||||
|
// inspired by http://fxexperience.com/2012/01/curve-fitting-and-styling-areachart/
|
||||||
|
public class SmoothAreaChart extends AreaChart<Number, Number> {
|
||||||
|
|
||||||
|
public SmoothAreaChart(@NamedArg("xAxis") Axis<Number> xAxis, @NamedArg("yAxis") Axis<Number> yAxis) {
|
||||||
|
super(xAxis, yAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void layoutPlotChildren() {
|
||||||
|
super.layoutPlotChildren();
|
||||||
|
var iter = getDisplayedSeriesIterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
var series = iter.next();
|
||||||
|
final Path seriesLine = (Path)((Group)series.getNode()).getChildren().get(1);
|
||||||
|
final Path fillPath = (Path)((Group)series.getNode()).getChildren().get(0);
|
||||||
|
var dx = getXAxis().getWidth() / series.getData().size();
|
||||||
|
smooth(seriesLine.getElements(), fillPath.getElements(), dx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void smooth(ObservableList<PathElement> strokeElements, ObservableList<PathElement> fillElements, double dx) {
|
||||||
|
// as we do not have direct access to the data, first recreate the list of all the data points we have
|
||||||
|
final Point2D[] dataPoints = new Point2D[strokeElements.size()];
|
||||||
|
for (int i = 0; i < strokeElements.size(); i++) {
|
||||||
|
final PathElement element = strokeElements.get(i);
|
||||||
|
if (element instanceof MoveTo) {
|
||||||
|
final MoveTo move = (MoveTo)element;
|
||||||
|
dataPoints[i] = new Point2D(move.getX(), move.getY());
|
||||||
|
} else if (element instanceof LineTo) {
|
||||||
|
final LineTo line = (LineTo)element;
|
||||||
|
final double x = line.getX(), y = line.getY();
|
||||||
|
dataPoints[i] = new Point2D(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// next we need to know the zero Y value
|
||||||
|
final double zeroY = ((MoveTo) fillElements.get(0)).getY();
|
||||||
|
final double dx2 = dx / 2.0;
|
||||||
|
|
||||||
|
// now clear and rebuild elements
|
||||||
|
strokeElements.clear();
|
||||||
|
fillElements.clear();
|
||||||
|
// start both paths
|
||||||
|
strokeElements.add(new MoveTo(dataPoints[0].getX(),dataPoints[0].getY()));
|
||||||
|
fillElements.add(new MoveTo(dataPoints[0].getX(),zeroY));
|
||||||
|
fillElements.add(new LineTo(dataPoints[0].getX(),dataPoints[0].getY()));
|
||||||
|
// add curves
|
||||||
|
for (int i = 1; i < dataPoints.length; i++) {
|
||||||
|
final int ci = i-1;
|
||||||
|
strokeElements.add(new CubicCurveTo(
|
||||||
|
dataPoints[ci].getX() + dx2, dataPoints[ci].getY(),
|
||||||
|
dataPoints[i].getX() - dx2, dataPoints[i].getY(),
|
||||||
|
dataPoints[i].getX(), dataPoints[i].getY()));
|
||||||
|
fillElements.add(new CubicCurveTo(
|
||||||
|
dataPoints[ci].getX() + dx2, dataPoints[ci].getY(),
|
||||||
|
dataPoints[i].getX() - dx2, dataPoints[i].getY(),
|
||||||
|
dataPoints[i].getX(),dataPoints[i].getY()));
|
||||||
|
}
|
||||||
|
// end the paths
|
||||||
|
fillElements.add(new LineTo(dataPoints[dataPoints.length-1].getX(),zeroY));
|
||||||
|
fillElements.add(new ClosePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
<?import javafx.scene.layout.StackPane?>
|
<?import javafx.scene.layout.StackPane?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.shape.Arc?>
|
<?import javafx.scene.shape.Arc?>
|
||||||
|
<?import org.cryptomator.ui.stats.SmoothAreaChart?>
|
||||||
<HBox xmlns="http://javafx.com/javafx"
|
<HBox xmlns="http://javafx.com/javafx"
|
||||||
xmlns:fx="http://javafx.com/fxml"
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
fx:controller="org.cryptomator.ui.stats.VaultStatisticsController"
|
fx:controller="org.cryptomator.ui.stats.VaultStatisticsController"
|
||||||
@@ -38,7 +39,7 @@
|
|||||||
<!-- Read -->
|
<!-- Read -->
|
||||||
<VBox prefWidth="300" prefHeight="300" spacing="6" alignment="CENTER">
|
<VBox prefWidth="300" prefHeight="300" spacing="6" alignment="CENTER">
|
||||||
<ThrougputLabel styleClass="label-large" idleFormat="%stats.read.throughput.idle" kibsFormat="%stats.read.throughput.kibs" mibsFormat="%stats.read.throughput.mibs" bytesPerSecond="${controller.bpsRead}"/>
|
<ThrougputLabel styleClass="label-large" idleFormat="%stats.read.throughput.idle" kibsFormat="%stats.read.throughput.kibs" mibsFormat="%stats.read.throughput.mibs" bytesPerSecond="${controller.bpsRead}"/>
|
||||||
<AreaChart fx:id="readChart" styleClass="io-stats" createSymbols="false" animated="false">
|
<SmoothAreaChart fx:id="readChart" styleClass="io-stats" createSymbols="false" animated="false">
|
||||||
<xAxis>
|
<xAxis>
|
||||||
<NumberAxis fx:id="readChartXAxis" styleClass="io-stats" autoRanging="false" forceZeroInRange="false" side="BOTTOM"/>
|
<NumberAxis fx:id="readChartXAxis" styleClass="io-stats" autoRanging="false" forceZeroInRange="false" side="BOTTOM"/>
|
||||||
</xAxis>
|
</xAxis>
|
||||||
@@ -48,7 +49,7 @@
|
|||||||
<cursor>
|
<cursor>
|
||||||
<Cursor fx:constant="DEFAULT"/>
|
<Cursor fx:constant="DEFAULT"/>
|
||||||
</cursor>
|
</cursor>
|
||||||
</AreaChart>
|
</SmoothAreaChart>
|
||||||
<DataLabel byteFormat="%stats.read.total.data.none" kibFormat="%stats.read.total.data.kib" mibFormat="%stats.read.total.data.mib" gibFormat="%stats.read.total.data.gib" dataInBytes="${controller.totalBytesRead}"/>
|
<DataLabel byteFormat="%stats.read.total.data.none" kibFormat="%stats.read.total.data.kib" mibFormat="%stats.read.total.data.mib" gibFormat="%stats.read.total.data.gib" dataInBytes="${controller.totalBytesRead}"/>
|
||||||
<DataLabel byteFormat="%stats.decr.total.data.none" kibFormat="%stats.decr.total.data.kib" mibFormat="%stats.decr.total.data.mib" gibFormat="%stats.decr.total.data.gib" dataInBytes="${controller.totalBytesDecrypted}"/>
|
<DataLabel byteFormat="%stats.decr.total.data.none" kibFormat="%stats.decr.total.data.kib" mibFormat="%stats.decr.total.data.mib" gibFormat="%stats.decr.total.data.gib" dataInBytes="${controller.totalBytesDecrypted}"/>
|
||||||
<FormattedLabel format="%stats.read.accessCount" arg1="${controller.filesRead}"/>
|
<FormattedLabel format="%stats.read.accessCount" arg1="${controller.filesRead}"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user