Files
alt-graph/src/main/kotlin/com/jaytux/altgraph/swing/DefaultVertexComponent.kt
2025-09-02 14:37:12 +02:00

87 lines
3.0 KiB
Kotlin

package com.jaytux.altgraph.swing
import com.jaytux.altgraph.layout.PseudoForestLayout
import java.awt.*
import java.awt.RenderingHints.KEY_ANTIALIASING
import java.awt.RenderingHints.VALUE_ANTIALIAS_ON
import java.awt.geom.AffineTransform
import java.awt.geom.Ellipse2D
import javax.swing.JLabel
class DefaultVertexComponent(
label: String,
private var _shape: Shape = Ellipse2D.Double(0.0, 0.0, 30.0, 30.0),
var labelOffset: Point = Point(20, 7),
) : IDrawable {
val label = JLabel(label)
private lateinit var _preferredSize: Dimension
private var _arrowTarget: Point = Point(0, 0)
private var _arrowTargetOffset: Float = 0.0f
var fillColor: Color = Color.LIGHT_GRAY
var borderStroke: Stroke = BasicStroke(1.0f)
var borderColor: Color = Color.BLACK
var shape: Shape
get() = _shape
set(value) {
_shape = value
_arrowTarget = Point(value.bounds.width / 2, value.bounds.height / 2)
_arrowTargetOffset = (value.bounds.width + value.bounds.height).toFloat() / 4.0f
updatePreferredSize()
}
init {
updatePreferredSize()
shape = _shape // to initialize arrow target and offset
}
fun updatePreferredSize() {
val bounds = shape.bounds
val textSize = label.preferredSize
val cx = bounds.width / 2; val cy = bounds.height / 2
val tx = cx + labelOffset.x; val ty = cy + labelOffset.y - textSize.height / 2
val textRect = Rectangle(tx, ty, textSize.width, textSize.height)
val total = bounds.union(textRect)
_preferredSize = Dimension(total.width, total.height)
}
override fun draw(graphics: Graphics2D) {
val g = graphics.create() as Graphics2D
g.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON)
val shapeBounds = shape.bounds
val cx = shapeBounds.width / 2; val cy = shapeBounds.height / 2
val tx = AffineTransform.getTranslateInstance((cx - shapeBounds.centerX), (cy - shapeBounds.centerY))
val transShape = tx.createTransformedShape(shape)
g.color = fillColor
g.fill(transShape)
g.color = borderColor
g.stroke = borderStroke
g.draw(transShape)
val textSize = label.preferredSize
val lx = cx + labelOffset.x; val ly = cy + labelOffset.y - textSize.height / 2
label.size = textSize
g.translate(lx, ly)
label.paint(g)
g.dispose()
}
fun vertexSize(): PseudoForestLayout.VertexSize {
val size = _preferredSize
val lSize = label.preferredSize
return PseudoForestLayout.VertexSize(size.graph(), labelOffset.graph(), lSize.graph())
}
fun asRenderData(): IVertexRenderer.RenderData =
IVertexRenderer.RenderData(this, _arrowTarget, _arrowTargetOffset)
}
fun <V> defaultRenderer(
toString: (V) -> String = { it.toString() }
) : IVertexRenderer<V> = IVertexRenderer { v: V ->
DefaultVertexComponent(toString(v)).asRenderData()
}