81 lines
2.8 KiB
Java
81 lines
2.8 KiB
Java
package io.swtc.proccessing;
|
|
|
|
import javax.swing.*;
|
|
import java.awt.*;
|
|
import java.awt.geom.CubicCurve2D;
|
|
|
|
/**
|
|
* Acts as a transparent layer over the entire window to draw connections.
|
|
*/
|
|
public class ConnectionOverlay extends JComponent {
|
|
private final Component source;
|
|
private final Component target;
|
|
private final Color connectionColor;
|
|
|
|
public ConnectionOverlay(Component source, Component target, Color color) {
|
|
this.source = source;
|
|
this.target = target;
|
|
this.connectionColor = color;
|
|
setOpaque(false); // Make sure we can see through it
|
|
}
|
|
|
|
@Override
|
|
protected void paintComponent(Graphics g) {
|
|
super.paintComponent(g);
|
|
if (!source.isShowing() || !target.isShowing()) return;
|
|
|
|
Graphics2D g2d = (Graphics2D) g.create();
|
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
// 1. Get absolute positions relative to this Overlay
|
|
Point p1 = SwingUtilities.convertPoint(source, 0, 0, this);
|
|
Point p2 = SwingUtilities.convertPoint(target, 0, 0, this);
|
|
|
|
int x1, y1, x2, y2, ctrl1X, ctrl2X;
|
|
|
|
// Calculate vertical centers
|
|
y1 = p1.y + (source.getHeight() / 2);
|
|
y2 = p2.y + (target.getHeight() / 2);
|
|
|
|
// 2. Logic to determine Left/Right orientation
|
|
// If source is to the left of target
|
|
if (p1.x + source.getWidth() < p2.x) {
|
|
x1 = p1.x + source.getWidth(); // Right edge of source
|
|
x2 = p2.x; // Left edge of target
|
|
}
|
|
// If source is to the right of target
|
|
else if (p1.x > p2.x + target.getWidth()) {
|
|
x1 = p1.x; // Left edge of source
|
|
x2 = p2.x + target.getWidth(); // Right edge of target
|
|
}
|
|
// If they are overlapping horizontally, use centers
|
|
else {
|
|
x1 = p1.x + (source.getWidth() / 2);
|
|
x2 = p2.x + (target.getWidth() / 2);
|
|
}
|
|
|
|
// 3. Dynamic Curve "Stiffness"
|
|
// The horizontal distance between the two points determines how far the curve pulls
|
|
int horizontalDist = Math.abs(x1 - x2);
|
|
int offset = Math.max(horizontalDist / 2, 20); // Minimum 20px pull for short distances
|
|
|
|
if (x1 < x2) {
|
|
ctrl1X = x1 + offset;
|
|
ctrl2X = x2 - offset;
|
|
} else {
|
|
ctrl1X = x1 - offset;
|
|
ctrl2X = x2 + offset;
|
|
}
|
|
|
|
// 4. Draw the Curve
|
|
g2d.setColor(connectionColor);
|
|
g2d.setStroke(new BasicStroke(3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
|
|
|
// We keep the Y coordinates for controls the same as the endpoints
|
|
// to create that "horizontal entry/exit" look.
|
|
CubicCurve2D curve = new CubicCurve2D.Float(x1, y1, ctrl1X, y1, ctrl2X, y2, x2, y2);
|
|
g2d.draw(curve);
|
|
|
|
g2d.dispose();
|
|
}
|
|
} |