diff --git a/src/main/java/de/neemann/digital/draw/elements/Circuit.java b/src/main/java/de/neemann/digital/draw/elements/Circuit.java index 4469cabb0..8aedb8eb9 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Circuit.java +++ b/src/main/java/de/neemann/digital/draw/elements/Circuit.java @@ -343,6 +343,20 @@ public class Circuit { modified(); } + /** + * Deletes a single wire + * + * @param wireToDelete the wire to delete + */ + public void delete(Wire wireToDelete) { + if (wires.remove(wireToDelete)) { + WireConsistencyChecker checker = new WireConsistencyChecker(wires); + wires = checker.check(); + dotsPresent = false; + modified(); + } + } + /** * Returns the element at the given position @@ -427,6 +441,20 @@ public class Circuit { return wires; } + /** + * Returns the matching wire + * + * @param pos the position + * @return the matching wire or null + */ + public Wire getWireAt(Vector pos, int radius) { + for (Wire w : wires) + if (w.contains(pos, radius)) + return w; + return null; + } + + /** * Deletes the references to the ObservableValues representing the elements or wire state. * So this circuit is detached from a generated model. diff --git a/src/main/java/de/neemann/digital/draw/elements/Wire.java b/src/main/java/de/neemann/digital/draw/elements/Wire.java index c3321b6fb..81a759dbc 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Wire.java +++ b/src/main/java/de/neemann/digital/draw/elements/Wire.java @@ -6,6 +6,8 @@ import de.neemann.digital.draw.graphics.Style; import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.shapes.Drawable; +import java.util.Collection; + /** * A simple wire described by two points * @@ -107,6 +109,23 @@ public class Wire implements Drawable, Moveable { return false; } + /** + * Test if the given wire is matched by the given position. + * Returns true if distance to wire is smaller then the given radius. + * + * @param v the position + * @param radius the matching radius + * @return true if matching + */ + public boolean contains(Vector v, int radius) { + if (p1.x == p2.x && Math.abs(p1.x - v.x) <= radius) + return (p1.y < v.y && v.y < p2.y) || (p2.y < v.y && v.y < p1.y); + else if (p1.y == p2.y && Math.abs(p1.y - v.y) < radius) + return (p1.x < v.x && v.x < p2.x) || (p2.x < v.x && v.x < p1.x); + else + return false; // ToDo: should also work for diagonal wires + } + /** * @return the orientation of the wire */ @@ -118,23 +137,35 @@ public class Wire implements Drawable, Moveable { return Orientation.diagonal; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + /** + * Returns true if the given wire is included in the given collection. + * To compare the wires it calls equalsContent. + * + * @param col the collection of wires + * @return true if wire is included + * @see Wire#equalsContent(Wire) + */ + public boolean isIncludedIn(Collection col) { + for (Wire w : col) + if (equalsContent(w)) + return true; + return false; + } - Wire wire = (Wire) o; + /** + * Returns true if wires are equal. + * It is not possible to overwrite Object.equals() because some algorithms + * (eg. highlighting) are depending on an object based equals! + * + * @param wire the other wire + * @return true if both wires are equal + */ + public boolean equalsContent(Wire wire) { + if (this == wire) return true; + if (wire == null) return false; if (!p1.equals(wire.p1)) return false; return p2.equals(wire.p2); - - } - - @Override - public int hashCode() { - int result = p1.hashCode(); - result = 31 * result + p2.hashCode(); - return result; } @Override diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index 871071ec2..fe4744d46 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -558,7 +558,11 @@ public class CircuitComponent extends JComponent { else mouseMoveElement.activate(vp, pos); } else { - mouseWire.activate(pos); + Wire w = circuit.getWireAt(pos, SIZE2); + if (w == null) + mouseWire.activate(pos); + else + mouseMoveSelected.activate(w, pos); } } } @@ -592,6 +596,7 @@ public class CircuitComponent extends JComponent { this.element = element; delta = null; deleteAction.setActive(true); + rotateAction.setEnabled(true); } @Override @@ -623,6 +628,12 @@ public class CircuitComponent extends JComponent { } mouseNormal.activate(); } + + @Override + public void rotate() { + element.rotate(); + repaint(); + } } private final class MouseControllerMoveElement extends MouseController { @@ -757,7 +768,6 @@ public class CircuitComponent extends JComponent { removeHighLighted(); mouseMoveSelected.activate(corner1, corner2, getPosVector(e)); } else { - corner2 = getPosVector(e); if ((e.getModifiersEx() & CTRL_DOWN_MASK) != 0) { Vector dif = corner2.sub(corner1); @@ -860,6 +870,7 @@ public class CircuitComponent extends JComponent { private ArrayList elements; private Vector lastPos; private boolean wasMoved; + private Wire remove; private MouseControllerMoveSelected(Cursor cursor) { super(cursor); @@ -870,6 +881,24 @@ public class CircuitComponent extends JComponent { lastPos = pos; wasMoved = false; elements = circuit.getElementsToMove(Vector.min(corner1, corner2), Vector.max(corner1, corner2)); + remove=null; + } + + private void activate(Wire w, Vector pos) { + super.activate(); + lastPos = pos; + wasMoved = false; + elements = new ArrayList<>(); + elements.add(w.getMovableP1()); + elements.add(w.getMovableP2()); + deleteAction.setEnabled(true); + addHighLighted(w); + remove=w; + } + + @Override + void moved(MouseEvent e) { + lastPos = getPosVector(e); } @Override @@ -894,8 +923,18 @@ public class CircuitComponent extends JComponent { void released(MouseEvent e) { if (wasMoved) circuit.elementsMoved(); + removeHighLighted(); mouseNormal.activate(); } + + @Override + public void delete() { + if (remove!=null) { + circuit.delete(remove); + removeHighLighted(); + mouseNormal.activate(); + } + } } private final class MouseControllerInsertCopied extends MouseController { diff --git a/src/test/java/de/neemann/digital/draw/elements/WireConsistencyCheckerTest.java b/src/test/java/de/neemann/digital/draw/elements/WireConsistencyCheckerTest.java index 1d9aa02c5..a1dbdb150 100644 --- a/src/test/java/de/neemann/digital/draw/elements/WireConsistencyCheckerTest.java +++ b/src/test/java/de/neemann/digital/draw/elements/WireConsistencyCheckerTest.java @@ -68,13 +68,13 @@ public class WireConsistencyCheckerTest extends TestCase { public static void checkContains(ArrayList wires, Wire wire) { for (Wire w : wires) - if (w.equals(wire)) + if (wire.equalsContent(wire)) return; wire = new Wire(wire.p2, wire.p1); for (Wire w : wires) - if (w.equals(wire)) + if (w.equalsContent(wire)) return; assertTrue(false); diff --git a/src/test/java/de/neemann/digital/draw/elements/WireMergerTest.java b/src/test/java/de/neemann/digital/draw/elements/WireMergerTest.java index 075a4d933..38b7ee09f 100644 --- a/src/test/java/de/neemann/digital/draw/elements/WireMergerTest.java +++ b/src/test/java/de/neemann/digital/draw/elements/WireMergerTest.java @@ -51,14 +51,14 @@ public class WireMergerTest extends TestCase { wm.addTo(newWires); assertEquals(6, newWires.size()); - assertTrue(newWires.contains(new Wire(new Vector(1, 3), new Vector(8, 3)))); - assertTrue(newWires.contains(new Wire(new Vector(1, 4), new Vector(5, 4)))); - assertTrue(newWires.contains(new Wire(new Vector(5, 5), new Vector(8, 5)))); + assertTrue(new Wire(new Vector(1, 3), new Vector(8, 3)).isIncludedIn(newWires)); + assertTrue(new Wire(new Vector(1, 4), new Vector(5, 4)).isIncludedIn(newWires)); + assertTrue(new Wire(new Vector(5, 5), new Vector(8, 5)).isIncludedIn(newWires)); - assertTrue(newWires.contains(new Wire(new Vector(1, 6), new Vector(8, 6)))); + assertTrue(new Wire(new Vector(1, 6), new Vector(8, 6)).isIncludedIn(newWires)); - assertTrue(newWires.contains(new Wire(new Vector(1, 7), new Vector(4, 7)))); - assertTrue(newWires.contains(new Wire(new Vector(5, 7), new Vector(8, 7)))); + assertTrue(new Wire(new Vector(1, 7), new Vector(4, 7)).isIncludedIn(newWires)); + assertTrue(new Wire(new Vector(5, 7), new Vector(8, 7)).isIncludedIn(newWires)); } public void testMerge2() { @@ -70,6 +70,6 @@ public class WireMergerTest extends TestCase { ArrayList newWires = new ArrayList<>(); wm.addTo(newWires); assertEquals(1, newWires.size()); - assertEquals(new Wire(new Vector(1, 3), new Vector(8, 3)), newWires.get(0)); + assertTrue(new Wire(new Vector(1, 3), new Vector(8, 3)).equalsContent(newWires.get(0))); } } \ No newline at end of file diff --git a/src/test/java/de/neemann/gui/language/ResourcesTest.java b/src/test/java/de/neemann/gui/language/ResourcesTest.java index 48cf2052e..b7d4ee0c7 100644 --- a/src/test/java/de/neemann/gui/language/ResourcesTest.java +++ b/src/test/java/de/neemann/gui/language/ResourcesTest.java @@ -4,6 +4,7 @@ import junit.framework.TestCase; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.util.Arrays; /** * @author hneemann @@ -13,23 +14,23 @@ public class ResourcesTest extends TestCase { = "\n" + "\n" + " Speichern\n" + - " Öffnen\n" + + " \u00D6ffnen\n" + ""; public void testWrite() throws Exception { Resources res = new Resources(); - res.put("menu_open", "Öffnen"); + res.put("menu_open", "\u00D6ffnen"); res.put("menu_save", "Speichern"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); res.save(baos); - assertEquals(example, baos.toString()); + assertTrue(Arrays.equals(example.getBytes("utf-8"), baos.toByteArray())); } public void testRead() throws Exception { - Resources res = new Resources(new ByteArrayInputStream(example.getBytes())); + Resources res = new Resources(new ByteArrayInputStream(example.getBytes("utf-8"))); - assertEquals("Öffnen", res.get("menu_open")); + assertEquals("\u00D6ffnen", res.get("menu_open")); assertEquals("Speichern", res.get("menu_save")); } } \ No newline at end of file