Files
2009scape/Server/src/main/kotlin/gui/GraphView.kt
T

132 lines
4.9 KiB
Kotlin

package gui
import java.awt.*
import javax.swing.JPanel
/**
* @author Rodrigo, Maritaria
* @author Ceikry (rewrote into Kotlin, adapted for specific use case)
*/
class GraphView() : JPanel() {
private val values: MutableList<Int> = ArrayList(10)
fun setValues(newValues: Collection<Int>) {
values.clear()
addValues(newValues)
}
fun addValues(newValues: Collection<Int>) {
if(values.size > 200) values.removeFirst()
values.addAll(newValues)
updateUI()
}
override fun paintComponent(graphics: Graphics) {
super.paintComponent(graphics)
if (graphics !is Graphics2D) {
graphics.drawString("Graphics is not Graphics2D, unable to render", 0, 0)
return
}
val g: Graphics2D = graphics
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
val length: Int = values.size
val width: Int = width
val height: Int = height
val maxScore: Double = maxScore
val minScore: Double = minScore
val scoreRange: Double = maxScore - minScore
// draw white background
g.color = Color.WHITE
g.fillRect(
padding + labelPadding,
padding,
width - (2 * padding) - labelPadding,
height - (2 * padding) - labelPadding
)
g.color = Color.BLACK
val fontMetrics: FontMetrics = g.fontMetrics
val fontHeight: Int = fontMetrics.height
// create hatch marks and grid lines for y axis.
for (i in 0 until numberYDivisions + 1) {
val x1: Int = padding + labelPadding
val x2: Int = pointWidth + padding + labelPadding
val y: Int =
height - (((i * (height - (padding * 2) - labelPadding)) / numberYDivisions) + padding + labelPadding)
if (length > 0) {
g.color = gridColor
g.drawLine(padding + labelPadding + 1 + pointWidth, y, width - padding, y)
g.color = Color.BLACK
val tickValue: Int = (minScore + ((scoreRange * i) / numberYDivisions)).toInt()
val yLabel: String = tickValue.toString() + ""
val labelWidth: Int = fontMetrics.stringWidth(yLabel)
g.drawString(yLabel, x1 - labelWidth - 5, y + (fontHeight / 2) - 3)
}
g.drawLine(x1, y, x2, y)
}
// 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
)
val oldStroke: Stroke = g.stroke
g.color = lineColor
g.stroke = graphStroke
val xScale: Double = (width.toDouble() - (2 * padding) - labelPadding) / (length - 1)
val yScale: Double = (height.toDouble() - (2 * padding) - labelPadding) / scoreRange
val graphPoints: MutableList<Point> = ArrayList(length)
for (i in 0 until length) {
val x1: Int = ((i * xScale) + padding + labelPadding).toInt()
val y1: Int = ((maxScore - values.get(i)) * yScale + padding).toInt()
graphPoints.add(Point(x1, y1))
}
for (i in 0 until graphPoints.size - 1) {
val x1: Int = graphPoints[i].x
val y1: Int = graphPoints[i].y
val x2: Int = graphPoints[i + 1].x
val y2: Int = graphPoints[i + 1].y
if(y2 != 0) {
g.drawLine(x1, y1, x2, y2)
}
}
val drawDots: Boolean = width > (length * pointWidth)
if (drawDots) {
g.stroke = oldStroke
g.color = pointColor
for (graphPoint: Point in graphPoints) {
val x: Int = graphPoint.x - pointWidth / 2
val y: Int = graphPoint.y - pointWidth / 2
g.fillOval(x, y, pointWidth, pointWidth)
}
}
}
private val minScore: Double
get() = values.stream().min { obj: Int, integer: Int? -> obj.compareTo((integer)!!) }.orElse(0)
.toDouble()
private val maxScore: Double
get() {
return values.stream().max { obj: Int, integer: Int? -> obj.compareTo((integer)!!) }.orElse(0)
.toDouble()
}
companion object {
private const val padding: Int = 25
private const val labelPadding: Int = 25
private const val pointWidth: Int = 4
private const val numberYDivisions: Int = 10
private val lineColor: Color = Color(44, 102, 230, 180)
private val pointColor: Color = Color(100, 100, 100, 180)
private val gridColor: Color = Color(200, 200, 200, 200)
private val graphStroke: Stroke = BasicStroke(2f)
}
init {
preferredSize = Dimension(padding * 2 + 300, padding * 2 + 200)
}
}