1 package net.mograsim.logic.ui.model.wires;
3 import java.util.ArrayList;
4 import java.util.Arrays;
7 import net.haspamelodica.swt.helper.gcs.GeneralGC;
8 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
9 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
10 import net.mograsim.logic.core.LogicObservable;
11 import net.mograsim.logic.core.LogicObserver;
12 import net.mograsim.logic.core.types.BitVectorFormatter;
13 import net.mograsim.logic.core.wires.Wire.ReadEnd;
14 import net.mograsim.logic.ui.ColorHelper;
15 import net.mograsim.logic.ui.model.ViewModelModifiable;
19 private final ViewModelModifiable model;
20 public final int logicWidth;
24 private final Rectangle bounds;
25 private double[] effectivePath;
27 private final List<Runnable> redrawListeners;
29 private final LogicObserver logicObs;
32 public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, WireCrossPoint pin2)
34 this(model, pin1, pin2, (Point[]) null);
37 public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, Pin pin2)
39 this(model, pin1, pin2, (Point[]) null);
42 public GUIWire(ViewModelModifiable model, Pin pin1, WireCrossPoint pin2)
44 this(model, pin1, pin2, (Point[]) null);
47 public GUIWire(ViewModelModifiable model, Pin pin1, Pin pin2)
49 this(model, pin1, pin2, (Point[]) null);
52 public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, WireCrossPoint pin2, Point... path)
54 this(model, pin1.getPin(), pin2.getPin(), path);
57 public GUIWire(ViewModelModifiable model, WireCrossPoint pin1, Pin pin2, Point... path)
59 this(model, pin1.getPin(), pin2, path);
62 public GUIWire(ViewModelModifiable model, Pin pin1, WireCrossPoint pin2, Point... path)
64 this(model, pin1, pin2.getPin(), path);
67 public GUIWire(ViewModelModifiable model, Pin pin1, Pin pin2, Point... path)
69 logicObs = (i) -> callRedrawListeners();
71 this.logicWidth = pin1.logicWidth;
72 if (pin2.logicWidth != pin1.logicWidth)
73 throw new IllegalArgumentException("Can't connect pins of different logic width");
78 this.path = path == null ? null : Arrays.copyOf(path, path.length);
79 this.bounds = new Rectangle(0, 0, -1, -1);
81 redrawListeners = new ArrayList<>();
83 pin1.addPinMovedListener(p -> pin1Moved());
84 pin2.addPinMovedListener(p -> pin2Moved());
86 recalculateEffectivePath();
88 model.wireCreated(this);
91 private void recalculateEffectivePath()
93 Point pos1 = pin1.getPos(), pos2 = pin2.getPos();
95 double boundsX1 = Math.min(pos1.x, pos2.x);
96 double boundsY1 = Math.min(pos1.y, pos2.y);
97 double boundsX2 = Math.max(pos1.x, pos2.x);
98 double boundsY2 = Math.max(pos1.y, pos2.y);
101 effectivePath = new double[] { pos1.x, pos1.y, (pos1.x + pos2.x) / 2, pos1.y, (pos1.x + pos2.x) / 2, pos2.y, pos2.x, pos2.y };
104 effectivePath = new double[path.length * 2 + 4];
105 effectivePath[0] = pos1.x;
106 effectivePath[1] = pos1.y;
107 for (int srcI = 0, dstI = 2; srcI < path.length; srcI++, dstI += 2)
109 double pathX = path[srcI].x;
110 double pathY = path[srcI].y;
111 effectivePath[dstI + 0] = pathX;
112 effectivePath[dstI + 1] = pathY;
113 if (pathX < boundsX1)
115 if (pathX > boundsX2)
117 if (pathY < boundsY1)
119 if (pathY > boundsY2)
122 effectivePath[effectivePath.length - 2] = pos2.x;
123 effectivePath[effectivePath.length - 1] = pos2.y;
128 bounds.width = boundsX2 - boundsX1;
129 bounds.height = boundsY2 - boundsY1;
132 private void pin1Moved()
134 recalculateEffectivePath();
135 callRedrawListeners();
138 private void pin2Moved()
140 recalculateEffectivePath();
141 callRedrawListeners();
144 public void destroy()
146 model.wireDestroyed(this);
149 public Rectangle getBounds()
151 return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
154 public void render(GeneralGC gc)
156 ColorHelper.executeWithDifferentForeground(gc, BitVectorFormatter.formatAsColor(end), () -> gc.drawPolyline(effectivePath));
159 public void setLogicModelBinding(ReadEnd end)
161 deregisterLogicObs(this.end);
163 registerLogicObs(end);
166 private void registerLogicObs(LogicObservable observable)
168 if (observable != null)
169 observable.registerObserver(logicObs);
172 private void deregisterLogicObs(LogicObservable observable)
174 if (observable != null)
175 observable.deregisterObserver(logicObs);
188 public Point[] getPath()
190 return path == null ? null : path.clone();
194 public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);}
196 public void removeRedrawListener(Runnable listener) {redrawListeners .remove(listener);}
198 private void callRedrawListeners() {redrawListeners.forEach(l -> l.run());}