mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-14 16:51:28 +00:00
Compare commits
1 Commits
2ndfactor
...
feature/sm
| 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.VBox?>
|
||||
<?import javafx.scene.shape.Arc?>
|
||||
<?import org.cryptomator.ui.stats.SmoothAreaChart?>
|
||||
<HBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="org.cryptomator.ui.stats.VaultStatisticsController"
|
||||
@@ -38,7 +39,7 @@
|
||||
<!-- Read -->
|
||||
<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}"/>
|
||||
<AreaChart fx:id="readChart" styleClass="io-stats" createSymbols="false" animated="false">
|
||||
<SmoothAreaChart fx:id="readChart" styleClass="io-stats" createSymbols="false" animated="false">
|
||||
<xAxis>
|
||||
<NumberAxis fx:id="readChartXAxis" styleClass="io-stats" autoRanging="false" forceZeroInRange="false" side="BOTTOM"/>
|
||||
</xAxis>
|
||||
@@ -48,7 +49,7 @@
|
||||
<cursor>
|
||||
<Cursor fx:constant="DEFAULT"/>
|
||||
</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.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}"/>
|
||||
|
||||
Reference in New Issue
Block a user