diff --git a/pom.xml b/pom.xml
index c2a4906..97e2980 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
it.cavallium
jlinegraph
- 1.0-SNAPSHOT
+ 1.1-SNAPSHOT
17
@@ -31,4 +31,4 @@
https://mvn.mchv.eu/repository/mchv-snapshot
-
\ No newline at end of file
+
diff --git a/src/main/java/it/cavallium/jlinegraph/AWTGraphExample.java b/src/main/java/it/cavallium/jlinegraph/AWTGraphExample.java
index 834a426..662a72b 100644
--- a/src/main/java/it/cavallium/jlinegraph/AWTGraphExample.java
+++ b/src/main/java/it/cavallium/jlinegraph/AWTGraphExample.java
@@ -95,12 +95,13 @@ public class AWTGraphExample {
new SeriesStyle(new Color(0.5f, 1f, 0.5f, 1f), 0, 1, 0.3, 1d),
new SeriesStyle(new Color(1f, 1f, 0.7f, 1f), 1.5, 2, 0, 1d)
),
- new GraphAxisStyle("X axis", true, "%.2fs"::formatted),
- new GraphAxisStyle("Y axis", true, "%.2fm"::formatted),
+ new GraphAxisStyle("X axis", false, AxisMode.SHOW_WITH_VALUES, "%.2fs"::formatted),
+ new GraphAxisStyle("Y axis", false, AxisMode.SHOW_WITH_VALUES, "%.2fm"::formatted),
GRAPH_COLOR,
new GraphFonts(10f, 18f, 12f, 12f),
2f,
- true
+ true,
+ 1
));
var r = new AWTGraphRenderer();
r.renderGraph(g, new RasterSize(w, h)).drawTo(g2d);
diff --git a/src/main/java/it/cavallium/jlinegraph/AWTGraphRenderer.java b/src/main/java/it/cavallium/jlinegraph/AWTGraphRenderer.java
index 6d7e290..414600f 100644
--- a/src/main/java/it/cavallium/jlinegraph/AWTGraphRenderer.java
+++ b/src/main/java/it/cavallium/jlinegraph/AWTGraphRenderer.java
@@ -48,25 +48,31 @@ public class AWTGraphRenderer implements IGraphRenderer {
var valuesFontMetrics = graphics2D.getFontMetrics(valuesFont);
var axisNameFontMetrics = graphics2D.getFontMetrics(axisNameFont);
+ var paddingMultiplier = graph.style().paddingMultiplier();
var graphBounds = graph.data().bounds();
var x = graph.style().x();
var y = graph.style().y();
+ var padding = defaultFontMetrics.getHeight() * paddingMultiplier;
var scaleX = new NiceScale(graphBounds.minX(), graphBounds.maxX());
scaleX.setMaxTicks(20);
var scaleY = new NiceScale(graphBounds.minY(), graphBounds.maxY());
scaleY.setMaxTicks(20);
- var topPadding = defaultFontMetrics.getHeight() + valuesFontMetrics.getHeight() / 2d;
- var leftPadding = defaultFontMetrics.getHeight();
- var rightPadding = defaultFontMetrics.getHeight()
- + valuesFontMetrics.stringWidth(y.valueFormat().apply(graphBounds.maxX())) / 2d;
- var bottomPadding = defaultFontMetrics.getHeight();
- var xValueLineLength = valuesFontMetrics.getHeight();
- var yValueLineLength = valuesFontMetrics.getHeight();
- var xValuesHeight = valuesFontMetrics.getHeight();
- var xValuesToXAxisNamePadding = (x.show() ? valuesFontMetrics.getHeight() : 0);
- var xAxisNameHeight = (x.show() ? axisNameFontMetrics.getHeight() : 0);
- var yAxisNameWidth = (y.show() ? axisNameFontMetrics.getHeight() : 0);
- var yValuesToYAxisNamePadding = (y.show() ? valuesFontMetrics.getHeight() : 0);
+ var halfMaxXLabelWidth = x.mode().showLabels()
+ ? (valuesFontMetrics.stringWidth(y.valueFormat().apply(graphBounds.maxX())) / 2d) : 0;
+ var halfMaxYLabelHeight = (y.mode().showLabels() ? valuesFontMetrics.getHeight() / 2d : 0);
+ var topPadding = padding + halfMaxYLabelHeight;
+ var leftPadding = padding
+ + ((y.mode() == AxisMode.HIDE && !y.showName()) ? halfMaxXLabelWidth : 0);
+ var rightPadding = padding + (x.mode().showLabels() ? halfMaxXLabelWidth : 0);
+ var bottomPadding = padding
+ + ((x.mode() == AxisMode.HIDE && !x.showName()) ? halfMaxYLabelHeight : 0);
+ var xValueLineLength = x.mode().showRuler() ? valuesFontMetrics.getHeight() : 0;
+ var yValueLineLength = y.mode().showRuler() ? valuesFontMetrics.getHeight() : 0;
+ var xValuesHeight = x.mode().showLabels() ? valuesFontMetrics.getHeight() : 0;
+ var xValuesToXAxisNamePadding = (x.showName() ? valuesFontMetrics.getHeight() / 2 : 0);
+ var xAxisNameHeight = (x.showName() ? axisNameFontMetrics.getHeight() : 0);
+ var yAxisNameWidth = (y.showName() ? axisNameFontMetrics.getHeight() : 0);
+ var yValuesToYAxisNamePadding = (y.showName() ? valuesFontMetrics.getHeight() / 2 : 0);
var graphHeight
// Start with total height
@@ -87,7 +93,7 @@ public class AWTGraphRenderer implements IGraphRenderer {
var xValueLineOffset = topPadding + graphHeight;
var yLabels = getYLabels(graph, graphHeight, valuesFontMetrics, scaleY);
- RasterSize yLabelsAreaSize = computeYLabelsAreaSize(graphHeight, valuesFontMetrics, yLabels);
+ RasterSize yLabelsAreaSize = computeYLabelsAreaSize(y.mode(), graphHeight, valuesFontMetrics, yLabels);
var yValuesWidth = yLabelsAreaSize.width();
var yValueLineOffset = leftPadding + yAxisNameWidth + yValuesToYAxisNamePadding + yValuesWidth;
@@ -129,9 +135,9 @@ public class AWTGraphRenderer implements IGraphRenderer {
var xLabels = getXLabels(graph, graphWidth, valuesFontMetrics, scaleX);
- RasterSize yAxisNameCenterOffset = new RasterSize(valuesFontMetrics.getHeight(), valuesFontMetrics.getHeight()
+ RasterSize yAxisNameCenterOffset = new RasterSize(leftPadding + valuesFontMetrics.getHeight() / 2d, valuesFontMetrics.getHeight()
// Add half of graph height
- + graphHeight / 2);
+ + graphHeight / 2 + topPadding);
RasterSize yValuesOffset = new RasterSize(leftPadding
// Add y axis name "90deg height"
@@ -182,11 +188,11 @@ public class AWTGraphRenderer implements IGraphRenderer {
return;
}
- renderGraphBorders(graphics2D, graph, graphOffset, graphSize, defaultStroke);
- if (y.show()) {
+ renderGraphBorders(graphics2D, graph, graphOffset, graphSize, defaultStroke, totalSize);
+ if (y.showName()) {
renderYAxisName(graphics2D, graph, yAxisNameCenterOffset, axisNameFont, axisNameFontMetrics);
}
- if (x.show()) {
+ if (x.showName()) {
renderXAxisName(graphics2D, graph, xAxisNameCenterOffset, axisNameFont, axisNameFontMetrics);
}
renderYAxisValueLabels(graphics2D,
@@ -198,7 +204,9 @@ public class AWTGraphRenderer implements IGraphRenderer {
yLabels,
yLabelsAreaSize,
yValuesOffset,
- defaultStroke
+ defaultStroke,
+ y.mode().showRuler(),
+ y.mode().showLabels()
);
renderXAxisValueLabels(graphics2D,
graph,
@@ -207,7 +215,9 @@ public class AWTGraphRenderer implements IGraphRenderer {
xValueLineOffset,
xValueLineLength,
xLabels, xValuesOffset,
- defaultStroke
+ defaultStroke,
+ x.mode().showRuler(),
+ x.mode().showLabels()
);
@@ -615,25 +625,33 @@ public class AWTGraphRenderer implements IGraphRenderer {
List yLabels,
RasterSize yLabelsAreaSize,
RasterSize yValuesOffset,
- BasicStroke defaultStroke) {
- graphics2D.setFont(valuesFont);
- graphics2D.setStroke(defaultStroke);
- graphics2D.setColor(graph.style().colors().foreground().toColor());
- yLabels.forEach(label -> {
- var lineStartOffsetY = yValuesOffset.height() + label.rasterOffset();
- var currentLineOffsetX = label.formattedText().isBlank() ? yValueLineLength / 3d : 0;
- var currentLineLength = yValueLineLength + (label.formattedText().isBlank() ? -yValueLineLength / 3d : 0);
- graphics2D.draw(new Line2D.Double(yValueLineOffset + currentLineOffsetX,
- lineStartOffsetY,
- yValueLineOffset + currentLineOffsetX + currentLineLength,
- lineStartOffsetY
- ));
- graphics2D.fill(generateShapeFromText(graphics2D,
- label.formattedText(),
- yValuesOffset.width() + yLabelsAreaSize.width() - valuesFontMetrics.stringWidth(label.formattedText()),
- yValuesOffset.height() + label.rasterOffset() + valuesFontMetrics.getHeight() / 2d - valuesFontMetrics.getDescent()
- ));
- });
+ BasicStroke defaultStroke,
+ boolean showRulerTicks,
+ boolean showRulerLabels) {
+ if ((yValueLineLength > 0 && showRulerTicks) || showRulerLabels) {
+ graphics2D.setFont(valuesFont);
+ graphics2D.setStroke(defaultStroke);
+ graphics2D.setColor(graph.style().colors().foreground().toColor());
+ yLabels.forEach(label -> {
+ if (showRulerTicks) {
+ var lineStartOffsetY = yValuesOffset.height() + label.rasterOffset();
+ var currentLineOffsetX = label.formattedText().isBlank() ? yValueLineLength / 3d : 0;
+ var currentLineLength = yValueLineLength + (label.formattedText().isBlank() ? -yValueLineLength / 3d : 0);
+ graphics2D.draw(new Line2D.Double(yValueLineOffset + currentLineOffsetX,
+ lineStartOffsetY,
+ yValueLineOffset + currentLineOffsetX + currentLineLength,
+ lineStartOffsetY
+ ));
+ }
+ if (showRulerLabels) {
+ graphics2D.fill(generateShapeFromText(graphics2D,
+ label.formattedText(),
+ yValuesOffset.width() + yLabelsAreaSize.width() - valuesFontMetrics.stringWidth(label.formattedText()),
+ yValuesOffset.height() + label.rasterOffset() + valuesFontMetrics.getHeight() / 2d - valuesFontMetrics.getDescent()
+ ));
+ }
+ });
+ }
}
private static void renderXAxisName(Graphics2D graphics2D,
@@ -662,28 +680,44 @@ public class AWTGraphRenderer implements IGraphRenderer {
int xValueLineLength,
List xLabels,
RasterSize xValuesOffset,
- BasicStroke defaultStroke) {
- graphics2D.setFont(valuesFont);
- graphics2D.setStroke(defaultStroke);
- graphics2D.setColor(graph.style().colors().foreground().toColor());
- xLabels.forEach(label -> {
- var lineStartOffsetX = xValuesOffset.width() + label.rasterOffset();
- var currentLineLength = label.formattedText().isBlank() ? xValueLineLength / 1.5d : xValueLineLength;
- //noinspection SuspiciousNameCombination
- graphics2D.draw(new Line2D.Double(lineStartOffsetX, xValueLineOffset, lineStartOffsetX, xValueLineOffset + currentLineLength));
- graphics2D.fill(generateShapeFromText(graphics2D,
- label.formattedText(),
- xValuesOffset.width() + label.rasterOffset() - valuesFontMetrics.stringWidth(label.formattedText()) / 2d,
- xValuesOffset.height() + valuesFontMetrics.getHeight()
- ));
- });
+ BasicStroke defaultStroke,
+ boolean showRulerTicks,
+ boolean showRulerLabels) {
+ if ((xValueLineLength > 0 && showRulerTicks) || showRulerLabels) {
+ graphics2D.setFont(valuesFont);
+ graphics2D.setStroke(defaultStroke);
+ graphics2D.setColor(graph.style().colors().foreground().toColor());
+ xLabels.forEach(label -> {
+ var lineStartOffsetX = xValuesOffset.width() + label.rasterOffset();
+ if (showRulerTicks) {
+ var currentLineLength = label.formattedText().isBlank() ? xValueLineLength / 1.5d : xValueLineLength;
+ //noinspection SuspiciousNameCombination
+ graphics2D.draw(new Line2D.Double(lineStartOffsetX, xValueLineOffset, lineStartOffsetX, xValueLineOffset + currentLineLength));
+ }
+ if (showRulerLabels) {
+ graphics2D.fill(generateShapeFromText(graphics2D,
+ label.formattedText(),
+ xValuesOffset.width() + label.rasterOffset() - valuesFontMetrics.stringWidth(label.formattedText()) / 2d,
+ xValuesOffset.height() + valuesFontMetrics.getHeight()
+ ));
+ }
+ });
+ }
}
private static void renderGraphBorders(Graphics2D graphics2D,
Graph graph,
RasterSize graphOffset,
RasterSize graphSize,
- BasicStroke defaultStroke) {
+ BasicStroke defaultStroke,
+ RasterSize totalSize) {
+ // Do not draw the border if the graph is fullscreen
+ if (graphOffset.width() <= 0
+ && graphOffset.height() <= 0
+ && graphSize.width() >= totalSize.width()
+ && graphSize.height() >= totalSize.height()) {
+ return;
+ }
var fgColor = graph.style().colors().foreground().toColor();
graphics2D.setColor(fgColor);
graphics2D.setStroke(defaultStroke);
@@ -694,7 +728,11 @@ public class AWTGraphRenderer implements IGraphRenderer {
));
}
- private static RasterSize computeYLabelsAreaSize(double graphHeight, FontMetrics valuesFontMetrics, List yLabels) {
+ private static RasterSize computeYLabelsAreaSize(AxisMode axisMode, double graphHeight, FontMetrics valuesFontMetrics,
+ List yLabels) {
+ if (!axisMode.showLabels()) {
+ return RasterSize.EMPTY;
+ }
double maxLabelWidth = 0d;
for (LabelWithOffset yLabel : yLabels) {
var currentMaxLabelWidth = valuesFontMetrics.stringWidth(yLabel.formattedText);
diff --git a/src/main/java/it/cavallium/jlinegraph/AxisMode.java b/src/main/java/it/cavallium/jlinegraph/AxisMode.java
new file mode 100644
index 0000000..3c8e592
--- /dev/null
+++ b/src/main/java/it/cavallium/jlinegraph/AxisMode.java
@@ -0,0 +1,21 @@
+package it.cavallium.jlinegraph;
+
+public enum AxisMode {
+ SHOW_WITH_VALUES,
+ SHOW_RULER_ONLY,
+ HIDE;
+
+ public boolean showLabels() {
+ return switch (this) {
+ case SHOW_WITH_VALUES -> true;
+ default -> false;
+ };
+ }
+
+ public boolean showRuler() {
+ return switch (this) {
+ case SHOW_WITH_VALUES, SHOW_RULER_ONLY -> true;
+ default -> false;
+ };
+ }
+}
diff --git a/src/main/java/it/cavallium/jlinegraph/GraphAxisStyle.java b/src/main/java/it/cavallium/jlinegraph/GraphAxisStyle.java
index 366f0ac..9048886 100644
--- a/src/main/java/it/cavallium/jlinegraph/GraphAxisStyle.java
+++ b/src/main/java/it/cavallium/jlinegraph/GraphAxisStyle.java
@@ -2,4 +2,4 @@ package it.cavallium.jlinegraph;
import java.util.function.Function;
-public record GraphAxisStyle(String title, boolean show, Function valueFormat) {}
+public record GraphAxisStyle(String title, boolean showName, AxisMode mode, Function valueFormat) {}
diff --git a/src/main/java/it/cavallium/jlinegraph/GraphStyle.java b/src/main/java/it/cavallium/jlinegraph/GraphStyle.java
index 76512fd..8311224 100644
--- a/src/main/java/it/cavallium/jlinegraph/GraphStyle.java
+++ b/src/main/java/it/cavallium/jlinegraph/GraphStyle.java
@@ -3,4 +3,4 @@ package it.cavallium.jlinegraph;
import java.util.List;
public record GraphStyle(List seriesStyles, GraphAxisStyle x, GraphAxisStyle y, GraphColors colors,
- GraphFonts fonts, double strokeWidth, boolean showLegend) {}
+ GraphFonts fonts, double strokeWidth, boolean showLegend, double paddingMultiplier) {}
diff --git a/src/main/java/it/cavallium/jlinegraph/RasterSize.java b/src/main/java/it/cavallium/jlinegraph/RasterSize.java
index c0fcec9..b3d9e6a 100644
--- a/src/main/java/it/cavallium/jlinegraph/RasterSize.java
+++ b/src/main/java/it/cavallium/jlinegraph/RasterSize.java
@@ -1,3 +1,5 @@
package it.cavallium.jlinegraph;
-public record RasterSize(double width, double height) {}
+public record RasterSize(double width, double height) {
+ public static final RasterSize EMPTY = new RasterSize(0, 0);
+}