From 301dc1d5fdfcfc8f1c42fff97921d29c90f4ed83 Mon Sep 17 00:00:00 2001 From: hneemann Date: Sun, 7 Feb 2021 17:41:59 +0100 Subject: [PATCH] fixes a rectangle selection issue, see #639 --- .../digital/draw/elements/VisualElement.java | 20 ++++++++-------- .../digital/draw/shapes/RectShape.java | 12 ++++++---- .../de/neemann/digital/draw/shapes/Shape.java | 7 ------ .../digital/draw/shapes/ShapeMatch.java | 23 +++++++++++++++++++ .../digital/integration/TestSelect.java | 2 +- 5 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 src/main/java/de/neemann/digital/draw/shapes/ShapeMatch.java diff --git a/src/main/java/de/neemann/digital/draw/elements/VisualElement.java b/src/main/java/de/neemann/digital/draw/elements/VisualElement.java index 8274ffa83..49844fdf9 100644 --- a/src/main/java/de/neemann/digital/draw/elements/VisualElement.java +++ b/src/main/java/de/neemann/digital/draw/elements/VisualElement.java @@ -148,17 +148,15 @@ public class VisualElement implements Drawable, Movable, AttributeListener { */ public boolean matches(Vector p, boolean includeText) { GraphicMinMax m = getMinMax(includeText); - if (getShape().onlyBorderClickable()) { - int width = SIZE2; - return ((Math.abs(p.x - m.getMin().x) < width || Math.abs(p.x - m.getMax().x) < width) - && (m.getMin().y <= p.y) && (p.y <= m.getMax().y)) - || ((Math.abs(p.y - m.getMin().y) < width || Math.abs(p.y - m.getMax().y) < width) - && (m.getMin().x <= p.x) && (p.x <= m.getMax().x)); - } else - return (m.getMin().x <= p.x) - && (m.getMin().y <= p.y) - && (p.x <= m.getMax().x) - && (p.y <= m.getMax().y); + boolean inBox = (m.getMin().x - SIZE2 <= p.x) + && (m.getMin().y - SIZE2 <= p.y) + && (p.x <= m.getMax().x + SIZE2) + && (p.y <= m.getMax().y + SIZE2); + + if (inBox && getShape() instanceof ShapeMatch) + return ((ShapeMatch) getShape()).matches(getTransform().invert().transform(p)); + + return inBox; } /** diff --git a/src/main/java/de/neemann/digital/draw/shapes/RectShape.java b/src/main/java/de/neemann/digital/draw/shapes/RectShape.java index d35c7210a..647387f09 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/RectShape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/RectShape.java @@ -14,11 +14,12 @@ import de.neemann.digital.draw.graphics.*; import de.neemann.digital.lang.Lang; import static de.neemann.digital.draw.shapes.GenericShape.SIZE; +import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; /** - * Simple text + * Simple rectangle */ -public class RectShape implements Shape { +public class RectShape implements ShapeMatch { private final String label; private final int width; private final int height; @@ -89,8 +90,11 @@ public class RectShape implements Shape { } @Override - public boolean onlyBorderClickable() { - return true; + public boolean matches(Vector pos) { + return (pos.x > -SIZE2 && pos.x < SIZE2 && pos.y >= 0 && pos.y < height * SIZE) + || (pos.x > width * SIZE - SIZE2 && pos.x < width * SIZE + SIZE2 && pos.y >= 0 && pos.y < height * SIZE) + || (pos.y > -SIZE2 && pos.y < SIZE2 && pos.x >= 0 && pos.x < width * SIZE) + || (pos.y > height * SIZE - SIZE2 && pos.y < height * SIZE + SIZE2 && pos.x >= 0 && pos.x < width * SIZE); } } diff --git a/src/main/java/de/neemann/digital/draw/shapes/Shape.java b/src/main/java/de/neemann/digital/draw/shapes/Shape.java index d19f36108..b59db8de4 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/Shape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/Shape.java @@ -51,11 +51,4 @@ public interface Shape extends Drawable, ObservableValueReader { default void registerModel(ModelCreator modelCreator, Model model, ModelEntry element) { } - /** - * @return if true, only the border of the shape is clickable. - */ - default boolean onlyBorderClickable() { - return false; - } - } diff --git a/src/main/java/de/neemann/digital/draw/shapes/ShapeMatch.java b/src/main/java/de/neemann/digital/draw/shapes/ShapeMatch.java new file mode 100644 index 000000000..9e67b7056 --- /dev/null +++ b/src/main/java/de/neemann/digital/draw/shapes/ShapeMatch.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.draw.shapes; + +import de.neemann.digital.draw.graphics.Vector; + +/** + * A shape where the clickable area is not simply the bounding box, but + * defined by the shape itself. + */ +public interface ShapeMatch extends Shape { + + /** + * Checks is the given position matches the shape + * + * @param pos the position + * @return true if the position matches the shape + */ + boolean matches(Vector pos); +} diff --git a/src/test/java/de/neemann/digital/integration/TestSelect.java b/src/test/java/de/neemann/digital/integration/TestSelect.java index e20b246e8..9072f52c4 100644 --- a/src/test/java/de/neemann/digital/integration/TestSelect.java +++ b/src/test/java/de/neemann/digital/integration/TestSelect.java @@ -20,7 +20,7 @@ public class TestSelect extends TestCase { Circuit c = new ToBreakRunner("dig/selectOuter.dig").getCircuit(); // don't select by clicking in label size bounding box - VisualElement el = c.getElementAt(new Vector(65, 15)); + VisualElement el = c.getElementAt(new Vector(75, 15)); assertNull(el); // select by clicking in shape size bounding box