Fixed the issue of disappearing components in some edge cases

This commit is contained in:
Bane Stojkovic
2026-10-12 15:58:38 +02:00
parent 5f09026ddd
commit 2cab737acf
7 changed files with 100 additions and 6 deletions
@@ -181,10 +181,26 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
maxY = p.getY();
}
}
Rectangle2D rect = new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
double margin = getClipMargin();
Rectangle2D rect = new Rectangle2D.Double(minX - margin, minY - margin,
maxX - minX + 2 * margin, maxY - minY + 2 * margin);
return !clip.intersects(rect);
}
/**
* Distance in pixels that the drawing may reach beyond the bounding box of the control points,
* such as half the width of a stroke running through them. {@link #checkPointsClipped(Shape)}
* widens the box by this much before testing it against the clip. The margin must stay positive,
* because {@link Shape#intersects(Rectangle2D)} reports a box with no width or height as disjoint
* from everything, which would hide a straight horizontal or vertical component whose control
* points all lie outside the clip.
*
* @return margin around the control points.
*/
protected double getClipMargin() {
return 1;
}
@SuppressWarnings("unchecked")
public IDIYComponent<T> clone() throws CloneNotSupportedException {
try {
@@ -22,10 +22,12 @@
package org.diylc.components;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
@@ -172,6 +174,37 @@ public class AbstractCurvedComponentTest {
}
}
@Test
public void checkPointsClipped_keepsAStraightRunThatCrossesTheClipWithBothEndsOutside() {
CurvedTestComponent horizontal = new CurvedTestComponent();
horizontal.setPointCount(PointCount.TWO);
horizontal.stretchBetween(new Point2D.Double(-100, 50), new Point2D.Double(300, 50));
assertFalse(horizontal.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
CurvedTestComponent vertical = new CurvedTestComponent();
vertical.setPointCount(PointCount.TWO);
vertical.stretchBetween(new Point2D.Double(50, -100), new Point2D.Double(50, 300));
assertFalse(vertical.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
}
@Test
public void checkPointsClipped_skipsAStraightRunThatMissesTheClip() {
CurvedTestComponent c = new CurvedTestComponent();
c.setPointCount(PointCount.TWO);
c.stretchBetween(new Point2D.Double(-100, 500), new Point2D.Double(300, 500));
assertTrue(c.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
}
@Test
public void checkPointsClipped_keepsARunWhoseStrokeReachesIntoTheClip() {
CurvedTestComponent c = new CurvedTestComponent();
c.setPointCount(PointCount.TWO);
c.stretchBetween(new Point2D.Double(-100, 105), new Point2D.Double(300, 105));
assertTrue(c.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
c.clipMargin = 10;
assertFalse(c.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
}
private static void assertPoint(double x, double y, Point2D actual) {
assertEquals(x, actual.getX(), DELTA);
assertEquals(y, actual.getY(), DELTA);
@@ -181,6 +214,13 @@ public class AbstractCurvedComponentTest {
private static final long serialVersionUID = 1L;
private double clipMargin = 1;
@Override
protected double getClipMargin() {
return clipMargin;
}
@Override
protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
IDrawingObserver drawingObserver) {}