Geyser/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GraphPanel.java

188 lines
7.3 KiB
Java

/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.platform.standalone.gui;
import lombok.Setter;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* This has been modified to fit Geyser more but is based on
* https://gist.github.com/roooodcastro/6325153#gistcomment-3107524
*/
public final class GraphPanel extends JPanel {
private final static int padding = 10;
private final static int labelPadding = 25;
private final static int pointWidth = 4;
private final static int numberYDivisions = 10;
private final static Color lineColor = new Color(44, 102, 230, 255);
private final static Color pointColor = new Color(100, 100, 100, 255);
private final static Color gridColor = new Color(200, 200, 200, 255);
private static final Stroke graphStroke = new BasicStroke(2f);
private List<Integer> values = new ArrayList<>(10);
@Setter
private String xLabel = "";
public GraphPanel() {
setPreferredSize(new Dimension(200 - (padding * 2), 150 - (padding * 2)));
}
public void setValues(Collection<Integer> newValues) {
values.clear();
addValues(newValues);
}
public void addValues(Collection<Integer> newValues) {
values.addAll(newValues);
updateUI();
}
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
if (!(graphics instanceof Graphics2D)) {
graphics.drawString("Graphics is not Graphics2D, unable to render", 0, 0);
return;
}
final Graphics2D g = (Graphics2D) graphics;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
final int length = values.size();
final int width = getWidth();
final int height = getHeight();
final int maxScore = getMaxScore();
final int minScore = getMinScore();
final int scoreRange = maxScore - minScore;
// draw white background
g.setColor(Color.WHITE);
g.fillRect(
padding + labelPadding,
padding,
width - (2 * padding) - labelPadding,
height - 2 * padding - labelPadding);
g.setColor(Color.BLACK);
final FontMetrics fontMetrics = g.getFontMetrics();
final int fontHeight = fontMetrics.getHeight();
// create hatch marks and grid lines for y axis.
for (int i = 0; i < numberYDivisions + 1; i++) {
final int x1 = padding + labelPadding;
final int x2 = pointWidth + padding + labelPadding;
final int y = height - ((i * (height - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding);
if (length > 0) {
g.setColor(gridColor);
g.drawLine(padding + labelPadding + 1 + pointWidth, y, width - padding, y);
g.setColor(Color.BLACK);
final int tickValue = (int) (minScore + ((scoreRange * i) / numberYDivisions));
final String yLabel = tickValue + "";
final int labelWidth = fontMetrics.stringWidth(yLabel);
g.drawString(yLabel, x1 - labelWidth - 5, y + (fontHeight / 2) - 3);
}
g.drawLine(x1, y, x2, y);
}
// and for x axis
if (length > 1) {
for (int i = 0; i < length; i++) {
final int x = i * (width - padding * 2 - labelPadding) / (length - 1) + padding + labelPadding;
final int y1 = height - padding - labelPadding;
final int y2 = y1 - pointWidth;
if ((i % ((int) ((length / 20.0)) + 1)) == 0) {
g.setColor(gridColor);
g.drawLine(x, height - padding - labelPadding - 1 - pointWidth, x, padding);
g.setColor(Color.BLACK);
/*g.setColor(Color.BLACK);
final String xLabel = i + "";
final int labelWidth = fontMetrics.stringWidth(xLabel);
g.drawString(xLabel, x - labelWidth / 2, y1 + fontHeight + 3);*/
}
g.drawLine(x, y1, x, y2);
}
}
// create x and y axes
g.drawLine(padding + labelPadding, height - padding - labelPadding, padding + labelPadding, padding);
g.drawLine(padding + labelPadding, height - padding - labelPadding, width - padding, height - padding - labelPadding);
g.setColor(Color.BLACK);
final int labelWidth = fontMetrics.stringWidth(xLabel);
final int labelX = ((padding + labelPadding) + (width - padding)) / 2;
final int labelY = height - padding - labelPadding;
g.drawString(xLabel, labelX - labelWidth / 2, labelY + fontHeight + 3);
final Stroke oldStroke = g.getStroke();
g.setColor(lineColor);
g.setStroke(graphStroke);
final double xScale = ((double) width - (2 * padding) - labelPadding) / (length - 1);
final double yScale = ((double) height - 2 * padding - labelPadding) / scoreRange;
final List<Point> graphPoints = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
final int x1 = (int) (i * xScale + padding + labelPadding);
final int y1 = (int) ((maxScore - values.get(i)) * yScale + padding);
graphPoints.add(new Point(x1, y1));
}
for (int i = 0; i < graphPoints.size() - 1; i++) {
final int x1 = graphPoints.get(i).x;
final int y1 = graphPoints.get(i).y;
final int x2 = graphPoints.get(i + 1).x;
final int y2 = graphPoints.get(i + 1).y;
g.drawLine(x1, y1, x2, y2);
}
boolean drawDots = width > (length * pointWidth);
if (drawDots) {
g.setStroke(oldStroke);
g.setColor(pointColor);
for (Point graphPoint : graphPoints) {
final int x = graphPoint.x - pointWidth / 2;
final int y = graphPoint.y - pointWidth / 2;
g.fillOval(x, y, pointWidth, pointWidth);
}
}
}
private int getMinScore() {
return 0;
}
private int getMaxScore() {
return 100;
}
}