X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=net.mograsim.logic.model%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fmodel%2Fmodel%2Fwires%2FGUIWire.java;h=c564571584dea4cd85af274da94304f8e1cc61c4;hb=1c0601faecd9a838587a5aa42c8deca7dd43563c;hp=c1070e53267de7cb6f6f7c035912b6aff026848b;hpb=b5d8c2d71e27350ea7c9314e40df5bb0584271cd;p=Mograsim.git 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 c1070e53..c5645715 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 @@ -3,6 +3,7 @@ package net.mograsim.logic.model.model.wires; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import org.eclipse.swt.SWT; @@ -17,6 +18,7 @@ import net.mograsim.logic.core.wires.Wire.ReadEnd; import net.mograsim.logic.model.model.ViewModelModifiable; import net.mograsim.preferences.ColorDefinition; import net.mograsim.preferences.ColorManager; +import net.mograsim.preferences.Preferences; /** * A wire connecting exactly two {@link Pin}s. @@ -29,6 +31,10 @@ public class GUIWire * The model this wire is a part of. */ private final ViewModelModifiable model; + /** + * The name of this wire. Is unique for all wires in its model. + */ + public final String name; /** * The logical width of this wire. Is equal to the logical with of {@link #pin1} and {@link #pin2}. */ @@ -56,7 +62,7 @@ public class GUIWire */ private double[] effectivePath; - private final List redrawListeners; + private final List> pathChangedListeners; /** * A LogicObserver calling redrawListeners. Used for logic model bindings. @@ -70,84 +76,164 @@ public class GUIWire // creation and destruction /** - * Creates a new {@link GUIWire} with automatic interpolation. + * Creates a new {@link GUIWire} with automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, WireCrossPoint pin2) { - this(model, pin1, pin2, (Point[]) null); + this(model, null, pin1, pin2); } /** - * Creates a new {@link GUIWire} with automatic interpolation. + * Creates a new {@link GUIWire} with automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, Pin pin2) { - this(model, pin1, pin2, (Point[]) null); + this(model, null, pin1, pin2); } /** - * Creates a new {@link GUIWire} with automatic interpolation. + * Creates a new {@link GUIWire} with automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, Pin pin1, WireCrossPoint pin2) { - this(model, pin1, pin2, (Point[]) null); + this(model, null, pin1, pin2); } /** - * Creates a new {@link GUIWire} with automatic interpolation. + * Creates a new {@link GUIWire} with automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, Pin pin1, Pin pin2) { - this(model, pin1, pin2, (Point[]) null); + this(model, null, pin1, pin2); } /** - * Creates a new {@link GUIWire} without automatic interpolation. + * Creates a new {@link GUIWire} without automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, WireCrossPoint pin2, Point... path) { - this(model, pin1.getPin(), pin2.getPin(), path); + this(model, null, pin1, pin2, path); } /** - * Creates a new {@link GUIWire} without automatic interpolation. + * Creates a new {@link GUIWire} without automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, Pin pin2, Point... path) { - this(model, pin1.getPin(), pin2, path); + this(model, null, pin1, pin2, path); } /** - * Creates a new {@link GUIWire} without automatic interpolation. + * Creates a new {@link GUIWire} without automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, Pin pin1, WireCrossPoint pin2, Point... path) { - this(model, pin1, pin2.getPin(), path); + this(model, null, pin1, pin2, path); } /** - * Creates a new {@link GUIWire} without automatic interpolation. + * Creates a new {@link GUIWire} without automatic interpolation and using the default name. * * @author Daniel Kirschten */ public GUIWire(ViewModelModifiable model, Pin pin1, Pin pin2, Point... path) { - logicObs = (i) -> callRedrawListeners(); + this(model, null, pin1, pin2, path); + } + + /** + * Creates a new {@link GUIWire} with automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, WireCrossPoint pin1, WireCrossPoint pin2) + { + this(model, name, pin1, pin2, (Point[]) null); + } + + /** + * Creates a new {@link GUIWire} with automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, WireCrossPoint pin1, Pin pin2) + { + this(model, name, pin1, pin2, (Point[]) null); + } + + /** + * Creates a new {@link GUIWire} with automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, Pin pin1, WireCrossPoint pin2) + { + this(model, name, pin1, pin2, (Point[]) null); + } + + /** + * Creates a new {@link GUIWire} with automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, Pin pin1, Pin pin2) + { + this(model, name, pin1, pin2, (Point[]) null); + } + + /** + * Creates a new {@link GUIWire} without automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, WireCrossPoint pin1, WireCrossPoint pin2, Point... path) + { + this(model, name, pin1.getPin(), pin2.getPin(), path); + } + + /** + * Creates a new {@link GUIWire} without automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, WireCrossPoint pin1, Pin pin2, Point... path) + { + this(model, name, pin1.getPin(), pin2, path); + } + + /** + * Creates a new {@link GUIWire} without automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, Pin pin1, WireCrossPoint pin2, Point... path) + { + this(model, name, pin1, pin2.getPin(), path); + } + + /** + * Creates a new {@link GUIWire} without automatic interpolation. + * + * @author Daniel Kirschten + */ + public GUIWire(ViewModelModifiable model, String name, Pin pin1, Pin pin2, Point... path) + { this.model = model; + this.name = name == null ? model.getDefaultWireName() : name; this.logicWidth = pin1.logicWidth; if (pin2.logicWidth != pin1.logicWidth) throw new IllegalArgumentException("Can't connect pins of different logic width"); @@ -158,25 +244,27 @@ public class GUIWire this.path = path == null ? null : Arrays.copyOf(path, path.length); this.bounds = new Rectangle(0, 0, -1, -1); - redrawListeners = new ArrayList<>(); + pathChangedListeners = new ArrayList<>(); + + logicObs = (i) -> model.requestRedraw(); pin1.addPinMovedListener(p -> pinMoved()); pin2.addPinMovedListener(p -> pinMoved()); recalculateEffectivePath(); - model.wireCreated(this); + model.wireCreated(this, this::destroyed); } /** - * Destroys this wire. This method implicitly calls {@link ViewModelModifiable#wireDestroyed(GUIWire) wireDestroyed()} for the model - * this component is a part of. + * Destroys this wire. This method is called from {@link ViewModelModifiable#wireDestroyed(GUIWire) wireDestroyed()} of the model this + * wire is a part of. * * @author Daniel Kirschten */ - public void destroy() + private void destroyed() { - model.wireDestroyed(this); + // nothing to do } // pins @@ -209,7 +297,7 @@ public class GUIWire private void pinMoved() { recalculateEffectivePath(); - callRedrawListeners(); + model.requestRedraw(); } // "graphical" operations @@ -280,9 +368,16 @@ public class GUIWire ColorDefinition wireColor = BitVectorFormatter.formatAsColor(end); if (wireColor != null) gc.setForeground(ColorManager.current().toColor(wireColor)); + if (logicWidth == 1) + gc.setLineWidth(Preferences.current().getDouble("net.mograsim.logic.model.linewidth.wire.singlebit")); + else + gc.setLineWidth(Preferences.current().getDouble("net.mograsim.logic.model.linewidth.wire.multibit")); gc.drawPolyline(effectivePath); + gc.setLineWidth(Preferences.current().getDouble("net.mograsim.logic.model.linewidth.default")); } + // 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)}.
@@ -293,7 +388,81 @@ 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(); + model.requestRedraw(); + } + + public Point getPathPoint(int index) + { + return pointCopy(path[index]); + } + + public void setPathPoint(Point p, int index) + { + path[index] = pointCopy(p); + recalculateEffectivePath(); + callPathChangedListeners(); + model.requestRedraw(); + } + + 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); + } + recalculateEffectivePath(); + callPathChangedListeners(); + } + + 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); + } + recalculateEffectivePath(); + callPathChangedListeners(); + } + + 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 @@ -349,11 +518,11 @@ public class GUIWire // listeners // @formatter:off - 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 removePathChangedListener(Consumer listener) {pathChangedListeners.remove(listener);} - private void callRedrawListeners() {redrawListeners.forEach(l -> l.run());} + private void callPathChangedListeners() {pathChangedListeners.forEach(l -> l.accept(this));} // @formatter:on @Override