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 defaultRenderer( toString: (V) -> String = { it.toString() } ) : IVertexRenderer = IVertexRenderer { v: V -> DefaultVertexComponent(toString(v)).asRenderData() }