From: Daniel Kirschten Date: Mon, 15 Jul 2019 16:10:19 +0000 (+0200) Subject: Fixed & cleaned up GUIWire: X-Git-Url: https://mograsim.net/gitweb/?a=commitdiff_plain;h=657f9c901e20c7b2efe53e0daa4b56c8082854b9;p=Mograsim.git Fixed & cleaned up GUIWire: It was possible to modify a GUIWire by changing arrays or points returned by it. --- diff --git a/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/HandleManager.java b/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/HandleManager.java index 91b0e3b0..c5e06a54 100644 --- a/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/HandleManager.java +++ b/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/HandleManager.java @@ -8,6 +8,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -114,8 +115,13 @@ public class HandleManager private void registerWire(GUIWire wire) { - wire.addPathChangedListener((w, diff) -> + Point[] path = wire.getPath(); + AtomicInteger oldLength = new AtomicInteger(path == null ? 0 : path.length); + wire.addPathChangedListener(w -> { + Point[] newPath = w.getPath(); + int newLength = newPath == null ? 0 : newPath.length; + int diff = oldLength.getAndSet(newLength) - newLength; if(diff != 0) { if(diff > 0) @@ -134,9 +140,9 @@ public class HandleManager pointHandlesPerWire.get(w).forEach(h -> h.updatePos()); }); addWireHandle(wire); - if (wire.getPath() == null) + if (path == null) return; - for (int i = 0; i < wire.getPath().length; i++) + for (int i = 0; i < path.length; i++) { addWirePointHandle(wire); } diff --git a/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/WireHandle.java b/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/WireHandle.java index dcb94517..0e6c4555 100644 --- a/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/WireHandle.java +++ b/net.mograsim.logic.model.editor/src/net/mograsim/logic/model/editor/handles/WireHandle.java @@ -10,9 +10,8 @@ import net.haspamelodica.swt.helper.swtobjectwrappers.Point; import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; import net.mograsim.logic.model.editor.states.EditorState; import net.mograsim.logic.model.model.wires.GUIWire; -import net.mograsim.logic.model.model.wires.GUIWire.PathChangedListener; -public class WireHandle extends Handle implements PathChangedListener +public class WireHandle extends Handle { private boolean selected = false; private final static double WIDTH = 2.0; @@ -22,7 +21,7 @@ public class WireHandle extends Handle implements PathChangedListener public WireHandle(GUIWire parent) { this.parent = parent; - parent.addPathChangedListener(this); + parent.addPathChangedListener(c -> updateBounds()); updateBounds(); } @@ -30,7 +29,7 @@ public class WireHandle extends Handle implements PathChangedListener void destroy() { super.destroy(); - parent.removePathChangedListener(this); + parent.removePathChangedListener(c -> updateBounds()); } public void updateBounds() @@ -152,10 +151,4 @@ public class WireHandle extends Handle implements PathChangedListener { return HandleType.WIRE; } - - @Override - public void pathChanged(GUIWire wire, int diff) - { - updateBounds(); - } } diff --git a/net.mograsim.logic.model/src/net/mograsim/logic/model/model/wires/GUIWire.java b/net.mograsim.logic.model/src/net/mograsim/logic/model/model/wires/GUIWire.java index d9b7cb91..7146d631 100644 --- a/net.mograsim.logic.model/src/net/mograsim/logic/model/model/wires/GUIWire.java +++ b/net.mograsim.logic.model/src/net/mograsim/logic/model/model/wires/GUIWire.java @@ -2,9 +2,8 @@ package net.mograsim.logic.model.model.wires; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.function.Consumer; import org.eclipse.swt.SWT; @@ -59,8 +58,7 @@ public class GUIWire private double[] effectivePath; private final List redrawListeners; - - private final Set pathChangedListeners; + private final List> pathChangedListeners; /** * A LogicObserver calling redrawListeners. Used for logic model bindings. @@ -150,8 +148,6 @@ public class GUIWire */ public GUIWire(ViewModelModifiable model, Pin pin1, Pin pin2, Point... path) { - pathChangedListeners = new HashSet<>(); - logicObs = (i) -> callRedrawListeners(); this.model = model; this.logicWidth = pin1.logicWidth; if (pin2.logicWidth != pin1.logicWidth) @@ -164,6 +160,9 @@ public class GUIWire this.bounds = new Rectangle(0, 0, -1, -1); redrawListeners = new ArrayList<>(); + pathChangedListeners = new ArrayList<>(); + + logicObs = (i) -> callRedrawListeners(); pin1.addPinMovedListener(p -> pinMoved()); pin2.addPinMovedListener(p -> pinMoved()); @@ -288,6 +287,8 @@ public class GUIWire gc.drawPolyline(effectivePath); } + // operations concerning the path + /** * The user-defined path between {@link #pin1} and {@link #pin2}. Note that this is not neccessarily equal to the effective path drawn * in {@link #render(GeneralGC)}.
@@ -298,7 +299,77 @@ public class GUIWire */ public Point[] getPath() { - return path == null ? null : path.clone(); + return deepPathCopy(path); + } + + public void setPath(Point... path) + { + this.path = deepPathCopy(path); + recalculateEffectivePath(); + callPathChangedListeners(); + callRedrawListeners(); + } + + public Point getPathPoint(int index) + { + return pointCopy(path[index]); + } + + public void setPathPoint(Point p, int index) + { + path[index] = pointCopy(p); + recalculateEffectivePath(); + callPathChangedListeners(); + callRedrawListeners(); + } + + public void insertPathPoint(Point p, int index) + { + if (path == null) + path = new Point[] { pointCopy(p) }; + else + { + Point[] oldPath = path; + path = new Point[oldPath.length + 1]; + System.arraycopy(oldPath, 0, path, 0, index); + if (index < oldPath.length) + System.arraycopy(oldPath, index, path, index + 1, oldPath.length - index); + path[index] = pointCopy(p); + } + } + + public void removePathPoint(int index) + { + if (path.length == 0) + path = null; + else + { + Point[] oldPath = path; + path = new Point[oldPath.length - 1]; + System.arraycopy(oldPath, 0, path, 0, index); + if (index < oldPath.length - 1) + System.arraycopy(oldPath, index + 1, path, index, oldPath.length - index - 1); + } + } + + public double[] getEffectivePath() + { + return Arrays.copyOf(effectivePath, effectivePath.length); + } + + private static Point[] deepPathCopy(Point[] path) + { + if (path == null) + return null; + Point[] copy = new Point[path.length]; + for (int i = 0; i < path.length; i++) + copy[i] = pointCopy(path[i]); + return copy; + } + + private static Point pointCopy(Point p) + { + return new Point(p.x, p.y); } // logic model binding @@ -354,29 +425,14 @@ public class GUIWire // listeners // @formatter:off - public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);} + public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);} + public void addPathChangedListener (Consumer listener) {pathChangedListeners.add (listener);} - public void removeRedrawListener(Runnable listener) {redrawListeners .remove(listener);} + public void removeRedrawListener (Runnable listener) {redrawListeners .remove(listener);} + public void removePathChangedListener(Consumer listener) {pathChangedListeners.remove(listener);} - private void callRedrawListeners() {redrawListeners.forEach(l -> l.run());} - - public void addPathChangedListener(PathChangedListener l) { pathChangedListeners.add(l); } - - public void removePathChangedListener(PathChangedListener l) { pathChangedListeners.remove(l); } - - public void callPathChangedListeners(int diff) { pathChangedListeners.forEach(l -> l.pathChanged(this, diff)); } - - @FunctionalInterface - public static interface PathChangedListener - { - /** - * Called whenever the {@link Wire}'s path changes - * - * @param wire The wire which had its path changed - * @param diff The length difference between before and after the path change. - */ - public void pathChanged(GUIWire wire, int diff); - } + private void callRedrawListeners () {redrawListeners .forEach(l -> l.run ( ));} + private void callPathChangedListeners() {pathChangedListeners.forEach(l -> l.accept(this));} // @formatter:on @Override @@ -384,65 +440,4 @@ public class GUIWire { return "GUIWire [" + pin1 + "---" + pin2 + ", value=" + (end == null ? "null" : end.getValues()) + "]"; } - - public void setPath(Point[] path) - { - int diff = (path == null ? 0 : path.length) - (this.path == null ? 0 : this.path.length); - this.path = path == null ? null : path.clone(); - recalculateEffectivePath(); - callPathChangedListeners(diff); - callRedrawListeners(); - } - - public void setPathPoint(Point p, int index) - { - path[index] = p; - recalculateEffectivePath(); - callPathChangedListeners(0); - callRedrawListeners(); - } - - public void insertPathPoint(Point p, int index) - { - Point[] path = getPath(); - if (path == null) - setPath(new Point[] { p }); - else - { - Point[] newPath = new Point[path.length + 1]; - System.arraycopy(path, 0, newPath, 0, index); - if (index < path.length) - System.arraycopy(path, index, newPath, index + 1, path.length - index); - newPath[index] = p; - setPath(newPath); - } - } - - public void removePathPoint(int index) - { - Point[] path = getPath(); - Point[] newPath = new Point[path.length - 1]; - System.arraycopy(path, 0, newPath, 0, index); - if (index < path.length - 1) - System.arraycopy(path, index + 1, newPath, index, path.length - index - 1); - setPath(newPath); - } - - /** - * @throws IndexOutOfBoundsException - */ - public Point getPathPoint(int index) - { - return path[index]; - } - - public int getPathLength() - { - return path.length; - } - - public double[] getEffectivePath() - { - return effectivePath.clone(); - } } \ No newline at end of file