fixes a mouse selection issue; closes #736

This commit is contained in:
hneemann 2021-05-06 12:50:03 +02:00
parent ee55b94276
commit 0b78f80c8c
4 changed files with 78 additions and 42 deletions

View File

@ -6,7 +6,9 @@
package de.neemann.digital.draw.elements;
import de.neemann.digital.core.SyncAccess;
import de.neemann.digital.core.Value;
import de.neemann.digital.core.element.*;
import de.neemann.digital.core.io.Const;
import de.neemann.digital.draw.graphics.*;
import de.neemann.digital.draw.shapes.Shape;
import de.neemann.digital.draw.shapes.*;
@ -18,7 +20,6 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE2;
import static de.neemann.digital.gui.components.CircuitComponent.raster;
/**
@ -143,20 +144,18 @@ public class VisualElement implements Drawable, Movable, AttributeListener {
* Checks if the given point is within the bounding box of the shape of this element.
*
* @param p a position
* @param includeText true if a click on a text also selectes the element
* @param includeText true if a click on a text also selects the element
* @return true if p is inside the bounding box of the shape of this element.
*/
public boolean matches(Vector p, boolean includeText) {
if (getShape() instanceof ShapeSpecificMatch)
return ((ShapeSpecificMatch) getShape()).matches(getTransform().invert().transform(p));
GraphicMinMax m = getMinMax(includeText);
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;
return (m.getMin().x <= p.x)
&& (m.getMin().y <= p.y)
&& (p.x <= m.getMax().x)
&& (p.y <= m.getMax().y);
}
/**
@ -391,11 +390,19 @@ public class VisualElement implements Drawable, Movable, AttributeListener {
@Override
public String toString() {
String lab = elementAttributes.getLabel();
if (lab != null && lab.length() > 0)
return elementName + " (" + lab + ")";
else
return elementName;
if (elementName.equals(Const.DESCRIPTION.getName())) {
return elementName + " ("
+ elementAttributes.getValueFormatter().formatToView(
new Value(elementAttributes.get(Keys.VALUE), elementAttributes.getBits())) + ")";
} else if (elementName.equals(Tunnel.DESCRIPTION.getName())) {
return elementName + " (" + elementAttributes.get(Keys.NETNAME) + ")";
} else {
String label = elementAttributes.getLabel();
if (label.isEmpty()) {
return elementName;
} else
return elementName + " (" + label + ")";
}
}
/**

View File

@ -19,7 +19,7 @@ import static de.neemann.digital.draw.shapes.GenericShape.SIZE2;
/**
* Simple rectangle
*/
public class RectShape implements ShapeMatch {
public class RectShape implements ShapeSpecificMatch {
private final String label;
private final int width;
private final int height;

View File

@ -11,7 +11,7 @@ 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 {
public interface ShapeSpecificMatch extends Shape {
/**
* Checks is the given position matches the shape

View File

@ -1669,16 +1669,19 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
}
private VisualElement getVisualElement(Vector pos, boolean includeText) {
VisualElement vp = null;
private SearchResult getVisualElement(Vector pos, boolean includeText) {
List<VisualElement> list = getCircuit().getElementListAt(pos, includeText);
if (list.size() == 1)
vp = list.get(0);
return new SearchResult(SearchResult.State.FOUND, list.get(0));
else if (list.size() > 1) {
ItemPicker<VisualElement> picker = new ItemPicker<>(parent, list);
vp = picker.select();
VisualElement vp = picker.select();
if (vp == null)
return new SearchResult(SearchResult.State.CANCELED, null);
else
return new SearchResult(SearchResult.State.FOUND, vp);
}
return vp;
return new SearchResult(SearchResult.State.NONE, null);
}
//CHECKSTYLE.ON: FinalClass
@ -1703,23 +1706,29 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
Vector pos = getPosVector(e);
if (mouse.isSecondaryClick(e)) {
VisualElement vp = getVisualElement(pos, true);
if (vp != null)
editAttributes(vp, e);
SearchResult sel = getVisualElement(pos, true);
if (sel.getVisualElement() != null)
editAttributes(sel.getVisualElement(), e);
} else if (mouse.isPrimaryClick(e) && hadFocusAtClick) {
VisualElement vp = getVisualElement(pos, false);
if (vp != null) {
if (vp.isPinPos(raster(pos)) && !mouse.isClickModifier(e)) {
if (!isLocked()) mouseWireRect.activate(pos);
} else
mouseMoveElement.activate(vp, pos);
} else if (!isLocked()) {
if (mouse.isClickModifier(e)) {
Wire wire = getCircuit().getWireAt(pos, SIZE2);
if (wire != null)
mouseMoveWire.activate(wire, pos);
} else
mouseWireRect.activate(pos);
SearchResult sel = getVisualElement(pos, false);
switch (sel.getState()) {
case FOUND:
VisualElement vp = sel.getVisualElement();
if (vp.isPinPos(raster(pos)) && !mouse.isClickModifier(e)) {
if (!isLocked()) mouseWireRect.activate(pos);
} else
mouseMoveElement.activate(vp, pos);
break;
case NONE:
if (!isLocked()) {
if (mouse.isClickModifier(e)) {
Wire wire = getCircuit().getWireAt(pos, SIZE2);
if (wire != null)
mouseMoveWire.activate(wire, pos);
} else
mouseWireRect.activate(pos);
}
break;
}
}
}
@ -2776,9 +2785,9 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
@Override
void clicked(MouseEvent e) {
Vector pos = getPosVector(e);
VisualElement vp = getVisualElement(pos, true);
if (vp != null)
wizardNotification.notify(vp);
SearchResult sel = getVisualElement(pos, true);
if (sel.getVisualElement() != null)
wizardNotification.notify(sel.getVisualElement());
}
@Override
@ -2816,4 +2825,24 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
*/
void modified(Modification<Circuit> modification);
}
private static final class SearchResult {
private final State state;
private final VisualElement visualElement;
enum State {NONE, FOUND, CANCELED}
private SearchResult(State state, VisualElement visualElement) {
this.state = state;
this.visualElement = visualElement;
}
private State getState() {
return state;
}
private VisualElement getVisualElement() {
return visualElement;
}
}
}